Zaawansowane algorytmy i struktury danych/Wykład 5: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Sank (dyskusja | edycje)
Sank (dyskusja | edycje)
Linia 100: Linia 100:
o ujemnych wagach.
o ujemnych wagach.


{{lemat||bf_poprawnosc_1|3=
{{lemat|1|bf_poprawnosc_1|3=
Niech <math>G = (V,E)</math> będzie grafem skierowanym i niech
Niech <math>G = (V,E)</math> będzie grafem skierowanym i niech
funkcja <math>w:E \to \mathcal{R}</math> zadaje wagi krawędzi. Niech
funkcja <math>w:E \to \mathcal{R}</math> zadaje wagi krawędzi. Niech
Linia 143: Linia 143:




{{wniosek|||3=
{{wniosek|2||3=
Niech <math>G = (V,E)</math> będzie grafem skierowanym i
Niech <math>G = (V,E)</math> będzie grafem skierowanym i
niech funkcja <math>w:E \to \mathcal{R}</math> zadaje wagi krawędzi.
niech funkcja <math>w:E \to \mathcal{R}</math> zadaje wagi krawędzi.
Linia 152: Linia 152:
}}
}}


{{twierdzenie||bf_poprawnosc|3=
{{twierdzenie|3|bf_poprawnosc|3=
Niech <math>G = (V,E)</math> będzie
Niech <math>G = (V,E)</math> będzie
grafem skierowanym i niech funkcja <math>w:E \to \mathcal{R}</math>
grafem skierowanym i niech funkcja <math>w:E \to \mathcal{R}</math>

Wersja z 13:10, 20 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 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.


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 istniej 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 Inicjalizacja algorytmu najkrótszych ścieżek


 INICJALIZUJ(G,s)
   for każdy wierzchołek vV do
     d(v)=
     π(v)=NIL
   d(s)=0


Ustalone przez tą procedure 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)
   if d(v)>d(u)+w(u,v) then
     d(v)=d(u)+w(u,v)
     π(v)=u

Algorytm

Po przypomnieniu czym była relaksacja gotowi jesteśmy na zapisanie algorytm Bellmana-Forda, a następnie udowodnienie jego poprawności.

Po przypomnieniu czym była relaksacja gotowi jesteśmy na zapisanie algorytm Bellmana-Forda, a następnie udowodnienie jego poprawności.

Algorytm Bellmana-Forda


 BELLMAN-FORD(G,w,s)
 1  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)
 5  for każda krawędź (u,v)E do
 6    if 'd(v)>d(u)+w(u,v) 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 O(|V||E|), co jest łatwo pokazać gdyż:

  • proces inicjacji linia 1 zajmuje czas O(|V|),
  • w każdym z |V| przebiegów głównej pętli w lini 2 algorytmu

przeglądane są wszystkie krawędzie grafu w linie 3 , co zajmuje czas O(|V||E|),

  • końcowa pętla algorytmu linie 5-7 działa w czasie O(|E|.

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.


Wniosek 2

Niech G=(V,E) będzie grafem skierowanym i

niech funkcja w:E zadaje wagi krawędzi. Niech d(v) to będą wartości wyznaczone przez algorytm Bellmana-Forda uruchomiano dla wierzchołka s. W G istnieje ścieżka z s do v

wtedy i tylko wtedy gdy d(v)<.

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 nie zawiera cyklu o ujemnej wadze osiągalnego ze źródła s to algorytm zwraca wartość TRUE, d(v) jest odległością z s do v, a π(v) wyznacza drzewo najkrótszych ścieżek o korzeniu w s. Jeżeli natomiast G zawiera cykl o ujemnej wadze osiągalny ze

źródła to algorytm zwraca wartość FALSE.