Algo&Komp. - Wichtige Begriffe Mattia Bergomi 2008 Woche 6−7 1 Kürzeste Pfade Hier arbeiten wir mit gewichteten Graphen, d.h. Graphen, deren Kanten mit einer Zahl gewichtet werden. Wir bezeichnen die Gewichtsfunktion mit l : E → R. Wir wollen P einen kürzesten s-t–Pfad finden, wobei die Länge eines Pfades ist definiert als e∈Pfad l(e). Der Unterschied, ob l ≥ 0 oder nicht, spielt eine wesentliche Rolle. In der Tat gilt für das Kürzeste-Pfad-Problem und Kürzeste-Weg-Problem mit l ≤ 0 folgendes: Graph ungerichtet: • Kürzester Weg: Problem unlösbar, da wir eine beliebige Kante mit l(e) < 0 beliebig oft durchlaufen können so, dass die Länge des Weges beliebig klein gemacht werden kann (also existiert kein minimaler Weg). • Kürzester Pfad: Das Problem besitzt eine optimale Lösung (es existieren nur endlich viele Pfade), aber es kann sehr schwierig sein, diese explizit zu finden. Graph gerichtet: • Kürzester Weg: Problem unlösbar, falls der Graph einen negativen Kreis (d.h. einen Kreis mit insgesamt negativer Länge) besitzt, da wir diesen Kreis beliebig oft durchlaufen können so, dass die Länge des Weges beliebig klein gemacht werden kann. • Kürzester Pfad: Das Problem besitzt eine optimale Lösung (es existieren nur endlich viele Pfade). Mit dem Algorithmus von Floyd-Warshall (s.u.) können wir testen, ob der Graph einen negativen Kreis enthält. 1.1 Algorithmus von Dijkstra Voraussetzungen: G ungerichtet, l ≥ 0. (s, t ∈ V ) Alle Knoten v werden zwei Eigenschaften bekommen: ρ[v] := Länge des kürzesten s-v Pfades. pred[v] := Letzter Knoten, der ρ[v] modifiziert hat. Wir unterscheiden hier 3 “virtuelle” Mengen von Knoten (siehe Abbildung 1): • W: Besuchte Knoten, von denen die Lösung schon bekannt ist (d.h. hier ist ρ[v] definitiv). • Grenzknoten G: Besuchte Knoten, wo wir einen Kandidaten suchen, der in W eingefügt werden kann (hier ist ρ[v] < ∞, aber noch nicht definitiv, da ein besserer Pfad existieren könnte). • Unbesuchte Knoten U: Knoten, die nie besucht wurden. Hier ist noch ρ[v] = ∞. -1- Algo&Komp. - Wichtige Begriffe Mattia Bergomi 2008 ∈ Γ(x0 ) ∈ Γ(x0 ) ∈ Γ(x0 ) s l(x0 , ) x0 t min ρ[v] W = Besucht (ρ[v] = definitiv) Grenzknoten Unbesucht (ρ[v] < ∞) (ρ[v] = ∞) Abbildung 1: Idee beim Algorithmus von Dijkstra Erklärung von Dijkstra durch ein Beispiel (siehe Abbildung 2!) 1. Man setzt alle ρ[v] = ∞ ausser ρ[s] = 0; definiert W = {s} und aktualisiert alle Nachbarn von s durch ρ[v] = l(s, v). (Im Beispiel: W = {s}, G = {v1 , v2 }, ρ[v1 ] = 3, ρ[v2 ] = 5) 2. Man sucht einen Nachbarn x0 von W (also in G), der minimales ρ hat (vgl. Abbildung 1) und fügt ihn in W ein. (Im Beispiel: x0 = v1 → W = {s, v1 }) 3. Man aktualisiert dann die ρ[v]’s und die pred[v]’s aller Nachbarn v von x0 , die nicht in W liegen: entweder ist jetzt s ; x0 ; v kürzer (neuer Pfad ⇒ ρ[v] aktualisieren), oder der alte direkte s ; v–Pfad war schon besser (ρ[v] unverändert, da es schon diesem alten Pfad entspricht): ( ρ[v] := ρ[x0 ] + l(x0 , v) if ρ[v] > ρ[x0 ] + l(x0 , v) then pred[v] := x0 (Im Beispiel: ρ[v3 ] = ∞ > 3 + 9 ⇒ ρ[v3 ] = 12, ρ[v4 ] = ∞ > 3 + 4 ⇒ ρ[v4 ] = 7, G = {v2 , v3 , v4 }) 4. Wiederholt Schritte 2 und 3, bis t in W eingefügt wird (und somit die definitive Lösung kriegt). (Im Beispiel: x0 = v3 → W = {s, v1 , v3 }, aktualisiere ρ[v2 ] = 6, ρ[v4 ] = 13, ρ[t] = 20, x0 = v2 , . . .) Diese Prozedur ist in Abbildung 2 dargestellt. ρ=3 v1 . ρ = 0s 3 7 ρ = 13 20 v4 2 v2 ρ=6 2 8 1 v3 15 W W W ρ = 15 t W W W = {s} = W ∪ {v1 } = W ∪ {v3 } = W ∪ {v2 } = W ∪ {v4 } = W ∪ {t} ρ=5 Abbildung 2: Ein Beispiel für den Algorithmus von Dijkstra: Endsituation -2- Algo&Komp. - Wichtige Begriffe Mattia Bergomi 2008 Die Resultate sind: → Die Laufzeit ist O |V |2 . → Indem man den Algorithmus laufen lässt, bis W = V wird, dann ist ρ[v] die Länge eines kürzesten s-v–Pfades, ∀v ∈ V . → Die Kanten {{v, pred[v]} | v 6= s} bilden einen Spannbaum T von G: dieser ist nicht minimal, aber die (eindeutigen) s-v–Pfade haben minimale Länge in G. 1.2 Algorithmus von Floyd-Warshall Voraussetzungen: s, t ∈ V und {G ungerichtet und l ≥ 0} oder {G gerichtet und l ∈ R} Sei o.B.d.A. V = {1, . . . , n}. Die Idee ist hier, sukzessive die besten i-j–Pfade zu finden, in denen nur die Knoten {1, . . . , k} ∪ {i, j} vorkommen (∀k = 0 . . . n). Wir speichern diese Informationen in k verschiedenen Matrizen Fk [i, j]. • Für k = 0 muss natürlich die Initialisierung sein: l(i, j) falls die Kante {i, j} existiert F0 [i, j] := 0 falls i = j ∞ sonst • Für die Aktualisierung k − 1 → k, analog wie bei Dijkstra, haben wir zwei mögliche Situationen: entweder wird der neue Knoten k benutzt, um ein besseren i-j–Pfad zu kriegen (und somit muss der neue minimale Pfad von i nach k und von k nach j gehen, also wird Fk [i, j] aktualisiert) oder wir benutzen diesen Knoten k nicht (Fk [i, j] bleibt unverändert). D.h.: k unbenutzt k benutzt z }| { z }| { Fk [i, j] := min{Fk−1 [i, j], Fk−1 [i, k] + Fk−1 [k, j]} • Am Ende ist dann Fn [i, j] die Länge eines kürzesten i-j–Pfades in G, ∀i, j (da wir alle Knoten benutzen durften). Für gerichtete Graphen mit einem negativen Kreis wird am Ende natürlich ein Fn [i, j] < 0 sein. Die Resultate sind: → Die Laufzeit ist O |V |3 . → Am Ende enthält Fn [i, j] die Länge eines kürzesten i-j–Pfades in G, ∀i, j. → Für G gerichtet: falls ein Fn [i, j] < 0 ist, so ist das ein Beweis, dass ein negativer Kreis existiert. -3- Algo&Komp. - Wichtige Begriffe 2 Mattia Bergomi 2008 Minimale Spannbäume Wieder arbeiten wir mit gewichteten Graphen und bezeichnen die Gewichtsfunktion mit l : E → R. Wir wollen einen minimalen Spannbaum T von G finden, wobei das P Gewicht eines Baumes definiert ist als e∈T l(e). Lemma (Eindeutigkeit des Min. Spannbaums) Sind die Kantengewichte eines Graphs alle unterschiedlich, so gibt es einen eindeutigen minimalen Spannbaum. 2.1 Algorithmus von Prim Das Algorithmus von Prim ist praktisch die “Übersetzung” des Algorithmus von Dijkstra für Spannbäume, und deswegen fast identisch. Alle Knoten v werden zwei Eigenschaften bekommen: ρ[v] := Länge der kürzesten Kante {v, x} für ein x ∈ W . pred[v] := Letzter Knoten, der ρ[v] modifiziert hat. Wieder unterscheiden wir 3 “virtuelle” Mengen von Knoten: • W: Besuchte Knoten (hier ist ρ[v] definitiv). • Grenzknoten G: Besuchte Knoten, wo wir ein Kandidat suchen, der in W eingefügt werden wird (hier ist ρ[v] < ∞, aber noch nicht definitiv). • Unbesuchte Knoten U: Knoten, die nie besucht wurden. Hier ist noch ρ[v] = ∞. und bauen F := {Kanten des min. Spannbaumes}. Erklärung von Prim 1. Man setzt alle ρ[v] = ∞ ausser ρ[s] = 0 (hier ist s beliebig gewählt); definiert W = {s} und aktualisiert alle Nachbarn von s durch ρ[v] = l(s, v), pred[v] = s. 2. Man sucht einen Nachbarn x0 von W (also in G), der minimales ρ hat und fügt ihn in W sowie die Kante pred[v] in F ein. 3. Man aktualisiert dann die ρ[v]’s und die pred[v]’s aller Nachbarn v von x0 , die nicht in W liegen: wenn sie ein ρ[v] > l(v; x0 ) haben (die neue minimale Distanz zu W ist kleiner), dann aktualisiert man (da jetzt x0 auch in W liegt): ( ρ[v] := l(x0 , v) if ρ[v] > l(x0 , v) then pred[v] = x0 4. Man wiederholt die Schritte 2 und 3, bis W = V wird. Die Resultate sind: → Die Laufzeit ist O |V |2 . → F ist ein minimaler Spannbaum. -4- Algo&Komp. - Wichtige Begriffe 2.2 Mattia Bergomi 2008 Algorithmus von Kruskal Der Algorithmus von Kruskal ist die einfachste Weise, einen Spannbaum eines Graphs zu finden: wenn man in einem konkreten Beispiel (z.B. in der Prüfung) ein Spannbaum eines Graphs finden muss, ohne ein Computer benutzen zu dürfen, dann soll man immer diesen Algorithmus verwenden—mit kleinen Graphen dauert das Ganze weniger als 30 Sekunden. . . . Die Idee von Kruskal ist die folgende: • Sortiere die Kanten nach der Gewicht: w(e1 ) ≤ . . . ≤ w(em ). • Setze Spannbaum F := ∅. • For k = 1 . . . m : Wenn F ∪ ek kreisfrei bleibt, dann addiere ek zu F , sonst nicht. Diese einfache Prozedur ist in Abbildung 3 dargestellt. . Nicht hinzugefügt (Schritt k = 4), da sonst würde ein Kreis entstehen! 15 5 2 20 7 4 8 1 Abbildung 3: Ein Beispiel für den Algorithmus von Kruskal: Endsituation Die Resultate sind: → Die Laufzeit ist O (|E| · |V |). → F ist ein minimaler Spannbaum. -5-