{{TOC float}}

{{Sources| Tohle je poněkud obšírnější výcuc ke státnicovým okruhům ze složitosti pro obory Státnice_-_Informatika_-_I3:_Matematická_lingvistika a Státnice_-_Informatika_-_I2:_Softwarové_systémy, pocházející ze zápisků z předmětu Složitost I -- User:Tuetschek 22:44, 16 Aug 2010 (CEST)

}}

Popis složitosti algoritmů

Definice (Velikost dat, krok algoritmu)

Velikost dat je obvykle počet bitů, potřebných k jejich zapsání, např. data D ⁣ D\,\! jako pro čísla a1,,an ⁣ a_1,\dots,a_n\,\! je velikost dat D=i=1nlogai ⁣ |D|=\sum_{i=1}^n \lceil \log a_i \rceil\,\!.

Krok algoritmu je jedna operace daného abstraktního stroje (např. Turingův stroj, stroj RAM), zjednodušeně jde o nějakou operaci, proveditelnou v konstantním čase (např. aritmetické operace, porovnání hodnot, přiřazení -- pro jednoduché číselné typy).

Definice (Časová složitost)

Časová složitost je funkce f:NN ⁣ f:\mathbb{N}\to\mathbb{N}\,\! taková, že f(D) ⁣ f(|D|)\,\! udává počet kroků daného algoritmu, pokud je spuštěn na datech D ⁣ D\,\!.

Definice (Asymptotická složitost)

Řekneme, že funkce f(n) ⁣ f(n)\,\! je asymptoticky menší nebo rovna než g(n) ⁣ g(n)\,\!, značíme f(n) ⁣ f(n)\,\! je O(g(n)) ⁣ O(g(n))\,\!, právě tehdy, když

:c>0n0n>n0:0f(n)cg(n) ⁣\exists c>0 \exists n_0 \forall n>n_0: 0 \leq f(n) \leq c \cdot g(n)\,\!

Funkce f(n) ⁣ f(n)\,\! je asymptoticky větší nebo rovna než g(n) ⁣ g(n)\,\!, značíme f(n) ⁣ f(n)\,\! je Ω(g(n)) ⁣ \Omega(g(n))\,\!, právě tehdy, když

:c>0n0n>n0:0cg(n)f(n) ⁣\exists c>0 \exists n_0 \forall n>n_0: 0 \leq c \cdot g(n) \leq f(n)\,\!

Funkce f(n) ⁣ f(n)\,\! je asymptoticky stejná jako g(n) ⁣ g(n)\,\!, značíme f(n) ⁣ f(n)\,\! je Θ(g(n)) ⁣ \Theta(g(n))\,\!, právě tehdy, když

:c1,c2>0n0n>n0:0c1g(n)f(n)c2g(n) ⁣\exists c_1,c_2>0 \exists n_0 \forall n>n_0: 0 \leq c_1 \cdot g(n) \leq f(n) \leq c_2 \cdot g(n)\,\!

