Tato tematika je zpracována v Záznamy přednášek: str

Podobné dokumenty
Tato tematika je zpracována v Záznamy přednášek: str

Rozklad problému na podproblémy

5. přednáška - Rozklad problému na podproblémy

Algoritmizace a programování

Časová složitost / Time complexity

KTE / ZPE Informační technologie

Úvod do programování - Java. Cvičení č.4

3. přednáška. Obsah: Řídící struktury sekvence, if-else, switch, for, while, do-while. Zpracování posloupnosti

ÚVODNÍ ZNALOSTI. datové struktury. správnost programů. analýza algoritmů

Prohledávání do šířky = algoritmus vlny

Binární soubory (datové, typované)

1. Téma 12 - Textové soubory a výjimky

Řídicí struktury. alg3 1

Algoritmy I, složitost

10. Složitost a výkon

Obsah přednášky. Analýza algoritmu Algoritmická složitost Návrhy algoritmů Urychlování algoritmů 1/41

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

Algoritmizace Dynamické programování. Jiří Vyskočil, Marko Genyg-Berezovskyj 2010

Algoritmizace. Jiří Vyskočil, Marko Genyg-Berezovskyj 2010

Obsah 7. přednášky: Tato tematika je zpracována v Záznamy přednášek: str

Algoritmizace a programování

5 Rekurze a zásobník. Rekurzivní volání metody

Úvod do programovacích jazyků (Java)

Dynamické programování

Výčtový typ strana 67

Lekce 01 Úvod do algoritmizace

Vyhledávání. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava. Prezentace ke dni 21.

11 VYPOČITATELNOST A VÝPOČTOVÁ SLOŽITOST

1. Téma 03 - Rozhodování

KTE / ZPE Informační technologie

Paměť počítače. alg2 1

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

7. přednáška - třídy, objekty třídy objekty atributy tříd metody tříd

Základní pojmy. Úvod do programování. Základní pojmy. Zápis algoritmu. Výraz. Základní pojmy

Dekompozice problému, rekurze

Soubor jako posloupnost bytů

7. Datové typy v Javě

Iterační výpočty Projekt č. 2

Datové struktury. alg12 1

6. Příkazy a řídící struktury v Javě

Abstraktní datové typy: zásobník

Složitost 1.1 Opera ní a pam ová složitost 1.2 Opera ní složitost v pr rném, nejhorším a nejlepším p ípad 1.3 Asymptotická složitost

Databáze, sítě a techniky programování X33DSP

1. Programování proti rozhraní

3 KTE / ZPE Informační technologie

Složitost algoritmů. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava

Rozklad problému na podproblémy, rekurze

Různé algoritmy mají různou složitost

Rozklad problému na podproblémy, rekurze

Doba běhu daného algoritmu/programu. 1. Který fragment programu z následujících dvou proběhne rychleji?

Vyhledávání. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava. Prezentace ke dni 12.

Algoritmizace a programování. Terminálový vstup a výstup

Generické programování

8. přednáška: Soubory a proudy

Proměnná. Datový typ. IAJCE Cvičení č. 3. Pojmenované místo v paměti sloužící pro uložení hodnoty.

Asymptotická složitost algoritmů

Datové struktury. Obsah přednášky: Definice pojmů. Abstraktní datové typy a jejich implementace. Algoritmizace (Y36ALG), Šumperk - 12.

Digitální učební materiál

8 Třídy, objekty, metody, předávání argumentů metod

2.1 Podmínka typu case Cykly Cyklus s podmínkou na začátku Cyklus s podmínkou na konci... 5

C# konzole Podíl dvou čísel, podmínka IF

Obsah 10. přednášky: Jak bude probíhat zkouška?! Podrobné informace:

Časová a prostorová složitost algoritmů

6 Příkazy řízení toku

Algoritmizace a programování

Rekurze. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava. Prezentace ke dni 12.

5 Přehled operátorů, příkazy, přetypování

B3B33ALP - Algoritmy a programování - Zkouška z předmětu B3B33ALP. Marek Boháč bohacm11

Pole a kolekce. v C#, Javě a C++

Řešení: PŘENESVĚŽ (N, A, B, C) = přenes N disků z A na B pomocí C

součet cvičení celkem. známka. Úloha č.: max. bodů: skut. bodů:

Test prvočíselnosti. Úkol: otestovat dané číslo N, zda je prvočíslem

8. Rekurze. doc. Ing. Jiří Vokřínek, Ph.D. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze

Teoretické minimum z PJV

Úvod do programovacích jazyků (Java)

Časová složitost algoritmů

3. úloha - problém batohu metodami branch & bound, dynamické programování, heuristika s testem

Java - výjimky. private void vstup() throws IOException {... }

Náplň. v Jednoduché příklady na práci s poli v C - Vlastnosti třídění - Způsoby (algoritmy) třídění

