The capture theorem for L: the deterministic machine of a specification #
DescriptiveComplexity.HeadCapture builds a machine for an FO(TC) definition by
guessing. A deterministic machine may not guess, and this file builds the one
that does not: it searches where the other one guesses, and it counts so
that a search leading nowhere is abandoned. With it, FO(DTC) definability is
recognizability by a deterministic two-way multi-head automaton
(DescriptiveComplexity.dtcDefinable_iff_automaton,
DescriptiveComplexity.mem_LOGSPACE_iff_automaton), the deterministic counterpart of
DescriptiveComplexity.tcDefinable_iff_automaton.
Where the deterministic machine differs #
Both machines simulate the walk of a specification, holding the current tuple on one block of heads and a candidate on another, with the mode in the control. Three things change.
- The candidate is scanned, not guessed. The walk being deterministic
(
DescriptiveComplexity.TCSpec.det_functional), a node has at most one successor, so the machine may look for it:DescriptiveComplexity.HeadProgram.lexNextPwalks the candidate block through every tuple in turn, and the transition formula is evaluated at each. The tuple that passes is the successor. - The source is scanned too, on a third block, and the machine keeps it there: when a walk leads nowhere it comes back and takes the next source.
- The walk is given a budget. A deterministic walk that does not reach an
accepting node cycles, and a machine following it would never come back. So
the machine counts its steps on a fourth block – with a mode in the control,
giving exactly as many counter values as the specification has nodes – and
abandons the source when the counter overflows. That this is enough is
DescriptiveComplexity.exists_iterate_lt_card: a node reachable along a functional relation is reachable in fewer steps than the type has elements.
Every block needs to know when a head is at the greatest element, which is not a
quantifier-free fact of one head; so one further head is parked there once and
for all (DescriptiveComplexity.HeadProgram.dmk), shared by the three odometers as
their marker.
The machine, and the half that says it never lies #
DescriptiveComplexity.HeadProgram.DetNode (the control graph),
DescriptiveComplexity.HeadProgram.dFam and DescriptiveComplexity.HeadProgram.dWire (its
fragments and its arcs), DescriptiveComplexity.HeadProgram.dP (the machine), the
layout of the heads with the fact that the protected heads are exactly the four
blocks and the marker (DescriptiveComplexity.HeadProgram.dHeadAgree_iff), the
relations its fragments run (DescriptiveComplexity.HeadProgram.dRel) with all of them
proved (DescriptiveComplexity.HeadProgram.runs_dFam) and local
(DescriptiveComplexity.HeadProgram.headLocal2_dRel), and soundness:
DescriptiveComplexity.HeadProgram.dInv – at any node of the walk phase the tuple on
the first block is a node of the specification reachable from a source, and at
commit the candidate is one deterministic step away – is carried along every
arc (DescriptiveComplexity.HeadProgram.dInv_of_walk), and at the accepting arc it
says that the specification accepts
(DescriptiveComplexity.HeadProgram.accepts_of_dExit).
The search for the successor #
It is proved in full, and both ways. Over
the tuples of one mode – DescriptiveComplexity.HeadProgram.scanFound (if the current
node's successor, unique by DescriptiveComplexity.TCSpec.det_step_iff, is in the mode
being tried with a tuple at or above the block's, the scan walks the block up to
it and reaches commit holding it) and
DescriptiveComplexity.HeadProgram.scanNone (if there is no successor in that mode,
the scan runs the block to its greatest tuple and moves on) – both inductions
downwards along the lexicographic order, in the style of
DescriptiveComplexity.HeadProgram.decides_scanP. And over the chain of modes –
DescriptiveComplexity.HeadProgram.modeFound and
DescriptiveComplexity.HeadProgram.modeNone, inductions on the number of mode indices
left. So from candMode the machine provably reaches commit holding the
successor when there is one, and srcNext when there is none, in both cases
leaving the current tuple, the source and the counter as they were.
One step of the simulated walk follows (DescriptiveComplexity.HeadProgram.walkStep)
– at a node that is not accepting but has a successor, with a counter block that
can still be stepped, the machine tests the target formula, searches out the
successor, commits it onto the current block and ticks, arriving at tgtTest
one node along with the counter's tuple advanced by one in the lexicographic
order.
The counter, and the two ways a walk ends #
The counter is read as a value of one finite linear order
(DescriptiveComplexity.HeadProgram.dcount): the index of its mode, lexicographically
above the tuple on its block. This is the whole of the budget argument, because
a tick is a cover in that order – dcount_covBy_tup where the tuple can be
stepped, dcount_covBy_mode where it cannot and the machine resets it and moves
to the next counter mode – and because the order has exactly as many elements
as the specification has nodes (DescriptiveComplexity.HeadProgram.card_dcount),
which is the number DescriptiveComplexity.exists_iterate_lt_card bounds a walk by.
DescriptiveComplexity.HeadProgram.dTick packages one tick: at a node that is neither
accepting nor stuck, with a cover above the counter, the machine moves to the
successor and its counter to that cover.
A walk then ends in one of two ways, and both are proved:
DescriptiveComplexity.HeadProgram.walkAcc– if the walk reaches an accepting node within the budget, the machine accepts: an induction on the number of steps left,Tickssupplying the coverdTickneeds at each of them;DescriptiveComplexity.HeadProgram.walkOut– whatever the specification does, the machine comes back: it accepts, or it reachessrcNextwith its source block untouched. This is an induction downwards along the counter's order (DescriptiveComplexity.order_induction_down), the measure being the counter itself; at the top of the order the tuple is greatest and the mode last, so the tick fails andtickResetfalls through to the next source (DescriptiveComplexity.HeadProgram.dcount_of_isTop), and where the walk is stuckDescriptiveComplexity.HeadProgram.walkStuckreachessrcNextthrough the exhausted chain of candidate modes.
The source enumeration, and the theorem #
DescriptiveComplexity.HeadProgram.srcEnum walks the sources in the same order –
mode index above source tuple – downwards from any position at or below the
source the specification accepts from: at each position the machine either
accepts (walkAcc, when the position is that source) or comes back to
srcNext (DescriptiveComplexity.HeadProgram.srcTried, which is walkOut with the
start arc in front of it), and the odometer of DescriptiveComplexity.HeadLex then
advances the position by exactly one cover – stepping the tuple, or resetting it
and taking the next source mode.
DescriptiveComplexity.HeadProgram.accepts_dP conjoins the two halves: the machine
accepts exactly what the determinized specification does. Its fragments are
evaluators, odometers and moves, all deterministic, so the program is
(DescriptiveComplexity.HeadProgram.deterministic_dP) and
DescriptiveComplexity.HeadProgram.compile true – at most one enabled transition per
reading whatever the guards, and agreeing with the program where they are
exclusive – gives a machine that DescriptiveComplexity.HeadAutomaton.IsDeterministic
holds of on the nose. DescriptiveComplexity.dtcDefinable_of_automaton closes the
loop.
The control graph #
The control nodes of the deterministic machine. Besides what it is doing,
a node carries the source mode ms it is walking from, the current mode m,
and the mode component cm of the step counter.
- init
{M : Type}
{r : ℕ}
: DetNode M r
Park the marker at the greatest element and start the source scan.
- srcMode
{M : Type}
{r : ℕ}
(i : Fin (r + 1))
: DetNode M r
Dispatch on the source mode of index
i. - srcTest
{M : Type}
{r : ℕ}
(ms : M)
: DetNode M r
Test the source formula of
mson the source block. - srcNext
{M : Type}
{r : ℕ}
(ms : M)
: DetNode M r
Step the source block to the next tuple.
- srcReset
{M : Type}
{r : ℕ}
(ms : M)
: DetNode M r
Reset the source block and move on to the next source mode.
- start
{M : Type}
{r : ℕ}
(ms : M)
: DetNode M r
Copy the source onto the current block and reset the counter.
- tgtTest
{M : Type}
{r : ℕ}
(ms m cm : M)
: DetNode M r
Test the target formula of
mon the current block. - candMode
{M : Type}
{r : ℕ}
(ms m cm : M)
(i : Fin (r + 1))
: DetNode M r
Reset the candidate block and dispatch on the candidate mode of index
i. - candTest
{M : Type}
{r : ℕ}
(ms m cm m' : M)
: DetNode M r
Test the transition formula from
mtom'. - candNext
{M : Type}
{r : ℕ}
(ms m cm m' : M)
: DetNode M r
Step the candidate block to the next tuple.
- commit
{M : Type}
{r : ℕ}
(ms m cm m' : M)
: DetNode M r
Copy the candidate onto the current block.
- tick
{M : Type}
{r : ℕ}
(ms m cm : M)
: DetNode M r
Step the counter.
- tickReset
{M : Type}
{r : ℕ}
(ms m cm : M)
: DetNode M r
Reset the counter block and step its mode component.
- dead
{M : Type}
{r : ℕ}
: DetNode M r
Nothing more to do.
Instances For
Dependency graph
Dependency graph
Evaluating a formula on any block #
The evaluator, with the formula's variables read off any heads below the protected level.
Dependency graph
The layout of the heads #
How many heads the deterministic machine has: four blocks – current tuple, candidate, source, counter – a marker parked at the greatest element, the evaluator's workspace, and a spare.
Equations
- DescriptiveComplexity.HeadProgram.dHeads spec = 4 * spec.k + DescriptiveComplexity.specDepth spec.det + 2
Instances For
Dependency graph
The heads the machine's fragments must give back untouched.
Equations
- DescriptiveComplexity.HeadProgram.dprot spec = 4 * spec.k + 1
Instances For
Dependency graph
Dependency graph
Block t of the machine's heads: 0 the current tuple, 1 the candidate,
2 the source, 3 the counter.
Instances For
Dependency graph
The marker head, parked at the greatest element.
Instances For
Dependency graph
The head at a given index.
Equations
- DescriptiveComplexity.HeadProgram.dshd spec i = if h : i < DescriptiveComplexity.HeadProgram.dHeads spec then ⟨i, h⟩ else ⟨0, ⋯⟩
Instances For
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
The tuple block t holds.
Equations
- DescriptiveComplexity.HeadProgram.dTup spec t x i = x (DescriptiveComplexity.HeadProgram.dblk spec t i)
Instances For
Dependency graph
The protected heads are exactly the four blocks and the marker: there is nothing else below the protected level.
Dependency graph
Everything but block t is where it was.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
The moves #
Dependency graph
Dependency graph
Dependency graph
Dependency graph
The moves that park the marker at the greatest element.
Equations
Instances For
Dependency graph
The moves that send block t to the least element.
Equations
Instances For
Dependency graph
The moves that copy block t onto block 0.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
The moves that start a walk: the source onto the current block, and the counter back to the least tuple.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
Dependency graph
The machine #
The fragments of the deterministic machine.
Equations
- One or more equations did not get rendered due to their size.
- DescriptiveComplexity.HeadProgram.dFam spec DescriptiveComplexity.HeadProgram.DetNode.init = DescriptiveComplexity.HeadProgram.moveP (DescriptiveComplexity.HeadProgram.dParkMoves spec)
- DescriptiveComplexity.HeadProgram.dFam spec (DescriptiveComplexity.HeadProgram.DetNode.srcMode i) = DescriptiveComplexity.HeadProgram.exitP true
- DescriptiveComplexity.HeadProgram.dFam spec (DescriptiveComplexity.HeadProgram.DetNode.srcReset ms) = DescriptiveComplexity.HeadProgram.moveP (DescriptiveComplexity.HeadProgram.dResetMoves spec 2)
- DescriptiveComplexity.HeadProgram.dFam spec (DescriptiveComplexity.HeadProgram.DetNode.start ms) = DescriptiveComplexity.HeadProgram.moveP (DescriptiveComplexity.HeadProgram.dStartMoves spec)
- DescriptiveComplexity.HeadProgram.dFam spec DescriptiveComplexity.HeadProgram.DetNode.dead = DescriptiveComplexity.HeadProgram.exitP false
Instances For
Dependency graph
Where the deterministic machine goes when a fragment exits.
Equations
- One or more equations did not get rendered due to their size.
- DescriptiveComplexity.HeadProgram.dWire spec DescriptiveComplexity.HeadProgram.DetNode.init x✝ = Sum.inl (DescriptiveComplexity.HeadProgram.DetNode.srcMode (DescriptiveComplexity.ix0 spec))
- DescriptiveComplexity.HeadProgram.dWire spec (DescriptiveComplexity.HeadProgram.DetNode.srcTest ms) true = Sum.inl (DescriptiveComplexity.HeadProgram.DetNode.start ms)
- DescriptiveComplexity.HeadProgram.dWire spec (DescriptiveComplexity.HeadProgram.DetNode.srcTest ms) false = Sum.inl (DescriptiveComplexity.HeadProgram.DetNode.srcNext ms)
- DescriptiveComplexity.HeadProgram.dWire spec (DescriptiveComplexity.HeadProgram.DetNode.srcNext ms) true = Sum.inl (DescriptiveComplexity.HeadProgram.DetNode.srcTest ms)
- DescriptiveComplexity.HeadProgram.dWire spec (DescriptiveComplexity.HeadProgram.DetNode.srcNext ms) false = Sum.inl (DescriptiveComplexity.HeadProgram.DetNode.srcReset ms)
- DescriptiveComplexity.HeadProgram.dWire spec (DescriptiveComplexity.HeadProgram.DetNode.tgtTest ms m cm) true = Sum.inr true
- DescriptiveComplexity.HeadProgram.dWire spec (DescriptiveComplexity.HeadProgram.DetNode.candTest ms m cm m') true = Sum.inl (DescriptiveComplexity.HeadProgram.DetNode.commit ms m cm m')
- DescriptiveComplexity.HeadProgram.dWire spec (DescriptiveComplexity.HeadProgram.DetNode.candTest ms m cm m') false = Sum.inl (DescriptiveComplexity.HeadProgram.DetNode.candNext ms m cm m')
- DescriptiveComplexity.HeadProgram.dWire spec (DescriptiveComplexity.HeadProgram.DetNode.candNext ms m cm m') true = Sum.inl (DescriptiveComplexity.HeadProgram.DetNode.candTest ms m cm m')
- DescriptiveComplexity.HeadProgram.dWire spec (DescriptiveComplexity.HeadProgram.DetNode.commit ms m cm m') x✝ = Sum.inl (DescriptiveComplexity.HeadProgram.DetNode.tick ms m' cm)
- DescriptiveComplexity.HeadProgram.dWire spec (DescriptiveComplexity.HeadProgram.DetNode.tick ms m cm) true = Sum.inl (DescriptiveComplexity.HeadProgram.DetNode.tgtTest ms m cm)
- DescriptiveComplexity.HeadProgram.dWire spec (DescriptiveComplexity.HeadProgram.DetNode.tick ms m cm) false = Sum.inl (DescriptiveComplexity.HeadProgram.DetNode.tickReset ms m cm)
- DescriptiveComplexity.HeadProgram.dWire spec DescriptiveComplexity.HeadProgram.DetNode.dead x✝ = Sum.inr false
Instances For
Dependency graph
The deterministic machine of a specification.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
What the fragments of the deterministic machine run.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
What the fragments run #
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
The fragments of the deterministic machine run what they are meant to.
Dependency graph
The relations the fragments run see only the four blocks and the marker.
Dependency graph
Soundness #
Dependency graph
Dependency graph
Dependency graph
Dependency graph
The invariant the deterministic machine carries: the tuple on the first
block is a node reachable from a source, and at commit the candidate is one
deterministic step away.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
The invariant is carried along the machine's walk.
Dependency graph
Soundness: if the deterministic machine accepts, the specification does.
Dependency graph
Completeness: the candidate scan #
Reachability in the machine's control graph.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Covers are unique in a linear order.
Dependency graph
The tuple scan finds the successor: from the candidate block at c, if
the (unique) successor of the current node is in mode m' with a tuple at or
above c, the scan reaches commit holding it.
Dependency graph
The tuple scan exhausts: if the current node has no successor in mode
m', the scan walks the candidate block to its greatest tuple and moves on to
the next candidate mode.
Dependency graph
Completeness: the chain of candidate modes #
Dependency graph
Dependency graph
Dependency graph
Dependency graph
The chain of candidate modes finds the successor.
Dependency graph
The chain of candidate modes exhausts: with no successor to find, the machine tries every mode and moves on to the next source.
Dependency graph
Completeness: one step of the simulated walk #
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
One step of the simulated walk: at a node that is not accepting but has a successor, with a counter that can still be stepped, the machine moves to the successor and ticks.
Dependency graph
Completeness: the counter as a linear order #
The value of the counter: the mode it carries in the control together
with the tuple on its block, ordered lexicographically with the mode most
significant. A tick of the machine is a cover in this order
(DescriptiveComplexity.HeadProgram.dcount_covBy_tup within a mode,
DescriptiveComplexity.HeadProgram.dcount_covBy_mode across one), and the order has
exactly as many elements as the specification has nodes
(DescriptiveComplexity.HeadProgram.card_dcount) – which is what makes the budget long
enough.
Equations
- DescriptiveComplexity.HeadProgram.DCount spec B = Lex (Fin (DescriptiveComplexity.modeCard spec) × Lex (Fin spec.k → B))
Instances For
Dependency graph
The counter's value, read off the mode in the control and the tuple on the block.
Equations
- DescriptiveComplexity.HeadProgram.dcount spec cm t = toLex ((DescriptiveComplexity.modeEquiv spec) cm, toLex t)
Instances For
Dependency graph
The counter's value determines the mode and the tuple.
Dependency graph
Stepping the tuple is a cover of the counter.
Dependency graph
The index of a mode the enumeration produces.
Dependency graph
Running the tuple out and moving to the next mode is a cover of the counter.
Dependency graph
The counter starts at the bottom of its order.
Dependency graph
The counter is exhausted when its tuple is the greatest one and its mode is the last of the enumeration.
Dependency graph
At the top of the counter there is nothing left: the tuple is the greatest one and the mode is the last of the enumeration.
Dependency graph
The counter has exactly as many values as the specification has nodes.
Dependency graph
Completeness: the remaining arcs #
The marker can be parked at the greatest element.
Dependency graph
A walk can be started: the source is copied onto the current block and the counter is set to its least tuple.
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
The machine accepts from here: its control walk reaches the true
exit.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
Dependency graph
Completeness: one tick of the counter #
Dependency graph
A step of the walk taken with the counter at its greatest tuple: the
machine moves to the successor, fails to tick, and lands at tickReset.
Dependency graph
One tick: at a node that is not accepting but has a successor, with a counter that still has a cover above it, the machine moves to the successor and sets its counter to that cover – stepping the tuple where it can, and crossing over to the next counter mode where it cannot.
Dependency graph
Completeness: the walk, and its two outcomes #
A walk that leads nowhere is abandoned: with no successor to go to, the machine tries every candidate mode and comes back for the next source.
Dependency graph
The machine follows the walk while its counter lasts: if the walk reaches an accepting node within the budget, the machine accepts.
Dependency graph
A walk always comes to an end: whatever the specification does, the machine either accepts or comes back for the next source, its source block untouched. The measure is the counter, which the machine steps once per node visited.
Dependency graph
Completeness: the source enumeration #
The counter mode the machine starts a walk with.
Dependency graph
A source is tried: from the test of a source, the machine either accepts or comes back for the next tuple of the enumeration, its source block where it was.
Dependency graph
The source enumeration reaches the source that works: from any position of the enumeration at or below a source from which the walk accepts within the budget, the machine accepts.
Dependency graph
The machine of a specification #
Dependency graph
The deterministic machine of a specification accepts exactly what the
determinized specification does. Soundness is the invariant of
DescriptiveComplexity.HeadProgram.dInv; completeness is the source enumeration,
each source walked out to its end – or to the budget, which
DescriptiveComplexity.exists_iterate_lt_card says is long enough.
Dependency graph
The capture theorem #
The capture theorem for FO(DTC): a problem is definable by a single
deterministic transitive closure exactly when a deterministic two-way
multi-head automaton recognizes it. One direction is
DescriptiveComplexity.dtcDefinable_of_automaton – a configuration is a node of a
specification, and determinism of the control is functionality of the walk –
and the other is the machine built here: it scans where the machine of
DescriptiveComplexity.HeadCapture guesses, and counts so that a walk leading nowhere
is abandoned.
Dependency graph
LOGSPACE is the class of the deterministic two-way multi-head
automata: membership in DescriptiveComplexity.LOGSPACE is recognizability by such
a machine, the deterministic counterpart of
DescriptiveComplexity.mem_NL_iff_automaton.