The machine of a CNF formula #
The program half of SAT ≤ᶠᵒ[≤] NTMAccept: the states, symbols and transitions
of the machine M_φ built inside an ordered SAT instance, on the tape laid out
in DescriptiveComplexity.Problems.Machine.Tape.
The program #
guess : ⊢ → at each cell (x,U) write (x,F), or (x,T) if x occurs in a
clause, moving right → ⊣
check c: sweep back over the cells, accumulating
flag := flag ∨ (posIn c x ∧ b) ∨ (negIn c x ∧ ¬b)
at the far marker: if flag, take the next clause and turn round;
if not, no transition exists and the run dies
accept: when the clause just checked was the last one
Two things make this small. The check is an first-order test on the source
structure – DescriptiveComplexity.SatLit – evaluated by the formula that will define
the transition relation, so no clause-width bound and no occurrence machinery
are needed and the source can be plain SAT rather than 3SAT. And the sweeps
alternate direction instead of rewinding, so a clause costs one pass and
there are no rewind states; the markers are what tell the machine a pass has
ended.
The machine is nondeterministic in exactly one place, the choice of (x,T) or
(x,F) in the guess phase, and it has that choice only at an element that is a
variable of the instance (DescriptiveComplexity.SatVar): elsewhere it writes
(x,F). The decision problem does not need this restriction; it is what makes
the accepting runs correspond one to one to the models of the formula
(DescriptiveComplexity.Problems.Machine.CountingHardness). Branching at the
guess only is a deliberate design decision, and it is what will make the ⇒
half of correctness a corollary of uniqueness rather than a second invariant
induction.
Semantics first #
Everything here is a plain predicate on tagged tuples, as
DescriptiveComplexity.SatPosn and DescriptiveComplexity.SatInp are: the machine is
assembled as a DescriptiveComplexity.TMData and reasoned about directly. Only once
its correctness is proved does the first-order transcription happen, one
realization lemma per relFormula. A transition table type-checks whatever it
says, so it has to be validated by a proof, not by elaboration.
The instance, read #
Being a clause of the CNF instance.
Equations
Instances For
Dependency graph
The variable x occurs positively in the clause c.
Equations
Instances For
Dependency graph
The variable x occurs negatively in the clause c.
Equations
Instances For
Dependency graph
The literal test: the cell x, holding the truth value v, satisfies
the clause c. This is the first-order test on the source structure that the
transition relation performs; it is the whole of the check phase.
Equations
- DescriptiveComplexity.SatLit c x v = (DescriptiveComplexity.SatPos c x ∧ v = true ∨ DescriptiveComplexity.SatNeg c x ∧ v = false)
Instances For
Dependency graph
The element x is a variable of the instance: it occurs in some clause.
The machine guesses a truth value only at such an element, and writes “false”
at the others, so that its accepting runs are the models of the formula and
not its satisfying assignments of all elements.
Equations
- DescriptiveComplexity.SatVar x = ∃ (c : A), DescriptiveComplexity.SatCl c ∧ (DescriptiveComplexity.SatPos c x ∨ DescriptiveComplexity.SatNeg c x)
Instances For
Dependency graph
c is the lowest clause.
Equations
- DescriptiveComplexity.SatMinCl c = (DescriptiveComplexity.SatCl c ∧ ∀ (e : A), DescriptiveComplexity.SatCl e → c ≤ e)
Instances For
Dependency graph
c is the highest clause.
Equations
- DescriptiveComplexity.SatMaxCl c = (DescriptiveComplexity.SatCl c ∧ ∀ (e : A), DescriptiveComplexity.SatCl e → e ≤ c)
Instances For
Dependency graph
c' is the clause immediately above c.
Equations
- DescriptiveComplexity.SatNextCl c c' = (DescriptiveComplexity.SatCl c ∧ DescriptiveComplexity.SatCl c' ∧ c < c' ∧ ∀ (e : A), DescriptiveComplexity.SatCl e → c < e → c' ≤ e)
Instances For
Dependency graph
The elements of the machine #
The least element of the instance, to which every constant of the machine is pinned.
Equations
Instances For
Dependency graph
Dependency graph
Dependency graph
The universe of the machine: tagged pairs.
Equations
- DescriptiveComplexity.SatV A = (DescriptiveComplexity.SatTag × (Fin 2 → A))
Instances For
Dependency graph
A constant of the machine: a tag on the pair of least elements.
Equations
- DescriptiveComplexity.cst t = (t, fun (x : Fin 2) => DescriptiveComplexity.botA)
Instances For
Dependency graph
A tag carrying one element, pinned in the second coordinate.
Equations
Instances For
Dependency graph
Symbols #
The left-marker symbol.
Equations
Instances For
Dependency graph
The right-marker symbol.
Instances For
Dependency graph
The blank symbol.
Equations
Instances For
Dependency graph
The symbol of an unassigned cell.
Instances For
Dependency graph
The symbol of a cell assigned the truth value v.
Equations
Instances For
Dependency graph
Positions #
The left-marker cell.
Equations
Instances For
Dependency graph
The cell of the element x.
Equations
Instances For
Dependency graph
The right-marker cell.
Instances For
Dependency graph
States #
The guessing state.
Equations
Instances For
Dependency graph
Checking the clause c, flag f, sweeping in direction d.
Equations
Instances For
Dependency graph
The accepting state.
Instances For
Dependency graph
The transition table #
Which tagged tuples are transitions. The payload is pinned exactly as far as the transition needs it, and the clause coordinates are required to be clauses, so that no junk element is ever a transition.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
The state a transition applies in.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
The symbol a transition reads.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
The state a transition moves to. The only place the instance is consulted
is the check clause, where the new flag depends on DescriptiveComplexity.SatLit.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
The symbol a transition writes: everything but the guess phase leaves the tape as it found it.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
Which transitions move the head right: the guess phase always does, a check sweep goes in its own direction, and a turn – whether it takes the next clause or accepts – reverses. A turn must reverse even when accepting: it fires at a marker, and there is no position beyond one.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
Dependency graph
Dependency graph
The machine of a CNF instance.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
The table is a table #
Before any run is considered: each transition has exactly one destination and
symbol written, and the two places where two tags could otherwise both apply
are exclusive. A mistake in the table shows up here first, which is why these
come before the correctness proof. (Sources and symbols read need no
functionality lemma of their own: DescriptiveComplexity.satTr_unique pins the whole
transition from them.)
Dependency graph
At most one transition applies, away from the one nondeterministic
choice of the guess phase: the state and the symbol read pin the tag
(DescriptiveComplexity.tag_cases), the tag pins the payload
(DescriptiveComplexity.satTr_payload), and the three ambiguities are the guess itself
and the two exclusive branch points.
Dependency graph
The positions of the tape, concretely #
The greatest element of the instance: the last cell of the tape.
Equations
Instances For
Dependency graph
Dependency graph
The machine is deterministic away from the guess. Once the transition
is pinned (DescriptiveComplexity.satTr_unique), the successor configuration is too: its
state by satDst_functional, the cell under the head by satWrite_functional,
every other cell by the frame condition, and the head itself by uniqueness of
the neighbor in the direction the transition names.
This is a deliberate design decision: with only the guess phase
branching, the ⇒ half of correctness becomes a corollary of uniqueness rather
than a second invariant induction.
Dependency graph
What a step leaves alone #
Three facts about arbitrary steps, which the counting form of the correctness
proof needs (DescriptiveComplexity.Problems.Machine.CountingHardness): only a guess
write changes the tape, the guessing state is never entered again once left,
and an accepting configuration has no successor.
The intended run: the guess phase #
The tape during the guess sweep, with the head at p: the markers hold
their own symbols, a cell strictly below the head has been assigned its value
under ν, a cell at or above the head is still unassigned, and every other
element reads blank.
A tuple carrying a cell's tag but a junk second coordinate is not a position,
and the machine never visits it – but the frame condition of a step quantifies
over it all the same, so its value must not move as the head advances. Hence
the guard ∀ a, q.2 1 ≤ a: junk cells read unassigned forever, which is also
what DescriptiveComplexity.SatInp says they hold initially.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
The configuration during the guess sweep, with the head at p.
Equations
- DescriptiveComplexity.confGuess ν p = { state := DescriptiveComplexity.stGuess, head := p, tape := DescriptiveComplexity.guessTape ν p }
Instances For
Dependency graph
The intended run: a check sweep #
The tape once the guess sweep has finished: every cell assigned. It does
not change again, so the frame condition of every later step is rfl.
Equations
Instances For
Dependency graph
One clause, checked end to end #
Each of these is a sweep followed by its turn. They are the step and the base
case of the induction over clauses; the induction itself only has to choose
between them. Each carries its step count, bounded by the rank of the right
marker: that is the honest per-clause cost, roughly the size of the instance,
and what lets the whole run fit the budget of
DescriptiveComplexity.TMData.Accepts.
Correctness, the chaining half #
Correctness, from an accepting run to an assignment #
By design, the machine branches only at the guess, so
an accepting run is the intended run of the assignment it wrote, and the flag
conditions along it force every clause to be satisfied. The analysis is one
induction on the length of the run, with one case per tag of the head position.
At each non-guess configuration the transition that fired is identified through
its tag – a decide over the finite tag type – and the actual step is equated
with the intended one by DescriptiveComplexity.step_functional_off_guess; at a guess
configuration the transition itself says which value was written.
The guess-phase analysis: an accepting run from a guess configuration
yields a satisfying assignment. Walking the guess sweep, the assignment is
rebuilt one cell at a time from the values the run chose to write; at the right
marker the run either accepts – no clause exists – or enters the check phase,
where DescriptiveComplexity.sat_of_chk takes over.
Dependency graph
The machine accepts exactly the satisfiable instances #
Correctness of the machine of a CNF formula: it accepts – within the budget – exactly the satisfiable instances.