# Programátorské strategie ## Algoritmizace **Proč se jí zabývat?** - rozvíjí abstraktní a logické myšlení potřebné nejen pro techniky - existují hotová řešení na různé problémy, ale vždy narazíme na trochu jiné problémy + je potřeba znát + základní problémy a jejich řešení + principy a techniky k řešení velké oblasti neznámých problémů **Algoritmus** - postup k vyřešení určitého úkolu - musí řešit obecný, dobře specifikovaný problém - procedura, která libovolná možná vstupní data transformuje na požadovaný výstup - **algoritmus** - vždy vede k cíli, **heuristika** - nemusí vést vždy k cíli ### Správnost a účinnost algoritmu **Cíl snažení** - algoritmy správné, efektivní a snadno implementovatelné - ne vždy je možné vše najednou **Zlepšení výkonu** - lepší algoritmus > lepší počítač - kdy nehledat účinnější řešení: - poběží jen několikrát - výpočet přes noc je OK - optimalizovat *bottleneck* (kritické místo - 90 % času v 10 % kódu) ### Robustnost algoritmu **Cíl snažení** - algoritmy odolné vůči numerickým aj. chybám - singulární případy: při první úvaze ignorovat, poté zahrnout **Robustnost** - malá chyba nesmí vést k selhání - algoritmy často odvozeny např. pro nekonečnou přesnost reálných čísel ### Analýza algoritmů **Cíl snažení** - hodnocení a porovnávání algoritmů nezávislé na typu počítače a na jazyku - typické chování pro očekávaná vstupní data **Nástroj** - asymptotická analýza složitosti - experimentální otestování na reprezentativních vstupních datech #### Složitost - paměťová x časová x předzpracování - nejčastěji nás zajímá nejhorší případ a očekávaný případ - => složitost v nejhorším případě, očekávaná složitost **Symbolika** - $O(f(n))$ - horní mez - $\Omega(f(n))$ - dolní mez - $\Theta(f(n))$ - omezeno shora i zdola (optimální algoritmus) **Časová složitost algoritmu** - nejdelší doba výpočtu potřebná pro vstup velikosti $n$ **Časová složitost problému** - časová složitost nejrychlejšího algoritu řešící tento problém - $O(n^2)$ - najít algoritmus, který vyřeší tento problém nejvýše v čase $cn^2$ - $\Omega(n^2)$ - dokázat, že žádný algoritmus nedokáže problém vyřešit rychleji #### Experimentální ověření složitosti - spotřeba času a paměti jako funkce velikosti vstupu - pro zmenšení chyby měřit více opakování, bez I/O, pro více datových množin, pro více typů dat - spočítat $t/f(n)$, zkoumat průměrné a nejhorší chování **Očekávaná složitost (Expected complexity)** - odhad pozorovaného chování algoritmu, často odhad podle implementace, závisí též na očekávaném typu vstupních dat #### Standardní třídy složitosti problému - **P** - problém v této třídě řešitelný výpočty v polynomiálním čase - **NP** - řešitelný v polynomiálním čase nedeterministicky - nevíme, jak řešit polynomiálně, ale umíme ověřit v polynomiálním čase řešení - dnes kolem 3000 problémů - **NP-úplné** - není známo žádné polynomiální řešení - nebylo dokázáno, že neexistuje ### Hledání řešení neznámého problému Pomáhá klást si správné otázky (v uvedeném pořadí): 1. Opravdu problému rozumím? - Co je vstupem? - Jaký přesně má být výstup? - Umím sestavit malý příklad a vyřešit ručně? Co se stane, když to zkusím? - Jak moc je pro mou aplikaci důležité najít vždy přesné, optimální řešení? Nestačí něco, co obvykle funguje docela dobře? - Jak velká je typická instance mého problému? 10? 1000? 1 mil.? - Jak důležitá je pro moji aplikaci rychlost? - Musí být problém vyřešen za 1s? 1 min? 1 h? 1 den? - Kolik času a úsilí mohu dát do implementace? - Budu řešit numerický problém? Grafový? Geometrický? Se znakovým řetězcem? Více možných formulací? Která se zdá nejlehčí? 2. Umím najít jednoduchý algoritmus nebo heuristiku řešící daný problém? - Umím najít algoritmus správně řešící můj problém prohledáním všech podmnožin a výběrem nejlepší? (Pokud ano, jsem si jist správností odpovědi? Umím změřit kvalitu nalezeného řešení? Stačí časově? Pokud ne, mám problém dostatečně definovaný, aby se dal vyřešit?) - Umím problém vyřešit opakovaným výběrem nejlepšího? Opakovaným náhodným výběrem? (Pokud ano, pro jaký vstup to funguje dobře, špatně? Je to rychlé?) 3. Není můj problém v katalogu algoritmických problémů? - Pokud ano, co je o problému známo? Není k mání implementace řešení? - Pokud ne, je to správné místo? Umím hledat v knihách? - Co Web? 4. Existující speciální případy, které umím řešit přesně? - Umím to, pokud ignoruji některé parametry? - Co se stane, když některé parametry nastavím na triviální hodnoty, jako je 0, 1? - Umím problém zjednodušit na případ, který je možné řešit přesně? Je teď triviální nebo stále zajímavý? - Pokud už umím řešit spec. případ, proč nejde řešení použít pro obecnější problém? - Je můj problém spec. případ některého obecného problému? 5. Které ze standardních paradigmat návrhu algoritmů je nejvhodnější pro můj problém? - Je možné položky setřídit? Ulehčí to řešení? (SORT) - Je možné problém rozdělit na 2 nebo více podproblémů? Malý a velký? Levý a pravý? 2 stejně velké? (D&C) - Má vstup nebo řešení přirozené pořadí zpředu dozadu, zleva doprava (řetězce, permutace, listy stromu)? (DP) - Opakuje se stejná operace nad stejnými daty (hledání), kterou by urychlila pomocná dat. struktura? (slovník, hašovací tabulka, hromada, prioritní fronta…) - Lze použít náhodné vzorkování pro výběr dalšího objektu? Výběr nejlepší z náhodně vybraných konfigurací? (řízená náhodnost, např. SA)? - Problém pro lineární programování? Celočíselné programování? 6. Jsem stále ztracen(a)? - Nenajmu si na to experta? - Nezkusím otázky projít znova? (Změnily se moje odpovědi?)