Aufgabe 5 (Bellman

Werbung
Aufgabe 5 (Bellman-Ford)
Andreas Beer (086/9625203)
Patrick Traxler (931/0027287)
18. November 2004
1
Aufgabenstellung
1. Erläutern Sie das Verfahren von Bellman-Ford zur Bestimmung der kürzesten
Wege in einem gerichteten Graphen mit negativen Kantengewichten.
Abschnitt 2 weiter unten.
2. Rechnen Sie den Algorithmus an einem Beispiel vor.
Abschnitt 3 auf Seite 2.
3. Argumentieren Sie die Korrektheit des Verfahrens.
Abschnitt 4 (Seite 6).
4. Wie ist die Worst Case Laufzeit? Begründung.
Beides in Abschnitt 5 auf Seite 8.
2
Der Algorithmus
Der Bellman-Ford Algorithmus – auch bekannt als Moore-Algorithmus – wird in seiner
Urform verwendet um die kürzesten Wege von einem fixen Knoten s zu allen anderen
Knoten eines gegeben gerichteten Graphen G = (V, E) zu bestimmen. Eine einfache
Pseudo-Implementation ist in Abbildung 1 (Seite 2) zu sehen.
In d(x) wird die Länge des momentan kürzesten Weges von s nach x gespeichert. p(x)
ist der Vorgängerknoten auf diesem Weg. Beide Arrays werden in den Zeilen 3 und
4 auf offensichtliche Art initialisiert: Kein Knoten hat einen Vorgängerknoten und die
Distanz von s zu s ist natürlich Null. Alle anderen Knoten sind zur Zeit unerreichbar.
(Distanz Unendlich.)
Im Hauptteil des Algorithmus (Zeilen 6 bis 13) wird nun (|V | − 1)-mal für jede Kante
(u, v) untersucht, ob nicht vielleicht der Endknoten v über u schneller zu erreichen ist
als bisher. Falls ja, so werden die Werte entsprechend adaptiert.
Warum wird die äußere Schleife gerade (|V | − 1)-mal durchlaufen? Nun man sieht leicht, dass
man nicht mit weniger Iterationen auskommen kann. Ein entarteter Baum, in dem die Wurzel s
und jeder innere Knoten Weggrad Eins und alle Knoten Hingrad Null haben würde genau besagte
|V | − 1 Schritte benötigen, um den „kürzesten“ Weg von s zum Blatt zu finden.
Auf der anderen Seite kann ein kürzester Weg jeden Knoten nur maximal einmal enthalten.
(Vorausgesetzt natürlich, dass es keine Zyklen negativer Länge gibt. Dazu später mehr.) Also
wird man auch nicht mehr als |V | − 1 Iterationen brauchen.
1
1 # G = (V, E), s ∈ V , w : E → R;
3 d(s) ← 0, p(s) ← NIL;
4 foreach (v ∈ V \{s}) { d(v) ← ∞ , p(v) ← NIL; }
5
6 for (i = 1, . . . , |V | − 1) {
7
foreach ((u, v) ∈ E ) {
8
if (d(v) > d(u) + w(u, v)) {
9
d(v) ← d(u) + w(u, v);
10
p(v) ← u;
11
}
12
}
13 }
15 foreach ((u, v) ∈ E ) {
16
if (d(v) > d(u) + w(u, v)) {
17
return false ;
18
}
19 }
20 return true ;
# ∃ neg. Zyklus
# d(v) . . . min. Distanz s → v
Abbildung 1: Bellman-Ford für festes s
Auch für das Auffinden von negativen Zyklen wird besagtes |V | − 1 gerade ausreichen. Der
interessierte Leser ist eingeladen sich dies an einem Graphen, der nur aus einem negativen Zyklus besteht, selbst zu überlegen.
Die Behauptung ist nun, dass nach dem Durchlaufen dieser Schleifen die Länge des kürzesten
Wegs von s zu v in d(v) gespeichert ist. Finden wir in der Schleife von Zeile 15 trotzdem über u
einen kürzeren Weg zu v, so muss es wohl einen Zyklus negativer Länge (auf dem Weg von s zu
u) geben.
Finden wir keinen solchen Widerspruch, so wissen wir, dass es keinen Zyklus negativer
Länge gibt.1 Außerdem kennen wir mit d(v) die Länge des kürzesten Wegs von s nach v für alle
Knoten v. (Den Weg selbst können wir leicht mithilfe der p(v)’s rekonstruieren.
Damit wäre das Problem des Bestimmens der kürzesten Wege von s zu allen Knoten bewältigt.
Führt man diesen Algorithmus nun für alle s ∈ V aus, so erhält man entweder entsprechende
Information über eventuelle Zyklen negativer Länge, oder eine Matrix in der die kürzesten Wege
zwischen allen Knoten verzeichnet sind.
3
Das Beispiel
Die Vorlesungsunterlagen von Prof. Erickson [2] enthalten ein sehr anschauliches Beispiel, das
im folgenden präsentiert werden soll.
Direkt nach der Initialisierung (Zeile 5 in Abbildung 1 weiter oben) haben wir die in Abbildung
2 (Seite 3) dargestellte Situation: Nur Knoten s ist von s aus (mit Distanz Null) erreichbar. Alle
1 Genauer: Es gibt keinen Zyklus negativer Länge, der von s aus erreichbar ist. Streng genommen hat ja
niemand behauptet, dass alle Knoten von s aus erreichbar sind.
2
Abbildung 2: nach der Initialisierung
e
89:;
?>=<
∞ Og O
OOO
ooo
−8 ooo
OO2O
o
OOO
o
o
f
o
d
OO
o
woo o
1
?>=<
89:;
89:;
?>=<
∞ Og O
∞
7
OOO
ooo
OO0O
5 ooo
o
OOO b
ooo
OO
ooo
89:;
?>=<
−3
−3
7 ∞ Og
ooo O OOOOO −1
8 ooo
OOO
oo
OOO ooooo
O
?>=<
89:;
89:;
?>=<
∞ Og O
4
o7 ∞
OOO
o
o
a
c
OOO
ooo
O
ooo3
o
6 OOOO
o
oo
0
s
anderen liegen in unendlicher Weite.
Der Algorithmus wird nun alle Kanten auf eine Verbesserungsmöglichkeit überprüfen. Wir
wissen aber, dass dies nur bei Kanten, die von einem Knoten endlicher Distanz ausgehen, einen
Sinn macht. Diese Knoten werden im Weiteren doppelt rechteckig umrandet dargestellt.
Im ersten Durchlauf – dargestellt in Abbildung 3 (Seite 4) – haben wir drei Knoten gefunden,
die sich nun über einen kürzeren Weg ereichen lassen. Die Distanzen wurden aktualisiert und die
Vorgänger entsprechend auf s gesetzt.
Man kann sich leicht überlegen, dass die (momentan) kürzesten Wege von s aus einen Baum
bilden.2 Dieser Baum wird in den folgenden Graphen durch gewellte Kanten dargestellt. Wie
eingangs erwähnt ergeben sich besagte kürzeste Wege durch die jeweiligen p(v) Einträge der
einzelnen Knoten v.
Es wird angenommen, dass die Wahl der betrachteten Kanten im zweiten Schritt – siehe Abbildung 4 auf Seite 4 – gleichzeitig bzw. in einer etwas unglücklichen Reihenfolge erfolgt: Würde
zuerst die Kante (c, b) betrachtet werden, so könnten die Gesamtdistanzen zu den Knoten d und
f noch niedriger gesetzt werden. Man würde sich also „einen Schritt ersparen“.
Auf jeden Fall wird in diesem Schritt (über c) ein neuer kürzester Weg zu b gefunden. Nachdem alle Distanzen und Vorgänger entsprechend gesetzt wurden geht es mit Schritt Drei in Abbildung 5 (Seite 5) weiter.
Die weiteren Abbildungen sprechen eigentlich für sich: In jedem Schritt werden alle Kanten auf
eine eventuelle Verbesserungsmöglichkeit untersucht.
Die oben erwähnte (etwas verspätete) Aktualisierung der Distanz von b pflanzt sich im dritten Schritt (Abbildung 5, Seite 5) zu f fort und erreicht im vierten Schritt (Abbildung 6 auf Seite
5) Knoten e.
Im fünften Schritt (Abbildung 7 auf Seite 6) führt sie zu einem besseren Weg nach d. Im sechsten
2 Streng genommen können bei nullwertigen Kanten auch Zyklen entstehen. Diese kann man aber ohne
größere Schwierigkeiten aufbrechen.
3
Abbildung 3: nach dem 1-ten Durchlauf
e
89:;
?>=<
∞ Og O
OOO
ooo
−8 ooo
OO2O
o
OOO
oo
f
o
d
OO
o
o
o
w
1
?>=<
89:;
89:;
?>=<
o
∞ Og O
7 ∞
OOO
ooo
OO0O
5 ooo
o
OOO b
ooo
OO
ooo
−3
−3
7 4 gO
ooo O O OOOOO −1
8 ooo
O
OOO
oo
O
OOO oooo
O
o
O
4
6 g g'
O
7w 7 3
g' g'
c
a
7w 7w
O
g' g'
w
7
7w
O
'
g
w
7
3
g' g'
6
7w 7w
89:;
?>=<
0
s
Abbildung 4: nach dem 2-ten Durchlauf
e
89:;
?>=<
∞
Og OO
OOO 2
ooo
−8 ooo
OOO
o
o
OOO
o
f
o
d
o
O
o
wo
o
1
9
4 g g'
7
g' g' 0
7w 7w
5 7w 7w
g' g'
g' g'
7w 7w
g' b 7w 7w
−3
7 2 g
ooo O 'g 'g 'g −1
o
o
'g 'g
ooo
g' 'g
oooo
'g o
?>=<
89:;
89:;
?>=<
4
6 g g'
7 3
7w 7w
g' g'
7
w
a
c
7w
g' g'
7w 7w 3
w
7
6 g' g' g'
7w
89:;
?>=<
0
s
−3
8
4
Abbildung 5: nach dem 3-ten Durchlauf
e
11 g 'g
oo
'g 'g 2
'g 'g
o
o
o
'g 'g
f
o
o
'g
o
wo
1
og
7 7
g' g'
7w 7w
g' g' 0
5 7w 7w
g' g'
7w
g' g' b 7w 7w 7w
89:;
?>=<
−3
oo7 2O g g' g'
o
o
g' g' −1
8 oo
o
g' g'
ooo
g' g' ooo
89:;
?>=<
4
7 3
gOOO
7w 7w
OOO
w
7
c
w
7
OOO
7w
w
7
O
OOO
3
6
7w 7w
89:;
?>=<
0
s
−8 ooo
d
2
O
O
O
−3 O
O
O
O
1
a
Abbildung 6: nach dem 4-ten Durchlauf
e
9 g 'g
oo
'g 'g 2
'g 'g
o
o
'g 'g
oo
d
o
'g
o
w
o
1
?>=<
89:;
2 g o g'
w
7
g' g' 0
7w
O
5 7w 7w
g' g'
w
7
O
g' g'
w
7
O
g' b 7w 7w
89:;
?>=<
−3 O
7 2 g
O
ooo O g' g' g' −1
O
8 ooo
g' g'
O
oo
g' g'
oooo
g'
4
−1 gO
w
7
OOO
7w 7w
OOO
a
7w 7w
O
w
7
O
OOO
3
6
7w 7w
89:;
?>=<
0
−8 oooo
s
5
89:;
?>=<
7 7
f
−3
89:;
?>=<
3
7
c
Abbildung 7: nach dem 5-ten Durchlauf
e
89:;
?>=<
9 g 'g
7w 7w
'g 'g 2
−8 7w 7w
'g 'g
w7
7
w
'g 'g
w7
d
'g
wo w7
1
1 gOO
w
7
OOO
7w
O
5 7w 7w
OO0O
7w
OOO b
O
w
7
OO
O
7w 7w
89:;
?>=<
−3 O
2
g
7
O
ooo O g' g' g' −1
O
8oooo
g' g'
o
O
g' g'
ooooo
g'
@ABC
GFED
4
−1 Og O
w
7
OOO
7w 7w
a
OOO
7w 7w
O
w
7
O
OOO
3
6
7w 7w
89:;
?>=<
0
s
89:;
?>=<
7 7
f
−3
89:;
?>=<
7 3
c
und letzten Schritt (Abbildung 8, Seite 7) gibt es schlussendlich noch eine Aktualisierung der
Distanz von a.
Man sieht, dass der kürzeste Weg von s nach a über alle anderen Knoten des Graphen läuft.
Es waren also wirklich die eingangs erwähnten |V | − 1 Schritte notwendig um alle kürzesten
Wege zu berechnen.
4
Die Korrektheit
Frei nach dem Motto „Talk is cheap!“ wollen wir uns nun der Korrektheit dieses Algorithmus
zuwenden. Zuerst einmal ist leicht zu sehen, dass unerreichbare Knoten Distanz ∞ haben.
Behauptung 1. Ein Knoten v ist genau dann nicht von s aus erreichbar, wenn seine Distanz
nach Ablauf des Algorithmus mit ∞ angegeben wird.
Beweis. Die Distanz aller Knoten (außer s) wird mit ∞ initialisiert und nur dann geändert, wenn
besagter Knoten über einen seiner Vorgänger erreicht werden kann.
⇒ Da v aber nicht von s aus erreichbar ist, lässt sich auch keiner seiner Vorgänger von s
aus erreichen. Somit bleibt während aller |V | − 1 Schritte die Distanz von v gleich ∞.
⇐ Die Distanz von v kann nur dann ∞ bleiben, wenn wir v nicht innerhalb von |V | − 1
Durchläufen erreichen können. Wir wissen aber, dass der längste kürzeste3 Weg in einem Graphen jeden Knoten nur maximal einmal enthalten darf. Wenn wir v also nicht innerhalb von
|V | − 1 Schritten erreicht haben, so ist v von s aus überhaupt nicht erreichbar. Wenden wir uns nun dem interessantesten Teil der Korrektheit zu.
Behauptung 2. Enthält (V, E) keinen negativen Zyklus, der von v aus erreichbar ist, so ist d(v)
nach Ablauf des Algorithmus die minimale Distanz von s nach v (δ(s, v)).
3 ‚Kürzeste‘
bezieht sich in diesem Fall nur auf die Anzahl der Kanten.
6
Abbildung 8: Endergebnis
e
89:;
?>=<
9 g 'g
7w 7w
'g 'g 2
−8 7w 7w
'g 'g
w7
7
w
'g 'g
d
w7 w7
'g
w
1
?>=<
89:;
o
1 gOOO
w
7
7w
OOO 0
O
5 7w 7w
OOO
7w
O
w
7
OOO b
O
7w 7w
O
89:;
?>=<
−3 O
2
7
g
O
ooo O g' g' g' −1
O
8oooo
g' g'
o
O
g' g'
ooooo
g'
@ABC
GFED
4
−2 Og O
w
7
OOO
7w 7w
a
OOO
7w 7w
O
w
7
O
OOO
3
6
7w 7w
89:;
?>=<
0
s
89:;
?>=<
7 7
f
−3
89:;
?>=<
7 3
c
Beweis. Ist v nicht von s aus erreichbar, so sind wir bereits mit Satz 1 von Seite 6 fertig. Es
existiere also ein Pfad4 von s nach v und
s = v0 , v1 , v2 , . . . , vk−1 , vk = v
sei der5 kürzeste dieser Wege. Wir wissen, dass k ≤ |V | − 1 gilt.
Können wir nun zeigen, dass nach dem i-ten Durchlauf
d(v j ) = δ(s, v j )
j = 0, 1, . . . , i
gilt, so hätten wir unsere Behauptung bewiesen: Spätestens nach der (|V | − 1)-ten Iteration wäre
d(vk ) = d(v) = δ(s, v).
Unser Mittel zum Zweck wird natürlich die vollständige Induktion sein.
Anfang: i = 0 d(s) ist korrekterweise Null.
Voraussetzung: Für festes i gelte
d(v j ) = δ(s, v j )
j = 0, 1, . . . , i.
Schluß: i i + 1 Im (i + 1)-ten Durchlauf wird unter anderem (vi , vi+1 ) betrachtet. Somit gilt
nach dieser Iteration sicher
d(vi+1 )
≤
=
=
d(vi ) + w(vi , vi+1 )
δ(s, vi ) + w(vi , vi+1 )
δ(s, vi+1 ).
(Induktionsvoraussetzung)
(kürzester Weg)
Die letzte Gleichheit folgt daraus, dass v0 , v1 , . . . , vk ein kürzester Weg ist. Insbesondere
ist also der kürzeste Weg von s nach vi+1 derjenige, der über vi läuft.
4 Damit
5 Ist
so ein Pfad existiert muss angenommen werden, dass kein Zyklus negativer Länge existiert.
der kürzeste Weg nicht eindeutig, so wählen wir zufällig einen der in Frage kommenden Pfade aus.
7
Summa summarum wissen wir also, dass nach dem (i+1)-ten Durchlauf zumindest d(vi+1 ) ≤
δ(s, vi+1 ) gilt. Da d(vi+1 ) aber nicht echt kleiner sein kann,6 muss die Gleichheit gelten.
Laut Konstruktion des Algorithmus können die Werte in d(v) nie zunehmen. Wir wissen somit
also, dass uns auch während bzw. nach allen übrigen Iterationen der korrekte Wert δ(s, v) in
d(v) erhalten bleibt. Abschließend wollen wir uns noch Zyklen negativer Länge zuwenden.
Behauptung 3. Der Algorithmus informiert uns genau dann über einen Zyklus negativer Länge,
wenn ein solcher existiert.
Beweis. Existieren keine Zyklen negativer Länge, so wissen wir aus Satz 2 (Seite 6), dass d(v) =
δ(s, v) ∀v gilt. Klarerweise ist die Länge des minimalen Weges nie größer als die eines beliebigen.
Mit anderen Worten gilt
d(v) ≤ d(u) + w(u, v)
∀(u, v) ∈ E
und der Algorithmus meldet (richtigerweise) keinen Zyklus.
Sei nun v0 , v1 , . . . , vk , vk+1 = v0 ein Zyklus negativer Länge. Dann gilt logischerweise
k
∑ w(vi , vi+1 ) < 0.
i=0
Der Beweis läuft nun indirekt: Angenommen wir erhalten keine Rückmeldung über die Existenz
des Zyklus. Dann muss aber wiederum
d(v) ≤ d(u) + w(u, v)
∀(u, v) ∈ E
gelten. Einsetzen, subtrahieren und aufsummieren führt uns nun zu
d(vi+1 )
d(vi+1 ) − d(vi)
∑ki=0 d(vi+1 ) − d(vi )
≤
≤
d(vi ) + w(vi , vi+1 )
w(vi , vi+1 )
i = 0, . . . , k
i = 0, . . . , k
≤
∑ki=0 w(vi , vi+1 )
(Teleskopsumme)
v0
k
z}|{
d(vk+1 ) − d(v0 )
|
{z
}
=0
≤
∑ w(vi , vi+1 )
i=0
|
{z
<0
}
und somit zu einem Widerspruch. Vorausgesetzt dass ein negativer Zyklus existiert, werden wir
also auch über dessen Existenz informiert. Diese drei Sätze – Satz 1 von Seite 6, Behauptung 2 (Seite 6) und Aussage 3 von weiter oben –
liefern uns in Summe die gesuchte Korrektheit des Algorithmus.
Natürlich ist somit auch der Gesamtalgorithmus (also das Hintereinanderausführen für jeden
Knoten) korrekt.
5
Die Laufzeit
Diese lässt sich ganz einfach aus der Pseudo-Implementation in Abbildung 1 auf Seite 2 ersehen:
Zuerst wird |V | mal initialisiert, danach durchlaufen wir (ca.) |V | mal eine Schleife in der wir |E|
mal etwas überprüfen. Zum Schluss wird abermals |E| mal nachgeschaut.
In Summe erhalten wir für die Berechnung der kürzesten Wege eines Knotens zu allen anderen einen Aufwand von
O(|V | + |V |·|E| + |E|) = O(|V |·|E|).
6 d(v) ist ja immer die Länge des kürzesten bisher gefundenen Weges von s nach v. Diese kann logischerweise nie kleiner als die des allerkürzesten welchen sein.
8
Schlussendlich werden diese Berechnungen für jeden Knoten ausgeführt, was zu einer Worst
Case Laufzeit von
O(|V |·|V |·|E|) = O(|V |2 ·|E|)
führt.
Literatur
[1] B RAINY E NCYCLOPEDIA: Bellman-Ford algorithm.
http://tinyurl.com/5kbrr.
[2] E RICKSON , J EFF: Combinatorial Algorithms. uploaded at
http://compgeom.cs.uiuc.edu/~jeffe/teaching/373/, Fall 2002. Lecture 11: Shortest Paths. 2
[3] K RUMKE , S VEN O LIVER, H ARTMUT N OLTEMEIER, S TEFAN S CHWARZ und H ANS C HRISTOPH W IRTH: Graphentheoretische Konzepte und Algorithmen. Skriptum zur gleichnamigen Vorlesung an der Universität Würzburg, 9. März 2000.
9
Herunterladen