Zaawansowane algorytmy i struktury danych/Wykład 5

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania

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 O(|V||E|). 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 G=(V,E), funkcję w:E przypisującą wagi krawędziom oraz jeden wybrany wierzchołek s. Wagę ścieżki p=(v0,v1,,vk) definiujemy jako wagę tworzących ją krawędzi:


w(p)=i=0k1w(vi,vi+1).


Odległość z wierzchołka u do wierzchołka v definiujemy jako

δ(u,v)={min{w(p):p ścieżka z u do v},jeżeli istnieje ścieżka z u do v,w przeciwnym przypadku.

Najkrótszą ścieżką z wierzchołka u do wierzchołka v jest każda ścieżka p z u do v, której waga w(p) jest równa odległości δ(u,v) z u do v.

W problemie najkrótszych ścieżek z jednego wierzchołka chcemy obliczyć odległości δ(s,v) dla wszystkich wierzchołków vV wraz z drzewem najkrótszych ścieżek z s. Drzewem najkrótszych ścieżek o korzeniu w s nazywamy podgraf skierowany G=(V,E), w którym VV, EE taki, że:

  • V' jest zbiorem wierzchołków w G do których istnieje ścieżka z s,
  • G jest drzewem którego korzeniem jest s,
  • dla każdego wierzchołka vV jedyna ścieżka z s

do v w grafie G jest najkrótszą ścieżką z s do v w grafie G.

W naszych algorytmach drzewo najkrótszych ścieżek będziemy reprezentować jako funkcję poprzedników π:VV określającą poprzednika wierzchołka v w drzewie najkrótszych ścieżek. Drzewo najkrótszych ścieżek G=(V,E) możemy uzyskać z π w następujący sposób:


V={vV:π(v)NIL}{s},
E={(π(v),v)E:vVπ{s}}.

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.

Znane algorytmy dla problemu obliczania najkrótszych ścieżek z jednego wierzchołka
Złożoność Autor
O(n4) Shimbel (1995)
O(nm) Ford (1956), Bellman (1958)
O(n34mlogW) Gabow (1983)
O(nmlog(nW)) Gabow and Tarjan (1989)
O(nmlog(W)) Goldberg (1993)
O(n2.38W) 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 G=(V,E) i funkcję wagową w:E. Algorytm Bellmana-Forda wylicza dla zadanego wierzchołka s, czy istnieje w grafie G cykl o ujemnej wadze osiągalny z s. Jeżeli taki cykl nie istnieje to algorytm oblicza najkrótsze ścieżki z s 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 vV utrzymujemy wartość d(v) będącą górnym ograniczeniem wagi najkrótszej ścieżki ze s do v. W algorytmie utrzymywać będziemy także dla każdego wierzchołka v wskaźnik π(v) 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(G,s)
 1  for każdy wierzchołek vV do
 2  begin
 3    d(v)=
 4    π(v)=NIL
 5  end
 6  d(s)=0
 7  return (d,π)


Ustalone przez tą procedurę wartości d(v) są dobrymi ograniczeniami górnymi na odległości.

Relaksacja krawędzi (u,v) polega na sprawdzeniu, czy przechodząc krawędzią (u,v) z u do v, nie otrzymamy krótszej ścieżki z s do vniż ta dotychczas znaleziona. Jeżeli tak, to aktualizowane są także wartości d(v) i π(v). W celu relaksacji krawędzi (u,v) używamy procedury RELAKSUJ.

Algorytm Relaksacja krawędzi


 RELAKSUJ(u,v,w,d,π)
 1  if d(v)>d(u)+w(u,v) then
 3  begin
 4    d(v)=d(u)+w(u,v)
 5    π(v)=u
 6  end

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(G,w,s)
 1  (d,π)=INICJUJ(G,s)
 2  for i=1 to |V|1 do
 3    for każda krawędź (u,v)E do
 4      RELAKSUJ(u,v,w,d,π)
 5  for każda krawędź (u,v)E do
 6    if 'd(v)>d(u)+w(u,v) then
 7      return NIL
 8  return (d,\pi)

Poniższa animacja przedstawia działanie algorytmu dla grafu o pięciu wierzchołkach.


<flash>file=Zasd_fft1.swf|width=460|height=350</flash>


Algorytm ten działa w czasie O(|V||E|), co łatwo pokazać gdyż:

  • proces inicjacji w linii 1 zajmuje czas O(|V|),
  • w każdym z |V| przebiegów głównej pętli w linii 2 algorytmu przeglądane są wszystkie krawędzie grafu w linii 3 , co zajmuje czas O(|V||E|),
  • końcowa pętla algorytmu w liniach 5-7 działa w czasie O(|E|).

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

Niech G=(V,E) będzie grafem skierowanym i niech funkcja w:E zadaje wagi krawędzi. Niech s będzie wierzchołkiem z którego liczymy odległości algorytmem Bellmana-Forda. Jeżeli w grafie nie ma cykli o ujemnej wadze osiągalnych z s, to algorytm poprawnie oblicza odległości, tzn. na koniec działania algorytmu dla każdego vV wartość d(v) jest odległością w G z s do v.

Dowód

Oznaczmy przez δ(v,u) odległość z wierzchołka v do u w grafie G. Niech v będzie wierzchołkiem osiągalnym ze źródła s i niech p=(v0,v1,,vk) oznacza najkrótszą ścieżkę z s do v, gdzie v0=s oraz vk=v. Ścieżka ta jest ścieżką prostą, bo najkrótsze ścieżki muszą być proste, więc k|V|1. Pokażemy teraz indukcyjnie, że poczynając od i-tego przebiegu zachodzi d(vi)=δ(s,vi) dla i=0,1,,k. W algorytmie wykonujemy |V|1 obrotów pętli oraz k|V|1, co oznacza, że z tej tezy indukcyjnej wynika poprawność algorytmu.

Zauważmy, że teza indukcyjna zachodzi po inicjacji algorytmu, gdyż d(v0)=d(s)=0δ(s,s)=δ(s,v0). Załóżmy, że teza indukcyjna zachodzi dla kroku k'tego. Ponieważ ścieżki p=(v0,v1,,vi) dla ik są najkrótsze jako podścieżki ścieżki p, to po k+1 wykonaniu pętli wartości d(vi) dla ik się nie zmienią. Pozostaje nam więc do pokazania to, że wartość d(vk+1) będzie dobrze policzona. W k+1 przebiegu wykonujemy między innymi relaksację krawędzi (vk,vk+1). Ponieważ d(vk) jest dobrze policzone, to po tej relaksacji wyznaczona będzie także poprawnie wartość d(vk+1), bo założyliśmy, że najkrótsza ścieżka do vk+1 przechodzi przez vk.

Pozostaje nam jedynie zastanowić się co się dzieje gdy wierzchołek v nie jest osiągalny z s. Musi wtedy zachodzić d(v)= 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 s do v. Sprzeczność.


Dowód

Dowód ten można przeprowadzić w podobny sposób do dowodu Lematu 1.

Twierdzenie 3

Niech G=(V,E) będzie grafem skierowanym i niech funkcja w:E zadaje wagi krawędzi. Załóżmy, że algorytm Bellmana-Forda został wykonany dla wierzchołka s. Jeżeli graf zawiera cyklu o ujemnej wadze osiągalny ze źródła s to algorytm zwraca wartość NIL, w przeciwnym wypadku d(v) jest odległością z s do v, a π(v) wyznacza drzewo najkrótszych ścieżek o korzeniu w s.


{{dowod|||3=Załóżmy najpierw, że graf nie zawiera cykli o ujemnej wadze, które byłyby osiągalne z s. Wtedy z Lematu 1 wiemy, że d(v) są poprawnie policzonymi odległościami. Jeżeli odległości d(v) zostały poprawnie policzone przez funkcję RELAKSUJ to π(v) 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 G istnieje cykl ujemnej długości osiągalny z s. Jeżeli nie ma takiego cyklu to wtedy d(v) są poprawnie policzone przed wykonaniem testu w liniach 5-8 algorytmu Bellmana-Forda. W takim razie zachodzi:


d(v)=δ(s,v)δ(s,u)+w(u,v)=d(u)+w(u,v).


Powyższa nierówność zachodzi ponieważ suv jest ścieżką w grafie, a więc jest nie krótsza niż najkrótsza ścieżka sv. Widzimy więc, że w tym przypadku żaden z testów w linijce 6 algorytmu nie będzie spełniony i algorytm nie zwróci NIL.

Załóżmy teraz, że w grafie G istnieje cykl o ujemnej wadze osiągalny z s. Oznaczmy ten cykl jako c=(v0,v1,,vk), gdzie v0=vk. Dla cyklu tego mamy:

i=0kw(vi,vi+1)<0.      (1)

Gdyby w tej sytuacji algorytm Bellmana-Forda nie zwrócił wartości NIL to dla każdej krawędzi (vi,vi+1) musiałaby zachodzić nierówność d(vi)+w(vi,vi+1)d(vi+1). Sumując tą nierówność stronami po wszystkich i=0,,k1 otrzymujemy.


i=0k1[d(vi)+w(vi,vi+1)]i=0k1d(vi+1),
i=0k1d(vi)+i=0k1w(vi,vi+1)i=1kd(vi),


ponieważ v0=vk to


i=0k1d(vi)+i=0k1w(vi,vi+1)i=0k1d(vi).


Wiemy, że cykl c jest osiągalny a zatem dla każdego i=0,,k mamy d(v)<. Możemy więc skrócić i=0k1d(vi) po obydwu stronach równania i otrzymujemy:


i=0k1w(vi,vi+1)0,


co stoi w sprzeczności z nierównością (1). Jeżeli więc w grafie istnieje cykl o ujemnej wadze osiągalny z s, to algorytm zwróci NIL. }}