Walks of bounded length and the midpoint recursion #
This file extends upstream Relation.RelatesInSteps and Relation.RelatesWithinSteps (a walk of
exactly, or at most, n steps of a relation r) with the facts behind Savitch's theorem.
A walk of at most n steps of r is a walk of exactly n steps of the reflexive closure
Relation.ReflGen r, which may stay put. In that form a walk of at most m + n steps is exactly
a walk of at most m steps to a midpoint followed by a walk of at most n steps from it, so a
bound of 2 ^ (i + 1) reduces to two independent bounds of 2 ^ i: the recursion that Savitch's
algorithm runs, storing one midpoint per level. On a finite type with N elements, everything
reachable is reachable within N - 1 steps, hence within 2 ^ ⌈log₂ N⌉ steps, which fixes the
recursion depth at ⌈log₂ N⌉.
Nothing here mentions a machine: these are the facts about the configuration graph that Savitch's algorithm relies on.
Main results #
Function.iterate_trans: iterated function applications compose across step counts.Relation.relatesWithinSteps_iff_relatesInSteps_reflGen: a walk of at mostnsteps is a walk of exactlynsteps that may stay put.Relation.RelatesWithinSteps.succ_iff: one more step of breadth-first search.Relation.RelatesInSteps.add_iff,Relation.RelatesWithinSteps.add_iff: walks split at any point; the second is the midpoint recursion.Relation.RelatesWithinSteps.two_mul_iff,Relation.RelatesWithinSteps.two_pow_succ_iff,Relation.RelatesWithinSteps.one_iff: the recursion of Savitch's algorithm and its base case.Relation.ReflTransGen.relatesWithinSteps_of_encard_le,Relation.reflTransGen_iff_relatesWithinSteps: reachability is reachability within one step fewer than the number of elements.Relation.reflTransGen_iff_relatesWithinSteps_two_pow_clog: the bound Savitch's recursion starts from.
References #
Walks that may stay put #
A reflexive relation relates every element to itself in any number of steps.
A walk of at most n steps is a walk.
A walk of at most n steps is a walk of exactly n steps that may stay put. This is how
a walk of bounded length is guessed and checked one step at a time.
One more step of breadth-first search. An element is reached within n + 1 steps exactly
when it is reached in at most one step from an element reached within n steps.
A walk of at most one step is a step of the reflexive closure.
Splitting walks #
Walks split at any point. A walk of m + n steps passes through a midpoint after exactly
m of them.
The midpoint recursion. A walk of at most m + n steps is exactly a walk of at most m
steps to some midpoint followed by a walk of at most n steps from it. The midpoint is all a
recursive search has to remember.
The halving form of the midpoint recursion: a bound of 2 n splits into two independent
bounds of n.
The recursion of Savitch's algorithm. A bound of 2 ^ (i + 1) splits into two
subproblems with bound 2 ^ i, so the recursion from a bound of 2 ^ i has depth i and each
level stores one midpoint; its base case is Relation.RelatesWithinSteps.one_iff
Sipser, Theorem 8.5.
Walks on few elements are short #
Everything reachable is reachable within one step fewer than the number of reachable
elements. A longer walk repeats an element, and the loop between the repetitions can be cut
out (upstream Relation.ReflTransGen.relatesInSteps_lt_encard).
The bound Savitch's recursion starts from. On a finite type with N elements, reachability
is reachability within 2 ^ ⌈log₂ N⌉ steps, so the recursion of
Relation.RelatesWithinSteps.two_pow_succ_iff decides it at depth ⌈log₂ N⌉
Sipser, Theorem 8.5.