Algorithm Search⌘K

Proofs: Floyd-Warshall algorithm

These are the human proofs of Floyd-Warshall algorithm, at full length.

Floyd-Warshall computes all distances or detects a negative cycle full

This proof shows: correctness, termination.

Claim. Let GG be a directed graph on the vertices 1,…,n1, \ldots, n with real weights. At the end of FLOYD-WARSHALL:

  1. each finite D[i][j]D[i][j] is the weight of a walk from ii to jj (the empty walk when i=ji = j and D[i][i]=0D[i][i] = 0);
  2. D[i][j]≤w(p)D[i][j] \le w(p) for each path pp from ii to jj with i≠ji \ne j, and D[i][i]≤min⁡(0,w(C))D[i][i] \le \min(0, w(C)) for each cycle CC through ii with no repeated vertex.

Consequently, if GG has no negative cycle, then D[i][j]=δ(i,j)D[i][j] = \delta(i, j) for all i,ji, j; and if GG has a negative cycle, then D[i][i]<0D[i][i] < 0 for some ii. Also, D[i][i]<0D[i][i] < 0 for some ii only if GG has a negative cycle.

Termination. The loops have the fixed bounds mm, then n⋅n⋅nn \cdot n \cdot n, so the algorithm ends.

Notation. A path inside K⊆VK \subseteq V is a path from ii to jj whose inner vertices (all but the first and the last) are in KK. A cycle through ii inside KK is a cycle with no repeated vertex other than its start and end ii, whose other vertices are in KK. Let [k]={1,…,k}[k] = \{1, \ldots, k\}.

Invariant. At the end of pass kk of line L3 (k=0k = 0 means after line L2):

  • (W) each finite D[i][j]D[i][j] is the weight of a walk from ii to jj;
  • (P) D[i][j]≤w(p)D[i][j] \le w(p) for each path pp from i≠ji \ne j to jj inside [k][k], and D[i][i]≤min⁡(0,w(C))D[i][i] \le \min(0, w(C)) for each cycle CC through ii inside [k][k].

Base, k=0k = 0. Line L1 sets D[i][i]=0D[i][i] = 0, the empty walk, and ∞\infty elsewhere. Line L2 lowers D[u][v]D[u][v] to the least weight of an edge from uu to vv, a walk of one edge. A path inside ∅\emptyset from i≠ji \ne j is one edge, and a cycle through ii inside ∅\emptyset is a self-loop; line L2 covers both, and D[i][i]≤0D[i][i] \le 0 from line L1. So (W) and (P) hold.

Maintenance, from k−1k - 1 to kk. Entries only decrease in pass kk, so (P) for paths and cycles inside [k−1][k-1] stays true. Line L7 sets D[i][j]=D[i][k]+D[k][j]D[i][j] = D[i][k] + D[k][j] with both terms finite (else the test of line L6 fails, with ∞+x=∞\infty + x = \infty). By (W), these are the weights of walks i⇝ki \leadsto k and k⇝jk \leadsto j; joined, they form a walk i⇝ji \leadsto j of that weight. So (W) holds at each step of the pass.

For (P), take a path pp from ii to j≠ij \ne i inside [k][k] that passes through kk as an inner vertex (the paths that do not are inside [k−1][k-1]). Since pp repeats no vertex, it splits at kk into a path p1p_1 from ii to kk and a path p2p_2 from kk to jj, both inside [k−1][k-1]. By (P) for k−1k - 1, D[i][k]≤w(p1)D[i][k] \le w(p_1) and D[k][j]≤w(p2)D[k][j] \le w(p_2) at the start of pass kk, and these entries can only be smaller when line L6 tests the pair (i,j)(i, j). After that test, D[i][j]≤D[i][k]+D[k][j]≤w(p1)+w(p2)=w(p)D[i][j] \le D[i][k] + D[k][j] \le w(p_1) + w(p_2) = w(p), and it only decreases later. The same split works for a cycle CC through ii inside [k][k] that contains k≠ik \ne i: it splits into a path from ii to kk and a path from kk to ii, both inside [k−1][k-1], so after the test of the pair (i,i)(i, i), D[i][i]≤w(C)D[i][i] \le w(C). If k=ik = i, a cycle through ii inside [k][k] has its other vertices in [k−1][k-1], so it is already inside [k−1][k-1]. Thus (P) holds after pass kk.

At the end (k=nk = n). Every path and every cycle is inside [n][n], so parts 1 and 2 of the claim hold.

No negative cycle. Then every closed walk has weight at least 0, because it splits into cycles. A walk from ii to jj therefore weighs at least δ(i,j)\delta(i, j), so (W) gives D[i][j]≥δ(i,j)D[i][j] \ge \delta(i, j). A shortest walk can be taken to be a path, since removing a closed sub-walk does not increase the weight, so (P) gives D[i][j]≤δ(i,j)D[i][j] \le \delta(i, j) for i≠ji \ne j. For i=ji = j, δ(i,i)=0\delta(i, i) = 0, and 0≤D[i][i]≤00 \le D[i][i] \le 0. So D=δD = \delta.

A negative cycle. A closed walk of negative weight contains a cycle with no repeated vertex and negative weight, because a closed walk splits into such cycles and their weights add up to its weight. Let CC be such a cycle and ii a vertex of CC. By part 2, D[i][i]≤w(C)<0D[i][i] \le w(C) < 0.

Conversely, if D[i][i]<0D[i][i] < 0, then by part 1 it is the weight of a closed walk from ii (not the empty one, which weighs 0), so a negative cycle exists. ■\blacksquare

The next-hop matrix. This proof covers the matrix DD. The matching statement for the predecessor matrix, that it encodes shortest paths when no negative cycle exists, is proved in CLRS, Section 23.2, and the next-hop matrix is its mirror image.

Back to Floyd-Warshall algorithm