Funkce f(n) ⁣ f(n)\,\! je asymptoticky ostře menší než g(n) ⁣ g(n)\,\! (f(n) ⁣ f(n)\,\! je o(g(n)) ⁣ o(g(n))\,\!, když

:c>0n0n>n0:0f(n)<cg(n) ⁣\forall c>0 \exists n_0 \forall n>n_0: 0\leq f(n) <c\cdot g(n)\,\!

Funkce f(n) ⁣ f(n)\,\! je asymptoticky ostře větší než g(n) ⁣ g(n)\,\! (f(n) ⁣ f(n)\,\! je w(g(n)) ⁣ w(g(n))\,\!, když

:c>0n0n>n0:0cg(n)<f(n) ⁣\forall c>0 \exists n_0 \forall n>n_0: 0\leq c\cdot g(n) <f(n)\,\!

Poznámka

Asymptotická složitost zkoumá chování algoritmů na velkých datech, zařazuje je podle toho do kategorií. Zanedbává multiplikativní a aditivní konstanty.

Rozděl a panuj

*Pasáž knihy Jakuba Černého - Rozděl a panuj

Definice (Metoda rozděl a panuj)

Rozděl a panuj je metoda návrhu algoritmů (ne strukturované programování), která má 3 kroky:

  1. rozděl -- rozdělí úlohu na několik podúloh stejného typu, ale menší velikosti

  2. vyřeš -- vyřeší podúlohy a to buď přímo pro dostatečně malé, nebo rekurzivně pro větší

  3. sjednoť -- sjednotí řešení podúloh do řešení původní úlohy

Aplikace

{{TODO|Strassen}}

Analýza složitosti algoritmů rozděl a panuj

Poznámka (Vytvoření rekurentní rovnice)

Pro časovou složitost algoritmů typu rozděl a panuj zpravidla dostávám nějakou rekurentní rovnici.

  • T(n) ⁣ T(n)\,\! budiž doba zpracování úlohy velikosti n ⁣ n\,\!, za předpokladu, že T(n)=Θ(1) ⁣ T(n)=\Theta(1)\,\! pro nn0 ⁣ n\leq n_0\,\!.

  • D(n) ⁣ D(n)\,\! budiž doba na rozdělení úlohy velikosti n ⁣ n\,\! na a ⁣ a\,\! podúloh stejné velikosti nc ⁣ \frac{n}{c}\,\!.

  • S(n) ⁣ S(n)\,\! budiž doba na sjednocení řešení podúloh velikosti nc ⁣ \frac{n}{c}\,\! na jednu úlohu velikosti n ⁣ n\,\!. Dostávám rovnici

:T(n)={D(n)+aT(nc)+S(n)n>n0Θ(1)nn0 ⁣T(n)=\begin{cases} D(n)+aT(\frac{n}{c})+S(n) \quad\quad & n > n_0 \\ \Theta(1) & n \leq n_0 \end{cases}\,\!

Poznámka

Při řešení rekurentních rovnic:

  • Zanedbávám celočíselnost (n2 ⁣ \frac{n}{2}\,\! místo n2 ⁣ \lceil\frac{n}{2}\rceil\,\! a n2 ⁣ \lfloor\frac{n}{2}\rfloor\,\!)

  • Nehledím na konkrétní hodnoty aditivních a multiplikativních konstant, asymptotické notace používám i v zadání rekurentních rovnic, i v jejich řešení.

Věta (Substituční metoda)

  1. Uhodnu asymptoticky správné řešení

  2. Indukcí ověřím správnost (zvláště horní a dolní odhad)

Věta (Metoda "kuchařka" (Master Theorem))

Nechť a1,c>1,d0R ⁣ a\geq 1, c>1,d\geq 0\in\mathbb{R}\,\! a nechť T:NN ⁣ T:\mathbb{N}\to\mathbb{N}\,\! je neklesající funkce taková, že n ⁣ \forall n\,\! tvaru ck ⁣ c^k\,\! platí

:T(n)=aT(nc)+Θ(nd) ⁣T(n)=aT(\frac{n}{c}) + \Theta(n^d)\,\!

Potom

  1. Je-li logcad ⁣ \log_c a \neq d\,\!, pak T(n) ⁣ T(n)\,\! je Θ(nmax{logca,d}) ⁣ \Theta( n^{\max\{\log_c a, d\}} )\,\!

  2. Je-li logca=d ⁣ \log_c a = d\,\!, pak T(n) ⁣ T(n)\,\! je Θ(ndlogcn) ⁣ \Theta( n^d \log_c n )\,\!

Věta (Master Theorem, varianta 2)

Nechť 0<ai<1 ⁣ 0<a_i<1\,\!, kde i{1,,k} ⁣ i\in\{1,\dots,k\}\,\! a d0 ⁣ d\geq 0\,\! jsou reálná čísla a nechť T:NN ⁣ T:\mathbb{N}\to\mathbb{N}\,\! splňuje rekurenci

:T(n)=i=1kT(ain)+Θ(nd) ⁣T(n)=\sum_{i=1}^k T(a_i\cdot n) + \Theta(n^d)\,\!

Nechť je číslo x ⁣ x\,\! řešením rovnice i=1kaix=1 ⁣ \sum_{i=1}^k a_i^x = 1\,\!. Potom

  1. Je-li xd ⁣ x \neq d\,\! (tedy i=1kaid1 ⁣ \sum_{i=1}^k a_i^d \neq 1\,\!), pak T(n) ⁣ T(n)\,\! je Θ(nmax{x,d}) ⁣ \Theta( n^{\max\{x, d\}} )\,\!

  2. Je-li x=d ⁣ x = d\,\! (tedy i=1kaid=1 ⁣ \sum_{i=1}^k a_i^d = 1\,\!), pak T(n) ⁣ T(n)\,\! je Θ(ndlogn) ⁣ \Theta( n^d \log n )\,\!

Dynamické programování

{{Sources|Převzato z vypracovaných otázek V. Bedecse --

User:Tuetschek 10:34, 30 Aug 2010 (CEST)}} {{zkazky|

  • Dynamické programování (2012, Dvořák) - U dynamickýho programování jsem nějak sesmolil princip fungování a napsal jsem tam jeden konkrétní algoritmus (z grafiky - matchování vrcholů dvou mnohoúhelníků), na kterym jsem ukazoval, jak to funguje. To bylo OK, ale tahal ze mě pořád nějakej obecnej princip, jak to funguje. V rámci toho jsem ještě za pochodu vymýšlel algoritmus na batoh (to se mi vůbec nedělalo dobře, když vedle mě seděl a čekal na výsledek). Na konec jsme se teda asi dobrali toho, co chtěl slyšet - že se řešení konstruuje z menších podúloh stylem zdola nahoru (narozdíl od rozděl&panuj, kde to je v zásadě shora dolů).

}} Dynamické programování je metoda řešení problemů, které v sobě obsahují

překrývající se subproblémy (subproblémy jsou závislé narozdíl od Rozděl a panuj).

Příklad

Typickým příkladem je výpočet fibonaciho čísla. Fib. posloupnost je definována

jako: :f(0)=1,f(1)=1f(0) = 1, f(1) = 1

:f(n+2)=f(n+1)+f(n)f(n+2) = f(n+1) + f(n)

Výpočet třeba 4. čísla by pak byl f(4)=f(3)+f(2)=f(2)+f(1)+f(1)+f(0)=f(1)+f(0)+f(1)+f(1)+f(0)=5f(4) = f(3) + f(2) = f(2) + f(1) + f(1) + f(0) = f(1) + f(0) + f(1) +f(1) +f(0) = 5. Vidíme, že jsme f(2)f(2) počítali dvakrát, f(1)f(1) třikrát a f(0)f(0) dvakrát. Ve větším měřítku toto zbytečně počítání vede k exponenciální složitosti algoritmu. Lepší cestou je počítat "od spodu", kdy pomoci f(0)f(0) a f(1)f(1) spočteme f(2)f(2), pak s jeho pomoci f(3)f(3) nakonec f(4)f(4) s lineární složitosti.

V dynamickém programování se například vytvoří mapa Fibonacciho čísel a jejich hodnot. Před tím, než začnu počítat hodnotu nějakého Fibonacciho čísla, se podívám do mapy.

Nutné podmínky

V dynamickém programování využíváme:

  1. Překrývání podproblému - problém lze rozdělit na podproblémy, jejichž řešení se využívá opakovaně.

  2. Optimální podstruktury - optimální řešení lze zkonstruovat z optimálních řešení podproblémů.

Postupy

Obvykle se používá jeden ze dvou přístupů k dynamickému programování:

  • Top-down - problém se rekurzivně dělí na podproblémy a po jejich vyřešení se zapamatují výsledky, které se použijí při případném opětovném řešení daného podproblému.

  • Bottom-up - nejdříve se spočítají všechny možné podproblémy (viz příklad s Fibonacciho posloupnosti), které se potom skládají do řešení větších problémů. Tento přístup je výhodnější z hlediska počtu volání funkci a místa na zásobníků, ale ne vždy musí být zřejmě, které všechny subproblémy je třeba předem spočítat.

Použití

Problém batohu -- máme věci různé váhy a batoh určité nosnosti. Které věci máme dát do batohu, abychom jej co nejlépe zaplnili (jednorozměrná varianta problému batohu)? Speciální případ je součet podmnožiny (SP). Algoritmus je popsán v sekci o NP-úplnosti.

Uzávorkování součinu matic (Matrix chain multiplication) tak, aby počet skalárních součinů byl co nejmenší. Dělá se pomocí 2 čtvercových matic (MM a KK) řádu rovného počtu násobených matic, kde pracujeme jen nad diagonálou. Hodnota na MijM_{ij} udává minimální počet skalárních součinů při nejlepším uzávorkování matic iijj, hodnota KijK_{ij} určuje matici, která rozděluje závorkování na dvě podmnožiny matic. Hodnotu MijM_{ij} lze zkonstruovat ze všech MikM_{ik} a MkjM_{kj} pro i<k<ji<k<j.

Hladové algoritmy

Motivace

Problém 1

Dán souvislý neorientovaný graf G=(V,E) ⁣ G=(V,E)\,\! a funkce d:ER+ ⁣ d:E\to\mathbb{R}^+\,\!, udávající délky hran. Najděte minimální kostru grafu G ⁣ G\,\!, tj. kostru G=(V,E) ⁣ G'=(V,E')\,\! tak, že eEd(e) ⁣ \sum_{e\in E'} d(e)\,\! je minimální.

Problém 2

Je dána množina S={1,,n} ⁣ S=\{1,\dots,n\}\,\! úkolů jednotkové délky. Ke každému úkolu je dána lhůta dokončení diN ⁣ d_i\in\mathbb{N}\,\! a pokuta wiN ⁣ w_i\in\mathbb{N}\,\!, kterou je úkol i ⁣ i\,\! penalizován, není-li hotov do své lhůty. Najděte rozvrh (permutaci úkolů od času 0 ⁣ 0\,\! do času n ⁣ n\,\!), který minimalizuje celkovou pokutu.

Problém 3

Je dána množina S={1,,n} ⁣ S=\{1,\dots,n\}\,\! úkolů. Ke každému úkolu je dán čas jeho zahájení si ⁣ s_i\,\! ukončení fi ⁣ f_i\,\!, sifi ⁣ s_i\leq f_i\,\!. Úkoly i ⁣ i\,\! a j ⁣ j\,\! jsou kompatibilní, pokud se intervaly

ParseError: KaTeX parse error: Undefined control sequence: \[ at position 2: \̲[̲s_i,f_i)\,\!

a

ParseError: KaTeX parse error: Undefined control sequence: \[ at position 2: \̲[̲s_j,f_j)\,\!

nepřekrývají. Najděte co největší množinu (po dvou) kompatibilních úkolů.

Matroid

Definice (Matroid)

Matroid je uspořádaná dvojice M=(S,I) ⁣ M=(S,I)\,\!, splňující:

  • S ⁣ S\,\! je konečná neprázdná množina (*prvky matroidu * M ⁣ M\,\!)

  • I ⁣ I\,\! je neprázdná množina podmnožin S ⁣ S\,\! (nezávislé podmnožiny), která má

  1. dědičnou vlastnost: BIABAI ⁣ B\in I \wedge A\subseteq B\quad \Rightarrow\quad A\in I\,\!,

  2. výměnnou vlastnost: A,BIA<BxB\A:A{x}I ⁣ A,B\in I \wedge |A|<|B|\quad \Rightarrow\quad \exists x\in B\backslash A: A\cup\{x\}\in I\,\!.

Věta (O velikosti maximálních nezávislých podmnožin)

Všechny maximální (maximální vzhledem k inkluzi) nezávislé podmnožiny v matroidu mají stejnou velikost.

Důkaz

Z výměnné vlastnosti, nechť A,BI ⁣ A, B\in I\,\! maximální, A<B ⁣ |A|<|B|\,\!, pak A{x}I,xA ⁣ A\cup\{x\}\in I, x\notin A\,\!, což je spor.

Definice (Vážený matroid)

Matroid M=(S,I) ⁣ M=(S,I)\,\! je vážený, pokud je dána funkce w:SR+ ⁣ w:S\to\mathbb{R}^+\,\! a její rozšíření na podmnožiny množiny S ⁣ S\,\! je definováno předpisem:

:ASw(A)=xAw(x) ⁣A\subseteq S \Rightarrow w(A)=\sum_{x\in A}w(x)\,\!

Problém 1 a 2 -- zobecněný

Pro daný vážený matroid nalezněte nezávislou podmnožinu s co největší vahou (optimální množinu). Protože váhy jsou kladné, vždy se bude jednat o maximální nez. množinu.

Problém 1 je spec. případ tohoto, protože můžeme uvažovat grafový matroid (nad hranami) -- MG=(S,I) ⁣ M_G = (S, I)\,\!, kde S=E ⁣ S = E\,\! a pro AE ⁣ A\subseteq E\,\! platí AI ⁣ A\in I\,\!, pokud hrany z A ⁣ A\,\! netvoří cyklus (tj. indukovaný podgraf tvoří les).

Dědičná vlastnost této struktury je zřejmá, výměnnost se dá dokázat následovně: mějme A,BE,A<B ⁣ A,B\subseteq E, |A|<|B|\,\!. Pak lesy z A,B ⁣ A, B\,\! mají na>nb ⁣ n-a > n-b\,\! stromů (vč. izolovaných vrcholů). V B ⁣ B\,\! musí být strom, který se dotýká 2 ⁣ \geq 2\,\! různých stromů z A ⁣ A\,\!. Ten obsahuje hranu, která není v žádném stromě A ⁣ A\,\! a netvoří cyklus a tak ji můžu k A ⁣ A\,\! přidat.

Váhovou funkci převedu na hledání maxim: w(e)=cd(e) ⁣ w(e) = c - d(e)\,\!, kde c ⁣ c\,\! je dost velká konstanta, aby všechny váhy byly kladné. Algoritmus pak najde max. množinu, kde hrany netvoří cyklus. Implicitně bude mít n1 ⁣ n-1\,\! hran, takže půjde o kostru a její w ⁣ w\,\! bude maximální, tedy původní váha minimální.

Pro problém 2 zavedeme pojem kanonického rozvrhu -- takového rozvrhu, kde jsou všechny včasné úkoly rozvrženy před všemi zpožděnými a uspořádány podle neklesající lhůty dokončení (tohle na celkové pokutě nic nezmění a máme bijekci mezi množinou včasných úkolů a kanonickými rozvrhy).

Optimální množinu pak lze hledat jen nad kanonickými rozvrhy -- nezávislou množinou úkolů nazvu takovou, pro kterou existuje kanonický rozvrh tak, že žádný úkol v ní obsažený není zpožděný. Potom hledání max. nezávislé množiny při ohodnocení pokutami je hledání nejmenší pokuty (odeberu co nejvíc z možné celkové pokuty).

Pak zbývá dokázat, že takto vytvořená struktura je matroid. Dědičná vlastnost je triviální -- vyhodím-li něco z nezávislé množiny, nechám v rozvrhu mezery a bude platit stále. Pro výměnnou vlastnost zavedu pomocnou funkci Nt(C)={iCdit} ⁣ N_t(C) = |\{i\in C| d_i\leq t\}|\,\!, udávající počet úkolů z množiny C ⁣ C\,\! se lhůtou do času t ⁣ t\,\!. Pak množina C ⁣ C\,\! je nezávislá, právě když t{1,,n}:Nt(C)t ⁣ \forall t\in\{1,\dots,n\}: N_t(C)\leq t\,\!.

Pak máme-li 2 nezávislé A ⁣ A\,\!, B ⁣ B\,\!, B>A ⁣ |B|>|A|\,\!, označíme k ⁣ k\,\! největší okamžik takový, že Nk(B)Nk(A) ⁣ N_k(B)\leq N_k(A)\,\!, tj. od k+1 ⁣ k+1\,\! dál platí Nt(A)<Nt(B) ⁣ N_t(A) <N_t(B)\,\!. To skutečně nastane, protože B=Nn(B)>Nn(A)=A ⁣ |B| = N_n(B) > N_n(A) = |A|\,\!. Pak určitě v B ⁣ B\,\! je ostře víc úkolů s di=k+1 ⁣ d_i = k+1\,\! než v A ⁣ A\,\!, tj. xB\A ⁣ \exists x\in B\backslash A\,\! se lhůtou k+1 ⁣ k+1\,\!. A{x} ⁣ A \cup \{x\}\,\! je nezávislá, protože Nt(A{x})=Nt(A) ⁣ N_t(A\cup\{x\}) = N_t(A)\,\! pro tk ⁣ t\leq k\,\! a Nt(A{x})Nt(B) ⁣ N_t(A\cup\{x\}) \leq N_t(B)\,\! pro tk+1 ⁣ t\geq k+1\,\!.

Hladový algoritmus na váženém matroidu

Algoritmus (Greedy)

Mám zadaný matroid M=(S,I) ⁣ M=(S,I)\,\!, kde S={x1,,xn} ⁣ S = \{x_1,\dots,x_n\}\,\! a w:SR+ ⁣ w:S\to\mathbb{R}^+\,\!. Potom

  1. A:= ⁣ A:=\emptyset\,\!, setřiď a přeznač S ⁣ S\,\! sestupně podle vah

  2. pro každé xi ⁣ x_i\,\! zkoušej: je-li A{xi}I ⁣ A\cup\{x_i\}\in I\,\!, tak A:=A{xi} ⁣ A:=A\cup\{x_i\}\,\!

  3. vrať A ⁣ A\,\! jako maximální nezávislou množinu

Pokud přidám nějaké xi ⁣ x_i\,\!, nikdy nezruším nezávislost množiny; s už přidanými prvky se nic nestane. Časová složitost je Θ(nlogn) ⁣ \Theta(n\log n)\,\! na setřídění podle vah, testování nezávislosti množiny závisí na typu matriodu (f(n) ⁣ f(n)\,\!), takže celkem něco jako Θ(nlogn+nf(n)) ⁣ \Theta(n\log n + n\cdot f(n))\,\!.

Důkaz

  • Vyhození prvků, které samy o sobě nejsou nezávislé množiny, nic nezkazí (z dědičné vlastnosti).

  • První vybrané xi ⁣ x_i\,\! je "legální" (nezablokuje mi cestu), protože mezi max. nez. množinami určitě existuje taková, která jím mohla vzniknout (z výměnné vlastnosti -- vezmeme první prvek, který je sám o sobě nez. mn. a s pomocí nějaké max. nez. množiny B ⁣ B\,\! ho doplníme, vzniklé {xi}(B\{xj}) ⁣ \{x_i\}\cup (B\backslash \{ x_j\})\,\! musí být také maximální).

  • Nalezení optimální množiny obsahující pevné (první vybrané) xi ⁣ x_i\,\! v M=(S,I) ⁣ M=(S,I)\,\! je ekvivalentní nalezení optimální množiny v M=(S,I) ⁣ M' = (S', I')\,\!, kde S={yS{xi,y}I} ⁣ S' = \{ y \in S | \{ x_i,y\}\in I\}\,\! a I={BS\{xi}B{xi}I} ⁣ I' = \{ B\subset S\backslash \{x_i\} | B\cup \{x_i\} \in I\}\,\! (je-li S ⁣ S'\,\! neprázdná, je to matroid, vlastnosti se přenesou z původního; pokud je S ⁣ S'\,\! prázdná, tak algoritmus končí) a tedy když vyberu xi ⁣ x_i\,\!, nezatarasím si cestu k optimu -- stačí ukázat, že A{x} ⁣ A\cup\{x\}\,\! je optimální v M ⁣ M\,\! právě když A ⁣ A\,\! je optimální v M ⁣ M'\,\!.

  • Takže když budu vybírat (indukcí opakovaně) xi ⁣ x_i\,\! podle váhy, dojdu k optimální množině.

Algoritmus (Hladový algoritmus na problém 3)

Máme S={1,,n} ⁣ S=\{1,\dots,n\}\,\! množinu úkolů s časy startů si ⁣ s_i\,\! a konců fi ⁣ f_i\,\!. Provedeme:

  1. A:= ⁣ A:=\emptyset\,\!, f0:=0,j:=0 ⁣ f_0:= 0, j:= 0\,\!

  2. setřiď úkoly podle fi ⁣ f_i\,\! vzestupně a přeznač

  3. pro každé i ⁣ i\,\! zkoušej: je-li sifj ⁣ s_i \geq f_j\,\!, pak A:=A{i} ⁣ A:=A\cup\{i\}\,\! a j:=i ⁣ j:=i\,\!

  4. vrať A ⁣ A\,\! jako max. množinu nekryjících se úkolů

Složitost je nlogn ⁣ n\log n\,\! na setřídění, zbytek už lineární. Sice to funguje, ale tahle struktura NENÍ matroid -- nesplňuje výměnnou vlastnost. Algoritmus má ale stejný důkaz jako předchozí na matroidech (legálnost hladového výběru -- existuje max. množina obsahující prvek 1 ⁣ 1\,\! -- a existenci optimální množiny -- převod na "menší" zadání).

{{Statnice I3}}