NEJKRATŠÍ CESTY I Doc. RNDr. Josef Kolář, CSc. Katedra teoretické informatiky, FIT České vysoké učení technické v Praze BI-GRA, LS 2010/2011, Lekce 7 Evropský sociální fond Praha & EU: Investujeme do vaší budoucnosti Doc. Josef Kolář (ČVUT) Prohledávání Nejkratší cesty grafů GRA, LS 2010/11, Lekce 4 7 1 / 17 15 18
Nejkratší cesty z jednoho uzlu Seznámíme se s následujícími pojmy: w-vzdálenost (vzdálenost na ohodnoceném grafu) relaxace, strom nejkratších cest Dijkstrův algoritmus Bellman-Fordův algoritmus Skripta kap. 6, str. 110 122 Doc. Josef Kolář (ČVUT) Prohledávání Nejkratší cesty grafů GRA, LS 2010/11, Lekce 47 2 / 15 18
Několik obecných úvah Uvažujeme nejobecnější případ - ohodnocené OG: w-délka spojení h 1, h 2,..., h k = Σ w(h i ) w-vzdálenost d w (u,v) = w-délka nejkratšího spojení nebo + nedostupné uzly - vzdálenost + < 0 spojení obsahující záporný cykl vzdálenost - počítání s nekonečny: a + (- ) = (- ) + a = - pro a a + = + a = pro a - Doc. Josef Kolář (ČVUT) Prohledávání Nejkratší cesty grafů GRA, LS 2010/11, Lekce 47 3 / 15 18
Několik obecných úvah Uvažujeme nejobecnější případ - ohodnocené OG: w-délka spojení h 1, h 2,..., h k = Σ w(h i ) w-vzdálenost d w (u,v) = w-délka nejkratšího spojení nebo + (0) d(u,v) je nezáporné celé číslo nedostupné uzly - vzdálenost + (1) d(u,v) 0, přičemž d(u,v)=0, právě když u=v (2) d(u,v) = d(v,u) spojení se záporným (3) d(u,v) cyklem d(u,z) + d(z,v) vzdálenost - (4) je-li d(u,v)>1, pak z: z u,v: d(u,v) = d(u,z) + d(z,v) < 0 < 0 počítání s nekonečny: a + (- ) = (- ) + a = - pro a a + = + a = pro a -? Které z vlastností 0 až 4 má takováto vzdálenost? Doc. Josef Kolář (ČVUT) Prohledávání Nejkratší cesty grafů GRA, LS 2010/11, Lekce 47 4 / 15 18
Varianty úlohy hledání nejkratších cest 1 1 1 n n 1 n n Důležité zjištění: Pro libovolnou hranu (u,v) H a uzel s U platí d w (s,v) d w (s,u) + w(u,v) d w (s,v) v s d w (s,u) u w(u,v)! Platí pro konečné i nekonečné hodnoty w-vzdáleností! Doc. Josef Kolář (ČVUT) Prohledávání Nejkratší cesty grafů GRA, LS 2010/11, Lekce 47 5 / 15 18
Implementace hledání 1 n Datové struktury: d[u]... w-délka (dosud nalezené) minimální cesty p[u]... předchůdce na (dosud nalezené) minimální cestě Q... množina otevřených uzlů (prioritní fronta?) Společné operace pro základní varianty algoritmů: void InitPaths(Graph G, Node s) { // inicializace 1 for (Node u in U(G)) 2 { d[u] = + ; p[u] = null; } 3 d[s] = 0; } void Relax (Node u, Node v, Weights w) { 1 newval = d[u]+w(u,v); 2 if (d[v] > newval) // příp.úprava délky cesty 3 { d[v] = newval; p[v] = u; } } Doc. Josef Kolář (ČVUT) Prohledávání Nejkratší cesty grafů GRA, LS 2010/11, Lekce 47 6 / 15 18
Implementace hledání 1 n V: Předpokládejme, že pro nějaký graf provedeme operaci InitPaths a pak libovolný počet operací Relax. Potom platí d[u] d w (s,u) jakmile d[u] dosáhne hodnoty d w (s,u), už se nemění jakmile se žádné d[u] nemění, máme strom nejkratších cest do všech dosažitelných uzlů z uzlu s 0 1 6 2 8 1 1 4 2 4 1 4 2 1 42 4 12 5 1 2 1? V jakém pořadí hran a jak dlouho máme provádět relaxaci? Doc. Josef Kolář (ČVUT) Prohledávání Nejkratší cesty grafů GRA, LS 2010/11, Lekce 47 7 / 15 18
Dijkstrův algoritmus Základní předpoklad w : H R + (nezáporné délky hran) Jedná se o upravený algoritmus prohledávání do šířky: otevřené uzly se vybírají podle nejmenší hodnoty d[u] (to je horní aproximace vzdálenosti d w (s,u)) vybraný uzel získá definitivní d[u], sousední d[v] se průběžně upravují s 0 1 4 2 6 1 7 HOTOVO 1 4 2 4 1 4 2 1 42 4 5 1 2 1 Doc. Josef Kolář (ČVUT) Prohledávání Nejkratší cesty grafů GRA, LS 2010/11, Lekce 47 8 / 15 18
Dijkstrův algoritmus void Dijkstra(Graph G, Node s, Weights w) { 1 InitPaths(G,s); O( U ) 2 S = ; Q = U(G); // Q OPEN, S CLOSED 3 while (Q!= )) { 4 u = uzel z Q s minimální hodnotou d[u] ; 5 S = S {u}; Q = Q-{u}; O( U. U ) 6 for (Node v in Adj[u]) { 7 Relax(u,v,w); O( H ) 8 } } } Předpokládáme ukládání / hledání hodnot d[u] v poli (seznamu) celková složitost O( H + U 2 ) = O( U 2 ) optimální pro husté grafy, jinak nepoměr H vs. U 2, co s tím? Doc. Josef Kolář (ČVUT) Prohledávání Nejkratší cesty grafů GRA, LS 2010/11, Lekce 47 9 / 15 18
Správnost Dijkstrova algoritmu Tvrzení: Při uzavření uzlu u (řádka 5... S = S {u}) platí d[u] = d w (s,u) D: sporem - nechť je d[u] > d w (s,u) pro nějaký uzavřený uzel, mějme nejkratší cestu s u, nechť x je její poslední uzavřený uzel s uzavřené uzly S x y 0 d[y] = d w (s,y) d w (s,u) < d[u] spor s vybráním uzlu u, když byl u k dispozici uzel y s menší hodnotou Doc. Josef Kolář (ČVUT) Prohledávání Nejkratší cesty grafů GRA, LS 2010/11, Lekce 47 10 / 15 18
Varianty Dijkstrova algoritmu Zpětná varianta chceme nalézt nejkratší cesty ze všech uzlů do jednoho (n 1) předpokládáme reprezentaci G pomocí seznamů předchůdců Obousměrná varianta střídáme postup dopředu a zpět (S, Q S, Q ) kdy můžeme hledání ukončit? jak určíme nejkratší cestu? Jak upravit pro cesty v acyklických grafech? topologicky uspořádáme uzly otevřené uzly procházíme v topologickém pořadí relaxujeme z nich vycházející hrany složitost O( H + U ) proč to bude fungovat? Doc. Josef Kolář (ČVUT) Prohledávání Nejkratší cesty grafů GRA, LS 2010/11, Lekce 47 11 / 15 18
Dijkstrův algoritmus používající frontu Q void Dijkstra(Graph G, Node s, Weights w) { 1 InitPaths(G,s); 2 S = ; Q.Init(); 3 for (Node u in U(G)) Q.Push(u); O( U ) 4 while (!Q.Empty()) { 5 u = Q.ExtMin(); S = S {u}; O( U. lg U ) 6 for (Node v in Adj[u]) { 7 Relax(u,v,w); } } } O( H. lg U ) void Relax (Node u, Node v, Weights w) { 1 newval = d[u]+w(u,v); 2 if (d[v] > newval) { 3 Q.DecreaseKey(v,newVal); p[v] = u;} } // d[v]=newval; Složitost O(( H + U ).lg U ) pro frontu implementovanou jako binární halda O( H + U.lg U ) pro Fibonacci-ho haldu Doc. Josef Kolář (ČVUT) Prohledávání Nejkratší cesty grafů GRA, LS 2010/11, Lekce 47 12 / 15 18
Dialova implementace Dijkstrova algoritmu Předpoklad délky hran jsou nezáporná celá čísla ( C), U =n, H =m Postup o víme, že hodnoty d[u] uzavíraných uzlů tvoří neklesající posloupnost o každé konečné d[u] je celéčíslo mezi 0 a (n-1).c (proč?) uzly se ukládají do přihrádek číslovaných 0,1,2,, (n-1).c podle d[u] uzly v přihrádce k tvoří dvojsměrně zřetězený seznam cont[k] přihrádky prohlížíme zdola, vybíráme uzly z první nalezené neprázdné, následníky při Relax přemisťujeme do nižších přihrádek Paměťová složitost O(m + n.c), časová složitost O(n.C)!!! Při zpracování přihrádky d[u] může vzniknout d[v] maximálně rovné d[u]+c stačí použít kruhovou frontu s (C+1) přihrádkami Radix-heap implementace používá log(n.c) přihrádek a máčasovou složitost jen (?!?) O(m + n.log(n.c)) Doc. Josef Kolář (ČVUT) Prohledávání Nejkratší cesty grafů GRA, LS 2010/11, Lekce 47 13 / 15 18
Dijkstrův algoritmus a záporné hrany Co se stane, když má graf záporně ohodnocené hrany? Bude algoritmus vždycky fungovat špatně? d[]=3 s 3-2 4 d[]=4 Relax se musí doplnit o vracení uzlů do prioritní fronty už to není Dijkstrův algoritmus (?? ukončení algoritmu, časová složitost??) Doc. Josef Kolář (ČVUT) Prohledávání Nejkratší cesty grafů GRA, LS 2010/11, Lekce 47 14 / 15 18
Bellmanův-Fordův algoritmus? Co obecně dělat v případě záporně ohodnocených hran? Relaxovat, relaxovat, relaxovat... boolean B-Ford (Graph G, Node s, Weights w) { 1 InitPaths(G,s); 2 for (int i=1; i< U ; i++) 3 for (Edge (u,v) in H) 4 Relax(u,v,w); 5 for (Edge (u,v) in H) { 6 if (d[v] > d[u] + w(u,v)) return false; } 7 return true; 8 } Složitost O( U. H )?Proč má nyní Relax opět konstantní časovou složitost? Doc. Josef Kolář (ČVUT) Prohledávání Nejkratší cesty grafů GRA, LS 2010/11, Lekce 47 15 / 15 18
Úpravy B-F algoritmu Co když zavedeme frontu uzlů s úspěšným Relax a bereme jen hrany vycházející z těchto uzlů? (a máme upraveného Dijkstru!) ukončení - při vyprázdnění fronty problém - co když se fronta nevyprázdní? v nejhorším případě zase O( U. H ) A úprava pro acyklické grafy? DAG-Paths - nejkratší cesty pro acyklické grafy 1 "Topologicky uspořádáme uzly grafu G" 2 InitPaths(G,s); 3 for (Node u in U(G) v pořadí top. uspořádání) { 4 for (Node v in Adj[u]) Relax(u,v,w); 5 }?? Složitost?? O( H + U )!! Doc. Josef Kolář (ČVUT) Prohledávání Nejkratší cesty grafů GRA, LS 2010/11, Lekce 47 16 / 15 18
Kontrolní otázky 7.1 Kteráčást Dijkstrova algoritmu je podstatně závislá na předpokladu nezáporného ohodnocení hran? Ukažte na jednom příkladu, že pro záporně ohodnocené hrany může Dijkstrův algoritmus dát špatný výsledek, a na jiném příkladu, že může dát správný výsledek. 7.2 Je možné prohlásit, že Dijkstrův algoritmus bude fungovat správně i při záporném ohodnocení hran, pokud bude zadaný graf acyklický? 7.3 Je možné prohlásit, že Dijkstrův algoritmus bude fungovat správně i při záporném ohodnocení hran, pokud bude použit k určení vzdáleností z kořene do ostatních uzlů kořenového stromu? 7.4 Navrhněte časově efektivní algoritmus pro určení celkového počtu různých orientovaných cest v acyklickém grafu. (Návod: Inspirujte se algoritmem DAG-Paths a za hodnotu d[u] berte počet cest končících v uzlu u.) 7.5 Navrhněte algoritmus, který určí vzdálenost ze všech uzlů do uzlu s v acyklickém orientovaném grafu. Určete potřebné datové struktury a časovou složitost navrženého algoritmu. 7.6 Navrhněte algoritmus lineární složitosti pro hledání nejdelších cest z daného uzlu do všech ostatních uzlů v acyklickém grafu. 7.7 Doplňte Dijkstrův a Bellman-Fordův algoritmus o výpočet hodnoty r[u], která představuje počet hran nejkratší cesty z uzlu s do uzlu u. (Návod: Stačí vhodně upravit operace InitPaths a Relax.) Doc. Josef Kolář (ČVUT) Prohledávání Nejkratší cesty grafů GRA, LS 2010/11, Lekce 47 17 / 15 18
Kontrolní otázky 7.8 Navrhněte algoritmus, který v orientovaném grafu s nezáporným ohodnocením hran w nalezne druhou nejkratší orientovanou cestu z uzlu u do uzlu v. Určete asymptotickou časovou složitost tohoto algoritmu. Doc. Josef Kolář (ČVUT) Prohledávání Nejkratší cesty grafů GRA, LS 2010/11, Lekce 47 18 / 15 18