Algorithm Search⌘K

Proofs: Warshall's algorithm

These are the human proofs of Warshall's algorithm, at full length.

Warshall's algorithm computes the transitive closure full

This proof shows: correctness, termination.

Let G=(V,E)G = (V, E) be a directed graph with V={0,…,n−1}V = \{0, \ldots, n-1\}, where parallel arcs and loops are allowed. A walk from ii to jj of length ℓ≥1\ell \ge 1 is a sequence i=x0,x1,…,xℓ=ji = x_0, x_1, \ldots, x_\ell = j with (xt−1,xt)∈E(x_{t-1}, x_t) \in E for each tt; its inner vertices are x1,…,xℓ−1x_1, \ldots, x_{\ell-1}. For 0≤k≤n0 \le k \le n, let

Pk={(i,j):some walk of length at least 1 from i to j has all its inner vertices in {0,…,k−1}}.P_k = \{(i, j) : \text{some walk of length at least 1 from } i \text{ to } j \text{ has all its inner vertices in } \{0, \ldots, k - 1\}\}.

We view RR as a set of pairs: (i,j)∈R(i, j) \in R when R[i][j]=1R[i][j] = 1. Write RkR_k for the value of RR just before round kk of line L2, so that RnR_n is the value returned by line L6.

Lemma 1. P0=EP_0 = E, as a set of pairs, and PnP_n is the transitive closure E+E^+.

Proof. A walk with no inner vertex has length 1 and is an arc, and an arc is such a walk. Every inner vertex is in V={0,…,n−1}V = \{0, \ldots, n - 1\}, so PnP_n contains every pair joined by a walk of length at least 1. □\square

Lemma 2. Pk⊆Pk+1P_k \subseteq P_{k+1}, and if (i,k)∈Pk(i, k) \in P_k and (k,j)∈Pk(k, j) \in P_k, then (i,j)∈Pk+1(i, j) \in P_{k+1}.

Proof. The first claim is clear. For the second, join a walk from ii to kk and a walk from kk to jj, both with inner vertices below kk. The result is a walk of length at least 2 from ii to jj whose inner vertices are those of the two walks and kk, all in {0,…,k}\{0, \ldots, k\}. □\square

Lemma 3. If (i,j)∈Pk+1(i, j) \in P_{k+1}, then (i,j)∈Pk(i, j) \in P_k, or both (i,k)∈Pk(i, k) \in P_k and (k,j)∈Pk(k, j) \in P_k.

Proof. Take a walk i=x0,…,xℓ=ji = x_0, \ldots, x_\ell = j with inner vertices in {0,…,k}\{0, \ldots, k\}. If kk is not an inner vertex, (i,j)∈Pk(i, j) \in P_k. Else let xax_a be the first inner vertex equal to kk and xbx_b the last, with 0<a≤b<ℓ0 < a \le b < \ell. The walk x0,…,xax_0, \ldots, x_a goes from ii to kk, has length a≥1a \ge 1, and its inner vertices x1,…,xa−1x_1, \ldots, x_{a-1} are inner vertices of the whole walk other than kk, so they are below kk. So (i,k)∈Pk(i, k) \in P_k. In the same way xb,…,xℓx_b, \ldots, x_\ell shows (k,j)∈Pk(k, j) \in P_k. □\square

Lemma 4 (one round). If Rk=PkR_k = P_k, then Rk+1=Pk+1R_{k+1} = P_{k+1}.

Proof. During round kk, line L5 adds to row ii the pairs (i,j)(i, j) with (k,j)(k, j) in the current row kk, for those ii with (i,k)(i, k) in the current RR. We first show that row kk does not change in round kk. A change of row kk can only happen when line L5 runs with i=ki = k, and it then takes the OR of row kk with itself. So throughout round kk, row kk equals row kk of Rk=PkR_k = P_k.

Rk+1⊆Pk+1R_{k+1} \subseteq P_{k+1}. We show that R⊆Pk+1R \subseteq P_{k+1} holds throughout round kk. It holds at the start, as Rk=Pk⊆Pk+1R_k = P_k \subseteq P_{k+1}. Suppose it holds before some run of line L5 with row ii, where (i,k)∈R(i, k) \in R. Each pair it adds is (i,j)(i, j) with (k,j)(k, j) in row kk, so (k,j)∈Pk(k, j) \in P_k. Also (i,k)∈R⊆Pk+1(i, k) \in R \subseteq P_{k+1}, and by Lemma 3 applied with j=kj = k, either (i,k)∈Pk(i, k) \in P_k, or (k,k)∈Pk(k, k) \in P_k and (i,k)∈Pk(i, k) \in P_k; in both cases (i,k)∈Pk(i, k) \in P_k. Lemma 2 gives (i,j)∈Pk+1(i, j) \in P_{k+1}.

Pk+1⊆Rk+1P_{k+1} \subseteq R_{k+1}. Let (i,j)∈Pk+1(i, j) \in P_{k+1}. Entries never change from 1 to 0, so if (i,j)∈Pk=Rk(i, j) \in P_k = R_k it is in Rk+1R_{k+1}. Else, by Lemma 3, (i,k)∈Pk(i, k) \in P_k and (k,j)∈Pk(k, j) \in P_k. When line L3 reaches row ii in round kk, (i,k)(i, k) is still in RR, so line L4 succeeds, and (k,j)(k, j) is in row kk, which has not changed. So line L5 sets R[i][j]=1R[i][j] = 1. □\square

Theorem. WARSHALL stops, after nn rounds of nn steps each, and returns RR with R[i][j]=1R[i][j] = 1 exactly when GG has a walk of length at least 1 from ii to jj.

Proof. The loops of lines L2 and L3 have nn steps each, and line L5 is a finite row operation, so the algorithm stops. Line L1 sets R0=E=P0R_0 = E = P_0 by Lemma 1, as parallel arcs set the same entry. By Lemma 4 and induction on kk, Rn=PnR_n = P_n, which is E+E^+ by Lemma 1. ■\blacksquare

Remark on the implementation. The Python code reads row kk once, as rk, before the loop over ii. This is the same as reading it at each step, because, as shown in Lemma 4, row kk does not change in round kk.

Back to Warshall's algorithm