Zaawansowane algorytmy i struktury danych/Wykład 5: Różnice pomiędzy wersjami
Nie podano opisu zmian |
|||
Linia 1: | Linia 1: | ||
== Abstrakt == | == Abstrakt == | ||
Pierwsza część tego wykładu poświęcona będzie problemowi obliczania | Pierwsza część tego wykładu poświęcona będzie problemowi obliczania najkrótszych ścieżek w grafie z jednego źródła w przypadku, w którym wagi krawędzi mogą być ujemne. Zaprezentujemy algorytm Bellmana-Forda, który rozwiązuje ten problem w czasie <math>O(|V||E|)</math>. W drugiej części zajmiemy się problemem obliczania odległości między wszystkimi parami wierzchołków. Pokażemy związki tego problemu z mnożeniem macierzy. | ||
najkrótszych ścieżek w grafie z jednego źródła w przypadku, w którym | |||
wagi krawędzi mogą być ujemne. Zaprezentujemy algorytm | |||
Bellmana-Forda, który rozwiązuje ten problem w czasie | |||
<math>O(|V||E|)</math>. W drugiej części zajmiemy się problemem | |||
obliczania odległości między wszystkimi parami wierzchołków. | |||
Pokażemy związki tego problemu z mnożeniem macierzy. | |||
== Definicja problemu == | == Definicja problemu == | ||
W wykładzie tym zajmiemy się problemem obliczania najkrótszych | W wykładzie tym zajmiemy się problemem obliczania najkrótszych ścieżek w grafie wychodzących z jednego wierzchołka. Załóżmy, że mamy dany graf <math>G = (V,E)</math>, funkcję <math>w: E \to \mathcal{R}</math> przypisującą wagi krawędziom oraz jeden wybrany wierzchołek <math>s</math>. {{kotwica|waga_ścieżki|'''Wagę'''|}} ścieżki <math>p=(v_0,v_1,\ldots,v_k)</math> definiujemy jako wagę tworzących ją krawędzi: | ||
ścieżek w grafie wychodzących z jednego wierzchołka. Załóżmy, że | |||
mamy dany graf <math>G = (V,E)</math>, funkcję <math>w: E \to | |||
\mathcal{R}</math> przypisującą wagi krawędziom oraz jeden wybrany | |||
wierzchołek <math>s</math>. '''Wagę''' ścieżki | |||
<math>p=(v_0,v_1,\ldots,v_k)</math> definiujemy jako wagę tworzących | |||
ją krawędzi: | |||
{{wzor2|1= | |||
<math> | |||
w(p) = \sum_{i=0}^{k-1} w(v_{i}, v_{i+1}). | w(p) = \sum_{i=0}^{k-1} w(v_{i}, v_{i+1}). | ||
</math> | </math>}} | ||
'''Odległość''' z wierzchołka <math>u</math> do wierzchołka | {{kotwica|odległość|'''Odległość'''}} z wierzchołka <math>u</math> do wierzchołka <math>v</math> definiujemy jako | ||
<math>v</math> definiujemy jako | |||
{{wzor2|1= | |||
<math> | |||
\delta(u,v) = \begin{cases} | \delta(u,v) = \begin{cases} | ||
\min\{w(p): p \mbox{ ścieżka z } u \mbox{ do } v\}, & \mbox{jeżeli istnieje ścieżka z } u \mbox{ do } v,\\ | \min\{w(p): p \mbox{ ścieżka z } u \mbox{ do } v\}, & \mbox{jeżeli istnieje ścieżka z } u \mbox{ do } v,\\ | ||
\infty & \mbox{w przeciwnym przypadku.} | \infty & \mbox{w przeciwnym przypadku.} | ||
\end{cases} | \end{cases} | ||
</math | </math> | ||
}} | |||
'''Najkrótszą ścieżką''' z wierzchołka <math>u</math> do wierzchołka | {{kotwica|najkrótsza_ścieżka|'''Najkrótszą ścieżką'''}} z wierzchołka <math>u</math> do wierzchołka <math>v</math> jest każda ścieżka <math>p</math> z <math>u</math> do <math>v</math>, której waga <math>w(p)</math> jest równa odległości <math>\delta(u,v)</math> z <math>u</math> do <math>v</math>. | ||
<math>v</math> jest każda ścieżka <math>p</math> z <math>u</math> do | |||
<math>v</math>, której waga <math>w(p)</math> jest równa odległości | |||
<math>\delta(u,v)</math> z <math>u</math> do <math>v</math>. | |||
'''W problemie najkrótszych ścieżek z jednego wierzchołka''' chcemy | {{kotwica|problem_sssp|'''W problemie najkrótszych ścieżek z jednego wierzchołka'''}} chcemy obliczyć odległości <math>\delta(s,v)</math> dla wszystkich wierzchołków <math>v\in V</math> wraz z drzewem najkrótszych ścieżek z <math>s</math>. {{kotwica|drzewo_najkrótszych_ścierzek|'''Drzewem najkrótszych ścieżek'''}} o korzeniu w <math>s</math> nazywamy podgraf skierowany <math>G' = (V', E')</math>, w którym <math>V' \subseteq V</math>, <math>E' \subseteq E</math> taki, że: | ||
obliczyć odległości <math>\delta(s,v)</math> dla wszystkich | * V' jest zbiorem wierzchołków w <math>G</math> do których istnieje ścieżka z <math>s</math>, | ||
wierzchołków <math>v\in V</math> wraz z drzewem najkrótszych ścieżek z <math>s</math>. | |||
nazywamy podgraf skierowany <math>G' = (V', E')</math>, w którym | |||
* V' jest zbiorem wierzchołków w <math>G</math> do których istnieje ścieżka | |||
* <math>G'</math> jest drzewem którego korzeniem jest <math>s</math>, | * <math>G'</math> jest drzewem którego korzeniem jest <math>s</math>, | ||
* dla każdego wierzchołka <math>v\in V'</math> jedyna ścieżka z <math>s</math> | * dla każdego wierzchołka <math>v\in V'</math> jedyna ścieżka z <math>s</math> | ||
do <math>v</math> w grafie <math>G'</math> jest najkrótszą ścieżką z <math>s</math> do <math>v</math> w grafie <math>G</math>. | |||
W naszych algorytmach drzewo najkrótszych ścieżek będziemy | W naszych algorytmach drzewo najkrótszych ścieżek będziemy reprezentować jako {{kotwica|funkcja_poprzedników|'''funkcję poprzedników'''}} <math>\pi:V \to V</math> określającą poprzednika wierzchołka <math>v</math> w drzewie najkrótszych ścieżek. Drzewo najkrótszych ścieżek <math>G'=(V',E')</math> możemy uzyskać z <math>\pi</math> w następujący sposób: | ||
reprezentować jako {{kotwica|funkcja_poprzedników|'''funkcję poprzedników'''}} <math>\pi:V \to V</math> określającą | |||
poprzednika wierzchołka <math>v</math> w drzewie najkrótszych | |||
ścieżek. Drzewo najkrótszych ścieżek <math>G'=(V',E')</math> możemy | |||
uzyskać z <math>\pi</math> w następujący sposób: | |||
Linia 71: | Linia 45: | ||
== Historia Problemu == | == Historia Problemu == | ||
W dalszej części tego wykładu zajmiemy się przedstawieniem algorytmu | W dalszej części tego wykładu zajmiemy się przedstawieniem algorytmu Bellmana-Forda, który jest jednym z kilku rozwiązań dla problemu obliczania najkrótszych ścieżek z jednego wierzchołka w grafie. Metoda ta jest oparta na dwóch oddzielnych algorytmach podanych przez Bellmana <!--<ref name=Bellman58>R. Bellman, On a Routing Problem, ''Quarterly of Applied Mathematics'', 16(1):87--90, 1958</ref>--> oraz Forda <!--<ref name=Ford56>L.R. Ford Jr, Network Flow Theory, Paper P-923, The RAND Corporation, Santa Monica, California, August 1956.</ref>--> Bellman opisał związek między problemem najkrótszych ścieżek a problemem ograniczeń liniowych (zobacz [[Zaawansowane_algorytmy_i_struktury_danych/ZASD_Ćwiczenia_5#Zadanie_1|Zadania 1]]), natomiast Ford podał jak rozwiązać ten drugi problem. Algorytm Bellmana-Forda jest najszybszym znanym algorytmem w pełni wielomianowym. Istnieje kilka szybszych algorytmów, które działają jednak tylko w przypadku całkowitoliczbowych wag krawędzi, a ich złożoność zależy od maksymalnej wagi krawędzi w grafie. Wszystkie te algorytmy przedstawione są w poniższej tabeli. Co ciekawe mimo, że jest to jeden z najbardziej klasycznych problemów algorytmiki, to jest on nadal żywy i najnowsze z tych algorytmów powstały w ostatnich latach. | ||
Bellmana-Forda, który jest jednym z kilku rozwiązań dla | |||
problemu obliczania najkrótszych ścieżek z jednego wierzchołka w | |||
grafie. Metoda ta jest oparta na dwóch oddzielnych algorytmach | |||
podanych przez Bellmana <!--<ref name=Bellman58>R. Bellman, On a Routing | |||
Problem, ''Quarterly of Applied Mathematics'', 16(1):87--90, | |||
1958</ref>--> oraz Forda <!--<ref name=Ford56>L.R. Ford Jr, Network Flow | |||
Theory, Paper P-923, The RAND Corporation, Santa Monica, California, | |||
August 1956.</ref>--> Bellman opisał związek między problemem | |||
najkrótszych ścieżek a problemem ograniczeń liniowych (zobacz | |||
[[Zaawansowane_algorytmy_i_struktury_danych/ZASD_Ćwiczenia_5#Zadanie_1|Zadania 1]]), | |||
natomiast Ford podał jak rozwiązać ten drugi problem. | |||
Algorytm Bellmana-Forda jest najszybszym znanym algorytmem | |||
w pełni wielomianowym. Istnieje kilka szybszych algorytmów, które | |||
działają jednak tylko w przypadku całkowitoliczbowych wag krawędzi, | |||
a ich złożoność zależy od maksymalnej wagi krawędzi w grafie. | |||
Wszystkie te algorytmy przedstawione są w poniższej tabeli. Co | |||
ciekawe mimo, że jest to jeden z najbardziej klasycznych problemów | |||
algorytmiki, to jest on nadal żywy i najnowsze z tych algorytmów | |||
powstały w ostatnich latach. | |||
{| border="1" style="width:500px;" | {| border="1" style="width:500px;" | ||
Linia 98: | Linia 53: | ||
| <math>O(n^4)</math> | | <math>O(n^4)</math> | ||
| Shimbel (1995)<!--<ref name=Shimbel55> | | Shimbel (1995)<!--<ref name=Shimbel55> | ||
A. Shimbel, Structure in Communication Nets, In | A. Shimbel, Structure in Communication Nets, In ''In Proceedings of the Symposium on Information Networks'', pages 199--203. Polytechnic Press of the Polytechnic Institute of Brooklyn, Brooklyn, 1955. | ||
''In Proceedings of the Symposium on Information Networks'', pages 199--203. | |||
Polytechnic Press of the Polytechnic Institute of Brooklyn, Brooklyn, 1955. | |||
</ref>--> | </ref>--> | ||
|- | |- | ||
Linia 121: | Linia 74: | ||
== Algorytm Bellmana-Forda == | == Algorytm Bellmana-Forda == | ||
'''Algorytm Bellmana-Forda''' służy do rozwiązania problemu | '''Algorytm Bellmana-Forda''' służy do rozwiązania problemu znalezienia najkrótszych ścieżek w grafie, w którym wagi krawędzi mogą być ujemne. W problemie tym mamy dany graf <math>G=(V,E)</math> i funkcję wagową <math>w:E \to \mathcal{R}</math>. Algorytm Bellmana-Forda wylicza dla zadanego wierzchołka <math>s</math>, czy istnieje w grafie <math>G</math> cykl o ujemnej wadze osiągalny z <math>s</math>. Jeżeli taki cykl nie istnieje to algorytm oblicza najkrótsze ścieżki z <math>s</math> do wszystkich pozostałych | ||
znalezienia najkrótszych ścieżek w grafie, w którym wagi krawędzi | |||
mogą być ujemne. W problemie tym mamy dany graf <math>G=(V,E)</math> | |||
i funkcję wagową <math>w:E \to \mathcal{R}</math>. Algorytm | |||
Bellmana-Forda wylicza dla zadanego wierzchołka <math>s</math>, czy | |||
istnieje w grafie <math>G</math> cykl o ujemnej wadze osiągalny z | |||
<math>s</math>. Jeżeli taki cykl nie istnieje to algorytm oblicza | |||
najkrótsze ścieżki z <math>s</math> do wszystkich pozostałych | |||
wierzchołków wraz z ich wagami. | wierzchołków wraz z ich wagami. | ||
=== Relaksacja === | === Relaksacja === | ||
Podobnie ja to było w [[algorytm_dijkstry|Algorytmie Dijkstry]] | Podobnie ja to było w [[algorytm_dijkstry|Algorytmie Dijkstry]] użyjemy metody relaksacji. Metoda ta polega na tym, że w trakcie działania algorytmu dla każdego wierzchołka <math>v \in V</math> utrzymujemy wartość <math>d(v)</math> będącą górnym ograniczeniem wagi najkrótszej ścieżki ze <math>s</math> do <math>v</math>. W algorytmie utrzymywać będziemy także dla każdego wierzchołka <math>v</math> wskaźnik <math>\pi(v)</math> wskazujący na poprzedni wierzchołek przez który prowadzi dotychczas znaleziona najkrótsza ścieżka. Na początku, wielkości te inicjujemy przy pomocy następującej procedury: | ||
użyjemy metody relaksacji. Metoda ta polega na tym, że w trakcie | |||
działania algorytmu dla każdego wierzchołka <math>v \in V</math> | |||
utrzymujemy wartość <math>d(v)</math> będącą górnym ograniczeniem | |||
wagi najkrótszej ścieżki ze <math>s</math> do <math>v</math>. W | |||
algorytmie utrzymywać będziemy także dla każdego wierzchołka | |||
<math>v</math> wskaźnik <math>\pi(v)</math> wskazujący na poprzedni | |||
wierzchołek przez który prowadzi dotychczas znaleziona najkrótsza | |||
ścieżka. Na początku, wielkości te inicjujemy przy pomocy | |||
następującej procedury: | |||
Linia 154: | Linia 91: | ||
Ustalone przez tą procedurę wartości <math>d(v)</math> są dobrymi ograniczeniami | Ustalone przez tą procedurę wartości <math>d(v)</math> są dobrymi ograniczeniami górnymi na odległości. | ||
górnymi na odległości. | |||
'''Relaksacja''' krawędzi <math>(u,v)</math> polega na | {{kotwica|relaksacja|'''Relaksacja'''}} krawędzi <math>(u,v)</math> polega na sprawdzeniu, czy przechodząc krawędzią <math>(u,v)</math> z <math>u</math> do <math>v</math>, nie otrzymamy krótszej ścieżki z <math>s</math> do <math>v </math>niż ta dotychczas znaleziona. Jeżeli tak, to aktualizowane są także wartości <math>d(v)</math> i <math>\pi(v)</math>. W celu relaksacji krawędzi <math>(u,v)</math> używamy procedury RELAKSUJ. | ||
sprawdzeniu, czy przechodząc krawędzią <math>(u,v)</math> z | |||
<math>u</math> do <math>v</math>, nie otrzymamy krótszej ścieżki z | |||
<math>s</math> do <math>v </math>niż ta dotychczas znaleziona. | |||
Jeżeli tak, to aktualizowane są także wartości <math>d(v)</math> i | |||
<math>\pi(v)</math>. W celu relaksacji krawędzi <math>(u,v)</math> | |||
używamy procedury RELAKSUJ. | |||
{{algorytm|Relaksacja krawędzi|algorytm_relaksacja_krawędzi| | {{algorytm|Relaksacja krawędzi|algorytm_relaksacja_krawędzi| | ||
Linia 174: | Linia 104: | ||
=== Algorytm === | === Algorytm === | ||
Po przypomnieniu czym była relaksacja gotowi jesteśmy na zapisanie algorytmu | Po przypomnieniu czym była relaksacja gotowi jesteśmy na zapisanie algorytmu Bellmana-Forda, a następnie udowodnienie jego poprawności. | ||
Bellmana-Forda, a następnie udowodnienie jego poprawności. | |||
{{algorytm|Bellmana-Forda|algorytm_Bellmana-Forda| | {{algorytm|Bellmana-Forda|algorytm_Bellmana-Forda| | ||
Linia 191: | Linia 120: | ||
Poniższa animacja przedstawia działanie algorytmu dla grafu o pięciu wierzchołkach. | Poniższa animacja przedstawia działanie algorytmu dla grafu o pięciu wierzchołkach. | ||
Algorytm ten działa w czasie <math>O(|V||E|)</math>, co łatwo pokazać gdyż: | Algorytm ten działa w czasie <math>O(|V||E|)</math>, co łatwo pokazać gdyż: | ||
* proces inicjacji w linii 1 zajmuje czas <math>O(|V|)</math>, | * proces inicjacji w linii 1 zajmuje czas <math>O(|V|)</math>, | ||
* w każdym z <math>|V|</math> przebiegów głównej pętli w linii 2 algorytmu przeglądane są wszystkie krawędzie grafu w linii 3 , co zajmuje czas <math>O(|V||E|)</math>, | * w każdym z <math>|V|</math> przebiegów głównej pętli w linii 2 algorytmu przeglądane są wszystkie krawędzie grafu w linii 3 , co zajmuje czas <math>O(|V||E|)</math>, | ||
Linia 226: | Linia 155: | ||
{{wzor2|1=<math> | |||
d(v) = \delta(s,v) \le \delta(s,u) + w(u,v) = d(u) + w(u,v). | d(v) = \delta(s,v) \le \delta(s,u) + w(u,v) = d(u) + w(u,v). | ||
</math> | </math>}} | ||
Linia 243: | Linia 172: | ||
{{wzor2|1=<math> | |||
\sum_{i=0}^{k-1} \left[d(v_i) + w(v_i, v_{i+1})\right] \ge \sum_{i=0}^{k-1} d(v_{i+1}), | \sum_{i=0}^{k-1} \left[d(v_i) + w(v_i, v_{i+1})\right] \ge \sum_{i=0}^{k-1} d(v_{i+1}), | ||
</math> | </math>}} | ||
{{wzor2|1=<math> | |||
\sum_{i=0}^{k-1} d(v_i) + \sum_{i=0}^{k-1} w(v_i, v_{i+1}) \ge \sum_{i=1}^{k} d(v_{i}), | \sum_{i=0}^{k-1} d(v_i) + \sum_{i=0}^{k-1} w(v_i, v_{i+1}) \ge \sum_{i=1}^{k} d(v_{i}), | ||
</math> | </math>}} | ||
Linia 255: | Linia 184: | ||
{{wzor2|1=<math> | |||
\sum_{i=0}^{k-1} d(v_i) + \sum_{i=0}^{k-1} w(v_i, v_{i+1}) \ge \sum_{i=0}^{k-1} d(v_{i}). | \sum_{i=0}^{k-1} d(v_i) + \sum_{i=0}^{k-1} w(v_i, v_{i+1}) \ge \sum_{i=0}^{k-1} d(v_{i}). | ||
</math> | </math>}} | ||
Linia 263: | Linia 192: | ||
{{wzor2|1=<math> | |||
\sum_{i=0}^{k-1} w(v_i, v_{i+1}) \ge 0, | \sum_{i=0}^{k-1} w(v_i, v_{i+1}) \ge 0, | ||
</math> | </math>}} | ||
co stoi w sprzeczności z [[#wzor_cykl|nierównością (1)]]. Jeżeli więc w grafie istnieje cykl o ujemnej wadze osiągalny z <math>s</math>, to algorytm zwróci FALSE. | co stoi w sprzeczności z [[#wzor_cykl|nierównością (1)]]. Jeżeli więc w grafie istnieje cykl o ujemnej wadze osiągalny z <math>s</math>, to algorytm zwróci FALSE. | ||
}} | }} |
Wersja z 18:50, 23 lip 2006
Abstrakt
Pierwsza część tego wykładu poświęcona będzie problemowi obliczania najkrótszych ścieżek w grafie z jednego źródła w przypadku, w którym wagi krawędzi mogą być ujemne. Zaprezentujemy algorytm Bellmana-Forda, który rozwiązuje ten problem w czasie . W drugiej części zajmiemy się problemem obliczania odległości między wszystkimi parami wierzchołków. Pokażemy związki tego problemu z mnożeniem macierzy.
Definicja problemu
W wykładzie tym zajmiemy się problemem obliczania najkrótszych ścieżek w grafie wychodzących z jednego wierzchołka. Załóżmy, że mamy dany graf , funkcję przypisującą wagi krawędziom oraz jeden wybrany wierzchołek . Wagę ścieżki definiujemy jako wagę tworzących ją krawędzi:
Odległość z wierzchołka do wierzchołka definiujemy jako
Najkrótszą ścieżką z wierzchołka do wierzchołka jest każda ścieżka z do , której waga jest równa odległości z do .
W problemie najkrótszych ścieżek z jednego wierzchołka chcemy obliczyć odległości dla wszystkich wierzchołków wraz z drzewem najkrótszych ścieżek z . Drzewem najkrótszych ścieżek o korzeniu w nazywamy podgraf skierowany , w którym , taki, że:
* V' jest zbiorem wierzchołków w do których istnieje ścieżka z , * jest drzewem którego korzeniem jest , * dla każdego wierzchołka jedyna ścieżka z
do w grafie jest najkrótszą ścieżką z do w grafie .
W naszych algorytmach drzewo najkrótszych ścieżek będziemy reprezentować jako funkcję poprzedników określającą poprzednika wierzchołka w drzewie najkrótszych ścieżek. Drzewo najkrótszych ścieżek możemy uzyskać z w następujący sposób:
Historia Problemu
W dalszej części tego wykładu zajmiemy się przedstawieniem algorytmu Bellmana-Forda, który jest jednym z kilku rozwiązań dla problemu obliczania najkrótszych ścieżek z jednego wierzchołka w grafie. Metoda ta jest oparta na dwóch oddzielnych algorytmach podanych przez Bellmana oraz Forda Bellman opisał związek między problemem najkrótszych ścieżek a problemem ograniczeń liniowych (zobacz Zadania 1), natomiast Ford podał jak rozwiązać ten drugi problem. Algorytm Bellmana-Forda jest najszybszym znanym algorytmem w pełni wielomianowym. Istnieje kilka szybszych algorytmów, które działają jednak tylko w przypadku całkowitoliczbowych wag krawędzi, a ich złożoność zależy od maksymalnej wagi krawędzi w grafie. Wszystkie te algorytmy przedstawione są w poniższej tabeli. Co ciekawe mimo, że jest to jeden z najbardziej klasycznych problemów algorytmiki, to jest on nadal żywy i najnowsze z tych algorytmów powstały w ostatnich latach.
Złożoność | Autor |
---|---|
Shimbel (1995) | |
Ford (1956), Bellman (1958) | |
Gabow (1983) | |
Gabow and Tarjan (1989) | |
Goldberg (1993) | |
Yuster and Zwick (2005), Sankowski (2005) |
Algorytm Bellmana-Forda
Algorytm Bellmana-Forda służy do rozwiązania problemu znalezienia najkrótszych ścieżek w grafie, w którym wagi krawędzi mogą być ujemne. W problemie tym mamy dany graf i funkcję wagową . Algorytm Bellmana-Forda wylicza dla zadanego wierzchołka , czy istnieje w grafie cykl o ujemnej wadze osiągalny z . Jeżeli taki cykl nie istnieje to algorytm oblicza najkrótsze ścieżki z do wszystkich pozostałych wierzchołków wraz z ich wagami.
Relaksacja
Podobnie ja to było w Algorytmie Dijkstry użyjemy metody relaksacji. Metoda ta polega na tym, że w trakcie działania algorytmu dla każdego wierzchołka utrzymujemy wartość będącą górnym ograniczeniem wagi najkrótszej ścieżki ze do . W algorytmie utrzymywać będziemy także dla każdego wierzchołka wskaźnik wskazujący na poprzedni wierzchołek przez który prowadzi dotychczas znaleziona najkrótsza ścieżka. Na początku, wielkości te inicjujemy przy pomocy następującej procedury:
Algorytm Inicjacja algorytmu najkrótszych ścieżek
INICJACJA for każdy wierzchołek do
Ustalone przez tą procedurę wartości są dobrymi ograniczeniami górnymi na odległości.
Relaksacja krawędzi polega na sprawdzeniu, czy przechodząc krawędzią z do , nie otrzymamy krótszej ścieżki z do niż ta dotychczas znaleziona. Jeżeli tak, to aktualizowane są także wartości i . W celu relaksacji krawędzi używamy procedury RELAKSUJ.
Algorytm Relaksacja krawędzi
RELAKSUJ if then
Algorytm
Po przypomnieniu czym była relaksacja gotowi jesteśmy na zapisanie algorytmu Bellmana-Forda, a następnie udowodnienie jego poprawności.
Algorytm Bellmana-Forda
BELLMAN-FORD 1 INICJUJ 2 for to do 3 for każda krawędź do 4 RELAKSUJ 5 for każda krawędź do 6 if ' then 7 return FALSE 8 return TRUE
Poniższa animacja przedstawia działanie algorytmu dla grafu o pięciu wierzchołkach.
Algorytm ten działa w czasie , co łatwo pokazać gdyż:
- proces inicjacji w linii 1 zajmuje czas ,
- w każdym z przebiegów głównej pętli w linii 2 algorytmu przeglądane są wszystkie krawędzie grafu w linii 3 , co zajmuje czas ,
- końcowa pętla algorytmu w liniach 5-7 działa w czasie .
Poprawność
Dowód poprawności algorytmu Bellmana-Forda zaczniemy od pokazania, że algorytm działa poprawnie przy założeniu, że w grafie nie ma cykli o ujemnych wagach.
Lemat 1
Dowód
Zauważmy, że teza indukcyjna zachodzi po inicjacji algorytmu, gdyż Załóżmy, że teza indukcyjna zachodzi dla kroku 'tego. Ponieważ ścieżki dla są najkrótsze jako podścieżki ścieżki , to po wykonaniu pętli wartości dla się nie zmienią. Pozostaje nam więc do pokazania to, że wartość będzie dobrze policzona. W przebiegu wykonujemy między innymi relaksację krawędzi . Ponieważ jest dobrze policzone, to po tej relaksacji wyznaczona będzie także poprawnie wartość , bo założyliśmy, że najkrótsza ścieżka do przechodzi przez .
Pozostaje nam jedynie zastanowić się co się dzieje gdy wierzchołek nie jest osiągalny z . Musi wtedy zachodzić pod koniec działania algorytmu. Gdyby tak nie było to oznaczałoby, z właściwości procedury RELAKSUJ, że istnieje ścieżka od do . Sprzeczność.
Dowód
Dowód ten można przeprowadzić w podobny sposób do dowodu Lematu 1.

Twierdzenie 3
{{dowod|||3=Załóżmy najpierw, że graf nie zawiera cykli o ujemnej wadze, które byłyby osiągalne z . Wtedy z Lematu 1 wiemy, że są poprawnie policzonymi odległościami. Jeżeli odległości zostały poprawnie policzone przez funkcję RELAKSUJ to koduje najkrótsze ścieżki w grafie. Wynika to z właściwości [[#algorytm_relaksacja_krawędzi|funkcji RELAKSUJ], która wyliczając odległość wyznaczą jednocześnie przez jaki wierzchołek prowadzi ta najkrótsza ścieżka.
Musimy teraz pokazać, że algorytm poprawnie wykrywa, czy w grafie istnieje cykl ujemnej długości osiągalny z . Jeżeli nie ma takiego cyklu to wtedy są poprawnie policzone przed wykonaniem testu w liniach 5-8 algorytmu Bellmana-Forda. W takim razie zachodzi:
Powyższa nierówność zachodzi ponieważ jest ścieżką w grafie, a więc jest nie krótsza niż najkrótsza ścieżka . Widzimy więc, że w tym przypadku żaden z testów w linijce 6 algorytmu nie będzie spełniony i algorytm zwróci TRUE.
Załóżmy teraz, że w grafie istnieje cykl o ujemnej wadze osiągalny z . Oznaczmy ten cykl jako , gdzie . Dla cyklu tego mamy:
(1)
Gdyby w tej sytuacji algorytm Bellmana-Forda zwrócił wartość TRUE to dla każdej krawędzi musiałaby zachodzić nierówność . Sumując tą nierówność stronami po wszystkich otrzymujemy.
ponieważ to
Wiemy, że cykl jest osiągalny a zatem dla każdego mamy . Możemy więc skrócić po obydwu stronach równania i otrzymujemy:
co stoi w sprzeczności z nierównością (1). Jeżeli więc w grafie istnieje cykl o ujemnej wadze osiągalny z , to algorytm zwróci FALSE.
}}