Erinnerung VL 15.06.2016 I Graphtraversierung I BFS (Breitensuche): in Schichten um Startknoten löst einfache Form des Kürzeste-Wege-Problems I DFS (Tiefensuche): erst absteigen, dann Alternativen ansehen generisch formuliert, viele Instanziierungen möglich I Heute: mehr zu DFS, kürzeste Wege KIT Institut für Theoretische Informatik 1 Erinnerung: Tiefensuchschema unmark all nodes; init s ∈ V do s is not marked mark s root(s) DFS(s, s) foreach if Procedure DFS(u, v then : NodeId) // // // make s a root and grow a new DFS tree rooted at s Explore v coming from u foreach (v , w ) ∈ E do if w is marked then traverseNonTreeEdge(v , w ) else traverseTreeEdge(v , w ) mark w DFS(v , w ) backtrack(u, v ) // return from v along the incoming edge KIT Institut für Theoretische Informatik 2 Wiederholung: Kantenklassizierung I Baumkanten: Elemente des Waldes, der bei der Suche gebaut wird I Vorwärtskanten: verlaufen parallel zu Wegen aus Baumkanten I Rückwärtskanten: verlaufen antiparallel zu Wegen aus Baumkanten I Querkanten: alle übrigen forward s tree backward cross KIT Institut für Theoretische Informatik 3 DFS-Nummerierung dfsPos=1 init: root(s): traverseTreeEdge(v , w ): : 1..n dfsNum[s]:= dfsPos++ dfsNum[w ]:= dfsPos++ u≺v :⇔ dfsNum[u] < dfsNum[v ] . Beobachtung: Knoten auf dem Rekursionsstapel sind bzgl. 1 tree backward s cross forward 2 b 3 e ≺ sortiert 4 g d c 7 6 5 f KIT Institut für Theoretische Informatik 4 Fertigstellungszeit init: nishingTime=1 backtrack(u, v ): nishTime[v ]:= nishingTime++ 7 tree backward s cross forward 5 b : 1..n 4 e 2 g d c 6 3 1 f KIT Institut für Theoretische Informatik 5 Kantenklassizierung bei DFS nishTime[w ] (v , w ) < dfsNum[w ] nishTime[v ] marked tree yes yes no forward yes yes yes backward no no yes cross no yes yes type dfsNum[v ] < w is forward s tree backward cross KIT Institut für Theoretische Informatik 6 Topologische Sortierung Denition 1 Eine lineare Anordnung t der Knoten eines DAGs G = (V , E ), in der alle Kanten von kleineren zu gröÿeren Knoten verlaufen, heiÿt topologische Sortierung, d. h. ∀(u, v ) ∈ E : t(u) < t(v ). Beispiel: topologisch sortierter Kleidergraph, Quelle: Wikipedia Kleidergraph, Quelle: Wikipedia KIT Institut für Theoretische Informatik 7 Topologisches Sortieren mittels DFS Theorem 2 G ist kreisfrei (DAG) ⇔ DFS ndet keine Rückwärtskante. In diesem Fall liefert t(v ):= n − nishTime[v ] eine topologische Sortierung. KIT Institut für Theoretische Informatik 8 Topologisches Sortieren mittels DFS Theorem 2 G ist kreisfrei (DAG) ⇔ DFS ndet keine Rückwärtskante. In diesem Fall liefert t(v ):= n − nishTime[v ] eine topologische Sortierung. Beweis ⇒: Annahme: ∃ Rückwärtskante. Zusammen mit Baumkanten ergibt sich ein Kreis. Widerspruch. forward s tree backward cross KIT Institut für Theoretische Informatik 8 Topologisches Sortieren mittels DFS Satz: G ⇔ DFS ndet keine t(v ):= n − nishTime[v ] ∀(u, v ) ∈ E : t(u) < t(v ). kreisfrei (DAG) In diesem Fall liefert Sortierung, d. h. Rückwärtskante. eine topologische Beweis ⇐: Keine Rückwärtskante Kantenklassizierung z}|{ ⇒ ⇒G ∀(v , w ) ∈ E : nishTime[v ] > nishTime[w ] ist kreisfrei und nishTime deniert umgekehrte topologische Sortierung. KIT Institut für Theoretische Informatik 9 Starke Zusammenhangskomponenten ∗ u↔v falls ∃ Pfad Beobachtung: ∗ ↔ ∗ ↔ mit hu, . . . , v i und ∃ Betrachte die Relation Pfad hv , . . . , ui. ist Äquivalenzrelation Die Äquivalenzklassen von ∗ ↔ Übung bezeichnet man als starke Zusammenhangskomponenten. DFS-basierter Linearzeitalgorithmus −→ Algorithmen II KIT Institut für Theoretische Informatik 10 Mehr DFS-basierte Linearzeitalgorithmen I 2-zusammenhängende Komponenten: bei Entfernen eines Knotens aus einer Komponente bleibt diese zusammenhängend (ungerichtet) I 3-zusammenhängende Komponenten I Planaritätstest (lässt sich der Graph kreuzungsfrei zeichnen?) I Einbettung planarer Graphen KIT Institut für Theoretische Informatik 11 BFS ←→ DFS pro BFS: I nichtrekursiv I keine Vorwärtskanten I kürzeste Wege, Umgebung pro DFS: I keine explizite Datenstruktur forward s tree backward cross (Rekursionsstapel) für ToDos, daher mglw. einfacher I Grundlage vieler Algorithmen KIT Institut für Theoretische Informatik 12 Kap. 10: Kürzeste Wege Eingabe: I Graph G = (V , E ) mit I Kostenfunktion/Kantengewicht c :E →R sowie I Startknoten Ausgabe: für alle I Länge I µ(v ) 3.0 km s. v ∈ V: des kürzesten Pfades von µ(v ) := min {c(p) : p ist Pfad von s k mit c(he1 , . . . , ek i) := ∑i=1 c(ei ). s nach nach v, v} KIT Institut für Theoretische Informatik 13 Kap. 10: Kürzeste Wege Eingabe: I Graph G = (V , E ) mit I Kostenfunktion/Kantengewicht c :E →R sowie I Startknoten Ausgabe: für alle I Länge I µ(v ) 3.0 km s. v ∈ V: des kürzesten Pfades von µ(v ) := min {c(p) : p ist Pfad von s k mit c(he1 , . . . , ek i) := ∑i=1 c(ei ). s nach nach v, v} Oft wollen wir auch geeignete Repräsentation der kürzesten Pfade. KIT Institut für Theoretische Informatik 13 Anwendungen I Routenplanung I Straÿennetze I Spiele I Kommunikationsnetze I Unterprogramm I Flüsse in Netzwerken I ... I Tippfehlerkorrektur 3.0 km I Disk Scheduling I ... KIT Institut für Theoretische Informatik 14 Grundlagen Gibt es immer einen kürzesten Pfad? Es kann negative Kreise geben! s p u C q v s p (2) uC q v ... weitere Grundlagen just in time KIT Institut für Theoretische Informatik 15 Azyklische Graphen später KIT Institut für Theoretische Informatik 16 Kantengewichte ≥ 0 Alle Gewichte gleich: Breitensuche (BFS)! b s 0 e g c d f 1 2 tree backward cross forward 3 KIT Institut für Theoretische Informatik 17 Dijkstras Algorithmus Nun: Beliebige nichtnegative Kantengewichte M 0 Distance to M R 5 Lösung ohne Rechner: I Kanten → Fäden I Kantengewicht L → Q Fadenlänge I Knoten → Knoten I Dann: Am Startknoten anheben. 11 13 15 O H G N F K P E C 17 17 18 19 20 S V J W KIT Institut für Theoretische Informatik 18 Korrektheit der Bindfäden M 0 Distance to M Betrachte beliebigen Knoten mit Hängetiefe ∃ R v d[v ]. L Pfad mit Hängetiefe: Q kürzerer Pfad: falls es einen solchen Pfad gäbe, wäre einer seiner Fäden zerrissen! 11 13 15 O verfolge strae Fäden ¬∃ 5 H G N F K P E C 17 17 18 19 20 S V J W KIT Institut für Theoretische Informatik 19 Edsger Wybe Dijkstra 19302002 I 1972 ACM Turing Award I THE: das erste Mulitasking-OS I Semaphor I Selbst-stabilisierende Systeme I GOTO Statement Considered Harmful Bildquelle: Wikipedia KIT Institut für Theoretische Informatik 20 Allgemeine Denitionen Knotenarrays: d[v ] = aktuelle (vorläuge) Distanz von Invariante: I parent[v ] = s nach v d[v ] ≥ µ(v ) Vorgänger von v auf dem (vorläugen) kürzesten Pfad von s nach v Kante Kante I parent parent s Wie bei BFS benutzen wir zwei d[v] Initialisierung: d[s] = 0, parent[s] = s d[v ] = ∞, parent[v ] = ⊥ d[v ] Kante dieser Pfad bezeugt parent Invariante: v KIT Institut für Theoretische Informatik 21 Kante (u, v ) relaxieren d[u] + c(u, v ) < d[v ] d[v ] = ∞), Falls (vielleicht setze I d[v ] := d[u] + c(u, v ) und I parent[v ] := u Invarianten bleiben erhalten! Beobachtung: d[v ] kann sich mehrmals ändern! KIT Institut für Theoretische Informatik 22 Dijkstras Algorithmus: Pseudocode initialize d, parent all nodes are non-scanned ∃ non-scanned node u with d[u] < ∞ u := non-scanned node v with minimal d[v ] relax all edges (u, v ) out of u u is scanned now while Behauptung: Am Ende deniert d die optimalen Entfernungen und parent die zugehörigen Wege KIT Institut für Theoretische Informatik 23 Beispiel 2 3 2 b c a 2 9 s 10 5 1 8 0 e f 4 d 7 10 0 2 3 5 7 2 a b c 2 9 s 10 5 1 8 0 e f 4 d 6 0 6 7 2 3 5 2 a b c 2 9 s 10 5 1 8 0 e f 4 d 7 10 0 7 2 3 5 2 a c b 2 9 s 10 5 1 8 0 f e 4 d 6 0 6 7 2 3 5 7 2 a c b 2 9 s 10 5 1 8 0 d e f 4 10 0 6 7 2 3 5 7 2 a b c 2 9 s 10 5 1 8 0 f d e 4 6 0 6 7 KIT Institut für Theoretische Informatik 24 Korrektheit Wir zeigen: Annahme: alle Kosten nicht-negativ! ∀v ∈ V : I v erreichbar I v gescannt =⇒ v wird irgendwann gescannt =⇒ µ(v ) = d[v ] KIT Institut für Theoretische Informatik 25 v erreichbar =⇒ v wird irgendwann gescannt Annahme: v ist erreichbar, aber wird nicht gescannt gescannt ungescannt z }| { z}|{ s = v1 −→ v2 −→ · · · −→ vi−1 −→ vi −→ · · · −→ {z | ein kürzester s v Pfad =⇒ vi−1 wird gescannt =⇒ Kante vi−1 −→ vi wird relaxiert =⇒ d[vi ] < ∞ Widerspruch nur Knoten x mit d[x] = ∞ ungescannt z }| { vk = v werden nie gescannt } ? KIT Institut für Theoretische Informatik 26 v erreichbar =⇒ v wird irgendwann gescannt Annahme: v ist erreichbar, aber wird nicht gescannt gescannt ungescannt z }| { z}|{ s = v1 −→ v2 −→ · · · −→ vi−1 −→ vi −→ · · · −→ {z | ein kürzester s v Pfad =⇒ vi−1 wird gescannt =⇒ Kante vi−1 −→ vi wird relaxiert =⇒ d[vi ] < ∞ Widerspruch nur Knoten x mit d[x] = ∞ Ups: Spezialfall ungescannt z }| { vk = v } werden nie gescannt i = 1? Kann auch nicht sein. v1 = s wird nach Initialisierung gescannt. KIT Institut für Theoretische Informatik 26 v gescannt =⇒ µ(v ) = d[v ] Annahme: OBdA: t := v v gescannt und µ(v ) < d[v ] ist der erste gescannte Knoten mit Scan-Zeit von µ(v ) < d[v ]. v Scan-Zeit ≥ t Scan-Zeit = t Scan-Zeit < t z }| { z}|{ }| { z s = v1 −→ v2 −→ · · · −→ vi−1 −→ vi −→ · · · −→ vk = v | {z } ein kürzester s v Pfad Also gilt zur Zeit t: µ(vi−1 ) = d[vi−1 ] vi−1 → vi wurde relaxiert z}|{ =⇒ d[vi ] ≤ d[vi−1 ] + c(vi−1 , vi ) = µ(vi ) ≤ µ(v )< d[v ] =⇒ vi wird vor v gescannt. Widerspruch! Wieder: Spezialfall i =1 unmöglich. KIT Institut für Theoretische Informatik 27 Implementierung? initialize d, parent all nodes are non-scanned ∃ non-scanned node u with d[u] < ∞ u := non-scanned node v with minimal d[v ] relax all edges (u, v ) out of u u is scanned now while Wichtigste Operation: nde u KIT Institut für Theoretische Informatik 28 Prioritätsliste Wir speichern ungescannte erreichte Knoten in adressierbarer Prioritätsliste Schlüssel ist Q. d[v ]. Knoten speichern handles. oder gleich items KIT Institut für Theoretische Informatik 29 Implementierung ≈ BFS mit PQ statt FIFO Function Dijkstra(s : NodeId) : NodeArray×NodeArray // returns (d, parent) Initialisierung: d=h∞, . . . , ∞i : NodeArray of R ∪ {∞} // parent=h⊥, . . . , ⊥i parent[s]:= : NodeArray tentative distance from root of NodeId s Q : NodePQ d[s] := 0; Q .insert(s) // // self-loop signals root unscanned reached nodes KIT Institut für Theoretische Informatik 30 : NodeId) : NodeArray×NodeArray d = h∞, . . . , ∞i; parent[s]:= s ; d[s] := 0; Q .insert(s) while Q 6= 0 / do u := Q .deleteMin // scan u foreach edge e = (u, v ) ∈ E do if d[u] + c(e) < d[v ] then d[v ]:= d[u] + c(e) parent[v ] := u // if v ∈ Q then Q .decreaseKey(v ) else Q .insert(v ) return (d, parent) Function Dijkstra(s s u scanned // relax update tree u v reached KIT Institut für Theoretische Informatik 31 Beispiel 2 3 2 b c a 2 9 5 s 10 8 1 0 e f 4 d 0 7 10 2 3 5 7 2 a b c 2 9 5 s 10 8 1 0 e f 4 d 0 7 6 6 2 3 5 2 a b c 2 9 5 s 10 8 1 0 e f 4 d 7 10 0 7 2 3 5 2 a c b 2 9 5 s 10 8 1 0 f e 4 d 6 0 6 7 2 3 5 7 2 a c b 2 9 5 s 10 8 1 0 e f 4 d 10 0 6 7 2 3 5 7 2 a b c 2 9 s 10 5 1 8 0 f e 4 d 6 0 6 7 Operation insert(s) deleteMin 2 relax s → a 10 relax s → d deleteMin 3 relax a → b deleteMin 2 relax b → c 1 relax b → e deleteMin 9 relax e → b 8 relax e → c 0 relax e → d deleteMin 4 relax d → s 5 relax d → b deleteMin (s, 0) (a, 2) (b, 5) (e, 6) (d, 6) (c, 7) Queue h(s, 0)i hi h(a, 2)i h(a, 2), (d, 10)i h(d, 10)i h(b, 5), (d, 10)i h(d, 10)i h(c, 7), (d, 10)i h(e, 6), (c, 7), (d, 10) h(c, 7), (d, 10)i h(c, 7), (d, 10)i h(c, 7), (d, 10)i h(d, 6), (c, 7)i h(c, 7)i h(c, 7)i h(c, 7)i hi KIT Institut für Theoretische Informatik 32