Floyd-Warshall, Dijkstra ve Bellman-Ford algoritmaları arasındaki farklar konusunda haklı mıyım?


12

Üçünü inceledim ve çıkarımlarımı aşağıda belirtiyorum. Birisi bana bunları yeterince doğru anlayıp anlamadığımı söyleyebilir mi? Teşekkür ederim.

  1. Dijkstra'nın algoritması yalnızca tek bir kaynağınız olduğunda ve bir düğümden diğerine en küçük yolu bilmek istediğinizde kullanılır, ancak bu gibi durumlarda başarısız olur

  2. Floyd-Warshall'ın algoritması, tüm düğümlerden herhangi biri bir kaynak olduğunda kullanılır, bu nedenle en kısa mesafenin herhangi bir kaynak düğümden herhangi bir hedef düğüme ulaşmasını istersiniz. Bu sadece negatif döngüler olduğunda başarısız olur

(bu en önemlisi. Yani, en az emin olduğum bu :)

3.Bellman-Ford, tek bir kaynak olduğunda Dijkstra'nınki gibi kullanılır. Bu negatif ağırlıkları kaldırabilir ve çalışması tek bir kaynak hariç Floyd-Warshall'ınkiyle aynıdır, değil mi?

Bir göz atmanız gerekiyorsa, karşılık gelen algoritmalar (Wikipedia nezaket):

Bellman-Ford:

 procedure BellmanFord(list vertices, list edges, vertex source)
   // This implementation takes in a graph, represented as lists of vertices
   // and edges, and modifies the vertices so that their distance and
   // predecessor attributes store the shortest paths.

   // Step 1: initialize graph
   for each vertex v in vertices:
       if v is source then v.distance := 0
       else v.distance := infinity
       v.predecessor := null

   // Step 2: relax edges repeatedly
   for i from 1 to size(vertices)-1:
       for each edge uv in edges: // uv is the edge from u to v
           u := uv.source
           v := uv.destination
           if u.distance + uv.weight < v.distance:
               v.distance := u.distance + uv.weight
               v.predecessor := u

   // Step 3: check for negative-weight cycles
   for each edge uv in edges:
       u := uv.source
       v := uv.destination
       if u.distance + uv.weight < v.distance:
           error "Graph contains a negative-weight cycle"

Dijkstra:

 1  function Dijkstra(Graph, source):
 2      for each vertex v in Graph:                                // Initializations
 3          dist[v] := infinity ;                                  // Unknown distance function from 
 4                                                                 // source to v
 5          previous[v] := undefined ;                             // Previous node in optimal path
 6                                                                 // from source
 7      
 8      dist[source] := 0 ;                                        // Distance from source to source
 9      Q := the set of all nodes in Graph ;                       // All nodes in the graph are
10                                                                 // unoptimized - thus are in Q
11      while Q is not empty:                                      // The main loop
12          u := vertex in Q with smallest distance in dist[] ;    // Start node in first case
13          if dist[u] = infinity:
14              break ;                                            // all remaining vertices are
15                                                                 // inaccessible from source
16          
17          remove u from Q ;
18          for each neighbor v of u:                              // where v has not yet been 
19                                                                                 removed from Q.
20              alt := dist[u] + dist_between(u, v) ;
21              if alt < dist[v]:                                  // Relax (u,v,a)
22                  dist[v] := alt ;
23                  previous[v] := u ;
24                  decrease-key v in Q;                           // Reorder v in the Queue
25      return dist;

Floyd-Warshall:

 1 /* Assume a function edgeCost(i,j) which returns the cost of the edge from i to j
 2    (infinity if there is none).
 3    Also assume that n is the number of vertices and edgeCost(i,i) = 0
 4 */
 5
 6 int path[][];
 7 /* A 2-dimensional matrix. At each step in the algorithm, path[i][j] is the shortest path
 8    from i to j using intermediate vertices (1..k−1).  Each path[i][j] is initialized to
 9    edgeCost(i,j).
10 */
11
12 procedure FloydWarshall ()
13    for k := 1 to n
14       for i := 1 to n
15          for j := 1 to n
16             path[i][j] = min ( path[i][j], path[i][k]+path[k][j] );

