Proofs: Kahn's algorithm
These are the human proofs of Kahn's algorithm, at full length.
Kahn's algorithm returns a topological ordering or detects a cycle full
This proof shows: correctness, termination.
Let be a directed graph with vertices, possibly with parallel edges and self-loops, where each copy of an edge is one entry of an adjacency list. For a set , write for the number of edges with . Let also stand for the set of vertices in the list .
Invariant. At the start of each iteration of the loop of line L5, and when the loop ends:
- for each ;
- holds, each one time, exactly the vertices with ;
- for each edge with , also , and is before in .
Initialization. After line L2, is the number of entries in all lists, the in-degree of , and is empty, so part 1 holds. Line L4 enqueues each vertex with once, so part 2 holds. Part 3 holds because is empty.
Maintenance. Let one iteration dequeue . By part 2, and , so by part 1 each edge into comes from a vertex in . Line L6 appends to . Part 3 holds for the new : for edges , is in the old and so before , and because a self-loop would give . Edges into older vertices of are unchanged. For part 1, the new value of for is the old value minus the number of edges , and lines L7 and L8 decrease one time for each such entry of . Entries that are already in are decreased too, but their counts are not used again. For part 2, a vertex whose count becomes zero in this iteration had a positive count before, so it was not in , and line L9 enqueues it once, at the decrease that makes the count zero. A count that is already zero is never decreased again for , because a decrease of comes from an edge with , which part 1 counts. So no vertex is enqueued twice. The vertex left and joined . So part 2 holds.
Termination. By part 2, each dequeued vertex joins and never returns to , so the loop of line L5 runs at most times, and each iteration scans one finite list.
Lemma (remaining vertices). When the loop ends, let . If is not empty, then has a directed cycle all of whose vertices are in .
Proof. The queue is empty, so by part 2 each has , and by part 1 there is an edge with , that is, . Start at some , and choose with . Among some vertex repeats, with , and with the edge is a directed cycle in .
Theorem. KAHN terminates. If is acyclic, it returns a topological ordering. If has a directed cycle, it reports a cycle.
Proof. Termination was shown above.
If is acyclic, the lemma shows that is empty when the loop ends. So , line L10 does not report, and holds each vertex once, by part 2. By part 3, applied with , each edge has before . So is a topological ordering.
If has a directed cycle , no vertex of is in at the end. Assume otherwise, and let be the vertex of appended to first, and the vertex before on , so . By part 3, at the iteration after joined , is in and before . If , this says is before itself, which is false. Otherwise is a vertex of appended before , which contradicts the choice of . So , and line L10 reports a cycle.