TGH05 - Problém za milion dolarů. Jan Březina Technical University of Liberec 20. března 2012
Časová složitost algoritmu Závislost doby běhu programu T na velikosti vstupních dat n. O(n) notace, standardní definice: T (n) = O(f(n)) pokud existuje konstanta C, že pro dost velká n je analogie T f, př: T (n) < Cf(n) n 2 + log(n) = O(n 2 ), = O(n 3 ), O(n log(n))
Časová složitost algoritmu Pro jednoduchost budeme používat O(n) v přísnějším smyslu: T (n) = O(f(n)) pokud existují konstanty c, C analogie T = f, př: cf(n) < T (n) < Cf(n) n 2 + log(n) = Θ(n 2 ), Ω(n 3 ), Ω(n log(n)) Vlastnosti: Nezávisí na rychlosti počítače (ukrytá v konstantě). Nezávisí na kvalitě překladače, zručnosti programátora. Pomíjí členy nižšího řádu.
Složitost - asymtotická Složitost operací používaných v Dijkstrově algoritmu Binární halda Fibonacci halda Vložení O(lgn) O(1) Odeber Min. O(lgn) O(lgn) Zmenšení Kĺıče O(lgn) O(1) Praxe, Boost C++ library: Generating graph...10 000 vertices, 20 000 000 edges. Running Dijkstra s with binary heap...1.46 seconds. Running Dijkstra s with Fibonacci heap...1.31 seconds. Speedup = 1.1145.
Nejhorší vs. průměrný případ... quicksort
Amortizovaná složitost.. dynamické pole (std::vector)
Složitost rekurzivních algoritmů function Rekurze (A[1:n]) Θ(n); Rekurze (A[1:n/2]); Rekurze (A[n/2:n]) T (n) = 2T (n/2) + Θ(n), T (1) = 1 Theorem (Master theorem) Pokud T (n) = at (n/b) + f(n), a 1, b > 1 1. f(n) = O(n log b a ε ), pak T (n) = Θ(n log b a ) 2. f(n) = Θ(n log b a), pak T (n) = Θ(n log b a lg(n)) 3. f(n) = Ω(n log b +ε ), pak T (n) = Θ(f(n)) Složitost Rekurze je tedy případ 2, Θ(nlgn).
Optimální třídící algoritmus... nemůže mít lepší složitost než O(n log n). Rozhodovací strom. Celkový počet uspořádání je n! výška stromu log n! = n log n
Lehké a těžké problémy Lze libovolný problém řešit algoritmem v polynomiálním čase O(n k )? Ne. Např. neexistuje algoritmus, který v konečném čase rozhodne o jiném algoritmu zda skončí v konečném čase. Problémy řešitelné v polynomiálním čase označíme snadné.(p) Problémy neřešitelné v polynomiálním čase nazveme těžké.(not P) Existuje však třída problémů, o nichž se neví jestli zda jsou v (P) nebo ne. A právě na rozhodnutí této otázky je vypsána cena milion dolarů.
Putování po hranách vs. po vrcholech Hledání Eulerovské cesty - kružnice obsahující každou hranu právě jednou, O(V + E) Hamiltonova kružnice - je kružnice na grafu G které prochází každý vrchol právě jednou. Verifikovací problém: Pro danou kružnici rozhodni, zda je Hamiltonova. Řešení v O( V ) čase. Přímý problém: Rozhodni zda graf obsahuje Hamiltonovu kružnici. nebo: Najdi Hamiltonovu kružnici.!! Neznáme polynomiální algoritmus i přes velkou podobnoust s předchozí snadnou úlohou.
třídy problémů P : úlohy řešitelné v polynomiálním čase O(n k ) N P : úlohy jejichž řešení je verifikovatelné v polynomiálním čase. NP -hard : úlohy těžší než všechny NP, tj. všechny NP jsou na ně redukovatelné NP -úplné : nejtěžší z NP problémů, tj. NP NP -hard optimalizační problém vs. rozhodovací problém (druhý je lehčí) Rozhodovací problém A je redukovatelný na B pokud: Existuje polynomiálně složitá transformace vstupu a na vstup b tak, že A(a) právě když B(b) tj. pokud B je v P pak A je taky v P tj. pokud A není v P ani B není v P nebo B je těžší nebo stejně težký jako A Chceme najít nějaký N P -úplný problém. Mnoho problémů je ve třídě N P -úplných. Hamiltonova kružnice, nejdelší cesta v grafu, optimální skládání do batohu,...
NP-úplný problém I Rozhodovací problém je NP- úplný pokud je v NP, tj. řešení je verifikovatelné v polynomiálním čase každý problém v NP je na něj redukovatelný Uvažujme množinu M programů X ze třídy P, které pro každý vstup x dávají výstup ano nebo ne. Problém B: Pro daný program X M zjisti, zda existuje vstup x dávající výstup ano. Prakticky: Pro logický obvod X najdi vstup x, tak aby na výstupu byla jednička.
NP-úplný problém II Problém je z NP. Pro daný vstup x určíme v polynomiálním čase zda vyhovuje. B (X, x) = X(x) Problém je težší než všechny problémy A NP. Pro A najdeme zobrazení f vstupů a na vstupy X problému B, tak aby A(a) B(X). 1. A NP, takže existuje poly verifikační program A (a, a ) tak, že A(a) = 1 právě když a : A (a, a ) = 1 2. položme f(a) = X = F a, kde F a(a ) = A (a, a ) 3. program X je program A s předprogramovaným vstupem a, takže je polynomiální 4. A(a) a : F a(a ) = 1 x : X(x) = 1 B(X)
zero-knowledge proof Důkaz, že nějaké (matematické) tvrzení je pravdivé bez odhalení vlastního důkazu. Peggy zná Hamiltonovu kružnici v rozsáhlém grafu G a chce tuto znalost dokázat Viktorovi, aniž by jí prozradila. Oba provedou několik iterací postupu: 1. Peggy sestrojí graf H isomorfní s G. 2. Peggy zapíše tajně graf H, každou hranu zvlášt. (Zašifruje svým veřejným kĺıčem.) 3. Viktor náhodně určí zda chce odhalit, isomorfismus, nebo kružnici na H 4. V prvním případě Peggy odhaĺı celý graf H a isomorfní zobrazení na G. 5. V druhém případě Peggy odhaĺı jen hrany kružnice na H. V každém kole klesne pravěpodobnost, že Peggy kružnici nezná na polovinu.
Minimální halda - obecně Podporuje operace: insert - vložení ohodnoceného prvku accessmin - čtení minimálního prvku deletemin - odstranění minimálního prvku delete - odstranění prvku se známou polohou merge - spojení dvou hald decreasekey - zmenšení hodnoty prvku se známou polohou Podobně můžeme zavést i maximální haldu. Speciální případ prioritní fronta má alespoň operace insert, deletemin.
Triviální implementace min. haldy prvky uložené ve spojovém seznamu vložení prvku na konec v čase O(1) zmenši kĺıč, jen změna kĺıče O(1) nalezení nebo odebrání minima, průchod seznamem O(n)
Binární halda - I Vlastnosti binární minimální haldy: Kořenový binární strom. Uložení v poli, potomci vrcholu i jsou 2i, 2i + 1 (indexace od 1) Rodič menší než jeho dva potomci. Zaplnění všech vrstev krom poslední (pole nemá díry).
Vytvoření haldy Vytvoření haldy s kořenem i pokud podstromy už jsou haldami: Left(i) = 2i, Right(i) = 2i + 1 function Heapify (i,a[1 : n]) // najdi minimum z i,l,r; min = i; l = Left(i); r = Right(i); if l < n && A[l] < A[min] then min = l ; if r < n && A[r] < A[min] then min = r ; if min i then Swap (A[i],A[min]); Heapify (min,a[1:n]) function BuildHeap(A[1:n]) for i = n/2 down to 1 do Heapify(i,A[1 : n])
Operace s haldou function Insert(a, A[1:n]) přidej a na konec haldy (zvětš haldu) IncreaseKey(n + 1, a, A[1:n+1]) function DecreaseKey(i, key, A[1:n]) if key < A[i] then error: nový kĺıč menší než aktuální; A[i] = key; while i > 1 and A[P arent(i)] > A[i] do Swap (A[Parent(i)],A[i]); i=parent(i); function AccessMin(A[1:n]) return A[1] function DeleteMin(A[1:n]) Swap(A[n],A[1]); zmenši haldu na n 1; Heapify(1, A[1:n-1])
Heap sort - vlastnosti Heapify předpokládá, že potomci i mají korektní haldy a utvoří korektní haldu ve vrcholu i. Složitost je rovna výšce haldy tj. O(log n) Celková složitost první i druhé fáze je O(n log n). Výhody: Θ(n log n) worst case složitost Nevýhody: nevyužije již setříděné pole, špatné pro cache
Složitost různých implementací haldy Seznam Tříděné pole Binární halda Fibonacci heap Vložení O(1) O(n) O(lgn) O(1) Odeber Min. O(n) O(1) O(lgn) O(lgn) Najdi Min. O(n) O(1) O(1) O(1) Odebrání O(1) O(n) O(lgn) O(lgn) Zmenšení Kĺıče O(1) O(n) O(lgn) O(1) Spojení O(1) O(n) O(m lg(n + m)) O(1) - amortizovaný čas, průměrný čas při nejhorším scénáři