Bellman-Ford algorithm
From Wikipedia, the free encyclopedia
Graph search algorithms |
---|
Search |
The Bellman-Ford algorithm computes single-source shortest paths in a weighted digraph (where some of the edge weights may be negative). Dijkstra's algorithm accomplishes the same problem with a lower running time, but requires edge weights to be non-negative. Thus, Bellman-Ford is usually used only when there are negative edge weights.
Bellman Ford runs in O(V·E) time, where V and E are the number of vertices and edges respectively.
function 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): for each edge uv in edges: u := uv.source v := uv.destination // uv is the edge from u to v if v.distance > u.distance + uv.weight: 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 v.distance > u.distance + uv.weight: error "Graph contains a negative-weight cycle"
Contents |
[edit] Proof of correctness
The correctness of the algorithm can be shown by induction. The precise statement shown by induction is:
Lemma. After i repetitions of for cycle:
- If Distance(u) is not infinity, it is equal to the length of some path from s to u;
- If there is a path from s to u with at most i edges, then Distance(u) is at most the length of the shortest path from s to u with at most i edges.
Proof. For the base case of induction, consider i=0
and the moment before for cycle is executed for the first time. Then, for the source vertex, source.distance = 0
, which is correct. For other vertices u, u.distance = infinity
, which is also correct because there is no path from source to u with 0 edges.
For the inductive case, we first prove the first part. Consider a moment when a vertex's distance is updated by v.distance := u.distance + uv.weight
. By inductive assumption, u.distance
is the length of some path from source to u. Then u.distance + uv.weight
is the length of the path from source to v that follows the path from source to u and then goes to v.
For the second part, consider the shortest path from source to u with at most i edges. Let v be the last vertex before u on this path. Then, the part of the path from source to v is the shortest path from source to v with at most i-1 edges. By inductive assumption, v.distance
after i-1 cycles is at most the length of this path. Therefore, uv.weight + v.distance
is at most the length of the path from s to u. In the ith cycle, u.distance
gets compared with uv.weight + v.distance
, and is set equal to it if uv.weight + v.distance
was smaller. Therefore, after i cycles, u.distance
is at most the length of the shortest path from source to u that uses at most i edges.
When i equals the number of vertices in the graph, each path will be the shortest path overall, unless there are negative-weight cycles. If a negative-weight cycle exists and is accessible from the source, then given any walk, a shorter one exists, so there is no shortest walk. Otherwise, the shortest walk will not include any cycles (because going around a cycle would make the walk shorter), so each shortest path visits each vertex at most once, and its number of edges is less than the number of vertices in the graph.
[edit] Applications in routing
A distributed variant of Bellman-Ford algorithm is used in distance-vector routing protocols, for example the Routing Information Protocol (RIP). The algorithm is distributed because it involves a number of nodes (routers) within an Autonomous system, a collection of IP networks typically owned by an ISP. It consists of the following steps:
- Each node calculates the distances between itself and all other nodes within the AS and stores this information as a table.
- Each node sends its table to all neighbouring nodes.
- When a node receives distance tables from its neighbours, it calculates the shortest routes to all other nodes and updates its own table to reflect any changes.
The main disadvantages of Bellman-Ford algorithm in this setting are
- Does not scale well
- Changes in network topology are not reflected quickly since updates are spread node-by-node.
- Counting to infinity (if link or node failures render a node unreachable from some set of other nodes, those nodes may spend forever gradually increasing their estimates of the distance to it, and in the meantime there may be routing loops)
[edit] Implementations
[edit] C
#include <stdio.h> #include <stdlib.h> /* Let INFINITY be an integer value not likely to be confused with a real weight, even a negative one. */ #define INFINITY ((1 << 14)-1) typedef struct { int source; int dest; int weight; } Edge; void BellmanFord(Edge edges[], int edgecount, int nodecount, int source) { int *distance = malloc(nodecount * sizeof *distance); int i, j; for (i=0; i < nodecount; ++i) distance[i] = INFINITY; distance[source] = 0; for (i=0; i < nodecount; ++i) { for (j=0; j < edgecount; ++j) { if (distance[edges[j].source] != INFINITY) { int new_distance = distance[edges[j].source] + edges[j].weight; if (new_distance < distance[edges[j].dest]) distance[edges[j].dest] = new_distance; } } } for (i=0; i < edgecount; ++i) { if (distance[edges[i].dest] > distance[edges[i].source] + edges[i].weight) { puts("Negative edge weight cycles detected!"); free(distance); return; } } for (i=0; i < nodecount; ++i) { printf("The shortest distance between nodes %d and %d is %d\n", source, i, distance[i]); } free(distance); return; } int main(void) { /* This test case should produce the distances 2, 4, 7, -2, and 0. */ Edge edges[10] = {{0,1, 5}, {0,2, 8}, {0,3, -4}, {1,0, -2}, {2,1, -3}, {2,3, 9}, {3,1, 7}, {3,4, 2}, {4,0, 6}, {4,2, 7}}; BellmanFord(edges, 10, 5, 4); return 0; }
[edit] References
- Richard Bellman: On a Routing Problem, in Quarterly of Applied Mathematics, 16(1), pp.87-90, 1958.
- Lestor R. Ford jr., D. R. Fulkerson: Flows in Networks, Princeton University Press, 1962.
- Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein. Introduction to Algorithms, Second Edition. MIT Press and McGraw-Hill, 2001. ISBN 0-262-03293-7. Section 24.1: The Bellman-Ford algorithm, pp.588–592.