Proof of `Connected components in linear time`
groundedproofs/Lax11Proofs/CCMain.lean · lax-11
What this proof establishes
no assumptions
Assuming the claims on the left, the claim on the right holds — checked by the archive's pipeline. Proof code is not displayed here.
Description
Connected components can be computed in linear time on a word random access machine: labels the vertices of every graph given in compressed sparse row form by the least vertex of their component, within machine steps, at every word length for which .
Proof strategy
The witness is the compiled driver . Its IMP+ source reads the encoding into four arrays, sweeps the vertices in increasing order starting a breadth-first search at every unlabelled one, and writes the label array out; is that run, end to end, with output and cost at most . The cost is a single amortized argument — one potential for the whole sweep, so the searches are never counted separately — and the linearity in comes from the encoding's , which makes and both at most the length of the word.
discharges the compiler, the layout invariant and the machine in one step, charging machine steps per unit of IMP+ cost, plus one for the final . The array extents are chosen per input, as that lemma allows: declares , , , , which is what the reads fill.
Where the word length is paid for
The machine truncates every value modulo , so the run on the machine is the run in the unbounded semantics only as long as nothing the program computes reaches . The bound the driver is proved under is the length of the input word itself: every entry of an encoding is smaller than the encoding is long (), and every quantity the algorithm keeps of its own — vertex numbers, offsets, the queue pointers, the counter of scanned slots — is bounded by or by , hence again by the length. So the whole run needs the single hypothesis , and the compiled program needs in addition that the cells the layout addresses are words, which is . The statement's hypothesis, , gives both with room to spare; it is stated in that form because a bound on the running time is the condition a reader of an algorithm expects, and because it is the one inequality the machine model actually needs to be told.
What the program is allowed to help itself to
Two details of the program are shaped by the cost proof rather than by the algorithm, and a reader is entitled to ask whether either of them smuggles work out of the bound. Neither does.
The queue is global. It is never reset between searches: a search leaves its head and tail pointers equal, and the next search continues from there. So the tail only ever increases, and since a vertex is put on the queue only in the step that labels it, the tail never passes the number of vertices. "Queue capacity not yet used" is therefore a budget for the whole run out of which every enqueue is paid, instead of a budget per search that would force the searches to be counted one at a time. Resetting the queue is what would cost something; not resetting it is free.
A scalar counts the adjacency slots already scanned. The potential has to be a function of the program's own scalars, and "how much of the target array has been looked at" is not otherwise one of them, since the scan pointer restarts inside each vertex's block. The counter is incremented once per slot and read nowhere, so it costs one addition per slot — a constant factor on work already being done — and deleting it would leave the computed labels unchanged.
Nothing else is precomputed. The input word is read once into the four arrays in the order the tape presents it, so the reading phase is a plain copy and the encoding stays the dumb one the concept fixes.
Attribution
The first theorem of the submission; the algorithm is the textbook sweep of breadth-first searches.