The Floyd-Warshall Algorithm

Fractional CTO · Founder of Injuria.ai
The Floyd-Warshall Algorithm
The Floyd-Warshall algorithm is a fundamental dynamic programming algorithm used in computer science and graph theory to find the shortest paths between all pairs of vertices in a weighted, directed graph. Unlike single-source shortest path algorithms that compute distances from one specific starting node to all other nodes, this algorithm computes the minimum distance between every possible source and destination node in a single execution. It operates on graphs with positive or negative edge weights, provided there are no negative-weight cycles, and produces a complete distance matrix as its output.[20]
The algorithm systematically considers all possible paths between any two vertices by incrementally allowing the paths to pass through an expanding set of intermediate vertices. By applying the principle of optimality, it compares the current known shortest path between two nodes against a potential new path that routes through a newly permitted intermediate node.[21] If the routed path is shorter, the distance is updated. This recursive structure allows the algorithm to evaluate an exponential number of potential paths in polynomial time, specifically bounded by a cubic time complexity relative to the number of vertices.
The history of the algorithm includes multiple independent discoveries and generalizations during the late 1950s and early 1960s. It is most commonly attributed to Robert Floyd[1], who published the shortest path formulation in 1962, and Stephen Warshall[2], who published a highly related theorem on the transitive closure of Boolean matrices earlier the same year. However, the underlying mathematical structure was previously described by Bernard Roy[3] in 1959 and is deeply connected to Stephen Kleene's[4] 1956 work on finite automata. Today, the algorithm is a canonical example of dynamic programming and forms the basis for solving a wide class of problems known as the Algebraic Path Problem.
Mathematical Foundation and Problem Definition
To understand the algorithm, one must first define the mathematical structure of the All-Pairs Shortest Path problem. Let $G = (V, E)$ be a directed graph where $V$ is a set of $n$ vertices numbered 1 to $n$, and $E$ is a set of directed edges. The graph is associated with a weight function $w: E \to \mathbb{R}$ that maps each edge to a real-valued weight. If an edge exists from vertex $u$ to vertex $v$, its weight is denoted as $w(u, v)$. If no such edge exists, the weight is defined as positive infinity.
A path $p$ from a source vertex $u$ to a destination vertex $v$ is a sequence of vertices $\langle v_0, v_1, \dots, v_k \rangle$ such that $v_0 = u$, $v_k = v$, and $(v_{i-1}, v_i) \in E$ for all $i$ from 1 to $k$. The total weight of the path, denoted $w(p)$, is the sum of the weights of its constituent edges. The shortest path weight from $u$ to $v$, denoted $\delta(u, v)$, is defined as the minimum $w(p)$ over all possible paths from $u$ to $v$. If no path exists, $\delta(u, v)$ remains infinity.
The All-Pairs Shortest Path problem requires computing $\delta(u, v)$ for every pair of vertices $u, v \in V$. While algorithms like Dijkstra's algorithm[5] solve the single-source version of this problem efficiently, Dijkstra's algorithm requires all edge weights to be non-negative because it relies on a greedy approach that assumes path weights monotonically increase.[22] The Floyd-Warshall algorithm accommodates negative edge weights, which frequently appear in applications like financial arbitrage detection or operations research where negative weights represent profit, energy generation, or time gained.[23]
However, the algorithm requires that the graph contains no negative-weight cycles. A negative-weight cycle is a path that starts and ends at the same vertex and has a total weight less than zero. For example, if a path from vertex A to vertex B has a weight of 1, B to C has a weight of -5, and C to A has a weight of 2, the total cycle weight is -2. If such a cycle exists, one could traverse it infinitely many times to decrease the path weight indefinitely. This makes the concept of a shortest path mathematically undefined for any vertices reachable from that cycle. The Floyd-Warshall algorithm can be used to detect the presence of negative cycles. Because the distance from a vertex to itself is initialized to zero, traversing a negative cycle will eventually cause the distance from a vertex to itself to become negative. Therefore, negative cycles manifest as negative values on the main diagonal of the final distance matrix.
Mechanism and Dynamic Programming Approach
The Floyd-Warshall algorithm relies on the algorithmic paradigm of dynamic programming, which solves complex problems by breaking them down into simpler, overlapping subproblems and building up the solution from the optimal solutions to those subproblems. The algorithm restricts the set of vertices that can be used as intermediate stops on a path, and then incrementally relaxes this restriction.
Let an intermediate vertex of a simple path $p = \langle v_1, v_2, \dots, v_k \rangle$ be any vertex of $p$ other than the endpoints $v_1$ and $v_k$. The algorithm considers a subset of vertices ${1, 2, \dots, k}$ and asks a specific question. What is the shortest path from vertex $i$ to vertex $j$ if the path is only allowed to use vertices from this subset as intermediate vertices?
Let $d^{(k)}{i,j}$ represent the weight of the shortest path from vertex $i$ to vertex $j$ for which all intermediate vertices are drawn from the set ${1, 2, \dots, k}$. The algorithm computes $d^{(k)}{i,j}$ for all pairs $i, j$ iteratively for $k = 0, 1, \dots, n$.
When $k = 0$, the path is not allowed to use any intermediate vertices. Therefore, the shortest path from $i$ to $j$ is simply the direct edge between them. The base case is defined as $d^{(0)}{i,j} = w(i, j)$ if $i \neq j$, $d^{(0)}{i,i} = 0$, and $d^{(0)}_{i,j} = \infty$ if there is no direct edge.
For $k > 0$, the algorithm evaluates whether adding vertex $k$ to the set of allowed intermediate vertices improves the shortest path from $i$ to $j$. There are two possibilities for the optimal path using vertices ${1, 2, \dots, k}$:
- The shortest path does not pass through vertex $k$. In this case, the shortest path only uses vertices from ${1, 2, \dots, k-1}$, meaning its cost is exactly $d^{(k-1)}_{i,j}$.
- The shortest path does pass through vertex $k$. Because the graph contains no negative cycles, the path will pass through $k$ exactly once. This path can be decomposed into two segments. The first is a subpath from $i$ to $k$, and the second is a subpath from $k$ to $j$. Both subpaths only use intermediate vertices from the set ${1, 2, \dots, k-1}$. The cost of this routed path is $d^{(k-1)}{i,k} + d^{(k-1)}{k,j}$.
The principle of optimal substructure dictates that the true shortest path is the minimum of these two options. This yields the fundamental recurrence relation of the Floyd-Warshall algorithm:
$d^{(k)}{i,j} = \min(d^{(k-1)}{i,j}, d^{(k-1)}{i,k} + d^{(k-1)}{k,j})$
By computing this recurrence for $k = 1$ to $n$, the final matrix $d^{(n)}_{i,j}$ will contain the shortest path weights using all available vertices, which is the exact solution to the All-Pairs Shortest Path problem.
Algorithmic Implementation and Complexity
The mathematical recurrence translates directly into a highly compact algorithm. While the recurrence suggests the need for a three-dimensional matrix to store the distances at each step $k$, the algorithm can be optimized to use a single two-dimensional matrix, updating the values in place.
This optimization is mathematically sound because the values $d^{(k-1)}{i,k}$ and $d^{(k-1)}{k,j}$ do not change during the $k$-th iteration. A path from $i$ to $k$ that uses intermediate vertices up to $k$ cannot use $k$ as an intermediate vertex, as $k$ is the destination. Therefore, $d^{(k)}{i,k} = d^{(k-1)}{i,k}$. The same logic applies to the path from $k$ to $j$. Consequently, overwriting the matrix in place does not corrupt the data required for subsequent calculations in the same iteration.
The modern standard implementation, first detailed by Peter Ingerman[6] in 1962, uses three nested loops. The following pseudocode demonstrates the structure:
let dist be a |V| × |V| array of minimum distances initialized to infinity
for each vertex v from 1 to |V|
dist[v][v] = 0
for each edge (u, v) in E
dist[u][v] = weight(u, v)
for k from 1 to |V|
for i from 1 to |V|
for j from 1 to |V|
if dist[i][j] > dist[i][k] + dist[k][j]
dist[i][j] = dist[i][k] + dist[k][j]
The time complexity of this algorithm is strictly $O(|V|^3)$ in Big-O notation. The initialization takes $O(|V|^2)$ time, and the core logic consists of three nested loops, each iterating $|V|$ times. Inside the innermost loop, the algorithm performs a constant number of basic operations, specifically addition, comparison, and assignment. Because the algorithm evaluates every possible combination of $i, j,$ and $k$ regardless of the graph's sparsity, the best-case, average-case, and worst-case time complexities are all exactly $\Theta(|V|^3)$.
The space complexity is $O(|V|^2)$ due to the storage requirement of the two-dimensional distance matrix.[24] This is optimal for the All-Pairs Shortest Path problem, as the output itself is a matrix of size $|V| \times |V|$ containing $O(|V|^2)$ elements.
Path Reconstruction
While the standard algorithm computes the lengths of the shortest paths, many applications require the actual sequence of vertices that comprise those paths.[25] To reconstruct the paths, the algorithm must maintain a predecessor matrix, often denoted as $\Pi$.
The entry $\pi_{i,j}$ stores the index of the vertex that immediately precedes $j$ on the shortest path from $i$ to $j$. Initially, before the nested loops begin, the predecessor matrix is populated based on the direct edges. If there is an edge from $i$ to $j$, $\pi_{i,j}$ is set to $i$. If there is no edge, or if $i = j$, $\pi_{i,j}$ is set to a null value.
During the execution of the three nested loops, whenever the algorithm finds that routing through vertex $k$ produces a shorter path from $i$ to $j$, it updates the distance matrix. At the exact same time, it must update the predecessor matrix. If the path through $k$ is strictly shorter, the new predecessor of $j$ on the path from $i$ becomes the predecessor of $j$ on the path from $k$. The update rule is:
$\pi_{i,j} = \pi_{k,j}$
After the algorithm terminates, the shortest path from any source $i$ to any destination $j$ can be reconstructed by tracing backward from $j$ using the predecessor matrix. One looks up $\pi_{i,j}$ to find the vertex before $j$, then looks up the predecessor of that vertex, continuing until the source vertex $i$ is reached. The following pseudocode illustrates the reconstruction function:
function get_path(i, j)
if dist[i][j] == infinity
return "No path exists"
let path be an empty list
let current = j
while current is not null
prepend current to path
current = predecessor[i][current]
return path
This reconstruction process takes $O(|V|)$ time per path, as the maximum length of a simple path in a graph with $|V|$ vertices is $|V| - 1$.
Discovery and History
The algorithm is recognized for being independently discovered and formalized by multiple computer scientists and mathematicians over a span of six years. This reflects the rapid development of graph theory and computer science during the mid-twentieth century.
The earliest mathematical foundation was laid by Stephen Kleene[4] in 1956. Working at the RAND Corporation, Kleene published a seminal paper titled "Representation of events in nerve nets and finite automata". In this paper, Kleene introduced the concept of regular expressions and provided an algorithm to convert a deterministic finite automaton into a regular expression. Kleene's algorithm used an identical dynamic programming structure, incrementally allowing states to be used in the transition paths between nodes in the automaton.
In 1959, the French mathematician Bernard Roy[3] published "Transitivité et connexité" in the Comptes Rendus de l'Académie des Sciences. Roy was working in the field of operations research and was interested in routing and connectivity problems. He formulated the algorithm to compute the transitive closure of a directed graph, which determines whether a path exists between any two vertices, regardless of the path's length or weight. In French literature, the algorithm is frequently referred to as the Roy-Warshall or Roy-Floyd-Warshall algorithm in recognition of his priority.
In January 1962, Stephen Warshall[2] published a two-page paper titled "A theorem on Boolean matrices" in the Journal of the ACM. Warshall, working on compiler design and program analysis at Technical Operations, Inc., independently discovered the algorithm for computing the transitive closure of a Boolean matrix. His formulation used logical AND and OR operations instead of addition and minimization. Warshall proved that a single pass of three nested loops was sufficient to compute the closure, replacing older algorithms that required unpredictable iterative matrix multiplications.
In June 1962, Robert Floyd[1] published "Algorithm 97: Shortest Path" in the Communications of the ACM. Floyd recognized that Warshall's theorem could be generalized from Boolean logic to real-valued arithmetic to solve the shortest path problem. Floyd's publication was remarkably brief, consisting of only a few paragraphs of ALGOL 60 code and a short mathematical justification, yet it cemented the algorithm's application to weighted graphs.
Finally, in November 1962, Peter Ingerman[6] published "Algorithm 141: Path Matrix" in the Communications of the ACM. Ingerman provided the modern, highly optimized three-nested-loop implementation that extracted the logic from Floyd's recursive ALGOL procedures into the iterative structure used in textbooks today.
Generalization to the Algebraic Path Problem
The structural identicality of Kleene's algorithm for regular expressions, Warshall's algorithm for transitive closure, and Floyd's algorithm for shortest paths is not a coincidence. In 1977, Daniel Lehmann[7] explored algebraic structures for transitive closures, and in 1981, Robert Endre Tarjan[8] published "A unified approach to path problems". These works formalized that all these algorithms are specific instances of a single mathematical framework known as the Algebraic Path Problem.
The Algebraic Path Problem abstracts the graph operations over an algebraic structure called a closed semiring, or an idempotent semiring. A semiring is a set $S$ equipped with two binary operations, $\oplus$ (addition) and $\otimes$ (multiplication), and two identity elements, $\bar{0}$ and $\bar{1}$. The operations must satisfy specific axioms. The $\oplus$ operator must be associative and commutative with identity $\bar{0}$. The $\otimes$ operator must be associative with identity $\bar{1}$ and distribute over $\oplus$. Finally, $\bar{0}$ acts as an annihilator for $\otimes$. For path problems, the semiring is usually idempotent, meaning $a \oplus a = a$ for all $a \in S$.
By changing the semiring, the exact same three-nested-loop algorithm solves entirely different problems:
- Shortest Paths: Using the Tropical semiring $(\mathbb{R} \cup {\infty}, \min, +, \infty, 0)$, the $\oplus$ operator becomes the minimum function, and the $\otimes$ operator becomes standard addition. This yields the standard Floyd-Warshall algorithm.
- Transitive Closure: Using the Boolean semiring $({0, 1}, \lor, \land, 0, 1)$, the $\oplus$ operator becomes logical OR, and the $\otimes$ operator becomes logical AND. This yields Warshall's algorithm.
- Bottleneck Paths (Maximum Capacity): Using the Max-Min semiring $(\mathbb{R} \cup {-\infty, \infty}, \max, \min, -\infty, \infty)$, the algorithm finds the path between two nodes that maximizes the minimum edge weight along the path, a common requirement in network bandwidth routing.
- Regular Expressions: Using the String semiring over an alphabet, where $\oplus$ is set union and $\otimes$ is string concatenation, the algorithm generates the regular expression describing all valid paths through a finite automaton, matching Kleene's algorithm.
This generalization demonstrates that the cubic dynamic programming structure is a universal solver for any problem that can be mapped to a closed semiring.
Parallelization and Computational Refinements
While the $O(|V|^3)$ time complexity is fixed, the real-world execution time of the Floyd-Warshall algorithm is heavily dependent on memory access patterns. The standard three-nested-loop implementation exhibits poor spatial locality. As the matrix size grows, the algorithm frequently accesses memory locations that are not adjacent, leading to high cache miss rates and stalling the CPU. This phenomenon, known as the memory wall, has driven extensive research into computational refinements.
To improve cache performance, researchers developed block-striped or tiled versions of the algorithm. By dividing the $|V| \times |V|$ matrix into smaller sub-matrices that fit entirely within the CPU's L1 or L2 cache, the algorithm can compute the shortest paths for a block of vertices before moving to the next. G. Venkataraman et al.[9] formalized a blocked all-pairs shortest paths algorithm in 2003, and Joon-Sang Park et al.[10] demonstrated in 2004 that tiled implementations could achieve massive speedups over the standard iterative approach by minimizing data transfers between main memory and the processor cache.
A more advanced refinement is the cache-oblivious implementation. In 2006, Rezaul Chowdhury and Vijaya Ramachandran[11] mapped the Floyd-Warshall algorithm to the Gaussian Elimination Paradigm. By restructuring the algorithm using a recursive divide-and-conquer strategy, the cache-oblivious version optimally utilizes all levels of the memory hierarchy without requiring explicit tuning to the hardware's specific cache sizes.
The algorithm is also highly amenable to parallelization on modern hardware, particularly Graphics Processing Units (GPUs) and distributed computing clusters. Because the updates to the distance matrix in the $k$-th iteration depend only on the results of the $(k-1)$-th iteration, all $|V|^2$ elements of the matrix can be updated simultaneously. In 2007, Pawan Harish and P. J. Narayanan[12] published one of the first implementations of the algorithm using NVIDIA's CUDA architecture. By assigning individual threads to compute specific elements of the distance matrix and utilizing the GPU's high-speed shared memory to broadcast the $k$-th row and column, GPU implementations process massive dense graphs orders of magnitude faster than sequential CPU implementations. For extreme-scale graphs, distributed memory approaches using the Message Passing Interface (MPI) partition the matrix across multiple compute nodes. Piyush Sao et al.[13] demonstrated in 2021 that a distributed, multi-GPU implementation of Floyd-Warshall could achieve petascale performance on supercomputers by aggressively overlapping communication and computation.
Real-World Applications
The Floyd-Warshall algorithm is utilized across numerous domains where dense graph analysis or all-pairs relationships are required.
In computer networking, while protocols like OSPF use Dijkstra's algorithm for single-source routing, the Floyd-Warshall algorithm is employed in centralized network management and Software-Defined Networking (SDN). It is used for traffic engineering, calculating disjoint paths for network redundancy, and analyzing the complete topology to identify critical bottlenecks. The algorithm's ability to handle negative weights is applied in routing protocols that factor in link costs offset by energy generation or financial incentives.
Thomas H. Cormen et al.'s[14] "Introduction to Algorithms" documents arbitrage detection as an application of the Bellman-Ford algorithm, not the Floyd-Warshall algorithm.[25] By representing currencies as vertices and exchange rates as edge weights, one can apply a logarithmic transformation to the weights. A negative-weight cycle in this transformed graph corresponds directly to a sequence of currency trades that yields a guaranteed risk-free profit. The Floyd-Warshall algorithm computes the entire matrix of exchange paths and flags any negative diagonal entries, instantly identifying arbitrage loops.
In bioinformatics, the algorithm is used to analyze complex biological networks. Halil Ibrahim Kuru et al.[15]'s MatchMaker framework predicts drug synergy using drug chemical structures and cell line gene expression profiles, not by computing shortest path distances in protein-protein interaction networks using the Floyd-Warshall algorithm. Similarly, Paul Scherer and Pietro Liò[16] applied it to generate distributed representations of graphs for drug pair scoring.
In social network analysis, computing centrality metrics requires knowledge of all shortest paths. Betweenness centrality, which measures how often a node acts as a bridge along the shortest path between two other nodes, relies heavily on these computations. While Ulrik Brandes[17] introduced a faster algorithm for betweenness centrality in sparse networks in 2001, the Floyd-Warshall algorithm remains the standard approach for dense social graphs or small-group sociograms.
Additionally, the algorithm shares its exact structural loops with Gauss-Jordan elimination for matrix inversion. The computational techniques developed to optimize Floyd-Warshall, such as cache-oblivious recursion and GPU tiling, are directly transferable to dense linear algebra applications.
Significance and Tradeoffs
The significance of the Floyd-Warshall algorithm lies in its simplicity, its generality, and its extreme efficiency on dense graphs. However, it is not the optimal choice for all shortest path problems, and understanding its tradeoffs is necessary for algorithm selection.
The primary alternative for the All-Pairs Shortest Path problem is running a single-source algorithm from every vertex. Using a Fibonacci heap, Dijkstra's algorithm runs in $O(|E| + |V| \log |V|)$ time. Running it $|V|$ times yields a total time complexity of $O(|V||E| + |V|^2 \log |V|)$. For sparse graphs, where the number of edges $|E|$ is proportional to $|V|$, this repeated Dijkstra approach operates in $O(|V|^2 \log |V|)$ time, which is significantly faster than Floyd-Warshall's $O(|V|^3)$.
If a sparse graph contains negative edges, Dijkstra's algorithm cannot be used directly. The standard single-source solution for graphs with negative edges is the Bellman-Ford algorithm[18], published by Richard Bellman in 1958.[22] Running Bellman-Ford from every vertex takes $O(|V|^2|E|)$ time, which is slower than Floyd-Warshall for anything but the sparsest graphs.
To resolve this, Donald B. Johnson[19] published an algorithm in 1977 that uses a single pass of the Bellman-Ford algorithm to reweight the graph in $O(|V||E|)$ time, eliminating negative edges while preserving the shortest paths. After reweighting, Johnson's algorithm runs Dijkstra's algorithm from every node, achieving the same $O(|V|^2 \log |V| + |V||E|)$ time complexity. For sparse graphs with negative edges, Johnson's algorithm is mathematically superior to Floyd-Warshall.
Despite these alternatives, the Floyd-Warshall algorithm remains highly relevant. For dense graphs, where $|E|$ approaches $|V|^2$, the time complexity of repeated Dijkstra and Johnson's algorithm degrades to $O(|V|^3)$, matching Floyd-Warshall. In this dense scenario, Floyd-Warshall is highly efficient in practice. Its three nested loops contain almost no branching logic or complex data structures, resulting in a microscopic constant factor and highly predictable instruction pipelines. Furthermore, its ability to be easily parallelized and generalized to any semiring ensures its continued prominence in modern computer science.
Sources (25)
- Robert Floyd
- Stephen Warshall
- Bernard Roy
- Stephen Kleene's
- Dijkstra's algorithm
- Peter Ingerman
- Daniel Lehmann
- Robert Endre Tarjan
- G. Venkataraman et al.
- Joon-Sang Park et al.
- ACM Digital Library
- Pawan Harish and P. J. Narayanan
- Piyush Sao et al.
- mitpress.mit.edu: Thomas H. Cormen et al.'s
- Halil Ibrahim Kuru et al.
- Paul Scherer and Pietro Liò
- Ulrik Brandes
- Bellman-Ford algorithm
- Donald B. Johnson
- Jeremy Kubica, Graph Algorithms the Fun Way (No Starch Press, 2024)
- John David Stone, Algorithms for Functional Programming (Springer, 2018)
- Wuhong Wang, Martin Baumann, Xiaobei Jiang, Green, Smart and Connected Transportation Systems (Springer Nature, 2020)
- Jean-Michel Réveillac, Modeling and Simulation of Logistics Flows 1 (John Wiley & Sons, 2017)
- Cristopher Moore, Stephan Mertens, The Nature of Computation (OUP Oxford, 2011)
- Thomas H Cormen, Charles E Leiserson, Ronald L Rivest, Introduction To Algorithms (MIT Press, 2001)