Ho ragione sulle differenze tra gli algoritmi di Floyd-Warshall, Dijkstra e Bellman-Ford?


12

Ho studiato i tre e sto affermando le mie inferenze da loro sotto. Qualcuno potrebbe dirmi se le ho comprese abbastanza accuratamente o no? Grazie.

  1. L'algoritmo di Dijkstra viene utilizzato solo quando si dispone di un'unica fonte e si desidera conoscere il percorso più piccolo da un nodo all'altro, ma in casi come questo non riesce

  2. L'algoritmo di Floyd-Warshall viene utilizzato quando uno qualsiasi di tutti i nodi può essere un'origine, quindi si desidera che la distanza più breve raggiunga qualsiasi nodo di destinazione da qualsiasi nodo di origine. Questo fallisce solo quando ci sono cicli negativi

(questo è il più importante. Voglio dire, questo è quello di cui sono meno sicuro :)

3.Bellman-Ford è usato come Dijkstra, quando esiste una sola fonte. Questo può gestire pesi negativi e il suo funzionamento è uguale a quello di Floyd-Warshall ad eccezione di una fonte, giusto?

Se hai bisogno di dare un'occhiata, gli algoritmi corrispondenti sono (cortesia di Wikipedia):

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] );

Sono abbastanza sicuro che l'algoritmo di Dijkstra è in grado di gestire nodi a peso negativo. Se sono presenti cicli a peso negativo, il percorso più breve non è definito, indipendentemente dall'algoritmo.
Kevin Cline,

1
@kevincline: Wikipedia non supporta la tua richiesta (non sto affermando che Wikipedia sia giusta, e ho il mio libro AlgTheory a poche centinaia di miglia di distanza) Tuttavia, nei problemi di routing basati sul tempo reale o basati sulla velocità ci sono nessun vantaggio negativo, quindi di solito faccio Dijsktra o Floyd, a seconda delle necessità. Per quanto ricordo, la maggior parte degli algoritmi di routing cartografici della vita reale si basano sulla versione modernizzata di Dijsktra, ma ricordo solo alcuni articoli scientifici che ho letto sul mio posto di lavoro precedente.
Aadaam,

@Aadaam: sbaglio. Dijkstra sfrutta la non negatività per evitare di visitare ogni limite.
Kevin Cline,

Sì, hai capito bene :) :)
Sanghyun Lee

Risposte:


3

Se ti capisco correttamente, la tua comprensione è corretta.

  • Djikstra trova il percorso di costo più piccolo da un nodo di origine a ogni altro nodo nel grafico, tranne se c'è un limite di peso negativo. (Dijkstra può essere facilmente trasformato in un algoritmo A * semplicemente cambiandolo per arrestare una volta trovato il nodo target e aggiungendo euristica.)
  • Bellman-Ford fa lo stesso di Dijkstra, ma è più lento. Ma può gestire bordi di peso negativo.
  • Floyd-Warshall trova il costo del percorso di costo più piccolo da ciascun nodo a ogni altro nodo. (Restituisce una matrice numerica.) È molto più lento di quello di Djikstra o di Bellman-Ford. A differenza di ciò che hai scritto, non fallisce quando si verifica un ciclo negativo, riporta solo un numero negativo insignificante per il costo di un nodo a se stesso.

1
Nah, Floyd-Warshall può calcolare i percorsi stessi, come Djikstra e Bellman-Ford, non solo le lunghezze del percorso.
Konrad Rudolph,

Con modifiche, ovviamente.
Ceasar Bautista,

3
Considererei comunque il primo di Dijkstra se fosse fermato su un nodo target, ma non usasse l'euristica.
Eliot Ball

1
@CSA - Floyd Warshall è O (n ^ 3), quindi per un grafico così grande sarebbero necessarie circa 10 ^ 300 operazioni. Supponendo che ogni operazione richieda il tempo di Planck, quando il calcolo avrà terminato tutti i protoni nella materia normale nell'universo saranno decaduti e rimarranno solo buchi neri supermassicci . Credo che possa essere possibile parallelizzare il circuito interno. Se questo è vero, potresti essere abbastanza fortunato da finire prima che tutti i buchi neri che sono iniziati con la massa del sole siano evaporati.
Jules

1
(Supponendo che tu possa costruire un nodo di elaborazione usando meno di un atomo per processo, e puoi usare tutti gli atomi nell'universo osservabile, cioè ... ma allora probabilmente avrai bisogno di tutti quelli per memorizzare i tuoi dati per cominciare)
Jules,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.