====== IN19 Metody konstrukce efektivních algoritmů ====== ===== Zadanie ==== (Rozděl a panuj. Dynamické programování. Hladové strategie. Backtracking. Meze použitelnosti i jednotlivých technik. Příklady algoritmů postavených na jednotlivých technikách.) ===== Vypracovanie ===== ==== Rozdeľ a panuj ==== Túto techniku je možné ľahko popísať týmito krokmi. - Problém rozdeľ na prodproblémy - Vyrieš podproblémy - Z riešení podproblémov zostav riešenie Problém nájdenia maximálneho a minimálneho prvku postupnosti S[1..n]. Zložitostné kritérium - počet porovnaní prvkov. === Riešenie === Max(S) 1 max ← S[1] 2 for i = 2 to n do 3 if S[i] > max then max ← S[i] fi 4 od Procedúra Max nájde najväčší prvok, podobne sa nájde medzi ostatnými prvkami najmenší prvok. Časová zložitosť tohto algoritmu je zrejme (n - 1), pokud k tomu přidáme složitost hledání minimálního prvku (n-2) (hľadáme už len medzi n-1 prvkami) máme 2n-3. - Pole rozdeľ na 2 rovnaké postupnosti - Nájdi minimum a maximum oboch postupností - Maximálny prvok postupnosťí je väčší z maximálnych prvkov podpostupností, podobne minimálny function Maxmin(x, y) **predpoklad x < y 1 if y = x + 1 then return (max(S[x], S[y]),min(S[x], S[y])) fi 2 if y = x + 2 3 then použitím 3 porovnaní utrieď S[x], S[x + 1], S[y] 4 return (max, min) 5 fi 6 if y > x + 2 then 7 (max1, min1) ← Maxmin(x, ⌊(x + y)/2⌋) 8 (max2, min2) ← Maxmin(⌊(x + y)/2⌋ + 1, y) 9 return (max(max1, max2), min(min1, min2)) 10 fi Ľahko dokážeme, že tento algoritmus je korektný. Jeho časová zložitosť je: T(n)= \left\{ \begin{array}{ll} 1 & \mbox{$n = 2$}\\ 3 & \mbox{$n = 3$}\\ T(\lfloor n/2 \rfloor ) + T(\lceil n/2 \rceil) + 2 & \mbox{inak} \end{array} \right. Indukciou sa dá ľahko dokázať, že T(n) \le \frac{5}{3}n - 2 Časovú zložitosť máme často určenú rekurzívne. Vtedy sa jej dôkaz často oplatí použiť tzv. Master Theorem. Ak T(n) \le a \cdot T(\lceil n/b \rceil) + O(n^d) pre kladné a, b, d, potom: T(n)= \left\{ \begin{array}{ll} O(n^d) & \mbox{$a < b^d$}\\ O(n^d \cdot \log n) & \mbox{$a = b^d$}\\ O(n^{\log_b a}) & \mbox{$a > b^d$}\end{array} \right. Zde n je velikost problému, a je počet podproblémů, n/b je délka jednoho podproblému a O(n^d) udává časovou složitost výpočtu mimo rekurzivní volání, vč. samotného rozdělení problému na podproblémy a sestavení konečného řešení z částečných řešení. Inými typickými príkladmi použitia Rozdeľ a panuj sú algoritmy mergesort, ... . ==== Dynamické programovanie ==== - Charakterizuj štruktúru optimálneho riešenia //optimálne riešenie problému v sebe zahrňuje optimálne riešenia podproblémov// - Rekurzívne definuj hodnotu optimálneho riešenia - Vypočítaj hodnotu optimálneho riešenia zdola nahor - Z vypočítaných hodnôt zostav optimálne riešenie Táto technika je vhodná pre riešenie //optimalizačných problémov//, u ktorých dochádza k prekrývaniu podproblémov. Nech X = < x_1,x_2, ..., x_n > a Z = < z_1,z_2, ..., z_m > sú postupnosti symbolov. Z je podpostupnosťou X práve vtedy, ak existuje rastúca postupnosť indexov i_1, i_2, ..., i_k postupnosti X taká, že pre všetky j = 1, ..., k platí x_{i_j} = z_j. Pre dané 2 postupnosti symbolov X a Y hovoríme, že Z je ich spoločnou podpostupnosťou práve ak Z je podpostupnosťou X aj Y. Problém najdlhšej podpostupnosti je pre dané dve postupnosti X a Y nájsť ich najdlhšiu spoločnú podpostupnosť (NSP). === Štruktúra optimálneho riešenia problému najväčšej podpostupnosti === Označenie: pre postupnosť X = < x_1,x_2, ..., x_n > definujeme jej i-ty prefix (pre i=0,...,n) ako X_i = < x_1, ..., x_i > Nech X = < x_1,x_2, ..., x_n > a Y = < y_1, ..., y_m > sú postupnosti symbolov a nech Z = < z_1, ..., z_k > je ich NSP. - Ak xn = ym, tak zk = xn = yn a Zk-1 je NSP postupností Xn-1 a Ym-1. - Ak x_n \neq y_m a z_k \neq x_n, tak Z je NSP postupností Xn-1 a Y. - Ak x_n \neq y_m a z_k \neq y_m, tak Z je NSP postupností X a Ym-1. === Hodnota optimálneho riešenia === Definujme c[i,j] ako dĺžku NSP postupností Xi a Yj. Platí c[i,j] = \left\{ \begin{array}{ll} 0 & \mbox{ak i = 0 alebo j = 0}\\ c[i - 1, j - 1] + 1 & \mbox{ak $i, j > 0$ a $x_i = y_j$}\\ max(c[i, j - 1], c[i - 1, j]) & \mbox{ak $i, j > 0$ a $x_i \neq y_j$}\end{array} \right. Poradie výpočtu: c[1,1],...,c[1,m] c[2,1],...,c[2,m] . . . c[n,1],...,c[n,m] NSP(X, Y) 1 for i = 1 to m do c[i, 0] ← 0 od 2 for j = 0 to n do c[0, j] ← 0 od 3 for i = 1 to m do 4 for j = 1 to n do 5 if Xi = Yj then 6 c[i, j] ← c[i − 1, j − 1] + 1 7 b[i, j] ← ♣ 8 else if c[i − 1, j] ≥ c[i, j − 1] then 9 c[i, j] ← c[i − 1, j] 10 b[i, j] ← ♠ 11 else 12 c[i, j] ← c[i, j − 1] 13 b[i, j] ← ♥ 14 fi fi od od 15 return c, b Print NSP(b, X, i, j) 1 if i = 0 ∨ j = 0 then return fi 2 if b[i, j] = ♣ then 3 Print NSP(b, X, i − 1, j − 1) 4 print xi 5 else if b[i, j] = ♠ then 6 Print NSP(b, X, i − 1, j) 7 else 8 Print NSP(b, X, i, j − 1) 9 fi fi Ďalšími príkladmi dynamického programovanie sú algoritmy: Floydov algoritmus, Warshallov algoritmus, Konštrukcia vyváženého vyhľadávacieho stromu, ... . ==== Hladové algoritmy ==== - Technika je vhodná pre riešenie optimalizačných problémov, ktoré majú optimálnu subštruktúru (Optimálne riešenie problému v sebe obsahuje optimálne riešenie podproblémov). - Pre získanie optimálneho riešenie stačí poznať optimálne riešenie jedného z podproblémov. Tento podproblém vyberáme na základe kritéria lokálnej optimality (KLO), t.j. bez znalosti jeho riešenia. - Vo výpočte postupujeme zhora nadol. Táto technika však nie je použiteľná pre všetky optimalizačné problémy. Je daných n súborov dĺžky m1,..., mn . Súbory sa majú uložiť na pásku. Všetky súbory sa budú z pásky čítať. Prístupový čas k súboru i je rovný súčtu dĺžok súborov uložených pred ním plus jeho dĺžka mi. Úlohou je uložiť súbory na pásku v takom poradí, aby sa súčet jednotlivých prístupových časov k súborom minimalizoval. Problém má optimálnu štruktúru, pretože ak ako prvý uložíme na pásku súbor i, ostané súbory musíme usporiadať optimálne. Hladový algoritmus: KLO = vyber spomedzi ešte neuložených súbor najkratší a ulož ho na pásku (t.j. ulož na pásku súbory od najkratsieho po najdlhší) Dôkaz, že je takýto algoritmus naozaj korektný je možné nájsť v slajdoch k predmetnu Návrh algoritmů II. Medzi iné hladové algoritmy patrí Dijsktrov algoritmus, Primov a Kruskallov algoritmus pre najlacnejšie kostry, Huffmanove kódy, ... ==== Bactracking ==== Technika prehľadávania priestoru potencionálnych riešení založená na princípe Rozdeľ a panuj. * do priestoru potencionálnych riešení vnesieme stromovú štruktúru, (binárne reťazce, k-arne reťazce, permutácie, kombinácie) * stromovú štruktúru prehľadávame do hĺbky * prehľadávanie zefektívnime odrezávaním ciest, ktoré dokázateľne nevedú k hľadanému riešeniu === Návrh backtrakovacieho algoritmu === - Voľba spôsobou reprezentácie potencionálnych riešení - Generovanie potencionálnych riešení technikou rozdeľ a panuj - Testovanie požadovanej vlastnosti - Odrezávanie neperspektívnych ciest Daných je n tyčí dĺžky d1,...,dn a číslo D \in \mathbb{N}. Úlohou je vybrať tyče tak, aby súčet ich dĺžok bol presne //D//. === Rešenie === - Potencionálne riešenia sú všetky spôsoby výberu tyčí. Riešenia budeme reprezentovať ako binárne reťazce, konkrétne pomocou binárneho poľa A[1..n]. A[//i//]=1 ak tyč //i// bola vybraná. Binárne reťazce vytvárajú stromovú štruktúru. - Strom prehľadávame do hĺbky: pole A napĺňame zprava - Požadovanú vlastnosť testujeme vtedy, ak máme vygenerované celé potenciálne riešenie. - Cesty odrezávame, keď dĺžka vybraných tyčí prekročí daný limit. Pozn. Tento problém je riešiteľný dynamickým programovaním v O(nD). Tyč(m, l) 1 if m = 0 then 2 if l = 0 then print A fi 3 else 4 A[m] ← 0 5 Tyč(m − 1, l) 6 7 if dm ≤ l then 8 A[m] ← 1 9 Tyč(m − 1, l − dm) 10 fi 11 fi Pri používaní backtrackingu budeme často potrebovať preskúšať všetky permutácie. Tu je algoritmus na ich zistenie. procedure Permutácie(m) 1 if m = 1 then kontrola vlastností else Permutácie(m − 1) 2 for i = m − 1 downto 1 do 3 vymeň A[m] a A[i] 4 Permutácie(m − 1) 5 vymeň A[m] a A[i] 6 od fi ===== Predmety ===== * [[https://is.muni.cz/auth/predmety/predmet.pl?kod=IB108|FI:IB108]] Návrh algoritmů II, prof. RNDr. Ivana Černá, CSc. ===== Použitá literatúra ===== * prof. RNDr. Ivana Černá, CSc., [[https://is.muni.cz/auth/el/1433/jaro2007/IB108/um/slajdy.pdf|slajdy z přednášok]] ===== Vypracoval ===== Ľuboš Pecho, 172463, tomorrow@mail.muni.cz, 18.6.2008 ~~DISCUSSION~~