Eminim Dijkstra'nın algoritması negatif ağırlık düğümlerini işleyebilir. Negatif ağırlık döngüleri varsa, algoritmadan bağımsız olarak en kısa yol tanımsızdır.
kevin cline

1
@kevincline: Wikipedia iddianızı desteklemiyor (wikipedia'nın doğru olduğunu iddia etmiyorum ve AlgTheory kitabım birkaç yüz mil uzakta) Ancak gerçek zamanlı zamana dayalı veya hıza dayalı yönlendirme problemlerinde negatif kenar yok, bu yüzden ihtiyaca bağlı olarak genellikle Dijsktra veya Floyd'u yaparım. Hatırladığım kadarıyla, gerçek hayattaki kartografik yönlendirme algoslarının çoğu Dijsktra'nın modernleştirilmiş versiyonuna dayanıyor, ancak sadece önceki işyerimde okuduğum bazı bilimsel makalelerden hatırlıyorum.
Aadaam

@Aadaam: Yanılıyorum. Dijkstra, her kenarı ziyaret etmekten kaçınmak için olumsuzluklardan yararlanır.
kevin cline

Evet, doğru
anladın

Yanıtlar:


3

Seni doğru anlarsam, anlayışınız doğrudur.

  • Djikstra's, negatif ağırlık kenarı olması dışında, bir kaynak düğümden grafikteki diğer tüm düğümlere giden en küçük maliyet yolunu bulur. (Dijkstra'lar, hedef düğümü bulduktan sonra duracak ve buluşsal yöntemler ekleyerek kolayca A * algoritmasına dönüştürülebilir.)
  • Bellman-Ford, Dijkstra'nınkiyle aynı şeyi yapar, ancak daha yavaştır. Ancak negatif ağırlık kenarlarını işleyebilir.
  • Floyd-Warshall, her bir düğümden diğer düğümlere kadar olan en küçük maliyet yolunun maliyetini bulur. (Sayısal bir matris döndürür.) Djikstra veya Bellman-Ford'dan çok daha yavaştır. Yazdıklarınızdan farklı olarak, negatif bir döngü meydana geldiğinde başarısız olmaz, sadece bazı düğümlerin maliyeti için anlamsız bir negatif sayı rapor eder.

1
Hayır, Floyd-Warshall sadece yol uzunluklarını değil, Djikstra ve Bellman-Ford gibi yolları da hesaplayabilir.
Konrad Rudolph

Değişiklikler ile elbette.
Ceasar Bautista

3
Bir hedef düğümde durduysa, ancak sezgisel tarama kullanmadıysa, ilkinin Dijkstra's olduğunu düşünürdüm.
Eliot Ball

1
@CSA - Floyd Warshall O (n ^ 3) olduğundan, bu kadar büyük bir grafik için yaklaşık 10 ^ 300 işlem gerekecektir. Her bir işlemin Planck zaman alacağını varsayarsak, hesaplama tamamlandığında , evrendeki normal maddedeki tüm protonlar bozulur ve sadece süper kütleli kara delikler kalır . İç döngüyü paralel hale getirmenin mümkün olabileceğine inanıyorum. Bu doğruysa, güneşin kütlesi ile başlayan tüm kara delikler buharlaşmadan bitirmek için yeterince şanslı olabilirsiniz.
Jules

1
(İşlem başına birden fazla atom kullanarak bir işlem düğümü oluşturabileceğinizi ve gözlemlenebilir evrendeki tüm atomları kullanabileceğinizi varsayarsak, yani ... ama muhtemelen başlangıç ​​için verilerinizi saklamak için hepsine ihtiyacınız vardır)
Jules
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.