Java a XML. 10/26/09 1/7 Java a XML

Digitální učební materiál

Obsah přednášky 9. Skrývání informací. Skrývání informací. Zapouzdření. Skrývání informací. Základy programování (IZAPR, IZKPR) Přednáška 9

Programové konvence, dokumentace a ladění. Programování II 2. přednáška Alena Buchalcevová

Algoritmizace prostorových úloh

Poslední nenulová číslice faktoriálu

B3B33ALP - Algoritmy a programování - Zkouška z předmětu B3B33ALP. Marek Boháč bohacm11

IB015 Neimperativní programování. Časová složitost, Typové třídy, Moduly. Jiří Barnat Libor Škarvada

Obsah. Úvod 11 Základy programování 11 Objektový přístup 11 Procvičování 11 Zvláštní odstavce 12 Zpětná vazba od čtenářů 12 Errata 13

ABSTRAKTNÍ DATOVÉ TYPY (ADT)

Zápis programu v jazyce C#

9. přednáška - třídy, objekty

Základy programování. Úloha: Eratosthenovo síto. Autor: Josef Hrabal Číslo: HRA0031 Datum: Předmět: ZAP

Regulární výrazy. Vzory

for (i = 0, j = 5; i < 10; i++) { // tělo cyklu }

Typický prvek kolekce pro české řazení

type Obdelnik = array [1..3, 1..4] of integer; var M: Obdelnik;

Vyučovací hodina. 1vyučovací hodina: 2vyučovací hodiny: Opakování z minulé hodiny. Procvičení nové látky

typová konverze typová inference

Z. Kotala, P. Toman: Java ( Obsah )

Složitost algoritmů. Karel Richta a kol. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze Karel Richta a kol.

Transkript:

Obsah 9. přednášky: Fáze programování Řešení problémů, dekompozice a program Dekompozice objektový přístup* Efektivita algoritmů Složitost úvod Výpočet časové složitosti Odhad složitosti - příklady Posuzování složitosti Asymptotická složitost odhad* Přehled technik návrhů algoritmů* Tato tematika je zpracována v Záznamy přednášek: str. 208 220 Úlohy (řešení na konci přednášky) Problém 1: Napište program pro výpočet funkce g(x) s přesností ε. g(x)= 1 + x/1! + x 2 /2! + x 3 /3! + x 4 /4! +... Problém 2: Je možno najít takovou cestu, abychom prošli všemi mosty, ale každým z nich pouze jednou? (Euler: úloha o sedmi mostech města Královce) Problém 3: Nalezněte všechny způsoby, kterými může šachová figurka jezdce proskákat všechna políčka šachovnice, přičemž může na každé políčko skočit pouze jedenkrát. Přednášky KIV/PPA1, A. Netrvalová, 2016 9. přednáška

Fáze programování Formulace úlohy - podklady pro řešení, cíle řešení, požadavky na přesnost Analýza úlohy - výchozí informace, řešitelnost Návrh řešení - rozklad na podproblémy, metody řešení Sestavení algoritmu řešení - návrh datových struktur, zápis algoritmu, volba jazyka Kódování programu - zápis zdrojového kódu Odladění - sada testů, porovnání výsledků Optimalizace - zrychlení výpočtu, snížení nároků na paměť Řešení problémů, dekompozice a program - Dekompozice - najít ve složitém problému hierarchické uspořádání pro zápis složité akce pomocí akcí jednodušších, další redukce na akce jednodušší (metoda shora dolů) - Abstrakce - koncepční zjednodušení složitého problému ignorováním detailů na akce řešící problém po částech, tj. oddělení jádra problému od detailů (metoda zdola nahoru) Strana 2 (celkem 34)

Metoda návrhu algoritmu shora dolů - založena na analýze problému a jeho postupném rozkladu na dílčí problémy (podproblémy), které lze podle potřeby dále rozkládat, kde dekompozici odpovídá i návrh algoritmu - začíná jen osnovou - abstraktní příkazy (výrazy přirozeného jazyka) pro dosud nerozpracované dílčí algoritmy Metoda návrhu algoritmu zdola nahoru - zpravidla vázána na konkrétní programovací jazyk (výrazové prostředky), postup od jednoduchých příkazů (řídicích struktur), přes složitější až po celkové řešení, na počátku nutný hrubý návrh řešení Použití dané metody závisí na složitosti a povaze problému, charakteru výrazových prostředků, ale i na schopnostech programátora. První metoda je vhodná pro řešení problémů přesně definovaných, druhá se uplatní při řešení příbuzných problémů a problémů s neúplným zadáním. Příklad: rozklad problému na podproblémy hra NIM Základní akce: vstup dat a začátek hry, průběh hry, výpis výsledku hry Pravidla hry: dán náhodný počet zápalek; odebrat lze 1 až 3 zápalky hráč se střídá v odebírání se strojem (PC) prohraje ten, kdo odebere poslední zápalku Strana 3 (celkem 34)

Dílčí podproblémy: automatické zadání počtu zápalek (např. v rozmezí 15 až 35) odebrání zápalek hráčem (+ řešení chyby či podvodu) odebrání zápalek strojem ukončení a výsledek hry Hrubé schéma: int pocetzapalek; boolean stroj = false; //zadani_poctu_zapalek do { if (stroj){ //odebrani_zapalek_strojem else { //odebrani_zapalek_hracem stroj =!stroj; while (pocet>0); if (stroj){ // stroj je na tahu, ale nema co odebrat // vyhral_stroj else { // hrac je na tahu, ale nema co odebrat // vyhral_hrac Fakta: počet zápalek a kdy hraje hráč a kdy stroj, tj. hodnoty pocetzapalek a stroj budou realizovat proměnné Podproblémy: výsledek hry, vyřešeno již v hrubém schématu zadani_poctu_zapalek, odebrani_zapalek_strojem, odebrani_zapalek_hracem budou realizovat metody Strana 4 (celkem 34)

public class Nim { static private Scanner sc = new Scanner(System.in); static private Random r = new Random(); static int zadanipoctuzapalek() { static int berehrac(int pocetzapalek) { static int berestroj(int pocetzapalek) { public static void main(string[] args) { int pocetzapalek = zadanipoctuzapalek(); boolean stroj = false; // false = zacina hrac do { if(stroj) { pocetzapalek = berestroj(pocetzapalek); else { pocetzapalek = berehrac(pocetzapalek); stroj =!stroj; while (pocetzapalek > 0); if(stroj) { System.out.println("Vyhral stroj!"); else { System.out.println("Vyhral jste, gratuluji!"); Stroj - pravidla pro odebírání - tj. vítězná strategie (je-li možná): počet zápalek nevýhodných pro protihráče je 1, 5, 9, atd., obecně: 4n+1, kde n >0 stroj musí z počtu p zápalek odebrat x zápalek tak, aby platilo p x = 4n + 1, po úpravě: x = (p 1) mod 4 vyjde-li x = 0, znamená to, že okamžitý počet zápalek je pro stroj nevýhodný a bude-li protihráč postupovat správně, stroj prohraje Strana 5 (celkem 34)

static int zadanipoctuzapalek() { // nahodne generovani poctu zapalek (15-35) return r.nextint(21) + 15; static int berehrac(int pocetzapalek) { int x; boolean chyba; do { chyba = false; System.out.println("Pocet zapalek: " + pocetzapalek ); System.out.println("Kolik odeberete? "); x = sc.nextint(); if (x<1) { System.out.println("Prilis malo!"); chyba = true; else { if(x>3 x>pocetzapalek) { System.out.println("Prilis mnoho!"); chyba = true; while (chyba); return pocetzapalek -= x; static int berestroj(int pocetzapalek) { System.out.println("Pocet zapalek: " + pocetzapalek); int x = (pocetzapalek - 1) % 4; if (x==0) { x = 1; System.out.println("Odebiram: " + x); return pocetzapalek -= x; Otázka: Doplníte-li program o náhodné vygenerování začínajícího (tj. stroj či hráč), jaký bude dopad na hru, bude-li začínat stroj? Strana 6 (celkem 34)

Dekompozice objektový přístup* rozdělení na logicky ucelené části, každé části odpovídá samostatná metoda (objektový přístup). Návrh rozhraní jména metod, způsob jejich komunikace s okolím (tj., jaké mají parametry, návratové hodnoty tzv. signatury metody). Deklarace rozhraní je podobná deklaraci třídy: interface jmeno { // hlavičky metod Programujeme bez znalosti (resp. bez využívání znalosti) implementace. Přístup k rozhraní shora: voláme metody, o nichž víme, jak se volají a co dělají, ale nevíme, jak to dělají a pokud to náhodou víme, tak tuto znalost nevyužíváme (v budoucnu je možná změna implementace těchto metod) Přístup k rozhraní zdola: píšeme metody, o nichž víme, jak se budou volat a co mají dělat, ale nevíme, kdo a v jakém kontextu je bude používat a pokud to náhodou víme, tak tuto znalost nevyužíváme (v budoucnu je možná bude chtít volat také někdo další) (více v PPA2) Strana 7 (celkem 34)

Příklad: PASÁČEK KOZ (viz přednáška č. 7) Dekomponujeme na třídy: Vlk Koza Lov a aplikační třídu PomocPasackovi. /** * Trida Vlk */ public class Vlk { private int rychlostvlka; public Vlk(){ rychlostvlka = 50; public Vlk(int rycklostvlka){ setrychlostvlka(rychlostvlka); void setrychlostvlka(int rychlostvlka){ this.rychlostvlka = rychlostvlka; int getrychlostvlka(){ return rychlostvlka; public String tostring(){ return " rychlost vlka = " + rychlostvlka; Strana 8 (celkem 34)

/** * Trida Koza */ public class Koza { private int rychlostkozy; private int hmotnostkozy; public Koza(int hmotnostkozy, int rychlostkozy){ sethmotnostkozy(hmotnostkozy); setrychlostkozy(rychlostkozy); public Koza(){ rychlostkozy = 50; hmotnostkozy = 40; void setrychlostkozy(int rychlostkozy){ this.rychlostkozy = rychlostkozy; void sethmotnostkozy(int hmotnostkozy){ this.hmotnostkozy = hmotnostkozy; int getrychlostkozy(){ return rychlostkozy; int gethmotnostkozy(){ return hmotnostkozy; public String tostring(){ return " hmotnost/rychlost kozy: " + hmotnostkozy +"/" + rychlostkozy; Strana 9 (celkem 34)

/** * Trida Lov */ public class Lov { Koza [] kozy; Vlk vlk; private final int MAX_HODIN = 10; private final String NEUSPECH = "Vlk se nenazere, stado muze zustat!"; private final String USPECH_POZDEJI = "Vlk by sezral kozu! \npasacek musi stado odehnat do: "; private final String USPECH_NAPOPRVE = "Pasacek prijde o kozu!"; private String vysledeklovu = ""; public Lov(Vlk vlk, Koza [] kozy){ this.vlk = vlk; this.kozy = kozy; int najdirychlostnejvypasenejsi(koza[] kozy){ int nejvypasenejsi = kozy[0].gethmotnostkozy(); int indexnejvypas = 0; for(int i=0; i<kozy.length; i++){ if(kozy[i].gethmotnostkozy() > nejvypasenejsi) { nejvypasenejsi = kozy[i].gethmotnostkozy(); indexnejvypas = i; if(kozy[indexnejvypas].gethmotnostkozy() > 0){ kozy[indexnejvypas].sethmotnostkozy(-1); return kozy[indexnejvypas].getrychlostkozy(); else { return -1; //-kozy[indexnejvypas][1]; Strana 10 (celkem 34)

String vlklovi(vlk v, Koza kozy[]){ vysledeklovu = NEUSPECH; for(int pocethodin = 0; pocethodin<=max_hodin; pocethodin += 2){ int rnejvypas = najdirychlostnejvypasenejsi(kozy); if(rnejvypas > 0){ // dalsi nelovena koza nalezena if(rnejvypas > v.getrychlostvlka()){//vlk pomalejsi continue; // hledej dalsi kozu else { // uz neni dalsi dosud nelovena koza vysledeklovu = NEUSPECH; // vlk nebude uspesny break; if(pocethodin > 0){ // vlk bude uspesny, pokud stado zustane vysledeklovu = USPECH_POZDEJI + pocethodin + " hodin."; break; else { // vlk sezere uz prvni lovenou kozu vysledeklovu = USPECH_NAPOPRVE; break; return vysledeklovu; public String tostring(){ return "VysledekLovu: " + vysledeklovu; Strana 11 (celkem 34)

import java.io.bufferedwriter; import java.io.file; import java.io.filewriter; import java.io.ioexception; import java.io.printwriter; import java.util.scanner; /** * Pasacek objektove * Ovladani: * vstup ze souboru: je-li v argumentu zadan nazev vstupniho * souboru a ten existuje * vstup z klavesnice: neexistuje-li vstupni soubor * vystup do souboru: byl-li vstup ze souboru * vystup na obrazovku: byl-li vstup z klavesnice */ public class PomocPasackovi { private static Scanner sc; static String JMENO_VSTUPU = ""; static final String JMENO_VYSTUPU = "vysledeklovu.txt"; static boolean nastavzdrojvstupu () { boolean klavesnice = true; try { File f = new File(JMENO_VSTUPU); if (f.exists()){ sc = new Scanner(f); // ze souboru klavesnice = false; else { sc = new Scanner(System.in); // z klavesnice catch (Exception e){ e.printstacktrace(); return klavesnice; Strana 12 (celkem 34)

/** je-li vstup ze souboru, je i vystup do souboru * @param args pole argumentu * @param vysledek textovy retezec */ static void vypisvysledek(string vysledek){ File f = new File(JMENO_VSTUPU); File ff = new File(JMENO_VYSTUPU); if (f.exists()){ // existuje-li vstupni soubor try { PrintWriter pw = new PrintWriter( new BufferedWriter( new FileWriter(ff))); pw.println(vysledek); pw.close(); catch (IOException e){ e.printstacktrace(); System.exit(1); else { if(ff.exists()){ // smaze vyst. soubor, existuje-li ff.delete(); System.out.println(vysledek); /** * Vytvori a naplni jednu instanci tridy Koza */ public static Koza vytvoranactikozu() { int hmotnost = sc.nextint(); int rychlost = sc.nextint(); Koza k = new Koza(hmotnost, rychlost); return k; Strana 13 (celkem 34)

/** Vytvori a naplni instanci tridy Vlk */ public static Vlk vytvorvlka(){ int rychlostvlka = sc.nextint(); Vlk v = new Vlk(rychlostVlka); return v; /** * Spousteni programu - metoda main() * @param args - nazev vstupniho souboru */ public static void main(string[] args) { if(args.length!= 0){ //nazev soub. zadan v argumentu String jmeno = args[0]; JMENO_VSTUPU = "src/ /" + jmeno; //path + jmeno boolean klavesnice = nastavzdrojvstupu(); if(klavesnice){ System.out.print("Zadej rychlost vlka: "); Vlk vlk = vytvorvlka(); if(klavesnice){ System.out.print("Zadej pocet koz: "); int pocetkoz = sc.nextint(); if(klavesnice){ System.out.println("Zadej hmotnosti a rychlosti koz: "); Koza[] kozy = new Koza[pocetKoz]; for (int i = 0; i < kozy.length; i++) { kozy[i] = vytvoranactikozu(); Lov lov = new Lov(vlk, kozy); vypisvysledek(lov.vlklovi(vlk,kozy)); System.out.println(lov); Strana 14 (celkem 34)

Efektivita algoritmů Řešitelnost problému* - zúžení na tzv. rozhodovací problém (Ano/Ne). Algoritmicky rozhodnutelný problém* - algoritmus řeší rozhodovací problém, tj. pro vstup poskytne správný výstup v konečném čase Problémy - P, NP, převoditelnost, SAT (v PPA2) Efektivní algoritmus - řeší problém s minimálními nároky na hardware v co nejrychlejším čase, cílem je optimální využití existujících prostředků Nejjednodušší vs. nejrychlejší Nejjednodušší řešení - jednoduchá implementace - delší čas běhu Nejrychlejší řešení - náročná implementaci (časově kritické aplikace) Reálné aplikace kompromis Analýza efektivity - empiricky (porovnáním náhodná, nevhodná a reálná data) - exaktně (využití matematické analýzy) Cíl analýzy - porovnání algoritmů řešících stejný problém - odhad výkonnosti (pro jaký typ vstupu?) Strana 15 (celkem 34)

Složitost úvod (další informace - v PPA2) Složitost vztah algoritmu k prostředkům (čas a velikost paměti) Časová složitost - množina vstupních dat počet operací výpočtu - čas je dán počtem provedených operací (doba provedení operace nezáleží na rozsahu vstupních dat) Paměťová složitost - závislost paměťových nároků na vstupních datech Časová složitost časté potíže a omyly - podcenění nezkušenost, řešení triviálních úloh - použití rychlejšího PC problém vyřeší (NE) - zrychlení dílčími úpravami (NE) Řešení - použít rychlejší algoritmus (existuje-li) Výpočet časové složitosti stanovujeme v závislosti na: - konkrétních datech - na základě rozsahu dat - analýzou algoritmu obvykle složité Příklad: výpočet u triviálního algoritmu Operace: p přiřazení, c porovnání, s součet Strana 16 (celkem 34)

static int soucetprvku(int [] pole){ int suma = 0; // p1 for(int i=0; i<pole.length; i++) { // p2+c1+s1+p3 suma += pole[i]; // s2+p4 return suma; C(n) = p1+p2+(n+1)c1+n(s1+p3)+n(s2+p4) pokud a = (p=c=s) C(n) = a+a+(n+1)a+n(a+a)+n(a+a)= 3a+5an a trvá jednotku času C(n) = 3+5n C(n) = n - lineární složitost (náročné nedělá se takto) int n = 100; int sum = 0; for (int i = 0; i < n; i++){ for (int j = 0; j < i; j++){ sum += i+j; n = 100; sum = 0; for (int i = 0; i < n; i++){ for (int j = 0; j < n; j++){ sum += i+j; PŘÍKLAD: Která programová sekvence proběhne rychleji? Strana 17 (celkem 34)

První kód: vnější cyklus 100x, vnitřní 1, 2,...,99, celkem n(n-1)/2=100/2*99=4950x Druhý kód: vnější cyklus 100x, vnitřní cyklus 100, celkem 100*100=10000. První cyklus je rychlejší. Odhad složitosti - příklady Hrubý odhad orientace podle cyklů Př. 1: Určete řádovou složitost následujícího algoritmu. Sledovanou operací je sčítání.... for(int i = 0; i < m; i++) { for(int j = 0; j < n; j++) { c[i][j] = a[i][j] + b[i][j]; Složitost algoritmu O(m *n) Př. 2: Sledovanou operací je násobení ve výrazu j = j * 2 int n = 8; for(int i = 0; i < n; i++) { int j = 1; do { j = j * 2; while (j < n); Složitost algoritmu je O(n log 2 (n)) Strana 18 (celkem 34)

Př. 3: Určete řádovou složitost následující programové sekvence.... min = a[0]; for(int i = 0; i < n; i++) { if (min < a[i]) { min = a[i]; max = a[0]; for(int i = 0; i < n; i++){ if (max > a [i]) { max = a [i];... Složitost algoritmu: O(2*n) Př. 4: Určete řádovou složitost následujícího algoritmu. Sledovanou operací je: a = a / 3 final int n = 15; for(int i = 1; i < n ; i++) { float a = n; do { a = a / 3; while (a > 1); Složitost? Strana 19 (celkem 34)

Složitost algoritmu je: O((n-1)*log 3 (n)). Př. 5: Určete řádový odhad O následující funkce, pokud při zvětšení dat na n+1 dojde ke zvětšení počtu operací o 2 n. C1 2, Cn 2 n Cn 1 pro n 1 C1 2 C 2 2 2 C1 2 2 C 3 2 3 C2 2 3 2 2... C n C n 2 n 2 ( n - 1)... 2 2 n n n 1 2 2 i 2 n i 2 1 2 2 2 n Složitost algoritmu je O(n 2 ). Posuzování složitosti - nejhorší případ: max(t1(n),t2(n),...,tn(n)) - průměrný případ: ~t(t1(n),t2(n),...,tn(n)) - nejlepší případ: min(t1(n),t2(n),...,tn(n)) Strana 20 (celkem 34)

Malý rozdíl mezi nejlepším a nejhorším případem - dobře navržený algoritmus Optimalizace algoritmu - zmenšení rozdílu Když nejlepší = nejhorší případ, nelze optimalizovat Asymptotická složitost odhad* Složitější algoritmy - přesné (algebraické) vyjádření složitosti algoritmu matematicky náročné Ve většině případů postačí vhodný odhad Strana 21 (celkem 34)

Asymptotická složitost (pro n ) se limitně blíží k algebraické hodnotě složitosti Odhady - asymptotický horní odhad: O(g(N)) - asymptotický dolní odhad: Ω (g(n)) - asymptotický oboustranný odhad: Θ(g(N)) k, k1, k2 - konstanty, f(n) - fce, g(n) - odhad Strana 22 (celkem 34)

Strana 23 (celkem 34)

Př. 6: Problém s dobou řešení k n 2 je řešen na starém PC pro n = 10000. Jak je možné zvětšit vstup, aby byla úloha vyřešena na 10x rychlejším PC v tomtéž čase? Staré PC: k 10000 2 ;nové PC 10 k 10000 2 10 k 10000 2 = k n 2 n = 1000000000 = 31622,7766. Poměr se zvětší 31623/10000 ~ 3 Př. 7: Algoritmus A1 - pro řešení úlohy použije 10000n + 40000 operací Algoritmus A2 - použije 12n 2 + 9 operací Pro jakou množinu dat je výhodnější použít A2? 12n 2 + 9 10000n + 40000 12n 2-10000n-39991 < 0, n 1 = -4; n 2 = 837 Pro n < 837 je vhodnější algoritmus A2. Ukázka časové složitosti Složitost n = 10 n = 100 n = 1000 logaritmická 1 2 3 lineární 10 100 1000 kvadratická 100 10000 1.0 10 6 kubická 1000 1.0 10 6 1.0 10 9 exponenciální 1024 1.3 10 30 1.1 10 301 faktoriálová 3.6 10 6 9.3 10 157 4.0 10 2567 Strana 24 (celkem 34)

P - polynomiální algoritmy. - výpočetně zvládnutelné problémy V praxi - nejčastěji O(n), O(n log(n),o(n 2 ),O(n 3 ) Problémy - aritmetické operace, řazení, vyhledávání, některé grafové algoritmy, NP - nedeterministicky polynomiální algoritmy (bude v PPA2) Přehled technik návrhů algoritmů* - metoda hrubé síly (Brute Force Algorithm) - rozděl a panuj (Divide and Conquer) - heuristické algoritmy (Heuristic Algorithm) - aproximační algoritmy - pravděpodobnostní algoritmy Metoda hrubé síly Vyzkoušení všech variant řešení problému, vybráno je nejlepší z nich. Počet operací nutných k nalezení řešení neroste polynomiálně (exponenciálně: n c, s faktoriálem: n!). Výhodou je jednoduchost implementace. Lze aplikovat pouze na malé soubory dat, pro rozsáhlé soubory nelze vyzkoušet všechny metody, nalezené řešení nemusí být nejlepší. Rozděl a panuj Založena na opakovaném rozdělování problému na menší a jednodušší podproblémy. Dělení se provádí tak dlouho, až se nalezne triviální řešení podproblému. Strana 25 (celkem 34)

Takovéto řešení umíme zpravidla nalézt bez složitých výpočtů. Podproblémy jsou řešeny nezávisle na sobě a poté jsou jejich řešení spojena v celek, čímž získáme řešení původního problému. Odhad složitosti: Θ(n log n) Heuristické algoritmy Charakteristika heuristiky: - vygenerováno velké množství potenciálních řešení, v nich se hledá nejlepší možné řešení. Vygenerovaná množina nemusí obsahovat nejlepší možné řešení. Řešení nemusí být nalezeno rychle, některé heuristiky pracují poměrně dlouho. Není zaručeno, že takové řešení bude vždy nalezeno. Aproximační algoritmy - pro úlohy, pro které neznáme polynomiální algoritmus Cílem je nalezení přípustného řešení, hodnocení kvality aproximace, snaha o co nejrychlejší konvergenci. Pravděpodobnostní algoritmy - zavádí se do procesu řešení nedeterministický prvek, tj. prvek náhodnosti. Opakovaný běh algoritmu nad stejnou vstupní množinou může poskytovat různé výsledky, proto se algoritmy spouštějí opakovaně. Genetické algoritmy - princip evoluční biologie a techniky napodobující biologické procesy (křížení, mutace, dědičnost, atd.) pro postupné zlepšování dosaženého výsledku. (techniky návrhů algoritmů - součást ZEP, PT, ADE, PRO, ) Strana 26 (celkem 34)

Příklad: Hanojské věže (ještě jednou) Příběh: V jednom indickém chrámu prý mají tři věže Věž zrození, Věž života a Věž zkázy. Uvnitř každé z nich je kůl, na kterém je navlečeno několik zlatých disků. Každý disk je jinak široký. Disky smí být na kůlu navlečeny pouze tak, že menší a užší disk leží na širším. Počet všech disků je 64. Při stvoření chrámu byly všechny disky navlečeny na jeden kůl ve Věži stvoření. Kněží přenášejí každý den jeden disk tak, aby umístili všechny disky na kůl ve Věži zkázy. Stará legenda říká, že až se jim to podaří, tak nastane konec světa. Má smysl se obávat konce světa? Řešení: Pokusíme se problém rozložit na podproblémy, k jejichž vyřešení použijeme rekurzi (viz minulá přednáška). static void presundisky(int n, char zveze, char navez, char presvez) { if (n>=1) { presundisky(n-1, zveze, presvez, navez); System.out.println("presun disk "+n+" z "+ zveze+" na "+navez); presundisky(n-1, presvez, navez, zveze); Jaká je časová složitost? - jistě úměrná počtu přenesení disků. Označme tedy celkový počet přenesení disků pomocí T (n). Z uvedeného algoritmu plyne: T(n) = 2T(n 1) + 1 Postupným rozepisováním dostaneme: T(n) = 2T(n 1) + 1 = 2(2(T(n 2) + 1) + 1 = =2(2(2 (2T(1)+1) +1)+1)+1=2 n +2 n 1 + +2+1 = 2 n+1 Časová složitost algoritmu je tedy exponenciální. NE! 2 65 = 36 893 488 147 419 103 232 Strana 27 (celkem 34)

Úlohy Problém 1 (existuje více algoritmů) Napište program pro výpočet funkce g(x) s přesností ε. g(x)= 1 + x/1! + x 2 /2! + x 3 /3! + x 4 /4! +... - první nápad - napsání metody pro faktoriál, pak spočtení mocniny a postupné sčítání členů Řešení zcela nevhodné! public class EnaX { static private Scanner sc = new Scanner(System.in); static final double EPS = 1e-5; static long fak(int n){ long vysledek = 1; for (int i=2; i<=n; i++){ vysledek *= i; return vysledek; CHYBNĚ static double spoctienax(int x){ double soucet = 1; double clen = 1; int i = 1; do { clen = Math.pow(x,i)/ fak(i); i++; soucet += clen; while(clen > EPS); return soucet; Zadej x:15 Vypocteny vysledek = 1823967.9211000332 Spravny vysledek = 3269017.3724721107 Strana 28 (celkem 34)

Řešení správné - použití iteračního výpočtu (nikoliv opakovaný výpočet mocniny a faktoriálu), využití již jednou spočtených členů: a 0 =1, a 1 = a 0 *x/1, a 2 = a 1 *x/2, a 3 = a 2 *x/3,... import java.util.*; public class EnaX { static private Scanner sc = new Scanner(System.in); static final double EPS = 1e-5; static double spoctienax(int x){ double soucet = 1; double clen = 1; // clen je scitanec int i = 1; // i-ty scitanec do { clen *= (double)x / i++ ; // spocti clen soucet += clen; // a pricti ho k součtu while( clen > EPS); // je-li mensi nez eps, hotovo return soucet; public static void main(string[] args) { System.out.print("Zadej x:"); int x = sc.nextint(); SPRÁVNĚ System.out.println("Vypocteno = " + spoctienax(x)); System.out.println("Spravny vysledek = " + Math.exp(x)); Zadej x:15 Vypocteny vysledek = 3269017.3724691505 Spravny vysledek = 3269017.3724721107 Strana 29 (celkem 34)

Problém 2 [Zdroj: Wikipedia] Úloha o sedmi mostech města Královce: Je možno najít takovou cestu, abychom prošli všemi mosty, ale každým z nich pouze jednou? Řešení neexistuje, tj. takovou cestu najít nelze Euler Leonhard (1707-1783),1741: Solutio problematis ad geometriam situs pertinentis v publikaci: Commentarii academiae scientiarum Petropolitanae Eulerův tah (path) lze tehdy a jen tehdy, není-li žádný či jsou-li právě 2 vrcholy grafu lichého stupně (začátek a konec cesty) Příklad na Eulerův tah: (psaníčko jedním tahem) Alternativní úloha Eulerův uzavřený tah, tj. smyčka (circuit) - začátek a konec cesty v tomtéž vrcholu (nesmí být vrchol lichého stupně) - více v PPA2 Strana 30 (celkem 34)

Problém 3 Nalezněte všechny způsoby, kterými může šachová figurka jezdce proskákat všechna políčka šachovnice, přičemž může na každé políčko skočit pouze jedenkrát. [Zdroj: Wikipedia] Jednoduchá varianta: Úloha: Nalezněte nejkratší cestu šachovým koněm z jednoho pole (třeba d3) na všechna ostatní pole. Postup: 0. Na startovní pole zapiš číslo 0 1. Všechna dosud neoznačená pole dostupná jedním tahem z pole označeného 0 označ 1 2. Všechna dosud neoznačená pole dostupná jedním tahem z pole označeného 1 označ 2 3.... 2..... 3 atd. Nalezení cesty pak proveď odzadu (backtracking): Je-li cílové políčko označené N, hledáme políčko dostupné z něj jedním tahem a označené N-1 - až k políčku 0. d 3 Strana 31 (celkem 34)

Naše úloha [Zdroj: doc. P. Herout] 1. Prověříme všechny možnosti, tj. řešení hrubou silou - exponenciální složitost, neboť v ideálním případu můžeme skočit až na 8 polí O(8 n*n ) = 8 64 ~ 6 10 57 možností Pokud by ověření 1 možnosti trvalo jen 1ns, celý výpočet 2 10 41 let! 2. Zjednodušení - počet tahů je 63, ale skončíme neúspěchem mnohem dříve (po 4, 6, 8 tazích): 4 1 3 2 4 5 3 6 2 1 3 7 4 8 2 6 1 5 Strana 32 (celkem 34)

- z krajního políčka lze pokračovat 2, 3, 4 a 6 skoky - na 8 políček lze skočit pouze z 1. tahu (počet možností skoku z políčka je n-1, neboť skok musí být z přípustné pozice) - poslední tah má pouze jednu možnost, předposlední dvě možnosti, - řada tahů budou tzv. vynucené zbude pouze jedna možnost pro celý řetězec tahů Zpřesněný horní odhad: 1 4 *2 8 *3 20 *5 16 *7 15 = 6 10 35 možností, tj. 20 10 18 let! Pro šachovnici 8x8 polí není úloha zcela řešitelná. V současné době (s použitím PC) je úloha kompletně řešitelná pro šachovnici 6x6 polí. Zpřesněný odhad: 1 4 *2 8 *3 12 *5 8 *7 3 = 18 10 15 možností, tj. 34 let. Skutečný výpočet (6x6): 188 888 353 094 možností - 2958 sec. Java Pentium Centrino 1,5 GHz Kvalifikovaný odhad pro 8x8: skutečné možnosti 10-5 z horního odhadu 6 10 35 10-5 = 6 10 30 možností, tj. 2 10 14 let. [Výpočet: doc. P. Herout] Strana 33 (celkem 34)

Úloha pro zájemce* (prezentace řešení na další přednášce) Je dána posloupnost celých čísel a 1, a 2,..., a n. Nalezněte celistvý úsek posloupnosti a i až a j, takový, aby součet hodnot těchto prvků byl maximální. Nezapomeňte, že indexy i, j představují pořadí prvků, tj. i, j > 0. Ilustrační příklady: {-2, 11, -4, 13, -5, 2 i = 2, j = 4, s = 20 {1, -3, 4, -2, -1, 6 i = 3, j = 6, s = 7 {-1, -3, -5, -7, -2 i = 0, j = 0, s = 0 Pro řešení tohoto problému lze napsat odlišné, více či méně efektivní algoritmy. Strana 34 (celkem 34)