Zaawansowane algorytmy i struktury danych/Wykład 6: Różnice pomiędzy wersjami
Linia 41: | Linia 41: | ||
== Najkrótsze ścieżki i mnożenie macierzy == | == Najkrótsze ścieżki i mnożenie macierzy == | ||
Załóżmy, że dane mamy dwie [[#macierz_wag|macierze wag]] | Załóżmy, że dane mamy dwie [[#macierz_wag|macierze wag]] <math>C</math> oraz <math>D</math> rozmiaru <math>n\times n</math>. | ||
<math>C</math> oraz <math>D</math> rozmiaru <math>n\times n</math>. | Dla macierzy tych definiujemy operację <math>\times_{\min}</math>l {{kotwica|liczyn_odległości|'''iloczynu odległości'''}}, której wynikiem jest także macierz rozmiaru <math>n \times n</math>, zdefiniowana jako: | ||
Dla macierzy tych definiujemy operację <math>\times_{\min}</math>l | |||
{{kotwica|liczyn_odległości|'''iloczynu odległości'''}}, której | |||
wynikiem jest także macierz rozmiaru <math>n \times n</math>, | |||
zdefiniowana jako: | |||
{{wzor|wzór_1|1|3= | {{wzor|wzór_1|1|3= | ||
Linia 57: | Linia 53: | ||
{{wniosek|wniosek_konkatenacja|1|3= | {{wniosek|wniosek_konkatenacja|1|3= | ||
Jeżeli założymy, że <math>C</math> i <math>D</math> opisują | Jeżeli założymy, że <math>C</math> i <math>D</math> opisują minimalne wagi odpowiednio zbioru ścieżek odpowiednio | ||
minimalne wagi odpowiednio zbioru ścieżek odpowiednio | <math>\Pi_{C}</math> i <math>\Pi_{D}</math> w pewnym grafie <math>G</math>, to iloczyn odległości wyznacza minimalne wagi zbioru ścieżek powstałego z konkatenacji ścieżek ze zbioru <math>\Pi_{C}</math> ze ścieżkami zbioru <math>\Pi_{D}</math>. | ||
<math>\Pi_{C}</math> i <math>\Pi_{D}</math> w pewnym grafie | |||
<math>G</math>, to iloczyn odległości wyznacza minimalne wagi zbioru | |||
ścieżek powstałego z konkatenacji ścieżek ze zbioru | |||
<math>\Pi_{C}</math> ze ścieżkami zbioru <math>\Pi_{D}</math>. | |||
}} | }} | ||
Linia 70: | Linia 62: | ||
{{lemat|io_łączny|2|3= | {{lemat|io_łączny|2|3= | ||
Dla macierzy <math>C</math>, <math>D</math> i <math>E</math> | Dla macierzy <math>C</math>, <math>D</math> i <math>E</math> rozmiaru <math>n\times n</math>zachodzi: | ||
rozmiaru <math>n\times n</math>zachodzi: | |||
Linia 79: | Linia 70: | ||
}} | }} | ||
{{dowod||| Powyższa równość wynika wprost z [[#wzór_1|wzoru (1 | {{dowod||| Powyższa równość wynika wprost z [[#wzór_1|wzoru (1)]] oraz przemienności operacji <math>\min</math>. | ||
przemienności operacji <math>\min</math>. | |||
}} | }} | ||
Co więcej produkt odległości jest przemienny względem dodawania. | Co więcej produkt odległości jest przemienny względem dodawania. | ||
{{lemat|io_przemienny|3|3= Dla macierzy <math>C</math>, <math>D</math> | {{lemat|io_przemienny|3|3= Dla macierzy <math>C</math>, <math>D</math> i <math>E</math> rozmiaru <math>n\times n</math>zachodzi: | ||
i <math>E</math> rozmiaru <math>n\times n</math>zachodzi: | |||
Linia 98: | Linia 87: | ||
<center><math> | <center><math> | ||
\left(D + E \right) \times_{\min} C = D \times_{\min} C + E \times_{min} C. | \left(D + E \right) \times_{\min} C = D \times_{\min} C + E \times_{min} C. | ||
</math></center> | </math></center> }} | ||
Zdefiniujmy macierz <math>I_{\min}</math> rozmiaru <math>n \times | {{dowod||| Te dwie równości wynikają ponownie z [[#wzór_1|wzoru (1)]] oraz przemienności operacji <math>\min</math> względem dodawania. }} | ||
n</math> jako: <center><math> \left(I_{\min}\right)_{i,j} = | |||
\begin{cases} 0, & \mbox{jeśli } i=j, \infty, & \mbox{jeśli } i \neq | |||
j. | Zdefiniujmy macierz <math>I_{\min}</math> rozmiaru <math>n \times n</math> jako: | ||
<center><math> \left(I_{\min}\right)_{i,j} = | |||
\begin{cases} 0, & \mbox{jeśli } i=j, \infty, & \mbox{jeśli } i \neq j. | |||
\end{cases} | \end{cases} | ||
</math></center> | </math></center> | ||
Macierz ta jest jedynką dla iloczynu odległości. | Macierz ta jest jedynką dla iloczynu odległości. | ||
{{lemat|io_jedynka|4|3= Dla macierzy <math>C</math> rozmiaru <math>n | |||
\times n</math> zachodzi: | {{lemat|io_jedynka|4|3= Dla macierzy <math>C</math> rozmiaru <math>n \times n</math> zachodzi: | ||
Linia 124: | Linia 116: | ||
</math></center> | </math></center> | ||
ponieważ wszystkie elementy <math>\left(I_{\min}\right)_{i,k}</math> | ponieważ wszystkie elementy <math>\left(I_{\min}\right)_{i,k}</math> równe są <math>\infty</math> oprócz elementu <math>i = k</math>, to możemy je pominąć w operacji <math>\min</math> i: | ||
równe są <math>\infty</math> oprócz elementu <math>i = k</math>, to | |||
możemy je pominąć w operacji <math>\min</math> i: | |||
Linia 133: | Linia 123: | ||
Łączność iloczynu odległości ma dla nas bardzo ważne konsekwencję i | Łą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 <math>O(n^{3}\log n)</math>. Niech <math>W</math> będzie [[#macierz_wag|macierzą wag]] grafu <math>G = (V,E)</math>. Rozważmy macierz <math>W^m</math> zdefiniowaną jako: | ||
pozwoli nam na konstrukcję algorytmu obliczania odległości w grafie | |||
między wszystkimi parami wierzchołków działającego w czasie | |||
<math>O(n^{3}\log n)</math>. Niech <math>W</math> będzie | |||
[[#macierz_wag|macierzą wag]] grafu <math>G = (V,E)</math>. Rozważmy | |||
macierz <math>W^m</math> zdefiniowaną jako: | |||
Linia 149: | Linia 134: | ||
</center> | </center> | ||
Pokażemy teraz, że macierz <math>W^m</math> opisuje odległości | Pokażemy teraz, że macierz <math>W^m</math> opisuje odległości między wierzchołkami grafu ale tylko dla ścieżek używających mniej niż <math>m</math> krawędzi. | ||
między wierzchołkami grafu ale tylko dla ścieżek używających mniej niż | |||
<math>m</math> krawędzi. | |||
{{lemat|potęgi_odległości|5|3= | {{lemat|potęgi_odległości|5|3= | ||
Element <math>W_{i,j}^{m}</math> macierzy <math>W^{m}</math> zadaje | Element <math>W_{i,j}^{m}</math> macierzy <math>W^{m}</math> zadaje najmniejszą wagę ścieżki wychodzącej z wierzchołka <math>i</math> do wierzchołka <math>j</math> spośród ścieżek, które zawierają mniej niż <math>m</math> krawędzi, tzn.: | ||
najmniejszą wagę ścieżki wychodzącej z wierzchołka <math>i</math> do | |||
wierzchołka <math>j</math> spośród ścieżek, które zawierają | |||
mniej niż <math>m</math> krawędzi, tzn.: | |||
Linia 169: | Linia 149: | ||
}} | }} | ||
{{ | {{dowod|||3= Tezę tą udowodnimy przez indukcję po <math>m</math>. Dla danego wierzchołka istnieją dla niech tylko ścieżki długości zero prowadzące do niego samego, a więc dla <math>m=0</math> teza wynika wprost z definicji macierzy <math>W^0</math>. | ||
Dla danego wierzchołka istnieją dla niech tylko ścieżki długości | |||
zero prowadzące do niego samego, a więc dla <math>m=0</math> teza | |||
wynika wprost z definicji macierzy <math>W^0</math>. | |||
Załóżmy teraz, że teza zachodzi dla <math>m >0</math>. Mamy wtedy | Załóżmy teraz, że teza zachodzi dla <math>m >0</math>. Mamy wtedy <math>W^{m+1} = W \times_{\min} W^{m}</math>. Zauważmy, że ze definicji [[#macierz_wag|macierzy wag]] <math>W</math> opisuje ścieżki używające <math>\le 1</math> krawędź. Korzystając teraz z [[wniosek_konkatenacja|Wniosku 1]] otrzymujemy tezę dla <math>m+1</math>. | ||
<math>W^{m+1} = W \times_{\min} W^{m}</math>. Zauważmy, że ze | |||
definicji [[#macierz_wag|macierzy wag]] <math>W</math> opisuje | |||
ścieżki używające <math>\le 1</math> krawędź. Korzystając teraz | |||
z [[wniosek_konkatenacja|Wniosku 1]] otrzymujemy tezę dla <math>m+1</math>. | |||
}} | }} | ||
Zajmiemy się teraz konstrukcją algorytmu obliczającego najkrótsze | 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. | ||
ścieżki w grafie. W tym celu będziemy potrzebowali jeszcze udowodnić | |||
następujące dwa lematy. | |||
{{lemat|lemat_6|6|3= | {{lemat|lemat_6|6|3= | ||
Jeżeli w grafie <math>G=(V,E)</math>, w którym wagi krawędzi zadane | Jeżeli w grafie <math>G=(V,E)</math>, w którym wagi krawędzi zadane są macierzą <math>W</math> nie istnieje cykl o ujemnej wadze to: | ||
są macierzą <math>W</math> nie istnieje cykl o ujemnej wadze | |||
to: | |||
Linia 199: | Linia 168: | ||
}} | }} | ||
{{ | {{dowod|||3= Jeżeli w grafie nie istnieje cykl o ujemnej wadze, to wszystkie najkrótsze ścieżki są ścieżkami prostymi, a więc mają długość co najwyżej <math>n-1</math>. Z [[potęgi_odległości|Lematu 5]] wynika więc że odległości tych ścieżek są dobrze wyznaczone w <math>W^{k}</math> dla <math>k \le n-1</math>. }} | ||
wszystkie najkrótsze ścieżki są ścieżkami prostymi, a więc mają | |||
długość co najwyżej <math>n-1</math>. Z [[potęgi_odległości|Lematu | |||
5]] wynika więc że odległości tych ścieżek są dobrze wyznaczone w | |||
<math>W^{k}</math> dla <math>k \le n-1</math>. }} | |||
Zauważmy, że iloczyn odległości dwóch macierzy | Zauważmy, że iloczyn odległości dwóch macierzy możemy policzyć w czasie <math>O(|V|^3)</math> wykorzystując następujący | ||
możemy policzyć w czasie <math>O(|V|^3)</math> wykorzystując następujący | |||
algorytm. | algorytm. | ||
Linia 221: | Linia 185: | ||
}} | }} | ||
Ponieważ operacja iloczynu odległości jest łączna to możemy | Ponieważ operacja iloczynu odległości jest łączna to możemy wykorzystać [[algorytm_szybkiego_potęgowania|algorytm szybkiego | ||
wykorzystać [[algorytm_szybkiego_potęgowania|algorytm szybkiego | potęgowania]] i policzyć odległości przy pomocy następującego algorytmu. | ||
potęgowania]] i policzyć odległości przy pomocy następującego | |||
algorytmu. | |||
{{algorytm|algorytm_apsp_mnozenie|Algorytm obliczania odległości | {{algorytm|algorytm_apsp_mnozenie|Algorytm obliczania odległości | ||
Linia 237: | Linia 199: | ||
}} | }} | ||
Poprawności tego algorytmu wynika wprost z [[lemat_6|Lematu 6]] ponieważ | Poprawności tego algorytmu wynika wprost z [[lemat_6|Lematu 6]] ponieważ na zakończenie algorytmu <math>D = W^{m}</math> i <math>m > n-1</math>. | ||
na zakończenie algorytmu <math>D = W^{m}</math> i <math>m > n-1</math>. | |||
== Algorytm Floyda-Warshalla == | == Algorytm Floyda-Warshalla == |
Wersja z 23:02, 21 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
Załóżmy, że dane mamy dwie macierze wag oraz rozmiaru . Dla macierzy tych definiujemy operację l iloczynu odległości, której wynikiem jest także macierz rozmiaru , zdefiniowana jako:
(1)
Wniosek wniosek_konkatenacja
Pokażemy teraz, że produkt odległości jest operacją łączną.
Lemat io_łączny
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 io_jedynka
Łą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:
Parser nie mógł rozpoznać (nieznana funkcja „\begin{cases}”): {\displaystyle W^{m} = \begin{cases} I_{\min}, &\mbox{jeżeli } m=0,\\ W \times_{\min} W^{m-1}, &\mbox{jeżeli } m>0. }
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 potęgi_odległości
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 lemat_6
Dowód

Zauważmy, że iloczyn odległości dwóch macierzy możemy policzyć w czasie wykorzystując następujący algorytm.
Algorytm algorytm_iloczyn_odległości
{{{3}}}
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_apsp_mnozenie
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 {{kotwica|wierzchołek_wewnetrzny|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 lemat_7
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
między wszystkimi parami wierzchołków I ODLEGŁÓŚCI-II(W) 1 , 2 for to do 3 for to do 4 for to do 5 6 return