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)
Nie podano opisu zmian
Linia 71: Linia 71:
Po przypomnieniu czym była relaksacja gotowi jesteśmy na zapisanie algorytm
Po przypomnieniu czym była relaksacja gotowi jesteśmy na zapisanie algorytm
Bellmana-Forda, a następnie udowodnienie jego poprawności.
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|Algorytm Bellmana-Forda|algorytm_Bellmana-Forda|
  BELLMAN-FORD<math>(G,w,s)</math>
    INICJUJ<math>(G,s)</math>
    '''for''' <math>i=1</math> '''to''' <math>|V|-1</math> '''do'''
      '''for''' każda krawędź <math>(u,v) \in E</math> '''do'''
        RELAKSUJ<math>(u,v,w)</math>
    '''for''' każda krawędź <math>(u,v) \in E</math> '''do'''
      '''if''' '<math>d(v)>d(u) + w(u,v)</math> '''then'''
        '''return''' FALSE
    '''return''' TRUE
}}
Poniższa animacja przedstawia działanie algorytmu dla grafu o pięciu
wierzchołkach.
Algorytm ten działa w czasie <math>O(|V||E|)</math>, co jest łatwo
pokazać gdyż:
* proces inicjacji zajmuje czas <math>O(|V|)</math>,
* w każdym z <math>|V|</math> przebiegów głównej pętli algorytmu
przeglądane są wszystkie krawędzie grafu, co zajmuje czas <math>O(|V||E|)</math>,
* końcowa pętla algorytmu działa w czasie <math>O(|E|</math>.
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||bf_poprawnosc_1|
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
<math>s</math> 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 <math>s</math>, to algorytm poprawnie oblicza
odległości, tzn. na koniec działania algorytmu dla każdego <math>v
\in V</math> wartość <math>d(v)</math> jest odległością w <math>G</math> z
<math>s</math> do <math>v</math>.
}}

Wersja z 11:43, 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


 {{{3}}}

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 Algorytm Bellmana-Forda


 BELLMAN-FORD(G,w,s)
   INICJUJ(G,s)
   for i=1 to |V|1 do
     for każda krawędź (u,v)E do
       RELAKSUJ(u,v,w)
   for każda krawędź (u,v)E do
     if 'd(v)>d(u)+w(u,v) then
       return FALSE
   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 zajmuje czas O(|V|),
  • w każdym z |V| przebiegów głównej pętli algorytmu

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

  • końcowa pętla algorytmu 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

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.