Najkrótsze drogi
w grafach z wagami
dr Andrzej Mróz (UMK w Toruniu) 2013
Projekt wspóªnansowany ze ±rodków Unii Europejskiej w ramach Europejskiego Funduszu Spoªecznego Projekt pn. Wzmocnienie potencjaªu dydaktycznego UMK w Toruniu w dziedzinach
matematyczno-przyrodniczych
Spis tre±ci
1 Wst¦p 3 1.1 Problem . . . 3 2 Grafy z wagami 3 2.1 Graf z wagami . . . 3 2.2 Przykªad . . . 32.3 Reprezentacje grafu z wagami . . . 4
2.4 Waga drogi . . . 5
2.5 Najkrótsze drogi w grae z wagami . . . 5
2.6 Problem cykli ujemnych . . . 6
2.7 Warianty problemu najkrótszych dróg . . . 6
3 Przygotowanie 7 3.1 Oznaczenia i konwencje . . . 7 3.2 Procedura relaksacji . . . 7 3.3 Poprawno±¢ . . . 8 3.4 Inicjalizacja . . . 8 4 Dijkstra 8 4.1 Specykacja . . . 8 4.2 Ogólna idea . . . 8
4.3 Kolejka priorytetowa - przypomnienie . . . 9
4.4 Kolejka priorytetowa - relaksacja . . . 9
4.5 Algorytm . . . 10 4.6 Algorytm - zªo»ono±¢ . . . 10 4.7 Algorytm - przebieg . . . 11 4.8 Algorytm - wyniki . . . 12 5 Bellman-Ford 12 5.1 Uwagi wst¦pne . . . 12 5.2 Specykacja . . . 12 5.3 Algorytm . . . 13
1 Wst¦p
1.1 Problem
Na poprzednim wykªadzie omawiali±my problem znajdowania najkrótszych dróg w grae (algo-rytm BFS), przy czym najkrótsze drogi oznaczaªy drogi o najmniejszej liczbie kraw¦dzi.
W praktycznych zastosowaniach rzeczywisto±¢ lepiej modeluj¡ grafy, w których kraw¦dzie maj¡ dªugo±¢ (inaczej koszt = wag¦).
Na tym wykªadzie zajmiemy si¦ zagadnieniem poszukiwania najkrótszych dróg wzgl¦dem tego dodatkowego parametru.
Algorytm BFS wykorzystywaª kolejk¦. Przedstawimy algorytm Dijkstry, który b¦dzie w pewnym sensie modykacj¡ algorytmu BFS, wykorzystuj¡c¡ tym razem kolejk¦ priorytetow¡ (ze wzgl¦du na dodatkowy parametr, wag¦).
Przedstawimy te» inne podej±cie, algorytm Bellmana-Forda, realizuj¡cy zbli»one zadanie. Ma on gorsz¡ zªo»ono±¢ ale jest prostszy w implementacji (nie korzysta z kolejki priorytetowej).
Algorytmy te, zwªaszcza algorytm Dijkstry, s¡ w praktyce wykorzystywane w • routingu sieciowym,
• ro»nego rodzaju urz¡dzeniach nawigacyjnych (jak GPS...), • aplikacjach zwi¡zanych z mapami (jak Google Maps), • planowaniu lotów,
• sieciach telefonicznych,
• i innych, bardziej specjalistycznych zagadnieniach. Zaczniemy od sformalizowania problemu.
2 Grafy z wagami
2.1 Graf z wagami
Denicja. Grafem z wagami nazywamy graf (skierowany) G = (V, E) wraz z funkcj¡ wagi w : E → R.
Uwaga. W tej prezentacji ograniczamy si¦ do grafów zorientowanych, algorytmy w wersji niezorientowanej s¡ analogiczne.
Zauwa»my, »e w ogólnej denicji na funkcj¦ wagi nie nakªada si¦ »adnych ogranicze«, w szcze-gólno±ci jej warto±ci mog¡ by¢ ujemne.
2.2 Przykªad
Na rysunku grafu warto±ci funkcji wagi zaznaczamy zazwyczaj przy kraw¦dziach:
-10 5 ? 7 ? 20 @ @ @ R 10 -2 4,5 - −6 w g wg wg w g wg wg 1 2 3 4 5 6
Powy»szy diagram przedstawia graf G = (V, E), gdzie • V = {1, 2, 3, 4, 5, 6},
• E = { (1, 2), (2, 1), (1, 5), (1, 4), (4, 5), (2, 5), (5, 3), (5, 6) }, z funkcj¡ wagi w : E → R okre±lon¡:
w(1, 2) = 10 w(2, 1) = 5 w(1, 5) = 10 w(1, 4) = 7 w(4, 5) = 2 w(2, 5) = 20 w(5, 3) = −6 w(5, 6) = 4, 5.
2.3 Reprezentacje grafu z wagami
Ustalmy graf zorientowany G = (V, E) z funkcj¡ wagi w : E → R.
Najwygodniejsze reprezentacje grafów z wagami to odpowiednie modykacje macierzy s¡siedztwa lub list s¡siedztwa.
Macierz s¡siedztwa (wagowa): macierz A = A(G) ∈ Mn×n(Z) o wspóªczynnikach:
Ai,j =
0, (i, j) /∈ E, w((i, j)), (i, j) ∈ E (analogicznie w wersji niezorientowanej).
Przykªad wagowej macierzy s¡siedztwa.
-10 5 ? 7 ? 20 @ @ @ R 10 -2 4,5 - −6 w g wg wg w g wg wg 1 2 3 4 5 6 Ai,j 1 2 3 4 5 6 1 0 10 0 7 10 0 2 5 0 0 0 20 0 3 0 0 0 0 0 0 4 0 0 0 0 2 0 5 0 0 −6 0 0 4, 5 6 0 0 0 0 0 0
Listy s¡siedztwa (wagowe): tablica Adj[1..n], gdzie Adj[i] = wska¹nik do listy s¡siadów i, tj. tych wierzchoªków j, »e (i, j) ∈ E.
• Ka»dy element j listy s¡siadów wierzchoªka i zawiera dodatkowe pole z wag¡ w(i, j). Przykªad wagowych list s¡siedztwa.
-10 5 ? 7 ? 20 @ @ @ R 10 -2 4,5 - −6 w g wg wg w g wg wg 1 2 3 4 5 6
L[i] 1 → {2; 10} → {5; 10} → {4; 7} 2 → {1; 5} → {5; 20} 3 4 → {5; 2} 5 → {3; −6} → {6; 4, 5} 6
Lista kraw¦dzi (wagowa):
[ [u1, v1, w(u1, v1)], [u2, v2, w(u2, v2)], . . . , [um, vm, w(um, vm)] ],
gdzie E = { (ui, vi) : i = 1, . . . , m }.
Przykªad wagowej listy kraw¦dzi.
-10 5 ? 7 ? 20 @ @ @ R 10 -2 4,5 - −6 w g wg wg w g wg wg 1 2 3 4 5 6 [ [1, 2, 10], [2, 1, 5], [1, 5, 10], [1, 4, 7], [4, 5, 2], [2, 5, 20], [5, 3, −6], [5, 6, 4,5] ] 2.4 Waga drogi
Dla dowolnej drogi P = (v0, v1, . . . , vk) w grae G = (V, E), vi ∈ V, deniujemy jej wag¦ jako
liczb¦ w(P ) := k X i=1 w((vi−1, vi)).
Czyli rozszerzamy denicj¦ funkcji w z kraw¦dzi na wszystkie drogi. Przykªad. -10 5 ? 7 ? 20 @ @ @ R 10 -2 4,5 - −6 w g wg wg w g wg wg 1 2 3 4 5 6 w((1, 2, 5, 3)) = 10 + 20 − 6 = 24, w((1, 2, 1, 4)) = 10 + 5 + 7 = 22, w((1, 2, 1, 2, 5, 6)) = 10 + 5 + 10 + 20 + 4, 5 = 49, 5.
2.5 Najkrótsze drogi w grae z wagami Ustalmy graf G = (V, E) z wagami w : E → R.
Denicja. Waga najkrótszej drogi z u do v, dla u, v ∈ V , to liczba δ(u, v) :=
(
min{w(P ) : u v}, gdy istnieje droga z u do v,P
u v oznacza, »e P jest drog¡ z u do v.P
Uwaga. Minimum w denicji nie zawsze istnieje! Wrócimy do tego za chwil¦. Przykªad. -10 5 ? 7 ? 20 @ @ @ R 10 -2 4,5 - −6 w g wg wg w g wg wg 1 2 3 4 5 6 δ(1, 2) = 10, δ(1, 5) = 9, δ(2, 5) = 14, δ(1, 6) = 13, 5.
2.6 Problem cykli ujemnych Rozwa»my graf z wagami:
5 A A A K 5 -−15 w g w g wg 1 2 3 Wówczas w(1, 2, 3) = −10, w(1, 2, 3, 1, 2, 3) = −15, w(1, 2, 3, 1, 2, 3, 1, 2, 3) = −20, . . . Czyli warto±¢ δ(1, 3) = min{w(P ) : u P
v} jest nieokre±lona! W takiej sytuacji kªadziemy δ(1, 3) := −∞.
Jest to tzw. problem cykli ujemnych. Algorytm poszukiwania najkrótszych dróg powinien sobie z nim radzi¢ (albo go unikn¡¢).
2.7 Warianty problemu najkrótszych dróg 1. Najkrótsze drogi z jednym ¹ródªem.
Analogicznie jak BFS dla grafów bez wag z poprzedniego wykªadu. 2. Najkrótsze drogi z jednym wierzchoªkiem docelowym.
Ten problem mo»na rozwi¡za¢ przy pomocy pierwszego. 3. Najkrótsza droga mi¦dzy par¡ wierzchoªków.
Pokazuje si¦, »e ten problem jest obliczeniowo równowa»ny pierwszemu. Tzn. algo-rytmy szukaj¡ce najkrótszej drogi z u do v, jako skutek uboczny i tak musz¡ wyliczy¢ wszystkie najkrótsze drogi z jednym ¹ródªem u.
4. Najkrótsze drogi mi¦dzy wszystkimi parami wierzchoªków.
Ten problem mo»na rozwi¡za¢ przy pomocy pierwszego (dla wszystkich ¹ródeª). S¡ te» specjalne algorytmy opracowane dla tego konkretnego problemu, np. algorytm Floyda-Warshalla.
W dalszej cz¦±ci wykªadu omówimy dwa ró»ne algorytmy rozwi¡zuj¡ce wariant pierwszy, najkrótsze drogi z jednym ¹ródªem:
1. Algorytm Dijkstry.
2. Algorytm Bellmana-Forda.
3 Przygotowanie
3.1 Oznaczenia i konwencje Ustalmy graf z wagami G = (V, E).
Najkrótsze drogi z jednym ¹ródªem s ∈ V .
• π[v] poprzednik wierzchoªka v na tymczasowej najkrótszej drodze z s do v.
• Dla ka»dego v ∈ V trzymamy atrybut d[v] = oszacowanie wagi najkrótszej drogi = górne ograniczenie wagi najkrótszej drogi z s do v.
W trakcie algorytmów atrybuty (wektory) te b¦d¡ modykowane, by¢ mo»e wielokrotnie na tych samych wspóªrz¦dnych. Warto±ci d[v] b¦d¡ male¢. Po zako«czeniu algorytmów:
• π b¦dzie zawieraª poprzedników na najkrótszych drogach z s,
• d b¦dzie zawieraª wagi najkrótszych dróg z s, tj. d[v] = δ(s, v), dla ka»dego v ∈ V . Poniewa» wykorzystujemy znak ∞ jako stra»nika, ustalamy prost¡ arytmetyk¦ na niesko«-czono±ciach:
• Dla a ∈ R ∪ {∞}, przyjmujemy a + ∞ = ∞ + a = ∞.
• Dla a ∈ R ∪ {−∞}, przyjmujemy a + (−∞) = (−∞) + a = −∞. Realizacja tej arytmetyki zale»y od konkretnej implementacji.
3.2 Procedura relaksacji
Relaksacja (=osªabienie ogranicze«) kraw¦dzi (u, v) sprawdzenie, czy przechodz¡c przez u, mo»na znale¹¢ krótsz¡ od dotychczas najkrótszej drogi do v. Je»eli tak, uaktualniamy warto±ci d[v] i π[v].
Relax(u, v, w)
begin
if d[v] > d[u] + w(u,v)then begin
d[v] := d[u] + w(u,v); π[v] := u
end end;
3.3 Poprawno±¢
Oba algorytmy polegaj¡ na wykonaniu serii relaksacji w odpowiedniej kolejno±ci.
Dowód poprawno±ci obu algorytmów opiera si¦ na nast¦puj¡cych prostych faktach (zwi¡zanych z relaksacj¡).
Lemat 1. Poddroga najkrótszej drogi te» jest najkrótsz¡ drog¡.
Lemat 2 (Nierówno±¢ trójk¡ta). Dla ka»dych u, v, x ∈ V zachodzi nierówno±¢: δ(u, v) ≤ δ(u, x) + δ(x, v).
Peªen dowód pomijamy, mo»na go znale¹¢ np. w ksi¡»ce [1] ze spisu literatury do wykªadu (T. H. Cormen et al.).
3.4 Inicjalizacja
W obu algorytmach wykorzystamy nast¦puj¡c¡ inicjalizacj¦ wektorów π i d: Initialize(G, s) begin for ka»dy v ∈ V(G)do begin d[v] := ∞; π[v] := ∞ end; d[s] := 0 end;
4 Dijkstra
4.1 SpecykacjaPrzypomnijmy, »e przy ujemnych warto±ciach funkcji wagi mog¡ wyst¡pi¢ ujemne cykle. W przy-padku algorytmu Dijkstry po prostu nie dopuszcza si¦ wag ujemnych by unikn¡¢ problemu.
Algorytm Dijkstry.
Dane: graf skierowany G = (V, E), nieujemna funkcja wagi w oraz wierzchoªek ¹ródªowy s ∈ V.
Wynik: dla ka»dego v ∈ V osi¡galnego z s, warto±¢ d[v] = δ(s, v) oraz poprzednik π[v] na najkrótszej drodze z s do v.
4.2 Ogólna idea Strategia (zachªanna):
• S = zbiór wierzchoªków, dla których wagi najkrótszych dróg s¡ policzone, tj. ∀v∈Sd[v] =
δ(s, v).
bierzemy u ∈ V \ S o najmniejszej warto±ci d[u] (⇒ zbiór V \ S kolejka prioryte-towa!);
dodajemy u do S i wykonujemy relaksacj¦ na wszystkich kraw¦dziach u → v. Zbiór S i operacje na nim mo»na pomin¡¢ w implementacji.
4.3 Kolejka priorytetowa - przypomnienie
Kolejka priorytetowa (typu MIN) = struktura danych K, w której elementy s¡ liniowo uporz¡d-kowane (przy pomocy pewnego klucza, inaczej priorytetu) i przetwarzane w kolejno±ci od obiektu o najni»szym priorytecie do obiektu o najwy»szym priorytecie.
Operacja:
• ExtractMin(K) zwrócenie i usuni¦cie elementu o najni»szym priorytecie z kolejki K. Uwaga. W algorytmie Dijkstry elementami kolejki K b¦d¡ wierzchoªki, ich priorytetami warto±ci d[v].
• Przypomnijmy, »e kolejk¦ priorytetow¡ najefektywniej implementuje si¦ przy pomocy kopca.
• Mo»na te» zasymulowa¢ jej dziaªanie na zwykªej tablicy (wtedy operacja ExtractMin polega m.in. na wyszukaniu minimum w tablicy).
• Mo»na te» u»y¢ gotowych struktur, jak priority_queue biblioteki STL j¦zyka C++ http://www.cplusplus.com/reference/queue/priority_queue/
4.4 Kolejka priorytetowa - relaksacja
Uwaga techniczna: W procedurze relaksacji uaktualniamy warto±ci wektora d (czyli priory-tety):
Relax(u, v, w)
begin
if d[v] > d[u] + w(u,v)then begin
d[v] := d[u] + w(u,v); π[v] := u
end end;
Zatem w zale»no±ci od implementacji kolejki priorytetowej nale»y odpowiednio uaktualni¢ struktur¦ kolejki:
4.5 Algorytm Dijkstra(G, w, s) 1 begin 2 Initialize(G, s); 3 S := ∅; 4 Q := V(G); 5 while Q <> ∅do 6 begin 7 u := ExtractMin(Q); 8 S := S ∪ {u};
9 for ka»dy v ∈ Adj[u] do
10 Relax(u, v, w);
11 end
12 end;
Najwa»niejsze w dowodzie poprawno±ci: dla ka»dego u dodawanego do S mamy d[u] = δ(s, u) (por. 3.3).
4.6 Algorytm - zªo»ono±¢ Zªo»ono±¢ (szkic).
1. Kolejka implementowana na tablicy: • ExtractMin na tablicy: O(|V |);
• wiersz 7 wykonany |V | razy, st¡d skªadnik O(|V |2) w zªo»ono±ci caªego algorytmu;
• dodatkowo wiersz 10 globalnie wykonywany jest O(|E|) razy. ⇒ Zªo»ono±¢ caªego algorytmu
O(|V |2+ |E|) =O(|V |2), gdy» |E| = O(|V |2).
2. Kolejka implementowana na kopcu: • ExtractMin - koszt O(log|V |);
• relaksacja - koszt O(log|V |) (przywrócenie wªasno±ci kopca);
• wiersz 7 globalnie wykonywany jest O(|V |) razy, st¡d skªadnik O(|V |log|V |) w zªo-»ono±ci caªego algorytmu;
• wiersz 10 globalnie wykonywany jest O(|E|) razy, st¡d skªadnik O(|E|log|V |) w zªo-»ono±ci caªego algorytmu.
⇒ Zªo»ono±¢ caªego algorytmu
O((|V | + |E|) · log|V |).
Gdy G jest (sªabo) spójny, to |V | = O(|E|), a zatem wówczas zªo»ono±¢ wynosi
4.7 Algorytm - przebieg Rozwa»my graf G: -10 5 ? 7 ? 20 @ @ @ R 10 -2 4,5 - 6 w g wg wg w g wg wg 1 2 3 4 5 6
Jako wierzchoªek startowy we¹my s = 1. Przypomnijmy pseudokody Dijkstra(G, w, s) 1 begin 2 Initialize(G, s); 3 S := ∅; 4 Q := V(G); 5 while Q <> ∅do 6 begin 7 u := ExtractMin(Q); 8 S := S ∪ {u};
9 for ka»dy v ∈ Adj[u]do
10 Relax(u, v, w);
11 end
12 end;
Relax(u, v, w)
begin
if d[v] > d[u] + w(u,v) then begin
d[v] := d[u] + w(u,v); π[v] := u
end end;
Po przygotowaniach w wierszach 2-4 kolejka Q zawiera wierzchoªki 1, 2, 3, 4, 5, 6, a wektory π i d maj¡ ksztaªt
π[1] π[2] π[3] π[4] π[5] π[6]
∞ ∞ ∞ ∞ ∞ ∞
d[1] d[2] d[3] d[4] d[5] d[6]
0 ∞ ∞ ∞ ∞ ∞
Przebieg gªównej p¦tli
π d Q 1 2 3 4 5 6 1 2 3 4 5 6 u v d[v] d[u] w(u, v) 2 3 4 5 6 ∞ ∞ ∞ ∞ ∞ ∞ 0 ∞ ∞ ∞ ∞ ∞ 1 2 ∞ > 0 + 10 2 3 4 5 6 ∞ 1 ∞ ∞ ∞ ∞ 0 10 ∞ ∞ ∞ ∞ 1 4 ∞ > 0 + 7 2 3 4 5 6 ∞ 1 ∞ 1 ∞ ∞ 0 10 ∞ 7 ∞ ∞ 1 5 ∞ > 0 + 10 2 3 5 6 ∞ 1 ∞ 1 1 ∞ 0 10 ∞ 7 10 ∞ 4 5 10 > 7 + 2 2 3 6 ∞ 1 ∞ 1 4 ∞ 0 10 ∞ 7 9 ∞ 5 3 ∞ > 9 + 6 2 3 6 ∞ 1 5 1 4 ∞ 0 10 15 7 9 ∞ 5 6 ∞ > 9 + 4, 5 3 6 ∞ 1 5 1 4 5 0 10 15 7 9 13, 5 2 1 0 < 10 + 5 3 6 ∞ 1 5 1 4 5 0 10 15 7 9 13, 5 2 5 9 < 10 + 20 3 ∞ 1 5 1 4 5 0 10 15 7 9 13, 5 6 − ∞ 1 5 1 4 5 0 10 15 7 9 13, 5 3 −
4.8 Algorytm - wyniki
W poprzednim paragrae wykonali±my algorytm Dijkstry na grae
-10 5 ? 7 ? 20 @ @ @ R 10 -2 4,5 - 6 w g wg wg w g wg wg 1 2 3 4 5 6
dla s = 1. Otrzymali±my wynik:
w π[w] d[w] 1 ∞ 0 2 1 10 3 5 15 4 1 7 5 4 9 6 5 13, 5
• w wektorze π s¡ zakodowane najkrótsze drogi z s = 1 do poszczególnych wierzchoªków (poprzez system poprzedników),
• w wektorze d s¡ zakodowane ich dªugo±ci.
I tak np. najkrótsza droga z 1 do 3 to: 1 → 4 → 5 → 3, o dª. 15.
5 Bellman-Ford
5.1 Uwagi wst¦pne Algorytm Bellmana-Forda.
• Dopuszczamy ujemne wagi
(w przeciwie«stwie do algorytmu Dijkstry). • Algorytm potra wykry¢ ujemne cykle. • Nie wykorzystuje kolejki priorytetowej
(ªatwiejszy w implementacji).
• Ma za to wy»sz¡ zªo»ono±¢ od algorytmu Dijkstry.
5.2 Specykacja
Algorytm Bellmana-Forda.
Dane: graf skierowany G = (V, E), funkcja wagi w oraz wierzchoªek ¹ródªowy s ∈ V . Wynik: warto±¢ true, gdy G nie zawiera ujemnych cykli osi¡galnych z s, ponadto: dla ka»dego v ∈ V osi¡galnego z s, warto±¢ d[v] = δ(s, v) oraz poprzednik π[v] na najkrótszej drodze z s do v.
5.3 Algorytm
Bellman-Ford(G, w, s) 1 begin
2 Initialize(G, s);
3 for i := 1to |V(G)|−1do
4 for ka»da (u,v)∈ E(G) do
5 Relax(u, v, w);
6 for ka»da (u,v)∈ E(G) do
7 if d[v] > d[u]+w(u, v) then
8 return false; 9 return true 10 end;
Zªo»ono±¢: O(|V | · |E|) (p¦tla w wierszach 3-5 dominuj¡ca). 5.4 Algorytmy - proste porównanie
Zasymulowanie przebiegu algorytmu Bellmana-Forda zostawimy jako ¢wiczenie. W celu porównania obu algorytmów przypomnijmy, »e dla grafu G:
-10 5 ? 7 ? 20 @ @ @ R 10 -2 4,5 - 6 w g wg wg w g wg wg 1 2 3 4 5 6
algorytm Dijkstry wykonaª 8 relaksacji (tyle ile kraw¦dzi).
Natomiast algorytm Bellmana-Forda wykona (6 − 1) · 8 = 40 relaksacji (patrz wiersze 3-5 kodu).
(Czyli analogiczna tabela przebiegu, jak¡ przedstawili±my przy przebiegu algorytmu Dijkstry, tu b¦dzie miaªa 40 wierszy).