Proofs: Compressed sparse row
These are the human proofs of Compressed sparse row, at full length.
BUILD makes a valid compressed sparse row array and the queries answer for the stored graph full
This proof shows: correctness, termination.
Let be the input list of BUILD, of length , with distinct pairs , ; for an undirected graph it holds each edge in both orders and no loop. For a vertex let be the number of pairs of with first end . The structure stands for the graph with an edge , or , for each in the row . The invariant (C) is (C1) on the offsets, (C2) strictly sorted rows and (C3) symmetry without loops for an undirected graph.
Lemma 1 (offsets). After line L3, for . So (C1) holds and the row of has length .
Proof. After line L2, for , and . Line L3 sets and , so by induction on the claim holds. Then , the offsets do not decrease, and .
Lemma 2 (placement). After lines L4 to L6, the row of each holds exactly the second ends of the pairs of with first end , in the order in which these pairs occur in .
Proof. We claim that before each step of the loop of line L5, for each , , where is the number of pairs with first end processed so far, and the slots hold their second ends in order. This holds after line L4, with . A step on writes at slot and increases by 1, so the claim still holds. Since and the row of has slots by Lemma 1, each write stays inside the row of , so no write touches another row. At the end , so each row is full with its second ends in input order. The loop has steps, so it stops.
Lemma 3 (sorting). After line L7 each row is strictly increasing, so (C2) holds.
Proof. Line L7 is done by running lines L1 to L6 first with the second end as the key, which by Lemmas 1 and 2 lists the pairs in non-decreasing order of the second end, and then with the first end as the key on that list. By Lemma 2 the second pass places the pairs of each row in the order of the first list, which is non-decreasing in the second end. The pairs are distinct and have the same first end within a row, so their second ends are distinct, and the row is strictly increasing.
For an undirected graph the rows hold in the row of exactly when , which holds exactly when , and has no loop, so (C3) holds. So after BUILD, (C) holds and the stored graph is the graph given by .
Theorem. With (C) holding, NEIGHBORS outputs the neighbours of in increasing order, DEGREE returns their number, and ADJACENT returns whether is a neighbour of . Each of them stops.
Proof. NEIGHBORS reads exactly the row of in order, which by (C2) lists each neighbour once in increasing order. DEGREE returns the length of the row, which by (C2) is the number of distinct neighbours.
For ADJACENT, let and , so the row is , sorted by (C2). We show that the loop of lines L11 to L13 keeps
(S) , each entry at an index in is less than , and each entry at an index in is at least .
Line L10 makes (S) true with both ranges empty. In a step, . If , then since the row is sorted each entry at an index up to is less than , so setting keeps (S). Otherwise , and each entry from on is at least , so setting keeps (S). Each step decreases by at least 1, so the loop stops, with . Then by (S) the entries before are less than and the entries from on are at least . If is in the row, its index is therefore , and line L14 returns true. If is not in the row, either or , and line L14 returns false.