From e6c6d5cc41cf563dcd52dbca2f20dbdd82510374 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Mon, 27 Nov 2017 15:16:32 +0100 Subject: [PATCH] =?utf8?q?Dijkstra:=20Oprava=20scestn=C3=A9ho=20p=C5=99ek?= =?utf8?q?=C3=B3dov=C3=A1n=C3=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- 13-dijkstra/13-dijkstra.tex | 1002 +++++++++++++++++------------------ 1 file changed, 501 insertions(+), 501 deletions(-) diff --git a/13-dijkstra/13-dijkstra.tex b/13-dijkstra/13-dijkstra.tex index 48b28a4..942839d 100644 --- a/13-dijkstra/13-dijkstra.tex +++ b/13-dijkstra/13-dijkstra.tex @@ -1,679 +1,679 @@ \input ../sgr.tex -\prednaska{13}{NejkratĹĄĂ­ cesty}{} +\prednaska{13}{Nejkratší cesty}{} \def\ppsp{1-1} \def\sssp{1-$n$} \def\apsp{$n$-$n$} \def\astar{A\kern-0.15em *} -ProblĂŠm hledĂĄnĂ­ nejkratĹĄĂ­ cesty v~(obvykle ohodnocenĂŠm orientovanĂŠm) grafu -provĂĄzĂ­ teorii grafovĂ˝ch algoritmĹŻ od~samĂ˝ch počátkĹŻ. ZĂĄkladnĂ­ algoritmy -pro hledĂĄnĂ­ cest jsou nedĂ­lnou součástĂ­ zĂĄkladnĂ­ch kursĹŻ programovĂĄnĂ­ -a algoritmĹŻ, my se budeme věnovat zejmĂŠna rĹŻznĂ˝m jejich vylepĹĄenĂ­m. +Problém hledání nejkratší cesty v~(obvykle ohodnoceném orientovaném) grafu +provází teorii grafových algoritmů od~samých počátků. Základní algoritmy +pro hledání cest jsou nedílnou součástí základních kursů programování +a algoritmů, my se budeme věnovat zejména různým jejich vylepšením. -UvaĹžujme tedy nějakĂ˝ orientovanĂ˝ graf, jehoĹž kaĹždĂĄ hrana~$e$ je opatřena -{\I dĂŠlkou} $\ell(e)\in{\bb R}$. MnoĹžině hran (třeba sledu nebo cestě) -pak přiřadĂ­me dĂŠlku rovnou součtu dĂŠlek jednotlivĂ˝ch hran. +Uvažujme tedy nějaký orientovaný graf, jehož každá hrana~$e$ je opatřena +{\I délkou} $\ell(e)\in{\bb R}$. Množině hran (třeba sledu nebo cestě) +pak přiřadíme délku rovnou součtu délek jednotlivých hran. -Pro vrcholy $u,v$ definujeme jejich {\I vzdĂĄlenost} $d(u,v)$ jako nejmenĹĄĂ­ -moĹžnou dĂŠlku cesty z~$u$ do~$v$ (jelikoĹž cest je v~grafu konečně mnoho, -minimum vĹždy existuje). Pokud z~$u$ do~$v$ ŞådnĂĄ cesta nevede, poloŞíme +Pro vrcholy $u,v$ definujeme jejich {\I vzdálenost} $d(u,v)$ jako nejmenší +možnou délku cesty z~$u$ do~$v$ (jelikož cest je v~grafu konečně mnoho, +minimum vždy existuje). Pokud z~$u$ do~$v$ žádná cesta nevede, položíme $d(u,v) := \infty$. -Obvykle se studujĂ­ nĂĄsledujĂ­cĂ­ tři problĂŠmy: +Obvykle se studují následující tři problémy: \itemize\ibull -\:{\bo 1-1} neboli {\bo P2PSP} (Point to Point Shortest Path) -- chceme nalĂŠzt nejkratĹĄĂ­ - cestu z~danĂŠho vrcholu~$u$ do~danĂŠho vrcholu~$v$. (Pokud je nejkratĹĄĂ­ch cest - vĂ­ce, tak libovolnou z~nich.) -\:{\bo 1-n} neboli {\bo SSSP} (Single Source Shortest Paths) -- pro danĂ˝ vrchol~$u$ chceme - nalĂŠzt nejkratĹĄĂ­ cesty do~vĹĄech ostatnĂ­ch vrcholĹŻ. -\:{\bo n-n} neboli {\bo APSP} (All Pairs Shortest Paths) -- zajĂ­majĂ­ nĂĄs nejkratĹĄĂ­ cesty - mezi vĹĄemi dvojicemi vrcholĹŻ. +\:{\bo 1-1} neboli {\bo P2PSP} (Point to Point Shortest Path) -- chceme nalézt nejkratší + cestu z~daného vrcholu~$u$ do~daného vrcholu~$v$. (Pokud je nejkratších cest + více, tak libovolnou z~nich.) +\:{\bo 1-n} neboli {\bo SSSP} (Single Source Shortest Paths) -- pro daný vrchol~$u$ chceme + nalézt nejkratší cesty do~všech ostatních vrcholů. +\:{\bo n-n} neboli {\bo APSP} (All Pairs Shortest Paths) -- zajímají nás nejkratší cesty + mezi všemi dvojicemi vrcholů. \endlist -Překvapivě, tak obecně, jak jsme si uvedenĂŠ problĂŠmy definovali, je neumĂ­me -řeĹĄit v~polynomiĂĄlnĂ­m čase: pro grafy, kterĂŠ mohou obsahovat hrany zĂĄpornĂ˝ch -dĂŠlek bez jakĂ˝chkoliv omezenĂ­, je totiĹž hledĂĄnĂ­ nejkratĹĄĂ­ cesty NP-těžkĂŠ -(lze na~něj snadno převĂŠst existenci hamiltonovskĂŠ cesty). VĹĄechny znĂĄmĂŠ -polynomiĂĄlnĂ­ algoritmy totiĹž mĂ­sto nejkratĹĄĂ­ cesty hledajĂ­ nejkratĹĄĂ­ sled --- nijak nekontrolujĂ­, zda cesta neprojde jednĂ­m vrcholem vĂ­cekrĂĄt. - -NaĹĄtěstĂ­ pro nĂĄs je to v~grafech bez cyklĹŻ zĂĄpornĂŠ dĂŠlky totĂŠĹž: pokud se -v~nalezenĂŠm sledu vyskytne cyklus, mĹŻĹžeme jej \uv{vystřihnout} a tĂ­m zĂ­skat -sled, kterĂ˝ nenĂ­ delĹĄĂ­ a~kterĂ˝ mĂĄ mĂŠně hran. KaĹždĂ˝ nejkratĹĄĂ­ sled tak -mĹŻĹžeme upravit na~stejně dlouhou cestu. -V~grafech bez zĂĄpornĂ˝ch cyklĹŻ je tedy jedno, zda hledĂĄme sled nebo cestu; -naopak vyskytne-li se zĂĄpornĂ˝ cyklus dosaĹžitelnĂ˝ z~počátečnĂ­ho vrcholu, -nejkratĹĄĂ­ sled ani neexistuje. - -NavĂ­c se nĂĄm bude hodit, Ĺže kaĹždĂ˝ prefix nejkratĹĄĂ­ cesty je opět nejkratĹĄĂ­ -cesta. JinĂ˝mi slovy pokud některĂĄ z~nejkratĹĄĂ­ch cest z~$u$ do~$v$ vede -přes nějakĂ˝ vrchol~$w$, pak jejĂ­ část z~$u$ do~$w$ je jednou z~nejkratĹĄĂ­ch -cest z~$u$ do~$w$. (V~opačnĂŠm případě bychom mohli Ăşsek $u\ldots w$ vyměnit za~kratĹĄĂ­.) - -DĂ­ky tĂŠto {\I prefixovĂŠ vlastnosti} mĹŻĹžeme pro kaĹždĂ˝ vrchol~$u$ sestrojit jeho {\I strom -nejkratĹĄĂ­ch cest}~${\cal T}(u)$. To je nějakĂ˝ podgraf grafu~$G$, kterĂ˝ mĂĄ tvar -stromu zakořeněnĂŠho v~$u$ a orientovanĂŠho směrem od~kořene, a~platĂ­ pro něj, Ĺže -pro kaĹždĂ˝ vrchol~$v$ je (jedinĂĄ) cesta z~$u$ do~$v$ v~tomto stromu jednou -z~nejkratĹĄĂ­ch cest z~$u$ do~$v$ v~pĹŻvodnĂ­m grafu. - -\s{PozorovĂĄnĂ­:} Strom nejkratĹĄĂ­ch cest vĹždy existuje. +Překvapivě, tak obecně, jak jsme si uvedené problémy definovali, je neumíme +řešit v~polynomiálním čase: pro grafy, které mohou obsahovat hrany záporných +délek bez jakýchkoliv omezení, je totiž hledání nejkratší cesty NP-těžké +(lze na~něj snadno převést existenci hamiltonovské cesty). Všechny známé +polynomiální algoritmy totiž místo nejkratší cesty hledají nejkratší sled +-- nijak nekontrolují, zda cesta neprojde jedním vrcholem vícekrát. + +Naštěstí pro nás je to v~grafech bez cyklů záporné délky totéž: pokud se +v~nalezeném sledu vyskytne cyklus, můžeme jej \uv{vystřihnout} a tím získat +sled, který není delší a~který má méně hran. Každý nejkratší sled tak +můžeme upravit na~stejně dlouhou cestu. +V~grafech bez záporných cyklů je tedy jedno, zda hledáme sled nebo cestu; +naopak vyskytne-li se záporný cyklus dosažitelný z~počátečního vrcholu, +nejkratší sled ani neexistuje. + +Navíc se nám bude hodit, že každý prefix nejkratší cesty je opět nejkratší +cesta. Jinými slovy pokud některá z~nejkratších cest z~$u$ do~$v$ vede +přes nějaký vrchol~$w$, pak její část z~$u$ do~$w$ je jednou z~nejkratších +cest z~$u$ do~$w$. (V~opačném případě bychom mohli úsek $u\ldots w$ vyměnit za~kratší.) + +Díky této {\I prefixové vlastnosti} můžeme pro každý vrchol~$u$ sestrojit jeho {\I strom +nejkratších cest}~${\cal T}(u)$. To je nějaký podgraf grafu~$G$, který má tvar +stromu zakořeněného v~$u$ a orientovaného směrem od~kořene, a~platí pro něj, že +pro každý vrchol~$v$ je (jediná) cesta z~$u$ do~$v$ v~tomto stromu jednou +z~nejkratších cest z~$u$ do~$v$ v~původním grafu. + +\s{Pozorování:} Strom nejkratších cest vždy existuje. \proof -NechĹĽ $u=v_1,\ldots,v_n$ jsou vĹĄechny vrcholy grafu~$G$. IndukcĂ­ budeme -dokazovat, Ĺže pro kaĹždĂŠ~$i$ existuje strom~${\cal T}_i$, v~němĹž se nachĂĄzejĂ­ nejkratĹĄĂ­ -cesty z~vrcholu~$u$ do vrcholĹŻ $v_1,\ldots,v_i$. Pro $i=1$ stačí uvĂĄĹžit -strom obsahujĂ­cĂ­ jedinĂ˝ vrchol~$u$. Ze~stromu ${\cal T}_{i-1}$ pak vyrobĂ­me -strom ${\cal T}_i$ takto: Nalezneme v~$G$ nejkratĹĄĂ­ cestu z~$u$ do~$v_i$ -a označíme~$z$ poslednĂ­ vrchol na~tĂŠto cestě, kterĂ˝ se jeĹĄtě vyskytuje v~${\cal T}_{i-1}$. -Úsek nejkratĹĄĂ­ cesty od~$z$ do~$v_i$ pak přidĂĄme do~${\cal T}_{i-1}$ -a dĂ­ky prefixovĂŠ vlastnosti bude i cesta z~$u$ do~$v_i$ v~novĂŠm stromu -nejkratĹĄĂ­. +Nechť $u=v_1,\ldots,v_n$ jsou všechny vrcholy grafu~$G$. Indukcí budeme +dokazovat, že pro každé~$i$ existuje strom~${\cal T}_i$, v~němž se nacházejí nejkratší +cesty z~vrcholu~$u$ do vrcholů $v_1,\ldots,v_i$. Pro $i=1$ stačí uvážit +strom obsahující jediný vrchol~$u$. Ze~stromu ${\cal T}_{i-1}$ pak vyrobíme +strom ${\cal T}_i$ takto: Nalezneme v~$G$ nejkratší cestu z~$u$ do~$v_i$ +a označíme~$z$ poslední vrchol na~této cestě, který se ještě vyskytuje v~${\cal T}_{i-1}$. +Úsek nejkratší cesty od~$z$ do~$v_i$ pak přidáme do~${\cal T}_{i-1}$ +a díky prefixové vlastnosti bude i cesta z~$u$ do~$v_i$ v~novém stromu +nejkratší. \qed -ZbĂ˝vĂĄ se dohodnout, v~jakĂŠm tvaru majĂ­ naĹĄe algoritmy vydĂĄvat vĂ˝sledek. -U~problĂŠmĹŻ typu \ppsp{} je nejjednoduĹĄĹĄĂ­ vypsat celou cestu, u~\sssp{} mĹŻĹžeme jako vĂ˝stup -vydat strom nejkratĹĄĂ­ch cest z~danĂŠho počátku (vĹĄimněte si, Ĺže stačí -uvĂŠst předchĹŻdce kaĹždĂŠho vrcholu), u~\apsp{} vydĂĄme strom nejkratĹĄĂ­ch cest -pro kaĹždĂ˝ ze~zdrojovĂ˝ch vrcholĹŻ. +Zbývá se dohodnout, v~jakém tvaru mají naše algoritmy vydávat výsledek. +U~problémů typu \ppsp{} je nejjednodušší vypsat celou cestu, u~\sssp{} můžeme jako výstup +vydat strom nejkratších cest z~daného počátku (všimněte si, že stačí +uvést předchůdce každého vrcholu), u~\apsp{} vydáme strom nejkratších cest +pro každý ze~zdrojových vrcholů. -Často se ovĹĄem ukĂĄĹže, Ĺže podstatnĂĄ část problĂŠmu se skrĂ˝vĂĄ v~samotnĂŠm -vĂ˝počtu vzdĂĄlenostĂ­ a sestrojenĂ­ předchĹŻdcĹŻ je triviĂĄlnĂ­m rozšířenĂ­m algoritmu. -Budeme tedy obvykle jen počítat vzdĂĄlenosti a samotnou rekonstrukci cest -ponechĂĄme čtenáři jako snadnĂŠ cvičenĂ­. +Často se ovšem ukáže, že podstatná část problému se skrývá v~samotném +výpočtu vzdáleností a sestrojení předchůdců je triviálním rozšířením algoritmu. +Budeme tedy obvykle jen počítat vzdálenosti a samotnou rekonstrukci cest +ponecháme čtenáři jako snadné cvičení. -\h{RelaxačnĂ­ algoritmus} +\h{Relaxační algoritmus} -Začněme problĂŠmem \sssp{} a označme~$u$ vĂ˝chozĂ­ vrchol. VětĹĄina znĂĄmĂ˝ch -algoritmĹŻ funguje tak, Ĺže pro kaĹždĂ˝ vrchol~$v$ udrĹžujĂ­ ohodnocenĂ­ $h(v)$, -kterĂŠ v~kaĹždĂŠm okamĹžiku odpovĂ­dĂĄ dĂŠlce nějakĂŠho sledu z~$u$ do~$v$. Postupně -toto ohodnocenĂ­ upravujĂ­, aĹž se z~něj stane vzdĂĄlenost $d(u,v)$ a algoritmus -se mĹŻĹže zastavit. +Začněme problémem \sssp{} a označme~$u$ výchozí vrchol. Většina známých +algoritmů funguje tak, že pro každý vrchol~$v$ udržují ohodnocení $h(v)$, +které v~každém okamžiku odpovídá délce nějakého sledu z~$u$ do~$v$. Postupně +toto ohodnocení upravují, až se z~něj stane vzdálenost $d(u,v)$ a algoritmus +se může zastavit. -Vhodnou operacĂ­ pro vylepĹĄovĂĄnĂ­ ohodnocenĂ­ je takzvanĂĄ {\I relaxace.} -Vybereme si nějakĂ˝ vrchol~$v$ a pro vĹĄechny jeho sousedy~$w$ spočítĂĄme -$h(v) + \ell(v,w)$, tedy dĂŠlku sledu, kterĂ˝ vznikne rozšířenĂ­m aktuĂĄlnĂ­ho -sledu do~$v$ o~hranu $(v,w)$. Pokud je tato hodnota menĹĄĂ­ neĹž~$h(w)$, -tak jĂ­ $h(w)$ přepĂ­ĹĄeme. +Vhodnou operací pro vylepšování ohodnocení je takzvaná {\I relaxace.} +Vybereme si nějaký vrchol~$v$ a pro všechny jeho sousedy~$w$ spočítáme +$h(v) + \ell(v,w)$, tedy délku sledu, který vznikne rozšířením aktuálního +sledu do~$v$ o~hranu $(v,w)$. Pokud je tato hodnota menší než~$h(w)$, +tak jí $h(w)$ přepíšeme. -Abychom zabrĂĄnili opakovanĂ˝m relaxacĂ­m tĂŠhoĹž vrcholu, kterĂŠ nic nezměnĂ­, -budeme rozliĹĄovat tři stavy vrcholĹŻ: {\I neviděn} (jeĹĄtě jsme ho nenavĹĄtĂ­vili), -{\I otevřen} (změnilo se ohodnocenĂ­, časem chceme relaxovat) a {\I uzavřen} -(uĹž jsme relaxovali a nenĂ­ potřeba znovu). +Abychom zabránili opakovaným relaxacím téhož vrcholu, které nic nezmění, +budeme rozlišovat tři stavy vrcholů: {\I neviděn} (ještě jsme ho nenavštívili), +{\I otevřen} (změnilo se ohodnocení, časem chceme relaxovat) a {\I uzavřen} +(už jsme relaxovali a není potřeba znovu). -NĂĄĹĄ algoritmus bude fungovat nĂĄsledovně: +Náš algoritmus bude fungovat následovně: \algo \:$h(*)\leftarrow \infty$, $h(u)\leftarrow 0$. -\:$\(*)\leftarrow\$, $\(u)\leftarrow\$. -\:Dokud existujĂ­ otevřenĂŠ vrcholy, opakujeme: -\::$v\leftarrow\hbox{libovolnĂ˝ otevřenĂ˝ vrchol}$. -\::$\(v)\leftarrow\$. +\:$\(*)\leftarrow\$, $\(u)\leftarrow\$. +\:Dokud existují otevřené vrcholy, opakujeme: +\::$v\leftarrow\hbox{libovolný otevřený vrchol}$. +\::$\(v)\leftarrow\$. \::Relaxujeme~$v$: -\:::Pro vĹĄechny hrany $vw$ opakujeme: +\:::Pro všechny hrany $vw$ opakujeme: \::::Je-li $h(w) > h(v) + \ell(v,w)$: \:::::$h(w)\leftarrow h(v) + \ell(v,w)$. -\:::::$\(w)\leftarrow\$. -\:VrĂĄtĂ­me vĂ˝sledek $d(u,v)=h(v)$ pro vĹĄechna~$v$. +\:::::$\(w)\leftarrow\$. +\:Vrátíme výsledek $d(u,v)=h(v)$ pro všechna~$v$. \endalgo -Podobně jako u~minimĂĄlnĂ­ch koster, i zde se jednĂĄ o~meta-algoritmus, protoĹže -v~kroku~4 nespecifikuje, kterĂ˝ z~otevřenĂ˝ch vrcholĹŻ vybĂ­rĂĄ. Přesto -ale mĹŻĹžeme dokĂĄzat několik zajĂ­mavĂ˝ch tvrzenĂ­, kterĂĄ na~konkrĂŠtnĂ­m zpĹŻsobu -vĂ˝běru nezĂĄvisejĂ­. +Podobně jako u~minimálních koster, i zde se jedná o~meta-algoritmus, protože +v~kroku~4 nespecifikuje, který z~otevřených vrcholů vybírá. Přesto +ale můžeme dokázat několik zajímavých tvrzení, která na~konkrétním způsobu +výběru nezávisejí. -\s{Věta:} SpustĂ­me-li meta-algoritmus na graf bez zĂĄpornĂ˝ch cyklĹŻ, pak: +\s{Věta:} Spustíme-li meta-algoritmus na graf bez záporných cyklů, pak: \numlist\nparen -\:OhodnocenĂ­ $h(v)$ vĹždy odpovĂ­dĂĄ dĂŠlce nějakĂŠho sledu z~$u$ do~$v$. -\:$h(v)$ dokonce odpovĂ­dĂĄ dĂŠlce nějakĂŠ cesty z~$u$ do~$v$. -\:Algoritmus se vĹždy zastavĂ­. -\:Po zastavenĂ­ jsou označeny jako uzavřenĂŠ prĂĄvě ty vrcholy, kterĂŠ jsou dosaĹžitelnĂŠ z~$u$. -\:Po zastavenĂ­ majĂ­ konečnĂŠ~$h(v)$ prĂĄvě vĹĄechny uzavřenĂŠ vrcholy. -\:Pro kaĹždĂ˝ dosaĹžitelnĂ˝ vrchol je na~konci $h(v)$ rovno $d(u,v)$. +\:Ohodnocení $h(v)$ vždy odpovídá délce nějakého sledu z~$u$ do~$v$. +\:$h(v)$ dokonce odpovídá délce nějaké cesty z~$u$ do~$v$. +\:Algoritmus se vždy zastaví. +\:Po zastavení jsou označeny jako uzavřené právě ty vrcholy, které jsou dosažitelné z~$u$. +\:Po zastavení mají konečné~$h(v)$ právě všechny uzavřené vrcholy. +\:Pro každý dosažitelný vrchol je na~konci $h(v)$ rovno $d(u,v)$. \endlist \proof \numlist\nparen -\:DokĂĄĹžeme indukcĂ­ podle počtu krokĹŻ algoritmu. -\:Stačí rozmyslet, v~jakĂŠ situaci by vytvořenĂ˝ sled mohl obsahovat cyklus. -\:Cest, a~tĂ­m pĂĄdem i moĹžnĂ˝ch hodnot~$h(v)$ pro kaĹždĂ˝~$v$, je konečně mnoho. -\:Implikace $\Rightarrow$ je triviĂĄlnĂ­, pro $\Leftarrow$ stačí uvĂĄĹžit neuzavřenĂ˝ vrchol, - kterĂ˝ je dosaĹžitelnĂ˝ z~$u$ cestou o~co nejmenĹĄĂ­m počtu hran. -\:$h(v)$ nastavujeme na~konečnou hodnotu prĂĄvě v~okamĹžicĂ­ch, kdy se vrchol stĂĄvĂĄ otevřenĂ˝m. - KaĹždĂ˝ otevřenĂ˝ vrchol je časem uzavřen. +\:Dokážeme indukcí podle počtu kroků algoritmu. +\:Stačí rozmyslet, v~jaké situaci by vytvořený sled mohl obsahovat cyklus. +\:Cest, a~tím pádem i možných hodnot~$h(v)$ pro každý~$v$, je konečně mnoho. +\:Implikace $\Rightarrow$ je triviální, pro $\Leftarrow$ stačí uvážit neuzavřený vrchol, + který je dosažitelný z~$u$ cestou o~co nejmenším počtu hran. +\:$h(v)$ nastavujeme na~konečnou hodnotu právě v~okamžicích, kdy se vrchol stává otevřeným. + Každý otevřený vrchol je časem uzavřen. \:Kdyby tomu tak nebylo, - vyberme si ze~\uv{ĹĄpatnĂ˝ch} vrcholĹŻ~$v$ takovĂ˝, pro nějĹž obsahuje nejkratĹĄĂ­ cesta z~$u$ do~$v$ - nejmenĹĄĂ­ moĹžnĂ˝ počet hran. Vrchol~$v$ je zajistĂŠ rĹŻznĂ˝ od~$u$, takĹže mĂĄ na~tĂŠto cestě nějakĂŠho - předchĹŻdce~$w$. Přitom~$w$ uĹž musĂ­ bĂ˝t ohodnocen sprĂĄvně a relaxace, kterĂĄ mu toto ohodnocenĂ­ - nastavila, ho musela prohlĂĄsit za~otevřenĂ˝. JenĹže kaĹždĂ˝ otevřenĂ˝ vrchol je později uzavřen, - takĹže~$w$ potĂŠ musel bĂ˝t jeĹĄtě alespoň jednou relaxovĂĄn, coĹž muselo snĂ­Ĺžit~$h(v)$ na sprĂĄvnou - vzdĂĄlenost. + vyberme si ze~\uv{špatných} vrcholů~$v$ takový, pro nějž obsahuje nejkratší cesta z~$u$ do~$v$ + nejmenší možný počet hran. Vrchol~$v$ je zajisté různý od~$u$, takže má na~této cestě nějakého + předchůdce~$w$. Přitom~$w$ už musí být ohodnocen správně a relaxace, která mu toto ohodnocení + nastavila, ho musela prohlásit za~otevřený. Jenže každý otevřený vrchol je později uzavřen, + takže~$w$ poté musel být ještě alespoň jednou relaxován, což muselo snížit~$h(v)$ na správnou + vzdálenost. \qeditem \endlist -\>DokĂĄzali jsme tedy, Ĺže meta-algoritmus pro libovolnou implementaci kroku~4 -spočítĂĄ sprĂĄvnĂŠ vzdĂĄlenosti. +\>Dokázali jsme tedy, že meta-algoritmus pro libovolnou implementaci kroku~4 +spočítá správné vzdálenosti. \medskip -\s{CvičenĂ­:} +\s{Cvičení:} \itemize\ibull -\:NechĹĽ do algoritmu doplnĂ­me udrĹžovĂĄnĂ­ předchĹŻdcĹŻ tak, Ĺže v~kroku~9 - přenastavĂ­me předchĹŻdce vrcholu~$w$ na vrchol~$v$. DokaĹžte, Ĺže předchĹŻdci - dosaĹžitelnĂ˝ch vrcholĹŻ budou tvořit strom a Ĺže tento strom bude stromem - nejkratĹĄĂ­ch cest z~vrcholu~$u$. -\:DokaĹžte, Ĺže pro graf, v~němĹž je alespoň jeden zĂĄpornĂ˝ cyklus dosaĹžitelnĂ˝ - z~počátečnĂ­ho vrcholu, se algoritmus nezastavĂ­ a ohodnocenĂ­ vĹĄech vrcholĹŻ - na cyklu postupně klesnou libovolně hluboko. NedosaĹžitelnĂŠ zĂĄpornĂŠ cykly - chod algoritmu samozřejmě nijak neovlivnĂ­. +\:Nechť do algoritmu doplníme udržování předchůdců tak, že v~kroku~9 + přenastavíme předchůdce vrcholu~$w$ na vrchol~$v$. Dokažte, že předchůdci + dosažitelných vrcholů budou tvořit strom a že tento strom bude stromem + nejkratších cest z~vrcholu~$u$. +\:Dokažte, že pro graf, v~němž je alespoň jeden záporný cyklus dosažitelný + z~počátečního vrcholu, se algoritmus nezastaví a ohodnocení všech vrcholů + na cyklu postupně klesnou libovolně hluboko. Nedosažitelné záporné cykly + chod algoritmu samozřejmě nijak neovlivní. \endlist -\h{BellmanĹŻv-FordĹŻv-MooreĹŻv algoritmus} +\h{Bellmanův-Fordův-Mooreův algoritmus} -Bellman \cite{bellman:bfm}, Ford \cite{ford:bfm} a Moore objevili nezĂĄvisle na sobě algoritmus (říkejme mu BFM), -kterĂ˝ lze v~řeči naĹĄeho meta-algoritmu formulovat takto: OtevřenĂŠ vrcholy -udrĹžujeme ve~frontě (vĹždy relaxujeme vrchol na počátku fronty, nově otevĂ­ranĂŠ -zařazujeme na~konec). Co toto pravidlo zpĹŻsobĂ­? +Bellman \cite{bellman:bfm}, Ford \cite{ford:bfm} a Moore objevili nezávisle na sobě algoritmus (říkejme mu BFM), +který lze v~řeči našeho meta-algoritmu formulovat takto: Otevřené vrcholy +udržujeme ve~frontě (vždy relaxujeme vrchol na počátku fronty, nově otevírané +zařazujeme na~konec). Co toto pravidlo způsobí? -\s{Věta:} ČasovĂĄ sloĹžitost algoritmu~BFM činĂ­ $\O(nm)$. +\s{Věta:} Časová složitost algoritmu~BFM činí $\O(nm)$. \proof -Běh algoritmu rozdělĂ­me na~fĂĄze. NultĂĄ fĂĄze sestĂĄvĂĄ z~vloĹženĂ­ vrcholu~$u$ -do~fronty. V~$(i+1)$-nĂ­ fĂĄzi relaxujeme ty vrcholy, kterĂŠ byly do~fronty -uloĹženy během $i$-tĂŠ fĂĄze. - -JelikoĹž relaxace vrcholu trvĂĄ lineĂĄrně se stupněm vrcholu a kaĹždĂ˝ vrchol -se danĂŠ fĂĄze účastnĂ­ nejvýťe jednou, trvĂĄ jedna fĂĄze $\O(m)$. ZbĂ˝vĂĄ ukĂĄzat, -Ĺže fĂĄzĂ­ provedeme nejvýťe~$n$. - -IndukcĂ­ dokĂĄĹžeme, Ĺže na konci $i$-tĂŠ fĂĄze je kaĹždĂŠ ohodnocenĂ­ $h(v)$ shora omezeno -dĂŠlkou nejkratĹĄĂ­ho z~$uv$-sledĹŻ o~nejvýťe~$i$ hranĂĄch. Pro $i=0$ to triviĂĄlně -platĂ­. UvaĹžujme nynĂ­ vrchol~$v$ na konci $(i+1)$-nĂ­ fĂĄze a nějakĂ˝ nejkratĹĄĂ­ $uv$-sled~$P$ -o~$i+1$ hranĂĄch. Označme $wv$ poslednĂ­ hranu tohoto sledu a $P'$ sled bez tĂŠto hrany, -kterĂ˝ tedy mĂĄ dĂŠlku~$i$. Podle indukčnĂ­ho předpokladu je na konci $i$-tĂŠ fĂĄze -$h(w)\le \ell(P')$. Tuto hodnotu zĂ­skalo $h(w)$ nejpozději v~$i$-tĂŠ fĂĄzi, při tom jsme -vrchol~$w$ otevřeli, takĹže jsme ho nejpozději v~$(i+1)$-nĂ­ fĂĄzi zavřeli a relaxovali. -Po tĂŠto relaxaci je ovĹĄem $h(v)\le h(w)+\ell(w,v)\le \ell(P') + \ell(w,v) = \ell(P)$. +Běh algoritmu rozdělíme na~fáze. Nultá fáze sestává z~vložení vrcholu~$u$ +do~fronty. V~$(i+1)$-ní fázi relaxujeme ty vrcholy, které byly do~fronty +uloženy během $i$-té fáze. + +Jelikož relaxace vrcholu trvá lineárně se stupněm vrcholu a každý vrchol +se dané fáze účastní nejvýše jednou, trvá jedna fáze $\O(m)$. Zbývá ukázat, +že fází provedeme nejvýše~$n$. + +Indukcí dokážeme, že na konci $i$-té fáze je každé ohodnocení $h(v)$ shora omezeno +délkou nejkratšího z~$uv$-sledů o~nejvýše~$i$ hranách. Pro $i=0$ to triviálně +platí. Uvažujme nyní vrchol~$v$ na konci $(i+1)$-ní fáze a nějaký nejkratší $uv$-sled~$P$ +o~$i+1$ hranách. Označme $wv$ poslední hranu tohoto sledu a $P'$ sled bez této hrany, +který tedy má délku~$i$. Podle indukčního předpokladu je na konci $i$-té fáze +$h(w)\le \ell(P')$. Tuto hodnotu získalo $h(w)$ nejpozději v~$i$-té fázi, při tom jsme +vrchol~$w$ otevřeli, takže jsme ho nejpozději v~$(i+1)$-ní fázi zavřeli a relaxovali. +Po této relaxaci je ovšem $h(v)\le h(w)+\ell(w,v)\le \ell(P') + \ell(w,v) = \ell(P)$. \qed -\s{CvičenĂ­:} +\s{Cvičení:} \itemize\ibull -\:UkaĹžte, Ĺže asymptoticky stejnĂŠ časovĂŠ sloĹžitosti by dosĂĄhl algoritmus, - kterĂ˝ by vrcholy očísloval $v_1,\ldots,v_n$ a opakovaně by je v~tomto - pořadĂ­ relaxoval tak dlouho, dokud by se ohodnocenĂ­ měnila. -\:Jak algoritmus upravit, aby v~$i$-tĂŠ fĂĄzi spočítal minimĂĄlnĂ­ dĂŠlky sledĹŻ - o~prĂĄvě~$i$ hranĂĄch? -\:Jak lze algoritmus BFM vyuŞít k~nalezenĂ­ zĂĄpornĂŠho cyklu? +\:Ukažte, že asymptoticky stejné časové složitosti by dosáhl algoritmus, + který by vrcholy očísloval $v_1,\ldots,v_n$ a opakovaně by je v~tomto + pořadí relaxoval tak dlouho, dokud by se ohodnocení měnila. +\:Jak algoritmus upravit, aby v~$i$-té fázi spočítal minimální délky sledů + o~právě~$i$ hranách? +\:Jak lze algoritmus BFM využít k~nalezení záporného cyklu? \endlist -\h{DijkstrĹŻv algoritmus} +\h{Dijkstrův algoritmus} -Pokud jsou vĹĄechny dĂŠlky hran nezĂĄpornĂŠ, mĹŻĹžeme pouŞít efektivnějĹĄĂ­ pravidlo -pro vĂ˝běr vrcholu navrĹženĂŠ Dijkstrou \cite{dijkstra:mstandpath}. To říkĂĄ, Ĺže vĹždy relaxujeme ten z~otevřenĂ˝ch -vrcholĹŻ, jehoĹž ohodnocenĂ­ je nejmenĹĄĂ­. +Pokud jsou všechny délky hran nezáporné, můžeme použít efektivnější pravidlo +pro výběr vrcholu navržené Dijkstrou \cite{dijkstra:mstandpath}. To říká, že vždy relaxujeme ten z~otevřených +vrcholů, jehož ohodnocení je nejmenší. -\s{Věta:} DijkstrĹŻv algoritmus uzavĂ­rĂĄ vrcholy v~pořadĂ­ podle neklesajĂ­cĂ­ -vzdĂĄlenosti od~$u$ a kaĹždĂ˝ dosaĹžitelnĂ˝ vrchol uzavře prĂĄvě jednou. +\s{Věta:} Dijkstrův algoritmus uzavírá vrcholy v~pořadí podle neklesající +vzdálenosti od~$u$ a každý dosažitelný vrchol uzavře právě jednou. \proof -IndukcĂ­ dokĂĄĹžeme, Ĺže v~kaĹždĂŠm okamĹžiku majĂ­ vĹĄechny uzavřenĂŠ vrcholy ohodnocenĂ­ -menĹĄĂ­ nebo rovnĂŠ ohodnocenĂ­m vĹĄech otevřenĂ˝ch vrcholĹŻ. Na~počátku to jistě platĂ­. -NechĹĽ nynĂ­ uzavĂ­rĂĄme vrchol~$v$ s~minimĂĄlnĂ­m $h(v)$ mezi otevřenĂ˝mi. Během jeho -relaxace nemĹŻĹžeme Şådnou hodnotu snĂ­Ĺžit pod~$h(v)$, jelikoĹž v~grafu s~nezĂĄpornĂ˝mi -hranami je $h(v) + \ell(v,w) \ge h(v)$. Hodnota zbĂ˝vajĂ­cĂ­ch otevřenĂ˝ch vrcholĹŻ -tedy neklesne pod hodnotu tohoto nově uzavřenĂŠho. Hodnoty dříve uzavřenĂ˝ch vrcholĹŻ -se nemohou nijak změnit. +Indukcí dokážeme, že v~každém okamžiku mají všechny uzavřené vrcholy ohodnocení +menší nebo rovné ohodnocením všech otevřených vrcholů. Na~počátku to jistě platí. +Nechť nyní uzavíráme vrchol~$v$ s~minimálním $h(v)$ mezi otevřenými. Během jeho +relaxace nemůžeme žádnou hodnotu snížit pod~$h(v)$, jelikož v~grafu s~nezápornými +hranami je $h(v) + \ell(v,w) \ge h(v)$. Hodnota zbývajících otevřených vrcholů +tedy neklesne pod hodnotu tohoto nově uzavřeného. Hodnoty dříve uzavřených vrcholů +se nemohou nijak změnit. \qed -PřímočarĂĄ implementace Dijkstrova algoritmu by tedy pokaĹždĂŠ v~čase $\O(n)$ -vybrala otevřenĂ˝ vrchol s~nejmenĹĄĂ­m ohodnocenĂ­m, v~čase $\O(n)$ ho relaxovala -a toto by se opakovalo nejvýťe $n$-krĂĄt. Algoritmus by tudĂ­Ĺž doběhl v~čase $\O(n^2)$, -coĹž je pro hustĂŠ grafy zajistĂŠ optimĂĄlnĂ­. ZkusĂ­me nynĂ­ zrychlit vĂ˝počet -na~řídkĂ˝ch grafech. - -VĹĄechny relaxace trvajĂ­ dohromady $\O(\sum_v \deg(v)) = \O(m)$, takĹže ĂşzkĂ˝m hrdlem je -vybĂ­rĂĄnĂ­ minima. PouĹžijeme pro něj vhodnou datovou strukturu, v~nĂ­Ĺž budeme udrĹžovat -mnoĹžinu vĹĄech otevřenĂ˝ch vrcholĹŻ spolu s~jejich ohodnocenĂ­mi. Od~datovĂŠ struktury -potřebujeme, aby uměla operace \ (vloĹženĂ­ vrcholu), \ (nalezenĂ­ -a smazĂĄnĂ­ minima) a \ (snĂ­ĹženĂ­ hodnoty vrcholu). PrvnĂ­ dvě operace přitom -volĂĄme nejvýťe $n$-krĂĄt a operaci \ nejvýťe $m$-krĂĄt. CelĂ˝ algoritmus -tedy doběhne v~čase +Přímočará implementace Dijkstrova algoritmu by tedy pokaždé v~čase $\O(n)$ +vybrala otevřený vrchol s~nejmenším ohodnocením, v~čase $\O(n)$ ho relaxovala +a toto by se opakovalo nejvýše $n$-krát. Algoritmus by tudíž doběhl v~čase $\O(n^2)$, +což je pro husté grafy zajisté optimální. Zkusíme nyní zrychlit výpočet +na~řídkých grafech. + +Všechny relaxace trvají dohromady $\O(\sum_v \deg(v)) = \O(m)$, takže úzkým hrdlem je +vybírání minima. Použijeme pro něj vhodnou datovou strukturu, v~níž budeme udržovat +množinu všech otevřených vrcholů spolu s~jejich ohodnoceními. Od~datové struktury +potřebujeme, aby uměla operace \ (vložení vrcholu), \ (nalezení +a smazání minima) a \ (snížení hodnoty vrcholu). První dvě operace přitom +voláme nejvýše $n$-krát a operaci \ nejvýše $m$-krát. Celý algoritmus +tedy doběhne v~čase $$\O(nT_I(n) + nT_E(n) + mT_D(n)),$$ -kde $T_I(n)$, $T_E(n)$ a $T_D(n)$ jsou časovĂŠ sloĹžitosti jednotlivĂ˝ch operacĂ­ -na~struktuře o~nejvýťe~$n$ prvcĂ­ch (stačí amortizovaně). +kde $T_I(n)$, $T_E(n)$ a $T_D(n)$ jsou časové složitosti jednotlivých operací +na~struktuře o~nejvýše~$n$ prvcích (stačí amortizovaně). -\>JakĂŠ moĹžnosti mĂĄme pro volbu struktury? +\>Jaké možnosti máme pro volbu struktury? \itemize\ibull -\:{\I pole} -- \ a \ stojĂ­ konstantu, \ trvĂĄ $\O(n)$, +\:{\I pole} -- \ a \ stojí konstantu, \ trvá $\O(n)$, celkem tedy $\O(n^2)$. -\:{\I (binĂĄrnĂ­) halda} -- vĹĄechny tři operace umĂ­me provĂŠst v~čase $\O(\log n)$, takĹže celkem - $\O(m\log n)$. To je pro hustĂŠ grafy horĹĄĂ­, pro řídkĂŠ lepĹĄĂ­. -\:{\I $k$-regulĂĄrnĂ­ halda} -- pokud haldu upravĂ­me tak, Ĺže kaĹždĂ˝ prvek bude mĂ­t aĹž $k$ synĹŻ, - hloubka haldy klesne na~$\O(\log_k n)$. Operace \uv{vybublĂĄvajĂ­cĂ­} prvky směrem nahoru, - coĹž je \ a \, se zrychlĂ­ na~$\O(\log_k n)$. OvĹĄem \ potřebuje - zkoumat vĹĄechny syny kaĹždĂŠho navĹĄtĂ­venĂŠho prvku, takĹže se zpomalĂ­ na $\O(k\log_k n)$. - - CelkovĂĄ sloĹžitost tedy vyjde $\O(nk\log_k n + m\log_k n)$. Oba členy se vyrovnajĂ­ - pro $k=m/n$, čímĹž zĂ­skĂĄme $\O(m\log_{m/n} n)$. Člen $\log_{m/n} n$ je přitom $\O(1)$, - kdykoliv je $m\ge n^{1+\varepsilon}$ pro nějakĂŠ~$\varepsilon>0$, takĹže pro dostatečně - hustĂŠ grafy jsme zĂ­skali lineĂĄrnĂ­ algoritmus. - - (VĹĄimněte si, Ĺže pro $m\approx n^2$ algoritmus zvolĂ­ $k\approx n$, takĹže halda degeneruje - na jedinĂŠ patro, tedy na pole, kterĂŠ se opravdu ukĂĄzalo bĂ˝t optimĂĄlnĂ­ volbou pro hustĂŠ grafy.) -\:{\I Fibonacciho halda} \cite{ft:fibonacci} -- \ a \ stojĂ­ $\O(1)$, \ mĂĄ sloĹžitost - $\O(\log n)$ [vĹĄe amortizovaně]. DijkstrĹŻv algoritmus proto doběhne v~čase $\O(m + n\log n)$. - To je lineĂĄrnĂ­ pro grafy s~hustotou $\Omega(\log n)$. TĂŠĹže sloĹžitosti operacĂ­ dosahujĂ­ - i jinĂŠ, mĂŠně znĂĄmĂŠ haldy \cite{haeupler:rankph,elmasry:violheap}, kterĂŠ mohou bĂ˝t v~praxi - vĂ˝razně rychlejĹĄĂ­. -\:{\I MonotĂłnnĂ­ haldy} -- mĹŻĹžeme pouŞít nějakou jinou haldu, kterĂĄ vyuŞívĂĄ toho, - Ĺže posloupnost odebĂ­ranĂ˝ch prvkĹŻ je neklesajĂ­cĂ­. Pro celĂĄ čísla na~\hbox{RAMu} to mĹŻĹže - bĂ˝t například Thorupova halda \cite{thorup:queue} se sloĹžitostĂ­ $\O(\log\log n)$ u~operace \ - a $\O(1)$ u~ostatnĂ­ch operacĂ­. Dijkstra tedy běží v~$\O(m + n\log\log n)$. -\:{\I DatovĂŠ struktury pro omezenĂŠ universum} -- prozkoumĂĄme vzĂĄpětĂ­. +\:{\I (binární) halda} -- všechny tři operace umíme provést v~čase $\O(\log n)$, takže celkem + $\O(m\log n)$. To je pro husté grafy horší, pro řídké lepší. +\:{\I $k$-regulární halda} -- pokud haldu upravíme tak, že každý prvek bude mít až $k$ synů, + hloubka haldy klesne na~$\O(\log_k n)$. Operace \uv{vybublávající} prvky směrem nahoru, + což je \ a \, se zrychlí na~$\O(\log_k n)$. Ovšem \ potřebuje + zkoumat všechny syny každého navštíveného prvku, takže se zpomalí na $\O(k\log_k n)$. + + Celková složitost tedy vyjde $\O(nk\log_k n + m\log_k n)$. Oba členy se vyrovnají + pro $k=m/n$, čímž získáme $\O(m\log_{m/n} n)$. Člen $\log_{m/n} n$ je přitom $\O(1)$, + kdykoliv je $m\ge n^{1+\varepsilon}$ pro nějaké~$\varepsilon>0$, takže pro dostatečně + husté grafy jsme získali lineární algoritmus. + + (Všimněte si, že pro $m\approx n^2$ algoritmus zvolí $k\approx n$, takže halda degeneruje + na jediné patro, tedy na pole, které se opravdu ukázalo být optimální volbou pro husté grafy.) +\:{\I Fibonacciho halda} \cite{ft:fibonacci} -- \ a \ stojí $\O(1)$, \ má složitost + $\O(\log n)$ [vše amortizovaně]. Dijkstrův algoritmus proto doběhne v~čase $\O(m + n\log n)$. + To je lineární pro grafy s~hustotou $\Omega(\log n)$. Téže složitosti operací dosahují + i jiné, méně známé haldy \cite{haeupler:rankph,elmasry:violheap}, které mohou být v~praxi + výrazně rychlejší. +\:{\I Monotónní haldy} -- můžeme použít nějakou jinou haldu, která využívá toho, + že posloupnost odebíraných prvků je neklesající. Pro celá čísla na~\hbox{RAMu} to může + být například Thorupova halda \cite{thorup:queue} se složitostí $\O(\log\log n)$ u~operace \ + a $\O(1)$ u~ostatních operací. Dijkstra tedy běží v~$\O(m + n\log\log n)$. +\:{\I Datové struktury pro omezené universum} -- prozkoumáme vzápětí. \endlist -\s{CvičenĂ­:} +\s{Cvičení:} \itemize\ibull -\:Najděte příklad grafu se zĂĄpornĂ˝mi hranami (ale bez zĂĄpornĂ˝ch cyklĹŻ), - na~kterĂŠm DijkstrĹŻv algoritmus selĹže. -\:Rozmyslete si, Ĺže pokud nevyuĹžijeme nějakĂŠ speciĂĄlnĂ­ vlastnosti čísel (celočíselnost, - omezenĂ˝ rozsah), je mez $\O(m+n\log n)$ nejlepĹĄĂ­ moĹžnĂĄ, protoĹže DijkstrovĂ˝m algoritmem - mĹŻĹžeme třídit $n$-tici čísel. Thorup dokonce dokĂĄzal \cite{thorup:equiv}, Ĺže z~kaĹždĂŠho třídĂ­cĂ­ho algoritmu - se sloĹžitostĂ­ $\O(nT(n))$ mĹŻĹžeme odvodit haldu se sloĹžitostĂ­ mazĂĄnĂ­ $\O(T(n))$. -\:Jsou-li dĂŠlky hran celočíselnĂŠ, mĹŻĹžeme se na DijkstrĹŻv algoritmus dĂ­vat i takto: - Představme si, Ĺže kaĹždou hranu nahradĂ­me cestou tvořenou přísluĹĄnĂ˝m počtem hran jednotkovĂŠ dĂŠlky - a na vzniklĂ˝ neohodnocenĂ˝ graf spustĂ­me prohledĂĄvĂĄnĂ­ do~šířky. To samozřejmě vydĂĄ - sprĂĄvnĂ˝ vĂ˝sledek, ale poměrně pomalu, protoĹže bude větĹĄinu času trĂĄvit posouvĂĄnĂ­m - vlny \uv{uvnitř} pĹŻvodnĂ­ch hran. MĹŻĹžeme si tedy pro kaĹždou pĹŻvodnĂ­ hranu nařídit - \uv{budĂ­k}, kterĂ˝ nĂĄm řekne, za~kolik posunutĂ­ vlny dospějeme na~jejĂ­ konec. - DokaĹžte, Ĺže tento algoritmus je ekvivalentnĂ­ s~DijkstrovĂ˝m. +\:Najděte příklad grafu se zápornými hranami (ale bez záporných cyklů), + na~kterém Dijkstrův algoritmus selže. +\:Rozmyslete si, že pokud nevyužijeme nějaké speciální vlastnosti čísel (celočíselnost, + omezený rozsah), je mez $\O(m+n\log n)$ nejlepší možná, protože Dijkstrovým algoritmem + můžeme třídit $n$-tici čísel. Thorup dokonce dokázal \cite{thorup:equiv}, že z~každého třídícího algoritmu + se složitostí $\O(nT(n))$ můžeme odvodit haldu se složitostí mazání $\O(T(n))$. +\:Jsou-li délky hran celočíselné, můžeme se na Dijkstrův algoritmus dívat i takto: + Představme si, že každou hranu nahradíme cestou tvořenou příslušným počtem hran jednotkové délky + a na vzniklý neohodnocený graf spustíme prohledávání do~šířky. To samozřejmě vydá + správný výsledek, ale poměrně pomalu, protože bude většinu času trávit posouváním + vlny \uv{uvnitř} původních hran. Můžeme si tedy pro každou původní hranu nařídit + \uv{budík}, který nám řekne, za~kolik posunutí vlny dospějeme na~její konec. + Dokažte, že tento algoritmus je ekvivalentní s~Dijkstrovým. \endlist -\h{CeločíselnĂŠ dĂŠlky} - -UvaĹžujme nynĂ­ grafy, v~nichĹž jsou vĹĄechny dĂŠlky hran nezĂĄpornĂĄ celĂĄ čísla omezenĂĄ -nějakou konstantou~$L$. VĹĄechny vzdĂĄlenosti jsou tedy omezeny číslem~$nL$, takĹže -nĂĄm stačí datovĂĄ struktura schopnĂĄ uchovĂĄvat takto omezenĂĄ celĂĄ čísla. - -PouĹžijeme jednoduchou přihrĂĄdkovou strukturu: pole indexovanĂŠ hodnotami od~0 do~$nL$, -jeho $i$-tĂ˝ prvek bude obsahovat seznam vrcholĹŻ, jejichĹž ohodnocenĂ­ je rovno~$i$. -Operace \ a \ zvlĂĄdneme v~konstantnĂ­m čase, budeme-li si u~kaĹždĂŠho -prvku pamatovat jeho polohu v~seznamu. Operace \ potřebuje najĂ­t prvnĂ­ -neprĂĄzdnou přihrĂĄdku, ale jelikoĹž vĂ­me, Ĺže posloupnost odebĂ­ranĂ˝ch minim je monotĂłnnĂ­, -stačí hledat od mĂ­sta, kde se hledĂĄnĂ­ zastavilo minule. VĹĄechna hledĂĄnĂ­ přihrĂĄdek -tedy zaberou dohromady $\O(nL)$ a celĂ˝ DijkstrĹŻv algoritmus bude trvat $\O(nL + m)$. - -ProstorovĂĄ sloĹžitost $\O(nL+m)$ je nevalnĂĄ, ale mĹŻĹžeme ji jednoduchĂ˝m trikem -snĂ­Ĺžit: VĹĄimneme si, Ĺže vĹĄechna konečnĂĄ ohodnocenĂ­ vrcholĹŻ nemohou bĂ˝t větĹĄĂ­ -neĹž aktuĂĄlnĂ­ minimum zvětĹĄenĂŠ o~$L$. JinĂ˝mi slovy vĹĄechny neprĂĄzdnĂŠ přihrĂĄdky -se nachĂĄzejĂ­ v~Ăşseku pole dlouhĂŠm~$L+1$, takĹže stačí indexovat modulo~$L+1$. -Pouze si musĂ­me dĂĄvat pozor, abychom sprĂĄvně poznali, kdy se struktura -vyprĂĄzdnila, coĹž zjistĂ­me například pomocĂ­ počítadla otevřenĂ˝ch vrcholĹŻ. Čas si -asymptoticky nezhorĹĄĂ­me, prostor klesne na~$\O(L+m)$. - -PodobnĂ˝ trik mĹŻĹžeme pouŞít i pro libovolnou jinou datovou strukturu: rozsah čísel -rozdělĂ­me na~\uv{okna} velikosti~$L$ (v~$i$-tĂŠm okně jsou čísla $iL,iL+1,\ldots,(i+1)L-1$). -V~libovolnĂŠ chvĂ­li mohou tedy bĂ˝t neprĂĄzdnĂĄ nejvýťe dvě okna. Stačí nĂĄm proto -pořídit si dvě struktury pro uklĂĄdĂĄnĂ­ čísel v~rozsahu $0,\ldots,L-1$ -- jedna -z~nich bude reprezentovat aktuĂĄlnĂ­ okno (to, v~němĹž leĹželo minulĂŠ minimum), -druhĂĄ okno bezprostředně nĂĄsledujĂ­cĂ­. Minimum maĹžeme z~prvnĂ­ struktury; pokud -uĹž je prĂĄzdnĂĄ, obě struktury prohodĂ­me. Operace \ podle hodnoty určí, -do~kterĂŠ struktury se mĂĄ vklĂĄdat. S~operacĂ­ \ je to sloĹžitějĹĄĂ­ -- -hodnota z~vyĹĄĹĄĂ­ struktury mĹŻĹže přeskočit do tĂŠ niŞťí, ale v~takovĂŠm případě -ji ve~vyĹĄĹĄĂ­ struktuře vymaĹžeme (to je \ na $-\infty$ nĂĄsledovanĂ˝ -\em) a do~tĂŠ niŞťí vloŞíme. To se kaĹždĂŠmu prvku mĹŻĹže přihodit nejvýťe -jednou, takĹže stĂĄle platĂ­, Ĺže se kaĹždĂ˝ prvek účastnĂ­ $\O(1)$ vloĹženĂ­ a $\O(1)$ -extrakcĂ­ minima. - -UkĂĄzali jsme tedy, Ĺže pro naĹĄe potřeby postačuje struktura schopnĂĄ uchovĂĄvĂĄnĂ­ -čísel menĹĄĂ­ch nebo rovnĂ˝ch~$L$. - -NabĂ­zĂ­ se pouŞít van Emde-BoasĹŻv strom z~kapitoly o~vĂ˝početnĂ­ch modelech. -Ten dosahuje sloĹžitosti $\O(\log\log L)$ pro operace \ a \, -operaci \ musĂ­me překlĂĄdat na \ a \. CelkovĂĄ -sloĹžitost Dijkstrova algoritmu vyjde $\O(L+m\log\log L)$, přičemĹž čas~$L$ -spotřebujeme na inicializaci struktury (tĂŠ se lze za jistĂ˝ch podmĂ­nek vyhnout, -viz zmĂ­něnĂĄ kapitola). - -VraĹĽme se ale jeĹĄtě k~vyuĹžitĂ­ přihrĂĄdek\dots - -\h{VĂ­ceĂşrovňovĂŠ přihrĂĄdky} - -Podobně jako u~tříděnĂ­ čísel, i~zde se vyplĂĄcĂ­ stavět přihrĂĄdkovĂŠ struktury -vĂ­ceĂşrovňově (pĹŻvodně popsĂĄno Goldbergem a Silversteinem \cite{goldberg:mlb}). -JednotlivĂŠ hodnoty budeme zapisovat v~soustavě o~zĂĄkladu~$B$, -kterĂ˝ zvolĂ­me jako nějakou mocninu dvojky, abychom mohli s~číslicemi tohoto -zĂĄpisu snadno zachĂĄzet pomocĂ­ bitovĂ˝ch operacĂ­. KaĹždĂŠ číslo tedy zabere nejvýťe -$d=1+\lfloor\log_B L\rfloor$ číslic; pokud bude kratĹĄĂ­, doplnĂ­me ho zleva nulami. - -NejvyĹĄĹĄĂ­ patro struktury bude tvořeno polem $B$~přihrĂĄdek, v~$i$-tĂŠ z~nich -budou uloĹžena ta čísla, jejichĹž číslice nejvyĹĄĹĄĂ­ho řádu je rovna~$i$. Za~{\I aktivnĂ­} -prohlĂĄsĂ­me tu přihrĂĄdku, kterĂĄ obsahuje aktuĂĄlnĂ­ minimum. PřihrĂĄdky s~menĹĄĂ­mi -indexy jsou prĂĄzdnĂŠ a zĹŻstanou takovĂŠ aĹž do~konce vĂ˝počtu, protoĹže halda -je monotĂłnnĂ­. Pokud v~přihrĂĄdce obsahujĂ­cĂ­ minimum bude vĂ­ce prvkĹŻ, budeme -ji rozklĂĄdat podle druhĂŠho nejvyĹĄĹĄĂ­ho řádu na dalĹĄĂ­ch~$B$ přihrĂĄdek atd. -Celkem tak vznikne aĹž~$d$ ĂşrovnĂ­. - -\>Struktura bude obsahovat nĂĄsledujĂ­cĂ­ data: +\h{Celočíselné délky} + +Uvažujme nyní grafy, v~nichž jsou všechny délky hran nezáporná celá čísla omezená +nějakou konstantou~$L$. Všechny vzdálenosti jsou tedy omezeny číslem~$nL$, takže +nám stačí datová struktura schopná uchovávat takto omezená celá čísla. + +Použijeme jednoduchou přihrádkovou strukturu: pole indexované hodnotami od~0 do~$nL$, +jeho $i$-tý prvek bude obsahovat seznam vrcholů, jejichž ohodnocení je rovno~$i$. +Operace \ a \ zvládneme v~konstantním čase, budeme-li si u~každého +prvku pamatovat jeho polohu v~seznamu. Operace \ potřebuje najít první +neprázdnou přihrádku, ale jelikož víme, že posloupnost odebíraných minim je monotónní, +stačí hledat od místa, kde se hledání zastavilo minule. Všechna hledání přihrádek +tedy zaberou dohromady $\O(nL)$ a celý Dijkstrův algoritmus bude trvat $\O(nL + m)$. + +Prostorová složitost $\O(nL+m)$ je nevalná, ale můžeme ji jednoduchým trikem +snížit: Všimneme si, že všechna konečná ohodnocení vrcholů nemohou být větší +než aktuální minimum zvětšené o~$L$. Jinými slovy všechny neprázdné přihrádky +se nacházejí v~úseku pole dlouhém~$L+1$, takže stačí indexovat modulo~$L+1$. +Pouze si musíme dávat pozor, abychom správně poznali, kdy se struktura +vyprázdnila, což zjistíme například pomocí počítadla otevřených vrcholů. Čas si +asymptoticky nezhoršíme, prostor klesne na~$\O(L+m)$. + +Podobný trik můžeme použít i pro libovolnou jinou datovou strukturu: rozsah čísel +rozdělíme na~\uv{okna} velikosti~$L$ (v~$i$-tém okně jsou čísla $iL,iL+1,\ldots,(i+1)L-1$). +V~libovolné chvíli mohou tedy být neprázdná nejvýše dvě okna. Stačí nám proto +pořídit si dvě struktury pro ukládání čísel v~rozsahu $0,\ldots,L-1$ -- jedna +z~nich bude reprezentovat aktuální okno (to, v~němž leželo minulé minimum), +druhá okno bezprostředně následující. Minimum mažeme z~první struktury; pokud +už je prázdná, obě struktury prohodíme. Operace \ podle hodnoty určí, +do~které struktury se má vkládat. S~operací \ je to složitější -- +hodnota z~vyšší struktury může přeskočit do té nižší, ale v~takovém případě +ji ve~vyšší struktuře vymažeme (to je \ na $-\infty$ následovaný +\em) a do~té nižší vložíme. To se každému prvku může přihodit nejvýše +jednou, takže stále platí, že se každý prvek účastní $\O(1)$ vložení a $\O(1)$ +extrakcí minima. + +Ukázali jsme tedy, že pro naše potřeby postačuje struktura schopná uchovávání +čísel menších nebo rovných~$L$. + +Nabízí se použít van Emde-Boasův strom z~kapitoly o~výpočetních modelech. +Ten dosahuje složitosti $\O(\log\log L)$ pro operace \ a \, +operaci \ musíme překládat na \ a \. Celková +složitost Dijkstrova algoritmu vyjde $\O(L+m\log\log L)$, přičemž čas~$L$ +spotřebujeme na inicializaci struktury (té se lze za jistých podmínek vyhnout, +viz zmíněná kapitola). + +Vraťme se ale ještě k~využití přihrádek\dots + +\h{Víceúrovňové přihrádky} + +Podobně jako u~třídění čísel, i~zde se vyplácí stavět přihrádkové struktury +víceúrovňově (původně popsáno Goldbergem a Silversteinem \cite{goldberg:mlb}). +Jednotlivé hodnoty budeme zapisovat v~soustavě o~základu~$B$, +který zvolíme jako nějakou mocninu dvojky, abychom mohli s~číslicemi tohoto +zápisu snadno zacházet pomocí bitových operací. Každé číslo tedy zabere nejvýše +$d=1+\lfloor\log_B L\rfloor$ číslic; pokud bude kratší, doplníme ho zleva nulami. + +Nejvyšší patro struktury bude tvořeno polem $B$~přihrádek, v~$i$-té z~nich +budou uložena ta čísla, jejichž číslice nejvyššího řádu je rovna~$i$. Za~{\I aktivní} +prohlásíme tu přihrádku, která obsahuje aktuální minimum. Přihrádky s~menšími +indexy jsou prázdné a zůstanou takové až do~konce výpočtu, protože halda +je monotónní. Pokud v~přihrádce obsahující minimum bude více prvků, budeme +ji rozkládat podle druhého nejvyššího řádu na dalších~$B$ přihrádek atd. +Celkem tak vznikne až~$d$ úrovní. + +\>Struktura bude obsahovat následující data: \itemize\ibull \:Parametry $L$, $B$ a~$d$. -\:Pole ĂşrovnĂ­ (nejvyĹĄĹĄĂ­ mĂĄ číslo~$d-1$, nejniŞťí~0), kaĹždĂĄ Ăşroveň je buďto prĂĄzdnĂĄ - (a pak jsou prĂĄzdnĂŠ i~vĹĄechny niŞťí), nebo obsahuje pole~$U_i$ o~$B$ přihrĂĄdkĂĄch - a v~kaĹždĂŠ z~nich seznam prvkĹŻ. Pole ĂşrovnĂ­ pouŞívĂĄme jako zĂĄsobnĂ­k, udrĹžujeme - si číslo nejniŞťí neprĂĄzdnĂŠ Ăşrovně. -\:Hodnotu~$\mu$ předchozĂ­ho odebranĂŠho minima. +\:Pole úrovní (nejvyšší má číslo~$d-1$, nejnižší~0), každá úroveň je buďto prázdná + (a pak jsou prázdné i~všechny nižší), nebo obsahuje pole~$U_i$ o~$B$ přihrádkách + a v~každé z~nich seznam prvků. Pole úrovní používáme jako zásobník, udržujeme + si číslo nejnižší neprázdné úrovně. +\:Hodnotu~$\mu$ předchozího odebraného minima. \endlist -Operace \ vloŞí hodnotu do~nejhlubĹĄĂ­ moĹžnĂŠ přihrĂĄdky. PodĂ­vĂĄ se tedy -na~nejvyĹĄĹĄĂ­ Ăşroveň: pokud hodnota patří do přihrĂĄdky, kterĂĄ nenĂ­ aktivnĂ­, vloŞí -ji přímo. Jinak přejde o~Ăşroveň nĂ­Ĺže a zopakuje stejnĂ˝ postup. To vĹĄe lze provĂŠst -v~konstantnĂ­m čase: stačí se podĂ­vat, jakĂ˝ je nejvyĹĄĹĄĂ­ jedničkovĂ˝ bit ve~{\sc xor}u -novĂŠ hodnoty s~číslem~$\mu$ (opět viz kapitola o~vĂ˝početnĂ­ch modelech), a tĂ­m zjistit -číslo Ăşrovně, kam hodnota patří. +Operace \ vloží hodnotu do~nejhlubší možné přihrádky. Podívá se tedy +na~nejvyšší úroveň: pokud hodnota patří do přihrádky, která není aktivní, vloží +ji přímo. Jinak přejde o~úroveň níže a zopakuje stejný postup. To vše lze provést +v~konstantním čase: stačí se podívat, jaký je nejvyšší jedničkový bit ve~{\sc xor}u +nové hodnoty s~číslem~$\mu$ (opět viz kapitola o~výpočetních modelech), a tím zjistit +číslo úrovně, kam hodnota patří. -Pokud chceme provĂŠst \, odstranĂ­me hodnotu z~přihrĂĄdky, ve~kterĂŠ se -prĂĄvě nachĂĄzĂ­ (polohu si mĹŻĹžeme u~kaĹždĂŠ hodnoty pamatovat zvlĂĄĹĄĹĽ), a znovu ji -vloŞíme. +Pokud chceme provést \, odstraníme hodnotu z~přihrádky, ve~které se +právě nachází (polohu si můžeme u~každé hodnoty pamatovat zvlášť), a znovu ji +vložíme. -VětĹĄinu prĂĄce samozřejmě přenechĂĄme funkci \. Ta začne prohledĂĄvat -nejniŞťí obsazenou Ăşroveň od~aktivnĂ­ přihrĂĄdky dĂĄl (to, kterĂĄ přihrĂĄdka je na -kterĂŠ Ăşrovni aktivnĂ­, poznĂĄme z~číslic hodnoty~$\mu$). Pokud přihrĂĄdky na~tĂŠto -Ăşrovni dojdou, prĂĄzdnou Ăşroveň zruĹĄĂ­me a pokračujeme o~patro výťe. +Většinu práce samozřejmě přenecháme funkci \. Ta začne prohledávat +nejnižší obsazenou úroveň od~aktivní přihrádky dál (to, která přihrádka je na +které úrovni aktivní, poznáme z~číslic hodnoty~$\mu$). Pokud přihrádky na~této +úrovni dojdou, prázdnou úroveň zrušíme a pokračujeme o~patro výše. -Jakmile najdeme neprĂĄzdnou přihrĂĄdku, nalezneme v~nĂ­ minimum a to se stane novĂ˝m~$\mu$. -Pokud v~přihrĂĄdce nebyly ŞådnĂŠ dalĹĄĂ­ prvky, skončíme. V~opačnĂŠm případě zbĂ˝vajĂ­cĂ­ -prvky rozprostřeme do~přihrĂĄdek na~bezprostředně niŞťí Ăşrovni, kterou tĂ­m zaloŞíme. +Jakmile najdeme neprázdnou přihrádku, nalezneme v~ní minimum a to se stane novým~$\mu$. +Pokud v~přihrádce nebyly žádné další prvky, skončíme. V~opačném případě zbývající +prvky rozprostřeme do~přihrádek na~bezprostředně nižší úrovni, kterou tím založíme. -Čas strĂĄvenĂ˝ hledĂĄnĂ­m minima mĹŻĹžeme rozdělit na~několik částĂ­: +Čas strávený hledáním minima můžeme rozdělit na~několik částí: \itemize\ibull -\:$\O(B)$ na inicializaci novĂŠ Ăşrovně -- to naúčtujeme prvku, kterĂ˝ jsme - prĂĄvě mazali; -\:hledĂĄnĂ­ neprĂĄzdnĂ˝ch přihrĂĄdek -- prozkoumĂĄnĂ­ kaĹždĂŠ prĂĄzdnĂŠ přihrĂĄdky - naúčtujeme jejĂ­mu vytvořenĂ­, coĹž se rozpustĂ­ v~$\O(B)$ na inicializaci - Ăşrovně; -\:zruĹĄenĂ­ Ăşrovně -- opět naúčtujeme jejĂ­mu vzniku; -\:rozhazovĂĄnĂ­ prvkĹŻ do přihrĂĄdek -- jelikoĹž prvky v~hierarchii přihrĂĄdek - putujĂ­ během operacĂ­ pouze doleva a dolĹŻ (jejich hodnoty se nikdy nezvětĹĄujĂ­), - klesne kaĹždĂ˝ prvek nejvýťe~$d$-krĂĄt, takĹže stačí, kdyĹž na vĹĄechna rozhazovĂĄnĂ­ - přispěje časem $\O(d)$. +\:$\O(B)$ na inicializaci nové úrovně -- to naúčtujeme prvku, který jsme + právě mazali; +\:hledání neprázdných přihrádek -- prozkoumání každé prázdné přihrádky + naúčtujeme jejímu vytvoření, což se rozpustí v~$\O(B)$ na inicializaci + úrovně; +\:zrušení úrovně -- opět naúčtujeme jejímu vzniku; +\:rozhazování prvků do přihrádek -- jelikož prvky v~hierarchii přihrádek + putují během operací pouze doleva a dolů (jejich hodnoty se nikdy nezvětšují), + klesne každý prvek nejvýše~$d$-krát, takže stačí, když na všechna rozhazování + přispěje časem $\O(d)$. \endlist -\>Stačí tedy, aby kaĹždĂ˝ prvek při \u zaplatil čas $\O(B+d)$ a jak \, -tak \ budou mĂ­t konstantnĂ­ amortizovanou sloĹžitost. DijkstrĹŻv -algoritmus pak poběží v~$\O(m + n(B+d))$. +\>Stačí tedy, aby každý prvek při \u zaplatil čas $\O(B+d)$ a jak \, +tak \ budou mít konstantní amortizovanou složitost. Dijkstrův +algoritmus pak poběží v~$\O(m + n(B+d))$. -ZbĂ˝vĂĄ nastavit parametry tak, abychom minimalizovali vĂ˝raz $B+d = B + \log L/\log B$. -VhodnĂĄ volba je $B=\log L/\log\log L$. Při nĂ­ platĂ­ +Zbývá nastavit parametry tak, abychom minimalizovali výraz $B+d = B + \log L/\log B$. +Vhodná volba je $B=\log L/\log\log L$. Při ní platí $$ {\log L\over\log B} = {\log L \over \log\left(\log L/\log\log L\right) } = {\log L\over \log\log L - \log\log\log L} = \Theta(B). $$ -Tehdy Dijkstra vydĂĄ vĂ˝sledek v~čase $\O(m + n\cdot{\log L\over\log\log L})$. - -\h{HOT Queue -- kombinace přihrĂĄdek s~haldou} - -Cherkassky, Goldberg a Silverstein \cite{cherkassky:hotq} si vĹĄimli, Ĺže ve~vĂ­ceĂşrovňovĂ˝ch přihrĂĄdkovĂ˝ch strukturĂĄch -platĂ­me příliĹĄ mnoho za~Ăşrovně, ve~kterĂ˝ch se za~dobu jejich existence objevĂ­ jen malĂŠ -mnoĹžstvĂ­ prvkĹŻ. Navrhli tedy uklĂĄdat prvky z~\uv{malĂ˝ch} ĂşrovnĂ­ do~společnĂŠ haldy. -VĂ˝slednĂŠ struktuře se říkĂĄ HOT (Heap-on-Top) Queue. My si předvedeme jejĂ­ upravenou -variantu (v~tĂŠ pĹŻvodnĂ­ se skrĂ˝vĂĄ několik chyb). - -PořídĂ­me si haldu, řekněme Fibonacciho, a~navĂ­c ke~kaĹždĂŠ Ăşrovni počítadlo udĂĄvajĂ­cĂ­, -kolik prvkĹŻ z~tĂŠto Ăşrovně jsme uloĹžili do~haldy. Dokud toto počítadlo nepřeroste nějakĂ˝ -parametr~$H$, přihrĂĄdky nebudeme zaklĂĄdat a prvky poputujĂ­ do~haldy. Čas $\O(B)$ na -zaloĹženĂ­ Ăşrovně a jejĂ­ prochĂĄzenĂ­ proto mĹŻĹžeme rozpočítat mezi~$H$ prvkĹŻ, kterĂŠ se musely -na~danĂŠ Ăşrovni objevit, neĹž byla rozpřihrĂĄdkovĂĄna. (PovĹĄimněte si, Ĺže počítadlo nikdy -nesniĹžujeme, pouze ho vynulujeme, kdyĹž je Ăşroveň zruĹĄena. Proto vĹŻbec nemusĂ­ odpovĂ­dat -skutečnĂŠmu počtu prvkĹŻ z~přísluĹĄnĂŠ Ăşrovně, kterĂŠ jsou prĂĄvě uloĹženy v~haldě. To ovĹĄem -vĹŻbec nevadĂ­ -- počítadlo pouze hlĂ­dĂĄ, aby se Ăşroveň nevytvořila příliĹĄ brzy, tedy abychom -měli dost prvkĹŻ k~rozúčtovĂĄnĂ­ času.) - -Proměnnou~$\mu$ nechĂĄme ukazovat na~mĂ­sto, kde jsme se při hledĂĄnĂ­ minima v~přihrĂĄdkĂĄch -zastavili. SoučasnĂŠ globĂĄlnĂ­ minimum struktury mĹŻĹže bĂ˝t niŞťí, nachĂĄzĂ­-li se minimum -zrovna v~haldě. StĂĄle je vĹĄak zaručeno, Ĺže před~$\mu$ se nenachĂĄzĂ­ ŞådnĂĄ -neprĂĄzdnĂĄ přihrĂĄdka. +Tehdy Dijkstra vydá výsledek v~čase $\O(m + n\cdot{\log L\over\log\log L})$. + +\h{HOT Queue -- kombinace přihrádek s~haldou} + +Cherkassky, Goldberg a Silverstein \cite{cherkassky:hotq} si všimli, že ve~víceúrovňových přihrádkových strukturách +platíme příliš mnoho za~úrovně, ve~kterých se za~dobu jejich existence objeví jen malé +množství prvků. Navrhli tedy ukládat prvky z~\uv{malých} úrovní do~společné haldy. +Výsledné struktuře se říká HOT (Heap-on-Top) Queue. My si předvedeme její upravenou +variantu (v~té původní se skrývá několik chyb). + +Pořídíme si haldu, řekněme Fibonacciho, a~navíc ke~každé úrovni počítadlo udávající, +kolik prvků z~této úrovně jsme uložili do~haldy. Dokud toto počítadlo nepřeroste nějaký +parametr~$H$, přihrádky nebudeme zakládat a prvky poputují do~haldy. Čas $\O(B)$ na +založení úrovně a její procházení proto můžeme rozpočítat mezi~$H$ prvků, které se musely +na~dané úrovni objevit, než byla rozpřihrádkována. (Povšimněte si, že počítadlo nikdy +nesnižujeme, pouze ho vynulujeme, když je úroveň zrušena. Proto vůbec nemusí odpovídat +skutečnému počtu prvků z~příslušné úrovně, které jsou právě uloženy v~haldě. To ovšem +vůbec nevadí -- počítadlo pouze hlídá, aby se úroveň nevytvořila příliš brzy, tedy abychom +měli dost prvků k~rozúčtování času.) + +Proměnnou~$\mu$ necháme ukazovat na~místo, kde jsme se při hledání minima v~přihrádkách +zastavili. Současné globální minimum struktury může být nižší, nachází-li se minimum +zrovna v~haldě. Stále je však zaručeno, že před~$\mu$ se nenachází žádná +neprázdná přihrádka. Operace budou fungovat takto: \>\: \algo -\:SpočítĂĄme, do~kterĂŠ Ăşrovně~$i$ mĂĄ prvek padnout (bitovĂ˝mi operacemi). -\:Pokud je počítadlo tĂŠto Ăşrovně menĹĄĂ­ neĹž~$H$, zvýťíme ho, vloŞíme prvek do~haldy a skočíme. -\:Nebyly-li jeĹĄtě pro tuto Ăşroveň zaloĹženy přihrĂĄdky, vyrobĂ­me prĂĄzdnĂŠ. -\:VloŞíme prvek do~přísluĹĄnĂŠ přihrĂĄdky. +\:Spočítáme, do~které úrovně~$i$ má prvek padnout (bitovými operacemi). +\:Pokud je počítadlo této úrovně menší než~$H$, zvýšíme ho, vložíme prvek do~haldy a skočíme. +\:Nebyly-li ještě pro tuto úroveň založeny přihrádky, vyrobíme prázdné. +\:Vložíme prvek do~příslušné přihrádky. \endalgo \>\: \algo -\:Pokud se prvek nachĂĄzĂ­ v~haldě (to si u~kaĹždĂŠho prvku pamatujeme), provedeme - \ v~haldě a skončíme. -\:SmaĹžeme prvek z~jeho přihrĂĄdky a provedeme \ s~novou hodnotou. +\:Pokud se prvek nachází v~haldě (to si u~každého prvku pamatujeme), provedeme + \ v~haldě a skončíme. +\:Smažeme prvek z~jeho přihrádky a provedeme \ s~novou hodnotou. \endalgo \>\: \algo -\:Dokud je~$\mu$ menĹĄĂ­ neĹž aktuĂĄlnĂ­ minimum haldy, opakujeme: -\::Najdeme přihrĂĄdku odpovĂ­dajĂ­cĂ­ hodnotě~$\mu$. -\::Je-li tato přihrĂĄdka prĂĄzdnĂĄ, přejdeme na~dalĹĄĂ­ (upravĂ­me~$\mu$). Jsme-li na konci Ăşrovně, - zruĹĄĂ­me ji, vynulujeme jejĂ­ počítadlo a pokračujeme o~Ăşroveň výť. -\::NenĂ­-li prĂĄzdnĂĄ, rozprostřeme ji o~Ăşroveň nĂ­Ĺž (stejnĂ˝m zpĹŻsobem jako při \u, - takĹže prvnĂ­ch~$H$ prvkĹŻ vloŞíme do~haldy). -\:SmaĹžeme minimum z~haldy a vrĂĄtĂ­me ho jako vĂ˝sledek. +\:Dokud je~$\mu$ menší než aktuální minimum haldy, opakujeme: +\::Najdeme přihrádku odpovídající hodnotě~$\mu$. +\::Je-li tato přihrádka prázdná, přejdeme na~další (upravíme~$\mu$). Jsme-li na konci úrovně, + zrušíme ji, vynulujeme její počítadlo a pokračujeme o~úroveň výš. +\::Není-li prázdná, rozprostřeme ji o~úroveň níž (stejným způsobem jako při \u, + takže prvních~$H$ prvků vložíme do~haldy). +\:Smažeme minimum z~haldy a vrátíme ho jako výsledek. \endalgo -\>PustĂ­me se do~analĂ˝zy sloĹžitosti. Jako parametry si zvolĂ­me počet hladin~$d$ (takĹže -počet přihrĂĄdek~$B$ na jednĂŠ Ăşrovni je roven $L^{1/d}$) a \uv{haldovou konstantu}~$H$. +\>Pustíme se do~analýzy složitosti. Jako parametry si zvolíme počet hladin~$d$ (takže +počet přihrádek~$B$ na jedné úrovni je roven $L^{1/d}$) a \uv{haldovou konstantu}~$H$. -Nejprve si vĹĄimneme, Ĺže neĹž počítadlo nějakĂŠ Ăşrovně vynulujeme, jsou bezpečně -z~haldy pryč vĹĄechny prvky patřícĂ­ do~tĂŠto Ăşrovně. Celkem se tedy v~haldě -vyskytuje nejvýťe $\O(dH)$ prvkĹŻ. \ v~haldě proto trvĂĄ $\O(\log(dH))$, -ostatnĂ­ haldovĂŠ operace $\O(1)$. +Nejprve si všimneme, že než počítadlo nějaké úrovně vynulujeme, jsou bezpečně +z~haldy pryč všechny prvky patřící do~této úrovně. Celkem se tedy v~haldě +vyskytuje nejvýše $\O(dH)$ prvků. \ v~haldě proto trvá $\O(\log(dH))$, +ostatní haldové operace $\O(1)$. -NynĂ­ rozúčtujeme čas operacĂ­ mezi jednotlivĂŠ prvky (opět si vĹĄe předplatĂ­me -v~\u a ostatnĂ­ operace poběží v~amortizovaně konstantnĂ­m čase): +Nyní rozúčtujeme čas operací mezi jednotlivé prvky (opět si vše předplatíme +v~\u a ostatní operace poběží v~amortizovaně konstantním čase): \itemize\ibull -\:KaĹždĂ˝ prvek mĹŻĹže bĂ˝t nejvýťe jednou za~dobu svĂŠho Ĺživota vloĹžen do~haldy - a nejvýťe jednou z~nĂ­ vyjmut. Na~obojĂ­ dohromady přispěje $\O(\log dH)$. -\:Prvek se účastnĂ­ nejvýťe~$d$ přehozenĂ­ do~niŞťí Ăşrovně. Pokud byl přihozen - do~haldy, uĹž tam setrvĂĄ, jinak pokaĹždĂŠ zaplatĂ­ $\O(1)$ za~zařazenĂ­ do~přihrĂĄdky, +\:Každý prvek může být nejvýše jednou za~dobu svého života vložen do~haldy + a nejvýše jednou z~ní vyjmut. Na~obojí dohromady přispěje $\O(\log dH)$. +\:Prvek se účastní nejvýše~$d$ přehození do~nižší úrovně. Pokud byl přihozen + do~haldy, už tam setrvá, jinak pokaždé zaplatí $\O(1)$ za~zařazení do~přihrádky, celkem tedy $\O(d)$ na prvek. -\:VytvořenĂ­, projitĂ­ a smazĂĄnĂ­ přihrĂĄdek na~jednĂŠ Ăşrovni nastane aĹž tehdy, co bylo - $H$~prvkĹŻ patřícĂ­ch do~tĂŠto Ăşrovně vloĹženo do~haldy. Stačí tedy, aby kaĹždĂ˝ - prvek přispěl časem $\O(B/H) = \O(L^{1/d}/H)$. +\:Vytvoření, projití a smazání přihrádek na~jedné úrovni nastane až tehdy, co bylo + $H$~prvků patřících do~této úrovně vloženo do~haldy. Stačí tedy, aby každý + prvek přispěl časem $\O(B/H) = \O(L^{1/d}/H)$. \endlist -\>KaĹždĂ˝ prvek tedy platĂ­ $\O(d + \log dH + L^{1/d}/H) = \O(d + \log H + L^{1/d}/H)$. -Pojďme najĂ­t nastavenĂ­ parametrĹŻ, kterĂŠ tento vĂ˝raz minimalizuje. +\>Každý prvek tedy platí $\O(d + \log dH + L^{1/d}/H) = \O(d + \log H + L^{1/d}/H)$. +Pojďme najít nastavení parametrů, které tento výraz minimalizuje. Nejprve zvolme~$H$ tak, aby se~$d$ vyrovnalo s~$L^{1/d}/H$. Tedy $H = L^{1/d}/d$. -CelĂ˝ vĂ˝raz tĂ­m zjednoduĹĄĂ­me na $\O(d + \log\,(L^{1/d}/d))$ = -$\O(d + 1/d\cdot\log L - \log d) = \O(d + 1/d\cdot\log L)$. Oba sčítance volbou -$d=\sqrt{\log L}$ vyrovnĂĄme. +Celý výraz tím zjednodušíme na $\O(d + \log\,(L^{1/d}/d))$ = +$\O(d + 1/d\cdot\log L - \log d) = \O(d + 1/d\cdot\log L)$. Oba sčítance volbou +$d=\sqrt{\log L}$ vyrovnáme. -HOT Queue tedy zvlĂĄdne \ s~amortizovanou časovou sloĹžitostĂ­ $\O(\sqrt{\log L})$ -a ostatnĂ­ operace v~čase amortizovaně konstantnĂ­m. PouĹžijeme-li tuto strukturu -v~Dijkstrově algoritmu, spočte vzdĂĄlenosti v~čase $\O(m + n\sqrt{\log L})$. +HOT Queue tedy zvládne \ s~amortizovanou časovou složitostí $\O(\sqrt{\log L})$ +a ostatní operace v~čase amortizovaně konstantním. Použijeme-li tuto strukturu +v~Dijkstrově algoritmu, spočte vzdálenosti v~čase $\O(m + n\sqrt{\log L})$. -\h{DinicĹŻv algoritmus} +\h{Dinicův algoritmus} -ZajĂ­mavĂŠ vylepĹĄenĂ­ Dijkstrova algoritmu navrhl Dinic. VĹĄiml si, Ĺže pokud -je kaĹždĂĄ hrana dlouhĂĄ alespoň~$\delta$, mĹŻĹžeme uzavĂ­rat nejen -vrchol s~minimĂĄlnĂ­m ohodnocenĂ­m~$\mu$, ale i vĹĄechny s~ohodnocenĂ­m -menĹĄĂ­m neĹž $\mu+\delta$. +Zajímavé vylepšení Dijkstrova algoritmu navrhl Dinic. Všiml si, že pokud +je každá hrana dlouhá alespoň~$\delta$, můžeme uzavírat nejen +vrchol s~minimálním ohodnocením~$\mu$, ale i všechny s~ohodnocením +menším než $\mu+\delta$. -Pro takto upravenĂ˝ DijkstrĹŻv algoritmus bude stĂĄle platit, Ĺže při uzavĂ­rĂĄnĂ­ -vrcholu odpovĂ­dĂĄ ohodnocenĂ­ skutečnĂŠ vzdĂĄlenosti, takĹže uzavřenĂŠ vrcholy jiĹž -nejsou znovu otevĂ­rĂĄny. +Pro takto upravený Dijkstrův algoritmus bude stále platit, že při uzavírání +vrcholu odpovídá ohodnocení skutečné vzdálenosti, takže uzavřené vrcholy již +nejsou znovu otevírány. -O~monotonii vzdĂĄlenostĂ­ jsme sice přiĹĄli, ale v~přihrĂĄdkovĂŠ struktuře nebo -haldě mĹŻĹžeme klíče nahradit hodnotami $h'(v) := \lfloor h(v)/\delta \rfloor$. -Tyto hodnoty se totiĹž chovajĂ­ monotĂłnně a vrcholy se stejnĂ˝m $h'(v)$ mĹŻĹžeme -libovolně zaměňovat. +O~monotonii vzdáleností jsme sice přišli, ale v~přihrádkové struktuře nebo +haldě můžeme klíče nahradit hodnotami $h'(v) := \lfloor h(v)/\delta \rfloor$. +Tyto hodnoty se totiž chovají monotónně a vrcholy se stejným $h'(v)$ můžeme +libovolně zaměňovat. -Kteroukoli z~popsanĂ˝ch přihrĂĄdkovĂ˝ch struktur mĹŻĹžeme tedy pouŞít, pouze -v~rozboru časovĂŠ sloĹžitosti nahradĂ­me~$L$ vĂ˝razem $L/\delta$. Tento přístup -přitom funguje i pro neceločíselnĂŠ dĂŠlky hran, pouze potřebujeme mĂ­t předem -k~dispozici netriviĂĄlnĂ­ dolnĂ­ odhad na~vĹĄechny dĂŠlky. +Kteroukoli z~popsaných přihrádkových struktur můžeme tedy použít, pouze +v~rozboru časové složitosti nahradíme~$L$ výrazem $L/\delta$. Tento přístup +přitom funguje i pro neceločíselné délky hran, pouze potřebujeme mít předem +k~dispozici netriviální dolní odhad na~všechny délky. -\h{PotenciĂĄly} +\h{Potenciály} -Viděli jsme, Ĺže v~grafech s~nezĂĄpornĂ˝mi dĂŠlkami hran se nejkratĹĄĂ­ cesty -hledajĂ­ snĂĄze. NabĂ­zĂ­ se nalĂŠzt nějakou transformaci, kterĂĄ by -dovedla dĂŠlky hran upravit tak, aby byly nejkratĹĄĂ­ cesty zachovĂĄny (samozřejmě -ne jejich dĂŠlky, ale alespoň to, kterĂŠ cesty jsou nejkratĹĄĂ­). NabĂ­zĂ­ se -nĂĄsledujĂ­cĂ­ fyzikĂĄlnĂ­ inspirace: +Viděli jsme, že v~grafech s~nezápornými délkami hran se nejkratší cesty +hledají snáze. Nabízí se nalézt nějakou transformaci, která by +dovedla délky hran upravit tak, aby byly nejkratší cesty zachovány (samozřejmě +ne jejich délky, ale alespoň to, které cesty jsou nejkratší). Nabízí se +následující fyzikální inspirace: -\s{Definice:} {\I PotenciĂĄl} budeme říkat libovolnĂŠ funkci $\psi: V\rightarrow {\bb R}$. -Pro kaĹždĂ˝ potenciĂĄl zavedeme {\I redukovanĂŠ dĂŠlky hran} $\ell_\psi(u,v) := \ell(u,v) + \psi(u) - \psi(v)$. -PotenciĂĄl nazveme {\I přípustnĂ˝,} pokud ŞådnĂĄ hrana nemĂĄ zĂĄpornou redukovanou dĂŠlku. +\s{Definice:} {\I Potenciál} budeme říkat libovolné funkci $\psi: V\rightarrow {\bb R}$. +Pro každý potenciál zavedeme {\I redukované délky hran} $\ell_\psi(u,v) := \ell(u,v) + \psi(u) - \psi(v)$. +Potenciál nazveme {\I přípustný,} pokud žádná hrana nemá zápornou redukovanou délku. -\s{PozorovĂĄnĂ­:} Pro redukovanou dĂŠlku libovolnĂŠ cesty~$P$ z~$u$ do~$v$ platĂ­: $\ell_\psi(P) = \ell(P) + \psi(u) - \psi(v)$. +\s{Pozorování:} Pro redukovanou délku libovolné cesty~$P$ z~$u$ do~$v$ platí: $\ell_\psi(P) = \ell(P) + \psi(u) - \psi(v)$. \proof -NechĹĽ cesta~$P$ prochĂĄzĂ­ přes vrcholy $u=w_1,\ldots,w_k=v$. Potom: +Nechť cesta~$P$ prochází přes vrcholy $u=w_1,\ldots,w_k=v$. Potom: $$ \ell_\psi(P) = \sum_i \ell_\psi(w_i,w_{i+1}) = \sum_i \left( \ell(w_i,w_{i+1}) + \psi(w_i) - \psi(w_{i+1}) \right). $$ -Tato suma je ovĹĄem teleskopickĂĄ, takĹže z~nĂ­ zbude +Tato suma je ovšem teleskopická, takže z~ní zbude $$ \sum_i\ell(w_i,w_{i+1}) + \psi(w_1) - \psi(w_k) = \ell(P) + \psi(u) - \psi(v). $$ \vskip-\baselineskip \qed -\s{DĹŻsledek:} PotenciĂĄlovou redukcĂ­ se dĂŠlky vĹĄech cest mezi~$u$ a~$v$ -změnĂ­ o~tutĂŠĹž konstantu, takĹže struktura nejkratĹĄĂ­ch cest zĹŻstane nezměněna. +\s{Důsledek:} Potenciálovou redukcí se délky všech cest mezi~$u$ a~$v$ +změní o~tutéž konstantu, takže struktura nejkratších cest zůstane nezměněna. -ZbĂ˝vĂĄ přijĂ­t na~to, kde si obstarat nějakĂ˝ přípustnĂ˝ potenciĂĄl. Přidejme do~grafu -novĂ˝ vrchol~$z$, přiveďme z~něj hrany nulovĂŠ dĂŠlky do~vĹĄech ostatnĂ­ch vrcholĹŻ -a~označme~$\psi(v)$ vzdĂĄlenost ze~$z$ do~$v$ v~tomto grafu. Aby byl tento potenciĂĄl -přípustnĂ˝, musĂ­ pro kaĹždou hranu $uv$ platit $\ell_\psi(u,v) = \ell(u,v) + \psi(u) - \psi(v) \ge 0$. -Tuto nerovnost mĹŻĹžeme upravit na $\ell(u,v) + d(z,u) - d(z,v) \ge 0$, čili -$d(z,u) + \ell(u,v) \ge d(z,v)$, coĹž je ale obyčejnĂĄ trojĂşhelnĂ­kovĂĄ nerovnost -pro vzdĂĄlenost v~grafu, kterĂĄ jistě platĂ­. +Zbývá přijít na~to, kde si obstarat nějaký přípustný potenciál. Přidejme do~grafu +nový vrchol~$z$, přiveďme z~něj hrany nulové délky do~všech ostatních vrcholů +a~označme~$\psi(v)$ vzdálenost ze~$z$ do~$v$ v~tomto grafu. Aby byl tento potenciál +přípustný, musí pro každou hranu $uv$ platit $\ell_\psi(u,v) = \ell(u,v) + \psi(u) - \psi(v) \ge 0$. +Tuto nerovnost můžeme upravit na $\ell(u,v) + d(z,u) - d(z,v) \ge 0$, čili +$d(z,u) + \ell(u,v) \ge d(z,v)$, což je ale obyčejná trojúhelníková nerovnost +pro vzdálenost v~grafu, která jistě platí. -JednĂ­m vĂ˝počtem nejkratĹĄĂ­ch cest v~grafu se zĂĄpornĂ˝mi hranami (třeba algoritmem BFM) -tedy dokĂĄĹžeme spočítat potenciĂĄl, kterĂ˝ nĂĄm poslouŞí k~redukci vĹĄech hran na~nezĂĄpornĂŠ -dĂŠlky. To nĂĄm samozřejmě nepomĹŻĹže, chceme-li jednorĂĄzově hledat nejkratĹĄĂ­ cestu, -ale mĹŻĹže nĂĄm to vĂ˝razně zjednoduĹĄit dalĹĄĂ­, sloĹžitějĹĄĂ­ prĂĄci s~grafem. Jak uvidĂ­me -v~příštĂ­ kapitole, mĹŻĹžeme tak například nalĂŠzt vzdĂĄlenosti mezi vĹĄemi dvojicemi -vrcholĹŻ v~čase $\O(nm + n^2\log n)$. +Jedním výpočtem nejkratších cest v~grafu se zápornými hranami (třeba algoritmem BFM) +tedy dokážeme spočítat potenciál, který nám poslouží k~redukci všech hran na~nezáporné +délky. To nám samozřejmě nepomůže, chceme-li jednorázově hledat nejkratší cestu, +ale může nám to výrazně zjednodušit další, složitější práci s~grafem. Jak uvidíme +v~příští kapitole, můžeme tak například nalézt vzdálenosti mezi všemi dvojicemi +vrcholů v~čase $\O(nm + n^2\log n)$. -Na~zĂĄvěr tohoto oddĂ­lu dokĂĄĹžeme jedno pomocnĂŠ tvrzenĂ­ o~potenciĂĄlech, kterĂŠ -nĂĄm pomĹŻĹže v~konstrukci algoritmĹŻ typu \ppsp: +Na~závěr tohoto oddílu dokážeme jedno pomocné tvrzení o~potenciálech, které +nám pomůže v~konstrukci algoritmů typu \ppsp: -\s{Lemma:} Pokud $f$ a~$g$ jsou přípustnĂŠ potenciĂĄly, pak jsou jimi i: +\s{Lemma:} Pokud $f$ a~$g$ jsou přípustné potenciály, pak jsou jimi i: \numlist\ndotted -\:konvexnĂ­ kombinace $f$ a~$g$, tedy $\alpha f + \beta g$ pro libovolnĂŠ $\alpha,\beta\ge 0, \alpha+\beta=1$; +\:konvexní kombinace $f$ a~$g$, tedy $\alpha f + \beta g$ pro libovolné $\alpha,\beta\ge 0, \alpha+\beta=1$; \:$\min(f,g)$; \:$\max(f,g)$. \endlist -\proof Buď $uv$ hrana. Potom z~definice přípustnosti platĂ­ $\ell(u,v) \ge f(v) - f(u)$ a $\ell(u,v) \ge g(v) - g(u)$. -JednotlivĂŠ části tvrzenĂ­ dokĂĄĹžeme takto: +\proof Buď $uv$ hrana. Potom z~definice přípustnosti platí $\ell(u,v) \ge f(v) - f(u)$ a $\ell(u,v) \ge g(v) - g(u)$. +Jednotlivé části tvrzení dokážeme takto: \numlist\ndotted -\:Pokud obě strany nerovnosti pro~$f$ vynĂĄsobĂ­me konstantou~$\alpha$, u~nerovnosti pro~$g$ - konstantou~$\beta$ a obě nerovnosti sečteme, dostaneme: +\:Pokud obě strany nerovnosti pro~$f$ vynásobíme konstantou~$\alpha$, u~nerovnosti pro~$g$ + konstantou~$\beta$ a obě nerovnosti sečteme, dostaneme: $$ (\alpha+\beta) \cdot \ell(u,v) \ge (\alpha f(v) + \beta g(v)) - (\alpha f(u) + \beta g(u)), $$ - coĹž je přesně poĹžadovanĂĄ nerovnost pro přípustnost funkce $\alpha f+\beta g$. -\:Označme $h := \min(f,g)$. NechĹĽ bez Ăşjmy na obecnosti $f(u)\le g(u)$. Pokud takĂŠ platĂ­ $f(v)\le g(v)$, - shoduje se minimum s~funkcĂ­~$f$ a nenĂ­ co dokazovat. V~opačnĂŠm případě je $h(u) = f(u)$, $h(v) = g(v)$. - Tehdy si stačí vĹĄimnout, Ĺže $h(v) - h(u) = g(v) - f(u) < f(v) - f(u) \le \ell(u,v)$, takĹže - potenciĂĄl~$h$ je přípustnĂ˝. -\:DokĂĄĹžeme analogicky. + což je přesně požadovaná nerovnost pro přípustnost funkce $\alpha f+\beta g$. +\:Označme $h := \min(f,g)$. Nechť bez újmy na obecnosti $f(u)\le g(u)$. Pokud také platí $f(v)\le g(v)$, + shoduje se minimum s~funkcí~$f$ a není co dokazovat. V~opačném případě je $h(u) = f(u)$, $h(v) = g(v)$. + Tehdy si stačí všimnout, že $h(v) - h(u) = g(v) - f(u) < f(v) - f(u) \le \ell(u,v)$, takže + potenciál~$h$ je přípustný. +\:Dokážeme analogicky. \qeditem \endlist -\h{Algoritmy pro problĂŠm typu \ppsp} - -Zaměřme se nynĂ­ na~případ, kdy chceme hledat nejkratĹĄĂ­ cesty mezi zadanou dvojicĂ­ -vrcholĹŻ $s$,~$t$. Obvykle se i v~tĂŠto situaci pouŞívajĂ­ algoritmy \sssp{} (SSSP) a v~obecnĂŠm -případě ani nenĂ­ efektivnějĹĄĂ­ řeĹĄenĂ­ znĂĄmo. Existuje ovĹĄem velkĂŠ mnoĹžstvĂ­ heuristik, kterĂ˝mi -lze obvykle vĂ˝počet zrychlit. NěkterĂŠ z~nich si předvedeme na Dijkstrově algoritmu. - -DijkstrĹŻv algoritmus ve~svĂŠ klasickĂŠ podobě nevĂ­ vĹŻbec nic o~cĂ­lovĂŠm vrcholu a -prohledĂĄ celĂ˝ graf. Hned se nabĂ­zĂ­ vyuŞít toho, Ĺže od~okamĹžiku uzavřenĂ­ -kterĂŠhokoliv vrcholu se jiĹž jeho ohodnocenĂ­ nezměnĂ­. Pokud tedy uzavřeme cĂ­lovĂ˝ -vrchol, mĹŻĹžeme se zastavit. - -Jakou část grafu prohledĂĄvĂĄme teď? V~metrice danĂŠ vzdĂĄlenostmi v~grafu je to nejmenĹĄĂ­ -koule se středem ve~vrcholu~$u$, kterĂĄ obsahuje nejkratĹĄĂ­ cestu (dobře se to -představuje na~hledĂĄnĂ­ v~silničnĂ­ sĂ­ti na~rovinnĂŠ mapě). - -TakĂŠ mĹŻĹžeme spustit prohledĂĄvĂĄnĂ­ z~obou koncĹŻ zĂĄroveň, tedy zkombinovat hledĂĄnĂ­ -od~$s$ v~pĹŻvodnĂ­m grafu s~hledĂĄnĂ­m od~$t$ v~grafu s~obrĂĄcenou orientacĂ­ hran. -Oba postupy mĹŻĹžeme libovolně střídat a zastavĂ­me se v~okamĹžiku, kdy jsme jeden -vrchol uzavřeli v~obou směrech. Pozor ovĹĄem na to, Ĺže součet obou ohodnocenĂ­ -tohoto vrcholu nemusĂ­ bĂ˝t roven $d(v,u)$ -- zkuste vymyslet protipříklad. -NejkratĹĄĂ­ cesta jeĹĄtě mĹŻĹže vypadat tak, Ĺže přechĂĄzĂ­ po nějakĂŠ hraně mezi vrcholem -uzavřenĂ˝m v~jednom směru a vrcholem uzavřenĂ˝m ve~směru druhĂŠm (ponechme bez dĹŻkazu). -Stačí tedy během relaxace zjistit, zda je konec hrany uzavřenĂ˝ v~opačnĂŠm -směru prohledĂĄvĂĄnĂ­, a~pokud ano, započítat cestu do~prĹŻběžnĂŠho minima. - -ObousměrnĂ˝ DijkstrĹŻv algoritmus projde sjednocenĂ­ nějakĂŠ koule okolo~$s$ s~nějakou -koulĂ­ okolo~$t$, kterĂŠ obsahuje nejkratĹĄĂ­ cestu. PrĹŻměry koulĂ­ přitom zĂĄvisĂ­ na tom, -jak budeme během vĂ˝počtu střídat oba směry prohledĂĄvĂĄnĂ­. V~nejhorĹĄĂ­m případě samozřejmě -mĹŻĹžeme prohledat celĂ˝ graf. +\h{Algoritmy pro problém typu \ppsp} + +Zaměřme se nyní na~případ, kdy chceme hledat nejkratší cesty mezi zadanou dvojicí +vrcholů $s$,~$t$. Obvykle se i v~této situaci používají algoritmy \sssp{} (SSSP) a v~obecném +případě ani není efektivnější řešení známo. Existuje ovšem velké množství heuristik, kterými +lze obvykle výpočet zrychlit. Některé z~nich si předvedeme na Dijkstrově algoritmu. + +Dijkstrův algoritmus ve~své klasické podobě neví vůbec nic o~cílovém vrcholu a +prohledá celý graf. Hned se nabízí využít toho, že od~okamžiku uzavření +kteréhokoliv vrcholu se již jeho ohodnocení nezmění. Pokud tedy uzavřeme cílový +vrchol, můžeme se zastavit. + +Jakou část grafu prohledáváme teď? V~metrice dané vzdálenostmi v~grafu je to nejmenší +koule se středem ve~vrcholu~$u$, která obsahuje nejkratší cestu (dobře se to +představuje na~hledání v~silniční síti na~rovinné mapě). + +Také můžeme spustit prohledávání z~obou konců zároveň, tedy zkombinovat hledání +od~$s$ v~původním grafu s~hledáním od~$t$ v~grafu s~obrácenou orientací hran. +Oba postupy můžeme libovolně střídat a zastavíme se v~okamžiku, kdy jsme jeden +vrchol uzavřeli v~obou směrech. Pozor ovšem na to, že součet obou ohodnocení +tohoto vrcholu nemusí být roven $d(v,u)$ -- zkuste vymyslet protipříklad. +Nejkratší cesta ještě může vypadat tak, že přechází po nějaké hraně mezi vrcholem +uzavřeným v~jednom směru a vrcholem uzavřeným ve~směru druhém (ponechme bez důkazu). +Stačí tedy během relaxace zjistit, zda je konec hrany uzavřený v~opačném +směru prohledávání, a~pokud ano, započítat cestu do~průběžného minima. + +Obousměrný Dijkstrův algoritmus projde sjednocení nějaké koule okolo~$s$ s~nějakou +koulí okolo~$t$, které obsahuje nejkratší cestu. Průměry koulí přitom závisí na tom, +jak budeme během výpočtu střídat oba směry prohledávání. V~nejhorším případě samozřejmě +můžeme prohledat celý graf. \h{Algoritmus \astar} -V~umělĂŠ inteligenci se často pro hledĂĄnĂ­ nejkratĹĄĂ­ cesty v~rozsĂĄhlĂ˝ch grafech -(obvykle stavovĂ˝ch prostorech Ăşloh) pouŞívĂĄ algoritmus nazĂ˝vanĂ˝~\astar{} \cite{hart:astar}. -JednĂĄ se o~modifikaci Dijkstrova algoritmu, kterĂĄ vyuŞívĂĄ heuristickou funkci -pro dolnĂ­ odhad vzdĂĄlenosti do~cĂ­le; označme si ji $\psi(v)$. V~kaĹždĂŠm kroku pak uzavĂ­ra -vrchol~$v$ s~nejmenĹĄĂ­m moĹžnĂ˝m součtem $h(v)+\psi(v)$ aktuĂĄlnĂ­ho ohodnocenĂ­ s~heuristikou. +V~umělé inteligenci se často pro hledání nejkratší cesty v~rozsáhlých grafech +(obvykle stavových prostorech úloh) používá algoritmus nazývaný~\astar{} \cite{hart:astar}. +Jedná se o~modifikaci Dijkstrova algoritmu, která využívá heuristickou funkci +pro dolní odhad vzdálenosti do~cíle; označme si ji $\psi(v)$. V~každém kroku pak uzavíra +vrchol~$v$ s~nejmenším možným součtem $h(v)+\psi(v)$ aktuálního ohodnocení s~heuristikou. -Intuice za tĂ­mto algoritmem je jasnĂĄ: pokud vĂ­me, Ĺže nějakĂ˝ vrchol je blĂ­zko -od~počátačnĂ­ho vrcholu~$s$, ale bude z~něj určitě daleko do cĂ­le~$t$, zatĂ­m ho -odloŞíme a budeme zkoumat nadějnějĹĄĂ­ varianty. +Intuice za tímto algoritmem je jasná: pokud víme, že nějaký vrchol je blízko +od~počátačního vrcholu~$s$, ale bude z~něj určitě daleko do cíle~$t$, zatím ho +odložíme a budeme zkoumat nadějnější varianty. -Heuristika se přitom volĂ­ podle konkrĂŠtnĂ­ho problĂŠmu -- např. hledĂĄme-li cestu -v~mapě, mĹŻĹžeme pouŞít vzdĂĄlenost do~cĂ­le vzduĹĄnou čarou. +Heuristika se přitom volí podle konkrétního problému -- např. hledáme-li cestu +v~mapě, můžeme použít vzdálenost do~cíle vzdušnou čarou. -Je u~tohoto algoritmu zaručeno, Ĺže vĹždy najde nejkratĹĄĂ­ cestu? Na to nĂĄm dĂĄ odpověď -teorie potenciĂĄlĹŻ: +Je u~tohoto algoritmu zaručeno, že vždy najde nejkratší cestu? Na to nám dá odpověď +teorie potenciálů: -\s{Věta:} Běh algoritmu \astar{} odpovĂ­dĂĄ prĹŻběhu Dijkstrova algoritmu -na~grafu redukovanĂŠm potenciĂĄlem~$-\psi$. Přesněji, -pokud označíme $h^*$ aktuĂĄlnĂ­ ohodnocenĂ­ v~\astar{} a $h$ aktuĂĄlnĂ­ ohodnocenĂ­ -v~synchronně běžícĂ­m Dijkstrovi, bude vĹždy platit $h(v) = h^*(v) - \psi(s) + \psi(v)$. +\s{Věta:} Běh algoritmu \astar{} odpovídá průběhu Dijkstrova algoritmu +na~grafu redukovaném potenciálem~$-\psi$. Přesněji, +pokud označíme $h^*$ aktuální ohodnocení v~\astar{} a $h$ aktuální ohodnocení +v~synchronně běžícím Dijkstrovi, bude vždy platit $h(v) = h^*(v) - \psi(s) + \psi(v)$. \proof -IndukcĂ­ podle doby běhu obou algoritmĹŻ. Na počátku je $h^*(s)$ i $h(s)$ nulovĂŠ -a vĹĄechna ostatnĂ­ $h^*$ a~$h$ jsou nekonečnĂĄ, takĹže tvrzenĂ­ platĂ­. V~kaĹždĂŠm dalĹĄĂ­m -kroku \astar{} vybere vrchol~$v$ s~nejmenĹĄĂ­m $h^*(v) + \psi(v)$, coĹž je tentýŞ vrchol, -kterĂ˝ vybere Dijkstra ($\psi(s)$ je stĂĄle stejnĂŠ). - -UvaĹžujme, co se stane během relaxace hrany $vw$: Dijkstra se pokusĂ­ snĂ­Ĺžit ohodnocenĂ­ $h(w)$ -o~$\delta = h(w) - h(v) - \ell_{-\psi}(v,w)$ a provede to, pokud $\delta>0$. UkĂĄĹžeme, -Ĺže \astar{} udělĂĄ totĂŠĹž: +Indukcí podle doby běhu obou algoritmů. Na počátku je $h^*(s)$ i $h(s)$ nulové +a všechna ostatní $h^*$ a~$h$ jsou nekonečná, takže tvrzení platí. V~každém dalším +kroku \astar{} vybere vrchol~$v$ s~nejmenším $h^*(v) + \psi(v)$, což je tentýž vrchol, +který vybere Dijkstra ($\psi(s)$ je stále stejné). + +Uvažujme, co se stane během relaxace hrany $vw$: Dijkstra se pokusí snížit ohodnocení $h(w)$ +o~$\delta = h(w) - h(v) - \ell_{-\psi}(v,w)$ a provede to, pokud $\delta>0$. Ukážeme, +že \astar{} udělá totéž: $$\eqalign{ \delta &= (h^*(w) - \psi(s) + \psi(w)) - (h^*(v) - \psi(s) + \psi(v)) - (\ell(v,w) - \psi(v) + \psi(w)) \cr &= h^*(w) - \psi(s) + \psi(w) - h^*(v) + \psi(s) - \psi(v) - \ell(v,w) + \psi(v) - \psi(w) \cr &= h^*(w) - h^*(v) - \ell(v,w). }$$ -Oba algoritmy tedy aĹž na~posunutĂ­ danĂŠ potenciĂĄlem počítajĂ­ totĂŠĹž. +Oba algoritmy tedy až na~posunutí dané potenciálem počítají totéž. \qed -\s{DĹŻsledek:} Algoritmus \astar{} funguje jen tehdy, je-li potenciĂĄl $-\psi$ přípustnĂ˝. +\s{Důsledek:} Algoritmus \astar{} funguje jen tehdy, je-li potenciál $-\psi$ přípustný. -Například pro rovinnou mapu to heuristika danĂĄ euklidovskou vzdĂĄlenostĂ­~$\varrho$, tedy $\psi(v) := \varrho(v,t)$, splňuje: -Přípustnost poĹžaduje pro kaĹždou hranu $uv$ nerovnost +Například pro rovinnou mapu to heuristika daná euklidovskou vzdáleností~$\varrho$, tedy $\psi(v) := \varrho(v,t)$, splňuje: +Přípustnost požaduje pro každou hranu $uv$ nerovnost $\ell(u,v) - \psi(v) + \psi(u) \ge 0$, tedy $\ell(u,v) - \varrho(v,t) + \varrho(u,t) \ge 0$. -JelikoĹž $\ell(u,v) \ge \varrho(u,v)$, -stačí dokĂĄzat, Ĺže $\varrho(u,v) - \varrho(v,t) + \varrho(u,t) \ge 0$, -coĹž je ovĹĄem trojĂşhelnĂ­kovĂĄ nerovnost pro metriku~$\varrho$. +Jelikož $\ell(u,v) \ge \varrho(u,v)$, +stačí dokázat, že $\varrho(u,v) - \varrho(v,t) + \varrho(u,t) \ge 0$, +což je ovšem trojúhelníková nerovnost pro metriku~$\varrho$. \references \bye -- 2.39.5