Algorithm Search⌘K

Proofs: Read-Tarjan path enumeration

These are the human proofs of Read-Tarjan path enumeration, at full length.

Read-Tarjan lists every simple s-t path exactly once, with one branch per path full

This proof shows: correctness, termination.

Let GG be a finite directed graph on V={0,…,n−1}V = \{0, \ldots, n - 1\} with out-lists out(v)\mathrm{out}(v); an undirected graph is the directed graph with both arcs of every edge, and loops and parallel edges are removed, which does not change the set of simple paths as vertex sequences. Fix ss and tt. For a simple path π\pi from ss to uu, let S(π)S(\pi) be the set of simple ss-tt paths that start with π\pi. Call π\pi a branch if S(π)≠∅S(\pi) \ne \emptyset.

Lemma 1. For a simple path π\pi from ss to uu with u≠tu \ne t, S(π)≠∅S(\pi) \ne \emptyset if and only if tt is reachable from uu in G−BG - B, where BB is the set of vertices of π\pi other than uu.

Proof. A path in S(π)S(\pi) continues from uu to tt through vertices not in π\pi, which is a path from uu to tt in G−BG - B. Conversely, a path from uu to tt in G−BG - B can be taken simple, it meets π\pi only at uu, and appending it to π\pi gives a path in S(π)S(\pi). □\square

Lemma 2 (the set RR). In the loop of lines L11 to L14, at the test of line L13 for index ii, the blocked set is Xi=B∪{p0,…,pi}X_i = B \cup \{p_0, \ldots, p_i\}, and RR is the set RiR_i of vertices v∉Xiv \notin X_i from which tt is reachable in G−XiG - X_i.

Proof. For i=k−1i = k - 1, line L10 sets the blocked set to Xk−1X_{k-1} and computes Rk−1R_{k-1} by a reverse search from tt over unblocked vertices, which is correct because t∉Xk−1t \notin X_{k-1} (t=pkt = p_k and π\pi does not contain tt). For i<k−1i < k - 1, line L12 unblocks pi+1p_{i+1}, so the blocked set becomes Xi=Xi+1∖{pi+1}X_i = X_{i+1} \setminus \{p_{i+1}\}. Every vertex of Ri+1R_{i+1} is in RiR_i, since G−Xi+1G - X_{i+1} is a subgraph of G−XiG - X_i. A vertex v∈Ri∖Ri+1v \in R_i \setminus R_{i+1} has a path to tt in G−XiG - X_i, and each such path passes through pi+1p_{i+1}; so pi+1∈Rip_{i+1} \in R_i, and vv reaches pi+1p_{i+1} through vertices not in XiX_i. Moreover pi+1∈Rip_{i+1} \in R_i if and only if it has an arc into Ri+1R_{i+1}: a shortest path from pi+1p_{i+1} to tt in G−XiG - X_i does not return to pi+1p_{i+1}, so after its first arc it lies in G−Xi+1G - X_{i+1}. Line L12 tests exactly this, adds pi+1p_{i+1}, and the reverse search from it over unblocked vertices not yet in RR adds every vertex that reaches pi+1p_{i+1} in G−XiG - X_i. A vertex added this way reaches tt through pi+1p_{i+1}, so it is in RiR_i. Hence R=RiR = R_i. □\square

Lemma 3 (partition). Let π\pi be a branch ending at u≠tu \ne t, let P=(p0=u,…,pk=t)P = (p_0 = u, \ldots, p_k = t) be the path found at line L8, and for 0≤i<k0 \le i < k and x∈out(pi)x \in \mathrm{out}(p_i) with x≠pi+1x \ne p_{i+1} let πi,x=π p1⋯pi x\pi_{i,x} = \pi\, p_1 \cdots p_i\, x. Then S(π)S(\pi) is the disjoint union of {πP}\{\pi P\} and the sets S(πi,x)S(\pi_{i,x}) over all such (i,x)(i, x). Moreover S(πi,x)≠∅S(\pi_{i,x}) \ne \emptyset if and only if x∈Rix \in R_i.

Proof. By Lemma 1, PP exists, and πP∈S(π)\pi P \in S(\pi) since PP avoids BB. Let Q∈S(π)Q \in S(\pi) with Q≠πPQ \ne \pi P. Let ii be the largest index with π p1⋯pi\pi\, p_1 \cdots p_i a prefix of QQ. Then i<ki < k, since otherwise QQ starts with πP\pi P, which ends at tt, so Q=πPQ = \pi P. The path QQ does not end at pip_i, because pi≠tp_i \ne t for i<ki < k, so its next vertex xx is in out(pi)\mathrm{out}(p_i), and x≠pi+1x \ne p_{i+1} by the choice of ii. So Q∈S(πi,x)Q \in S(\pi_{i,x}). The pair (i,x)(i, x) is determined by QQ, so the sets are disjoint, and none contains πP\pi P. If xx lies in π\pi or in {p0,…,pi}\{p_0, \ldots, p_i\}, the sequence πi,x\pi_{i,x} is not simple and S(πi,x)=∅S(\pi_{i,x}) = \emptyset, and also x∈Xix \in X_i, so x∉Rix \notin R_i. Otherwise πi,x\pi_{i,x} is a simple path from ss to xx; if x=tx = t, S(πi,x)={πi,x}S(\pi_{i,x}) = \{\pi_{i,x}\} and t∈Rit \in R_i; if x≠tx \ne t, Lemma 1 with the blocked set XiX_i shows that S(πi,x)≠∅S(\pi_{i,x}) \ne \emptyset if and only if x∈Rix \in R_i. □\square

Lemma 4. When a branch π\pi is popped at line L5, the algorithm outputs, at that time and later through the branches pushed for it and their descendants, exactly the paths of S(π)S(\pi), each once.

Proof. By induction on n−∣π∣n - |\pi|, where ∣π∣|\pi| is the number of vertices of π\pi. If u=tu = t, S(π)={π}S(\pi) = \{\pi\}, since a simple path that contains tt ends there, and line L6 outputs π\pi and pushes nothing. Otherwise line L9 outputs πP\pi P, and by Lemmas 2 and 3, lines L13 and L14 push exactly the pairs (i,x)(i, x) with S(πi,x)≠∅S(\pi_{i,x}) \ne \emptyset, each a branch with more vertices than π\pi. Every pushed branch is popped later, because the loop runs until the stack is empty, and by induction it outputs exactly S(πi,x)S(\pi_{i,x}). By Lemma 3 these sets and {πP}\{\pi P\} are disjoint and their union is S(π)S(\pi). □\square

Theorem. READ-TARJAN terminates and outputs every simple ss-tt path exactly once. It pops exactly NN branches when N≥1N \ge 1 paths exist.

Proof. If s=ts = t, the only simple ss-tt path is (s)(s), and line L1 outputs it. If tt is not reachable from ss, there is no path and line L2 stops. Otherwise (s)(s) is a branch by Lemma 1, and by Lemma 4 the paths output are exactly S((s))S((s)), the set of all simple ss-tt paths, each once. Every popped branch outputs one path at line L6 or L9, and different branches output different paths by Lemma 4, so at most NN branches are popped, which proves termination; each branch does finite work because the searches and loops run over finite lists. Each path is output by the branch that pops it or by an ancestor's line L9, and the counting above shows that there are exactly NN branches. ■\blacksquare

Back to Read-Tarjan path enumeration