Recent from talks
Nothing was collected or created yet.
Bellman–Ford algorithm
View on Wikipedia| Class | Single-source shortest path problem (for weighted directed graphs) |
|---|---|
| Data structure | Graph |
| Worst-case performance | |
| Best-case performance | |
| Worst-case space complexity | |
The Bellman–Ford algorithm is an algorithm that computes shortest paths from a single source vertex to all of the other vertices in a weighted digraph.[1] It is slower than Dijkstra's algorithm for the same problem, but more versatile, as it is capable of handling graphs in which some of the edge weights are negative numbers.[2] The algorithm was first proposed by Alfonso Shimbel (1955), but is instead named after Richard Bellman and Lester Ford Jr., who published it in 1958 and 1956, respectively.[3] Edward F. Moore also published a variation of the algorithm in 1959, and for this reason it is also sometimes called the Bellman–Ford–Moore algorithm.[1]
Negative edge weights are found in various applications of graphs. This is why this algorithm is useful.[4] If a graph contains a "negative cycle" (i.e. a cycle whose edges sum to a negative value) that is reachable from the source, then there is no cheapest path: any path that has a point on the negative cycle can be made cheaper by one more walk around the negative cycle. In such a case, the Bellman–Ford algorithm can detect and report the negative cycle.[1][5]
Algorithm
[edit]
Like Dijkstra's algorithm, Bellman–Ford proceeds by relaxation, in which approximations to the correct distance are replaced by better ones until they eventually reach the solution. In both algorithms, the approximate distance to each vertex is always an overestimate of the true distance, and is replaced by the minimum of its old value and the length of a newly found path.[6]
However, Dijkstra's algorithm uses a priority queue to greedily select the closest vertex that has not yet been processed, and performs this relaxation process on all of its outgoing edges; by contrast, the Bellman–Ford algorithm simply relaxes all the edges, and does this times, where is the number of vertices in the graph.[6]
In each of these repetitions, the number of vertices with correctly calculated distances grows, from which it follows that eventually all vertices will have their correct distances. This method allows the Bellman–Ford algorithm to be applied to a wider class of inputs than Dijkstra's algorithm. The intermediate answers and the choices among equally short paths depend on the order of edges relaxed, but the final distances remain the same.[6]
Bellman–Ford runs in time, where and are the number of vertices and edges respectively.
function BellmanFord(list vertices, list edges, vertex source) is
// This implementation takes in a graph, represented as
// lists of vertices (represented as integers [0..n-1]) and
// edges, and fills two arrays (distance and predecessor)
// holding the shortest path from the source to each vertex
distance := list of size n
predecessor := list of size n
// Step 1: initialize graph
for each vertex v in vertices do
// Initialize the distance to all vertices to infinity
distance[v] := inf
// And having a null predecessor
predecessor[v] := null
// The distance from the source to itself is zero
distance[source] := 0
// Step 2: relax edges repeatedly
repeat |V|−1 times:
for each edge (u, v) with weight w in edges do
if distance[u] + w < distance[v] then
distance[v] := distance[u] + w
predecessor[v] := u
// Step 3: check for negative-weight cycles
for each edge (u, v) with weight w in edges do
if distance[u] + w < distance[v] then
predecessor[v] := u
// A negative cycle exists;
// find a vertex on the cycle
visited := list of size n initialized with false
visited[v] := true
while not visited[u] do
visited[u] := true
u := predecessor[u]
// u is a vertex in a negative cycle,
// find the cycle itself
ncycle := [u]
v := predecessor[u]
while v != u do
ncycle := concatenate([v], ncycle)
v := predecessor[v]
error "Graph contains a negative-weight cycle", ncycle
return distance, predecessor
Simply put, the algorithm initializes the distance to the source to 0 and all other nodes to infinity. Then for all edges, if the distance to the destination can be shortened by taking the edge, the distance is updated to the new lower value.
The core of the algorithm is a loop that scans across all edges at every loop. For every , at the end of the -th iteration, from any vertex v, following the predecessor trail recorded in predecessor yields a path that has a total weight that is at most distance[v], and further, distance[v] is a lower bound to the length of any path from source to v that uses at most i edges.
Since the longest possible path without a cycle can be edges, the edges must be scanned times to ensure the shortest path has been found for all nodes. A final scan of all the edges is performed and if any distance is updated, then a path of length edges has been found which can only occur if at least one negative cycle exists in the graph.
The edge (u, v) that is found in step 3 must be reachable from a negative cycle, but it isn't necessarily part of the cycle itself, which is why it's necessary to follow the path of predecessors backwards until a cycle is detected. The above pseudo-code uses a Boolean array (visited) to find a vertex on the cycle, but any cycle finding algorithm can be used to find a vertex on the cycle.
A common improvement when implementing the algorithm is to return early when an iteration of step 2 fails to relax any edges, which implies all shortest paths have been found, and therefore there are no negative cycles. In that case, the complexity of the algorithm is reduced from to where is the maximum length of a shortest path in the graph.
Proof of correctness
[edit]The correctness of the algorithm can be shown by induction:[2][7]
Lemma. After i repetitions of for loop,
- if Distance(u) is not infinity, it is equal to the length of some path from s to u; and
- 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 loop 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 a shortest path P (there may be more than one) from source to v with at most i edges. Let u be the last vertex before v on this path. Then, the part of the path from source to u is a shortest path from source to u with at most i-1 edges, since if it were not, then there must be some strictly shorter path from source to u with at most i-1 edges, and we could then append the edge uv to this path to obtain a path with at most i edges that is strictly shorter than P—a contradiction. By inductive assumption, u.distance after i−1 iterations is at most the length of this path from source to u. Therefore, uv.weight + u.distance is at most the length of P. In the ith iteration, v.distance gets compared with uv.weight + u.distance, and is set equal to it if uv.weight + u.distance is smaller. Therefore, after i iterations, v.distance is at most the length of P, i.e., the length of the shortest path from source to v that uses at most i edges.
If there are no negative-weight cycles, then every shortest path visits each vertex at most once, so at step 3 no further improvements can be made. Conversely, suppose no improvement can be made. Then for any cycle with vertices v[0], ..., v[k−1],
v[i].distance <= v[i-1 (mod k)].distance + v[i-1 (mod k)]v[i].weight
Summing around the cycle, the v[i].distance and v[i−1 (mod k)].distance terms cancel, leaving
0 <= sum from 1 to k of v[i-1 (mod k)]v[i].weight
I.e., every cycle has nonnegative weight.
Finding negative cycles
[edit]When the algorithm is used to find shortest paths, the existence of negative cycles is a problem, preventing the algorithm from finding a correct answer. However, since it terminates upon finding a negative cycle, the Bellman–Ford algorithm can be used for applications in which this is the target to be sought – for example in cycle-cancelling techniques in network flow analysis.[1]
Applications in routing
[edit]A distributed variant of the Bellman–Ford algorithm is used in distance-vector routing protocols, for example the Routing Information Protocol (RIP).[8] The algorithm is distributed because it involves a number of nodes (routers) within an Autonomous system (AS), 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 neighboring nodes.
- When a node receives distance tables from its neighbors, it calculates the shortest routes to all other nodes and updates its own table to reflect any changes.
The main disadvantages of the Bellman–Ford algorithm in this setting are as follows:
- It does not scale well.
- Changes in network topology are not reflected quickly since updates are spread node-by-node.
- Count 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.
Improvements
[edit]The Bellman–Ford algorithm may be improved in practice (although not in the worst case) by the observation that, if an iteration of the main loop of the algorithm terminates without making any changes, the algorithm can be immediately terminated, as subsequent iterations will not make any more changes. With this early termination condition, the main loop may in some cases use many fewer than |V| − 1 iterations, even though the worst case of the algorithm remains unchanged. The following improvements all maintain the worst-case time complexity.
A variation of the Bellman–Ford algorithm described by Moore (1959), reduces the number of relaxation steps that need to be performed within each iteration of the algorithm. If a vertex v has a distance value that has not changed since the last time the edges out of v were relaxed, then there is no need to relax the edges out of v a second time. In this way, as the number of vertices with correct distance values grows, the number whose outgoing edges that need to be relaxed in each iteration shrinks, leading to a constant-factor savings in time for dense graphs. This variation can be implemented by keeping a collection of vertices whose outgoing edges need to be relaxed, removing a vertex from this collection when its edges are relaxed, and adding to the collection any vertex whose distance value is changed by a relaxation step. In China, this algorithm was popularized by Fanding Duan, who rediscovered it in 1994, as the "shortest path faster algorithm".[9]
Yen (1970) described another improvement to the Bellman–Ford algorithm. His improvement first assigns some arbitrary linear order on all vertices and then partitions the set of all edges into two subsets. The first subset, Ef, contains all edges (vi, vj) such that i < j; the second, Eb, contains edges (vi, vj) such that i > j. Each vertex is visited in the order v1, v2, ..., v|V|, relaxing each outgoing edge from that vertex in Ef. Each vertex is then visited in the order v|V|, v|V|−1, ..., v1, relaxing each outgoing edge from that vertex in Eb. Each iteration of the main loop of the algorithm, after the first one, adds at least two edges to the set of edges whose relaxed distances match the correct shortest path distances: one from Ef and one from Eb. This modification reduces the worst-case number of iterations of the main loop of the algorithm from |V| − 1 to .[10][11]
Another improvement, by Bannister & Eppstein (2012), replaces the arbitrary linear order of the vertices used in Yen's second improvement by a random permutation. This change makes the worst case for Yen's improvement (in which the edges of a shortest path strictly alternate between the two subsets Ef and Eb) very unlikely to happen. With a randomly permuted vertex ordering, the expected number of iterations needed in the main loop is at most .[11]
Fineman (2024), at Georgetown University, created an improved algorithm that with high probability runs in time. Here, the is a variant of big O notation that hides logarithmic factors.
Notes
[edit]- ^ a b c d Bang-Jensen & Gutin (2000)
- ^ a b Lecture 14 stanford.edu
- ^ Schrijver (2005)
- ^ Sedgewick (2002).
- ^ Kleinberg & Tardos (2006).
- ^ a b c Cormen et al. (2022), Section 22.1.
- ^ Dinitz, Yefim; Itzhak, Rotem (2017-01-01). "Hybrid Bellman–Ford–Dijkstra algorithm". Journal of Discrete Algorithms. 42: 35–44. doi:10.1016/j.jda.2017.01.001. ISSN 1570-8667.
- ^ Malkin, Gary S. (November 1998). RIP Version 2 (Report). Internet Engineering Task Force.
- ^ Duan, Fanding (1994). "关于最短路径的SPFA快速算法 [About the SPFA algorithm]". Journal of Southwest Jiaotong University. 29 (2): 207–212.
- ^ Cormen et al., 4th ed., Problem 22-1, p. 640.
- ^ a b See Sedgewick's web exercises for Algorithms, 4th ed., exercises 5 and 12 (retrieved 2013-01-30).
References
[edit]Original sources
[edit]- Shimbel, A. (1955). Structure in communication nets. Proceedings of the Symposium on Information Networks. New York, New York: Polytechnic Press of the Polytechnic Institute of Brooklyn. pp. 199–203.
- Bellman, Richard (1958). "On a routing problem". Quarterly of Applied Mathematics. 16: 87–90. doi:10.1090/qam/102435. MR 0102435.
- Ford, Lester R. Jr. (August 14, 1956). Network Flow Theory. Paper P-923. Santa Monica, California: RAND Corporation.
- Moore, Edward F. (1959). The shortest path through a maze. Proc. Internat. Sympos. Switching Theory 1957, Part II. Cambridge, Massachusetts: Harvard Univ. Press. pp. 285–292. MR 0114710.
- Yen, Jin Y. (1970). "An algorithm for finding shortest routes from all source nodes to a given destination in general networks". Quarterly of Applied Mathematics. 27 (4): 526–530. doi:10.1090/qam/253822. MR 0253822.
- Bannister, M. J.; Eppstein, D. (2012). "Randomized speedup of the Bellman–Ford algorithm". Analytic Algorithmics and Combinatorics (ANALCO12), Kyoto, Japan. pp. 41–47. arXiv:1111.5414. doi:10.1137/1.9781611973020.6.
- Fineman, Jeremy T. (2024). "Single-source shortest paths with negative real weights in time". In Mohar, Bojan; Shinkar, Igor; O'Donnell, Ryan (eds.). Proceedings of the 56th Annual ACM Symposium on Theory of Computing, STOC 2024, Vancouver, BC, Canada, June 24–28, 2024. Association for Computing Machinery. pp. 3–14. arXiv:2311.02520. doi:10.1145/3618260.3649614.
Secondary sources
[edit]- Ford, L. R. Jr.; Fulkerson, D. R. (1962). "A shortest chain algorithm". Flows in Networks. Princeton University Press. pp. 130–134.
- Bang-Jensen, Jørgen; Gutin, Gregory (2000). "Section 2.3.4: The Bellman-Ford-Moore algorithm". Digraphs: Theory, Algorithms and Applications (First ed.). Springer. ISBN 978-1-84800-997-4.
- Schrijver, Alexander (2005). "On the history of combinatorial optimization (till 1960)" (PDF). Handbook of Discrete Optimization. Elsevier: 1–68.
- Cormen, Thomas H.; Leiserson, Charles E.; Rivest, Ronald L.; Stein, Clifford (2022) [1990]. Introduction to Algorithms (4th ed.). MIT Press and McGraw-Hill. ISBN 0-262-04630-X. Section 22.1: The Bellman–Ford algorithm, pp. 612–616. Problem 22–1, p. 640.
- Heineman, George T.; Pollice, Gary; Selkow, Stanley (2008). "Chapter 6: Graph Algorithms". Algorithms in a Nutshell. O'Reilly Media. pp. 160–164. ISBN 978-0-596-51624-6.
- Kleinberg, Jon; Tardos, Éva (2006). Algorithm Design. New York: Pearson Education, Inc.
- Sedgewick, Robert (2002). "Section 21.7: Negative Edge Weights". Algorithms in Java (3rd ed.). Addison-Wesley. ISBN 0-201-36121-3. Archived from the original on 2008-05-31. Retrieved 2007-05-28.
Bellman–Ford algorithm
View on GrokipediaHistory and Background
Origins and Development
The Bellman–Ford algorithm emerged in the 1950s as a key application of dynamic programming to optimization problems in networks, particularly for finding efficient paths in complex systems.[3][8] Although first proposed by Alfonso Shimbel in 1955 in his paper "Structure of Complex Systems and the Search for Their Inherent Simplicities," the algorithm is named after later contributors Richard Bellman and Lester Ford Jr.[9] This period marked a surge in operations research, driven by military and logistical needs during the Cold War, where researchers at institutions like the RAND Corporation sought mathematical tools to model resource allocation, routing, and control in uncertain environments.[10][11] Central to its formulation was Richard Bellman's principle of optimality, introduced in the late 1940s and early 1950s as a foundational concept in dynamic programming. This principle posits that an optimal policy for a multistage decision process has the property that, regardless of the initial state and decision, the remaining decisions must constitute an optimal policy for the subsequent subproblem.[12] Bellman developed this idea while working on multistage decision processes at RAND, coining the term "dynamic programming" to describe recursive optimization techniques that break down problems into overlapping subproblems.[12] The principle enabled systematic computation of optimal solutions by building from simpler stages, laying the groundwork for algorithms addressing shortest paths in graphs with potential negative weights. Detailed descriptions of the algorithm were provided by Lester R. Ford Jr. in 1956, who described a relaxation-based method for computing shortest paths in his RAND Corporation report on network flow theory, motivated by practical routing challenges.[8] Independently, Richard Bellman formalized a similar dynamic programming approach in his 1958 paper "On a Routing Problem," applying the principle of optimality to derive recursive equations for minimal-time paths in queueing networks.[3] These works, rooted in the era's emphasis on network analysis for defense and logistics, established the core iterative relaxation procedure that detects negative cycles and computes distances from a source vertex.[3][8]Key Contributors
The Bellman–Ford algorithm is named after two primary contributors, Richard Bellman and Lester Ford Jr., who independently developed key aspects of the method in the mid-1950s. Richard Bellman, an American applied mathematician born in 1920 and deceased in 1984, is widely recognized as the inventor of dynamic programming, a foundational technique he introduced in the early 1950s while working at the RAND Corporation, a think tank focused on operations research and systems analysis.[13] In 1958, Bellman applied dynamic programming principles to solve the shortest path problem in routing networks, describing an iterative approach to compute optimal paths in graphs with possible negative weights in his paper "On a Routing Problem," published in the Quarterly of Applied Mathematics.[3] Lester Ford Jr., born in 1927 and deceased in 2017, was an American mathematician specializing in network flow problems and operations research, also affiliated with the RAND Corporation during the algorithm's formative years.[14] In 1956, Ford, collaborating with D. R. Fulkerson, introduced the relaxation method—a core mechanism of iteratively updating distance estimates—in his RAND report "Network Flow Theory," where he outlined its use for finding shortest paths in networks as part of broader flow optimization techniques.[8] Ford's work extended to linear programming, contributing foundational methods for solving transportation and assignment problems through network-based formulations that bridged combinatorial optimization and linear constraints.[15] The algorithm also acknowledges independent contributions from Edward F. Moore, an American computer scientist and mathematician, who in 1959 published a variation emphasizing efficient path exploration in mazes and graphs, presented as "Algorithm D" in his paper "The Shortest Path through a Maze" at the International Symposium on the Theory of Switching.[16] Moore's formulation, while focused on unweighted cases, reinforced the relaxation-based paradigm and is sometimes referred to in extensions of the Bellman–Ford method.Algorithm Description
Problem Setup and Assumptions
The Bellman–Ford algorithm solves the single-source shortest path problem in a weighted directed graph , where is the finite set of vertices (also called nodes) and is the set of directed edges. Each edge is assigned a real-valued weight , representing the cost or length of traversing from vertex to vertex . These weights are finite and may include positive, negative, or zero values, allowing the algorithm to handle scenarios where some paths become cheaper by including negative-cost edges.[17] Given a designated source vertex , the objective is to compute the shortest path from to every other vertex . A path from to is a sequence of edges forming a walk from to without cycles, and its total weight is the sum of the weights of its edges. The algorithm assumes the graph contains no negative-weight cycles—closed paths with total weight less than zero—as such cycles would render shortest paths undefined by allowing arbitrarily low costs through repeated traversal. This assumption ensures that shortest paths exist and are well-defined for all vertices reachable from .[17] Standard notation for the problem includes , which denotes the shortest-path distance from to , defined as the minimum total weight over all paths from to (or if no such path exists). Additionally, represents the predecessor of in a shortest path from , forming part of the shortest path tree rooted at . These distances and predecessors enable reconstruction of the actual paths once computed.Step-by-Step Procedure
The Bellman–Ford algorithm initializes distance estimates from a designated source vertex to all other vertices in the graph. Specifically, the distance is set to 0, while for every vertex . An accompanying predecessor array is initialized such that null for all , enabling subsequent path reconstruction.[4][17] The algorithm then performs relaxation across all edges for exactly iterations, where denotes the number of vertices. In each iteration, every edge with weight is considered; if , the estimate is updated as and . This process systematically refines the distance estimates by propagating improvements from already-reached vertices to their neighbors.[17] The limit of iterations arises because, assuming no negative-weight cycles, any shortest path from to another vertex involves at most edges, ensuring that all relevant path lengths are fully relaxed within this bound.[17] At termination, the array provides the shortest-path distances from to all vertices (with indicating unreachability), while the predecessor array supports tracing the shortest paths by backtracking from any target vertex to .[4][17]Pseudocode and Example
The Bellman–Ford algorithm can be expressed in pseudocode as follows, where is a weighted directed graph, is the source vertex, denotes the weight of edge , represents the shortest-path distance estimate from to vertex , and is the predecessor of in the shortest path:BELLMAN-FORD(G, w, s)
Initialize d[v] ← ∞ for all v ∈ V
d[s] ← 0
π[v] ← NIL for all v ∈ V
for i ← 1 to |V| - 1
for each edge (u, v) ∈ E
if d[v] > d[u] + w(u, v)
d[v] ← d[u] + w(u, v)
π[v] ← u
BELLMAN-FORD(G, w, s)
Initialize d[v] ← ∞ for all v ∈ V
d[s] ← 0
π[v] ← NIL for all v ∈ V
for i ← 1 to |V| - 1
for each edge (u, v) ∈ E
if d[v] > d[u] + w(u, v)
d[v] ← d[u] + w(u, v)
π[v] ← u
- connects to (3) and (5).
- connects to (-1) and (8).
- connects to (2).
- : , .
- : , .
- : , .
- : , .
- : , .
