Zaawansowane algorytmy i struktury danych/Wykład 6: Różnice pomiędzy wersjami
Nie podano opisu zmian |
|||
Linia 263: | Linia 263: | ||
aby stały się one dodatnie, przy zachowaniu najkrótszych ścieżek. | aby stały się one dodatnie, przy zachowaniu najkrótszych ścieżek. | ||
Niech będzie dany graf skierowany <math>G(V,E)=</math> wraz z | |||
<math>G(V,E)=</math> wraz z funkcją wagową <math>w:E \to | funkcją wagową <math>w:E \to \mathcal{R}</math>. Funkcję <math>h:V \to | ||
\mathcal{R}</math>. | \mathcal{R}</math> będzie dowolną funkcją ze zbioru wierzchołków w | ||
dowolną funkcją | liczby rzeczywiste. Dla funkcji <math>h</math> oraz <math>w</math> | ||
definiujmy nową funkcję wagową oznaczoną <math>w_h</math> w | |||
<math>w</math> | następujący sposób: | ||
{{wzor|wzor_3|3|3= | {{wzor|wzor_3|3|3= | ||
Linia 276: | Linia 276: | ||
}} | }} | ||
Oznaczmy, przez <math>\delta(u,v)</math> odległości w grafie | |||
<math>G</math> dla funkcji wagowej <math>w</math> oraz przez | |||
<math>\delta_h(u,v)</math> odległości w gafie <math>G</math> dla | |||
funkcji wagowej <math>w_h</math>. | |||
{{lemat|lemat_8|8|3= | |||
Dla funkcji <math>w</math>, <math>w_h</math>, oraz dowolnej | |||
ścieżki <math>p= (v_0,\ldots,v_k)</math> zachodzi: | |||
{{wzor|||3= | |||
<math>w_h(p) = w(p) + h(v_0) - h(v_k).</math> | |||
}} | |||
}} | |||
{{dowod|||3= | |||
Mamy: | |||
{{wzor|||3= | |||
<math>w_h(p) = \sum_{i=0}^{k-1} w_h(v_i, v_{i+1}) =</math> | |||
}} | |||
{{wzor|||3= | |||
<math>= \sum_{i=0}^{k-1} \left(w(v_i, v_{i+1}) + h(v_i) - h(v_{i+1}) \right) =</math> | |||
}} | |||
{{wzor|||3= | |||
<math>= \sum_{i=0}^{k-1} w(v_i, v_{i+1}) + \sum_{i=0}^{k-1}h(v_i) - \sum_{i=0}^{k-1}h(v_{i+1}) =</math> | |||
}} | |||
{{wzor|||3= | |||
<math>= w(p) + h(v_0) - h(v_k).</math\> | |||
}} | |||
}} | |||
Widzimy więc, że zmiana długości ścieżki zależy tylko od jej końców. Otrzymujemy | |||
stąd wprost dwa wnioski. | |||
{{wniosek|wniosek_9|9|3= | |||
Dla funkcji <math>w</math>, <math>w_h</math>, oraz dowolnej pary | |||
wierzchołków zachodzi: | |||
{{wzor|||3= | |||
<math> | |||
\delta_h(u,v) = \delta(u,v) + h(u) - h(v). | |||
</math> | |||
}} | |||
}} | |||
{{wniosek | |||
|lemat_10|10|3= Ścieżka <math>p</math> z wierzchołka | |||
<math>u</math> do wierzchołka <math>v</math> jest najkrótszą ścieżką | |||
w <math>G= (V,E)</math> dla funkcji wagową <math>w</math> wtedy i | |||
tylko wtedy gdy jest najkrótszą ścieżką w <math>G</math> dla funkcji | |||
wagowej <math>w_h</math>. }} | |||
{{dowod|||3= Wniosek ten wynika wprost z [[#lemat_8|Lematu 8]] i | |||
[[#wniosek_9|Wniosku 9]], który pokazuje, że odległości transformują | |||
się tak samo jak wagi ścieżek, a wiec równość <math>w(p) = | |||
\delta(u,v)</math> jest równoważna równości <math>w_h(p) = | |||
\delta_h(u,v)</math>. | |||
}} | |||
Funkcję <math>h</math> nazwiemy | |||
{{kotwica|potencjał|'''potencjałem'''}} jeżeli | |||
zachodzi: | |||
{{wzor|wzor_4|4|3= | |||
<math> | |||
w_h(u,v) \ge 0, \mbox{ dla } <math>(u,v) \in E</math>. | |||
</math> | |||
}} | |||
}} | |||
Pokażemy teraz jak wyznaczyć funkcję potencjału <math>h</math> dla | |||
grafu <math>G</math>. Rozważmy następujący algorytm: | |||
{{algorytm|Algorytm obliczania potencjału|algorytm_potenciału|3= | |||
OBLICZ-POTENCJAŁ(G=(V,E), w) | |||
1 <math>s</math> nowy wierzchołek | |||
2 <math>V' = V \cup \{s\}</math> | |||
3 <math>E' = E \cup \{(s,v): v \in V\}</math> | |||
4 <math>w'(u,v) = \beign{cases}w(u,v), & \mbox{jeżeli} (u,v)\in E\\ 0, & \mbox{jeżeli} u=s\\0, \mbox{w pozostałych przypadkach}\end{cases}</math> | |||
5 '''if''' [[Wykład 5#algorytm_Bellmana-Forda|BELLMAN-FORD]]<math>(G',w,s) = FALSE</math> '''then''' | |||
6 '''return''' FALSE ''(graf zawiera cykl ujemnej długości)'' | |||
7 '''return''' TRUE ''(<math>d(v)</math> obliczone w algorytmie Bellmana-Forda jest potencjałem)'' | |||
}} | |||
{{lemat|lemat_11|11|3= Jeżeli graf <math>G=(V,E)</math> z wagami | |||
krawędzi zadanymi funkcją <math>w</math> zawiera cykl o ujemnej | |||
wadze to Algorytm OBLICZ-POTENCJAŁ zwraca wartość FALSE. Natomiast w | |||
przeciwnym wypadku algorytm zwraca TRUE i <math>d(v)</math> | |||
potencjałem dla grafu <math>G</math> z funkcją wagową <math>w</math>. }} | |||
{{dowod|||3= Zauważmy, że dodanie wierzchołka <math>s</math> do | |||
grafu <math>G</math>nie wprowadza nowych cykli do grafu, a jedynie | |||
powoduje, że wszystkie wierzchołki są osiągalne z <math>s</math>. | |||
Dlatego algorytm Bellmana-Forda uruchomiany dla <math>G'</math> i | |||
wierzchołka <math>s</math> zwraca TRUE wtedy i tylko wtedy gdy | |||
<math>G</math> nie zawiera cyklu o ujemnej wadze. | |||
Zakładamy teraz, że graf <math>G</math> nie zawiera cykli | |||
o ujemnej wadze, wtedy wartości <math>d(v)</math> jako odległości w grafie | |||
spełniają: | |||
<center><math> | |||
d(v) \le d(u) + w(u,v). | |||
</math></center> | |||
Innymi słowy: | |||
<center><math> | |||
w_d(u,v) = w(u,v) + d(u) - d(v) \ge 0, | |||
</math></center> | |||
co kończy dowód lematu. | |||
}} | |||
Powyższy lemat jest ostatnim składnikiem potrzebnym nam do konstrukcji | |||
algorytmu Johnsona. | |||
{{algorytm|Algorytm Johnsona|algorytm_johnsona|3= | |||
JOHNSON(G=(E,V),w) | |||
1 '''if''' OBLICZ-POTENCJAŁ<math>(G,w) = FALSE</math> '''then''' | |||
2 '''return''' FALSE | |||
3 '''for''' każda krawędź <math>(u,v) \in E</math> '''do''' | |||
4 <math>w_d(u,v) = w(u,v) + d(u) - d(v)</math> | |||
5 '''for''' każdy wierzchołek <math>u \in V</math> '''do''' | |||
6 wywołaj DIJKSTRA<math>(G,w_h,u)</math> do policzenia odległości <math>\delta_h(u,v)</math> dla <math>v\in V</math> | |||
7 '''for''' każdy wierzchołek <math>v \in V</math> '''do''' | |||
8 <math>d_{u,v) = d_h(u,v) + h(v) - h(u)</math> | |||
9 '''return''' <math>D</math> | |||
}} | |||
Poprawność tego algorytmu wynika wprost z [[#lemat_11|Lematu 11]]. | |||
Czas działania algorytmu jest równa sumie czasu działania algorytmu | |||
Bellmana-Forda i czasowi potrzebnemu na <math>O(|V|)</math> wywołań | |||
algorytmu Dijkstry, co doje całkowity czas <math>O(|V||E| + |V|^2 \log |V|)</math>. | |||
}} | }} |
Wersja z 17:46, 22 lip 2006
Abstrakt
W wykładzie tym zajmiemy się problemem obliczanie odległości w grafie między wszystkimi parami wierzchołków w grafie ważonym skierowanym . Przedstawimy trzy algorytmu rozwiązujące ten problem:
- algorytm wykorzystujący mnożenie macierzy działający w czasie ,
- algorytm Floyda-Warshalla działający w czasie ,
- algorytm Johnsona działający w czasie .
Problem najkrótszych ścieżek między wszystkimi parami wierzchołków
Problem najkrótszych ścieżek między wszystkimi parami wierzchołków można rozwiązać, wykonując razy algorytm dla problemu najkrótszych ścieżek z jednego wierzchołka. Jeżeli w grafie wagi krawędzi są nieujemne to możemy użyć algorytmu Dijkstry. Najszybsza implementacji algorytmu Dijskstry wykorzystująca kopce Fibonacciego działa w czasie , co daje nam algorytm rozwiązujący problem policzenia odległości między wszystkimi parami wierzchołków działający w czasie .
Jednakże tego rozwiązania nie możemy użyć jeżeli w grafie wagi krawędzi mogą być ujemne. W takim przypadku możemy użyć algorytm Bellmana-Forda. Otrzymamy wtedy algorytm działający w czasie . W rozdziale tym zaprezentujemy bardziej efektywne rozwiązania dla tego problemu.
W rozdziale tym będziemy zakładać, że algorytmy na wejściu otrzymują macierz wag rozmiaru reprezentującą wagi krawędzi -wierzchołkowego grafu . Dla macierzy tej zachodzi:
W problemie najkrótszych ścieżek między wszystkimi parami wierzchołków chcemy wyznaczyć macierz rozmiaru
taką, że jest równe odległości z wierzchołka do wierzchołka . Chcemy także wyznaczyć dla każdego wierzchołka drzewo najkrótszych ścieżek ukorzenione w . Podobnie jak w
poprzednim rozdziale drzewo możemy kodować dla każdego wierzchołka przy pomocy funkcji poprzedników . Ponieważ tutaj interesuje nas wiele drzew to łatwiej będzie nam używać 'macierzy poprzedników . Macierz tą definiujemy używając funkcji w następujący sposób:
W pozostałej części tego wykładu zajmiemy się tylko wyznaczaniem macierzy odległości . Jak to zostało pokazane w Zadaniu 3 do poprzedniego wykładu znając odległości w grafie drzewo najkrótszych ścieżek można wyznaczyć w czasie , a więc drzew możemy wyliczyć w czasie . Czas ten jest mniejszy niż czas działania wszystkich prezentowanych w tym wykładzie algorytmów, więc bez straty ogólności, a zyskując na prostocie prezentacji możemy ograniczyć się tylko do wyznaczenia macierzy odległości .
Co więcej będziemy zakładać, że w grafie nie ma ujemnych cykli. Ujemne cykle można wykryć w czasie przy użyciu Algorytmu Bellmana-Forda. Zobacz Zadanie 4 do Wykładu 4.
Najkrótsze ścieżki i mnożenie macierzy
Iloczyn odległości i jego właściwości
Załóżmy, że dane mamy dwie macierze wag oraz rozmiaru . Dla macierzy tych definiujemy operację iloczyn odległości, której wynikiem jest także macierz rozmiaru , zdefiniowana jako:
(1)
Wniosek 1
Pokażemy teraz, że produkt odległości jest operacją łączną.
Lemat 2
Dowód

Co więcej produkt odległości jest przemienny względem dodawania.
Lemat io_przemienny
oraz
Dowód

Zdefiniujmy macierz rozmiaru jako:
Macierz ta jest jedynką dla iloczynu odległości.
Lemat 4
Dowód
Pomysł algorytmu
Łączność iloczynu odległości ma dla nas bardzo ważne konsekwencję i pozwoli nam na konstrukcję algorytmu obliczania odległości w grafie między wszystkimi parami wierzchołków działającego w czasie . Niech będzie macierzą wag grafu . Rozważmy macierz zdefiniowaną jako:
Pokażemy teraz, że macierz opisuje odległości między wierzchołkami grafu ale tylko dla ścieżek używających mniej niż krawędzi.
Lemat 5
Dowód

Zajmiemy się teraz konstrukcją algorytmu obliczającego najkrótsze ścieżki w grafie. W tym celu będziemy potrzebowali jeszcze udowodnić następujące dwa lematy.
Lemat 6
Dowód

Algorytm
Zauważmy, że iloczyn odległości dwóch macierzy możemy policzyć w czasie wykorzystując następujący algorytm.
Algorytm Mnożenia macierzy odległości
MNOŻENIE-ODLEGŁOŚCI(C,D) 1 macierz rozmiaru 2 for to do 3 for to do 4 5 for to do 6 e_{i,j} = \min(c_{i,k} + d_{k,j}, e_{i,j}) 7 return D'
Ponieważ operacja iloczynu odległości jest łączna to możemy wykorzystać algorytm szybkiego potęgowania i policzyć odległości przy pomocy następującego algorytmu.
Algorytm Algorytm obliczania odległości między wszystkimi parami wierzchołków I
ODLEGŁÓŚCI-I(W) 1 , 2 3 while do 4 MNOŻENIE-ODLEGŁOŚCI 5 7 return
Poprawności tego algorytmu wynika wprost z Lematu 6 ponieważ na zakończenie algorytmu i .
Algorytm Floyda-Warshalla
W algorytmie Floyda-Warshalla wykorzystamy inną cechę najkrótszych ścieżek niż ta użyta w algorytmie z wykorzystaniem iloczynu odległości. W poprzednim algorytmie konstruowaliśmy coraz dłuższe ścieżki, natomiast tutaj będziemy konstruować ścieżki przechodzące przez coraz większy zbiór wierzchołków. Wierzchołkiem wewnetrznym ścieżki jest każdy wierzchołek na ścieżce różny od jej początku i końca .
Niech zbiorem wierzchołków grafu będzie . Niech dla oznacza najmniejszą wagę ścieżki z do , spośród ścieżek których wierzchołki wewnętrzne należą do zbioru . Pokażemy następujący rekurencyjny wzór na .
Lemat 7
(2)
Dowód
Niech będzie najkrótszą ścieżką z do , której wierzchołki wewnętrzne należą do zbioru . Mamy dwa przypadki:
- Wierzchołek nie leży na ścieżce . Wtedy zachodzi . Ponieważ jest najkrótszą ścieżką to także i powyższy wzór zachodzi.
- Jeżeli wierzchołek należy do ścieżki , to występuje on dokładnie raz i możemy podzielić na dwie ścieżki z do oraz z do . Ścieżki i nie zawierają wierzchołka jako wierzchołka wewnętrznego. Ponieważ są to podścieżki najkrótszej ścieżki, więc same też są najkrótsze. Zachodzi więc dla nich oraz . Otrzymujemy więc . Ponieważ jest najkrótszą ścieżką to i wzór zachodzi także w tym przypadku.
Wykorzystując wzór (2) możemy skonstruować następujący algorytm obliczający w czasie odległości między wszystkimi parami wierzchołków.
Algorytm Algorytm Floyda-Warshalla
ODLEGŁÓŚCI-II(W) 1 , 2 for to do 3 for to do 4 for to do 5 6 return
Algorytm Johnsona
W algorytmie Johnsona wykorzystamy spostrzeżenie uczynione przez nas na początku wykładu, że odległości w grafie w którym wszystkie wagi krawędzi są dodanie można obliczyć korzystając z algorytmu Dijkstry w czasie . Pokażemy tutaj jak zmienić wagi w grafie tak, aby stały się one dodatnie, przy zachowaniu najkrótszych ścieżek.
Niech będzie dany graf skierowany wraz z funkcją wagową . Funkcję będzie dowolną funkcją ze zbioru wierzchołków w liczby rzeczywiste. Dla funkcji oraz definiujmy nową funkcję wagową oznaczoną w następujący sposób:
(3)
Oznaczmy, przez odległości w grafie dla funkcji wagowej oraz przez odległości w gafie dla funkcji wagowej .
Lemat lemat_8
ścieżki zachodzi:
()
Dowód
()
()
()
Parser nie mógł rozpoznać (błąd składni): {\displaystyle = w(p) + h(v_0) - h(v_k).</math\> }} }} Widzimy więc, że zmiana długości ścieżki zależy tylko od jej końców. Otrzymujemy stąd wprost dwa wnioski. {{wniosek|wniosek_9|9|3= Dla funkcji <math>w} , , oraz dowolnej pary wierzchołków zachodzi:
()
Wniosek lemat_10
do wierzchołka jest najkrótszą ścieżką w dla funkcji wagową wtedy i tylko wtedy gdy jest najkrótszą ścieżką w dla funkcji
wagowej .Dowód
Wniosku 9, który pokazuje, że odległości transformują
się tak samo jak wagi ścieżek, a wiec równość jest równoważna równości .
Funkcję nazwiemy
potencjałem jeżeli
zachodzi:
. </math> (4)

Pokażemy teraz jak wyznaczyć funkcję potencjału dla grafu . Rozważmy następujący algorytm:
Algorytm Algorytm obliczania potencjału
OBLICZ-POTENCJAŁ(G=(V,E), w) 1 nowy wierzchołek 2 3 4 Parser nie mógł rozpoznać (nieznana funkcja „\beign”): {\displaystyle w'(u,v) = \beign{cases}w(u,v), & \mbox{jeżeli} (u,v)\in E\\ 0, & \mbox{jeżeli} u=s\\0, \mbox{w pozostałych przypadkach}\end{cases}} 5 if BELLMAN-FORD then 6 return FALSE (graf zawiera cykl ujemnej długości) 7 return TRUE ( obliczone w algorytmie Bellmana-Forda jest potencjałem)
Lemat lemat_11
krawędzi zadanymi funkcją zawiera cykl o ujemnej wadze to Algorytm OBLICZ-POTENCJAŁ zwraca wartość FALSE. Natomiast w przeciwnym wypadku algorytm zwraca TRUE i
potencjałem dla grafu z funkcją wagową .Dowód
grafu nie wprowadza nowych cykli do grafu, a jedynie powoduje, że wszystkie wierzchołki są osiągalne z . Dlatego algorytm Bellmana-Forda uruchomiany dla i wierzchołka zwraca TRUE wtedy i tylko wtedy gdy nie zawiera cyklu o ujemnej wadze.
Zakładamy teraz, że graf nie zawiera cykli o ujemnej wadze, wtedy wartości jako odległości w grafie spełniają:
Innymi słowy:

Powyższy lemat jest ostatnim składnikiem potrzebnym nam do konstrukcji
algorytmu Johnsona.
Algorytm Algorytm Johnsona
JOHNSON(G=(E,V),w)
1 if OBLICZ-POTENCJAŁ then 2 return FALSE 3 for każda krawędź do 4 5 for każdy wierzchołek do 6 wywołaj DIJKSTRA do policzenia odległości dla 7 for każdy wierzchołek do 8 Parser nie mógł rozpoznać (błąd składni): {\displaystyle d_{u,v) = d_h(u,v) + h(v) - h(u)} 9 return
Poprawność tego algorytmu wynika wprost z Lematu 11. Czas działania algorytmu jest równa sumie czasu działania algorytmu Bellmana-Forda i czasowi potrzebnemu na wywołań algorytmu Dijkstry, co doje całkowity czas .
}}