The unit-propagation machine of a Horn formula #
The program half of HORNSAT ≤ᶠᵒ[≤] DTMAccept, stage 4 of the machine bridge:
the states, symbols and transitions of the deterministic machine computing the
unit-propagation closure of a CNF instance and verifying it, on the tape laid
out in DescriptiveComplexity.Problems.Machine.HornTape.
The program #
init: at ⊢, dispatch – first check sweep if a clause exists, else accept
chk(r, c): sweep right, f := f ∧ (negIn c x → marked x)
mark(r, c): sweep back left; if the check succeeded, mark the positive
literal of c in passing
… next clause; after the last clause, next round; after the last round …
ver(c): sweep, f := f ∨ (posIn c x ∧ marked x) ∨ (negIn c x ∧ ¬marked x),
alternating direction; a failed clause leaves no transition
accept after the last verified clause – gated on the Horn condition
n rounds of one check-and-mark pass per clause compute the propagation
closure DescriptiveComplexity.Forced (DescriptiveComplexity.forced_forcedIn_card is the
stabilization), and the verification phase accepts exactly when the closure,
read as an assignment, satisfies every clause – which for a Horn instance is
satisfiability itself (DescriptiveComplexity.satisfiable_iff_forced_model).
The machine is deterministic everywhere – there is no guess phase – and
DescriptiveComplexity.TMData.Deterministic for the constructed machine is part of
the statement, not bookkeeping: it is what makes the image a potential
yes-instance of DTMAccept at all. The instance is read exactly as in stage 3
(DescriptiveComplexity.SatCl, DescriptiveComplexity.SatPos, …, imported from
DescriptiveComplexity.Problems.Machine.Hardness together with the clause-order
machinery), and the only two additions are the element order (rounds walk it)
and the Horn gate on the accept transition.
The elements of the machine #
The universe of the machine: tagged triples.
Equations
- DescriptiveComplexity.HV A = (DescriptiveComplexity.UPTag × (Fin 3 → A))
Instances For
Dependency graph
A constant of the machine: a tag on the triple of least elements.
Equations
- DescriptiveComplexity.cstH t = (t, fun (x : Fin 3) => DescriptiveComplexity.botA)
Instances For
Dependency graph
A tag carrying one element.
Equations
Instances For
Dependency graph
A tag carrying two elements.
Equations
Instances For
Dependency graph
Dependency graph
Symbols #
The left-marker symbol.
Equations
Instances For
Dependency graph
The right-marker symbol.
Equations
Instances For
Dependency graph
The blank symbol.
Equations
Instances For
Dependency graph
The symbol of the cell of x, with mark m.
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.
Equations
Instances For
Dependency graph
States #
The dispatch state.
Equations
Instances For
Dependency graph
Checking the clause c in round r, flag f.
Equations
Instances For
Dependency graph
The return sweep of clause c in round r, marking iff m.
Equations
Instances For
Dependency graph
Verifying the clause c, flag f, sweeping in direction d.
Equations
Instances For
Dependency graph
The accepting state.
Instances For
Dependency graph
Reading the order of the elements #
Dependency graph
Dependency graph
b is the successor of a in the order of the elements: rounds walk this
relation.
Instances For
Dependency graph
The satisfaction test of the verification phase: the cell x, with mark
m, satisfies the clause c under the marked assignment. This is
DescriptiveComplexity.SatLit with the marks as the valuation.
Equations
- DescriptiveComplexity.MLit c x m = (DescriptiveComplexity.SatPos c x ∧ m = true ∨ DescriptiveComplexity.SatNeg c x ∧ m = false)
Instances For
Dependency graph
The transition table #
Which tagged triples are transitions: the payload promises. Coordinates not pinned by the source state or the symbol read are pinned here, so that no junk element is 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 check and verification sweeps branch on a first-order test of the source instance; each pair of branches is exclusive, which is what keeps the table functional.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
The symbol a transition writes: only the return sweep of a successful check writes anything new, and only at the positive literal of its clause.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
Which transitions move the head right.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
Accepting states.
Equations
Instances For
Dependency graph
Start states: the dispatch state alone.
Equations
Instances For
Dependency graph
The unit-propagation machine of a CNF instance.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
The machine is well formed #
The machine is well formed: every conjunct comes from the tape layer.
Dependency graph
The machine is deterministic #
There is no guess phase, so – unlike stage 3 – the whole table is functional:
the state and the symbol read pin the transition's tag up to promise-exclusive
alternatives, the tag pins the payload, and the branching destinations and
writes are separated by their first-order tests. This discharges the
DescriptiveComplexity.TMData.Deterministic promise of the constructed instance,
which is part of the correctness of the reduction.
Two elements agree when their tag and all three coordinates do.
Dependency graph
Dependency graph
Dependency graph
The tag of the state a transition applies in.
Equations
- DescriptiveComplexity.hStateTag DescriptiveComplexity.UPTag.tInitChk = DescriptiveComplexity.UPTag.qInit
- DescriptiveComplexity.hStateTag DescriptiveComplexity.UPTag.tInitAcc = DescriptiveComplexity.UPTag.qInit
- DescriptiveComplexity.hStateTag (DescriptiveComplexity.UPTag.tChk m f) = DescriptiveComplexity.UPTag.qChk f
- DescriptiveComplexity.hStateTag (DescriptiveComplexity.UPTag.tChkEnd f) = DescriptiveComplexity.UPTag.qChk f
- DescriptiveComplexity.hStateTag (DescriptiveComplexity.UPTag.tMark m mk) = DescriptiveComplexity.UPTag.qMark mk
- DescriptiveComplexity.hStateTag (DescriptiveComplexity.UPTag.tMarkEndNext mk) = DescriptiveComplexity.UPTag.qMark mk
- DescriptiveComplexity.hStateTag (DescriptiveComplexity.UPTag.tMarkEndRound mk) = DescriptiveComplexity.UPTag.qMark mk
- DescriptiveComplexity.hStateTag (DescriptiveComplexity.UPTag.tMarkEndVer mk) = DescriptiveComplexity.UPTag.qMark mk
- DescriptiveComplexity.hStateTag (DescriptiveComplexity.UPTag.tVer m f d) = DescriptiveComplexity.UPTag.qVer f d
- DescriptiveComplexity.hStateTag (DescriptiveComplexity.UPTag.tVerNext d) = DescriptiveComplexity.UPTag.qVer true d
- DescriptiveComplexity.hStateTag (DescriptiveComplexity.UPTag.tVerAcc d) = DescriptiveComplexity.UPTag.qVer true d
- DescriptiveComplexity.hStateTag x✝ = x✝
Instances For
Dependency graph
The tag of the symbol a transition reads.
Equations
- DescriptiveComplexity.hReadTag DescriptiveComplexity.UPTag.tInitChk = DescriptiveComplexity.UPTag.sStart
- DescriptiveComplexity.hReadTag DescriptiveComplexity.UPTag.tInitAcc = DescriptiveComplexity.UPTag.sStart
- DescriptiveComplexity.hReadTag (DescriptiveComplexity.UPTag.tChk m f) = if m = true then DescriptiveComplexity.UPTag.sM else DescriptiveComplexity.UPTag.sU
- DescriptiveComplexity.hReadTag (DescriptiveComplexity.UPTag.tChkEnd f) = DescriptiveComplexity.UPTag.sEnd
- DescriptiveComplexity.hReadTag (DescriptiveComplexity.UPTag.tMark m mk) = if m = true then DescriptiveComplexity.UPTag.sM else DescriptiveComplexity.UPTag.sU
- DescriptiveComplexity.hReadTag (DescriptiveComplexity.UPTag.tMarkEndNext mk) = DescriptiveComplexity.UPTag.sStart
- DescriptiveComplexity.hReadTag (DescriptiveComplexity.UPTag.tMarkEndRound mk) = DescriptiveComplexity.UPTag.sStart
- DescriptiveComplexity.hReadTag (DescriptiveComplexity.UPTag.tMarkEndVer mk) = DescriptiveComplexity.UPTag.sStart
- DescriptiveComplexity.hReadTag (DescriptiveComplexity.UPTag.tVer m f d) = if m = true then DescriptiveComplexity.UPTag.sM else DescriptiveComplexity.UPTag.sU
- DescriptiveComplexity.hReadTag (DescriptiveComplexity.UPTag.tVerNext d) = if d = true then DescriptiveComplexity.UPTag.sEnd else DescriptiveComplexity.UPTag.sStart
- DescriptiveComplexity.hReadTag (DescriptiveComplexity.UPTag.tVerAcc d) = if d = true then DescriptiveComplexity.UPTag.sEnd else DescriptiveComplexity.UPTag.sStart
- DescriptiveComplexity.hReadTag x✝ = x✝
Instances For
Dependency graph
Being the tag of a transition.
Equations
- DescriptiveComplexity.isHTrTag DescriptiveComplexity.UPTag.tInitChk = true
- DescriptiveComplexity.isHTrTag DescriptiveComplexity.UPTag.tInitAcc = true
- DescriptiveComplexity.isHTrTag (DescriptiveComplexity.UPTag.tChk m f) = true
- DescriptiveComplexity.isHTrTag (DescriptiveComplexity.UPTag.tChkEnd f) = true
- DescriptiveComplexity.isHTrTag (DescriptiveComplexity.UPTag.tMark m mk) = true
- DescriptiveComplexity.isHTrTag (DescriptiveComplexity.UPTag.tMarkEndNext mk) = true
- DescriptiveComplexity.isHTrTag (DescriptiveComplexity.UPTag.tMarkEndRound mk) = true
- DescriptiveComplexity.isHTrTag (DescriptiveComplexity.UPTag.tMarkEndVer mk) = true
- DescriptiveComplexity.isHTrTag (DescriptiveComplexity.UPTag.tVer m f d) = true
- DescriptiveComplexity.isHTrTag (DescriptiveComplexity.UPTag.tVerNext d) = true
- DescriptiveComplexity.isHTrTag (DescriptiveComplexity.UPTag.tVerAcc d) = true
- DescriptiveComplexity.isHTrTag x✝ = false
Instances For
Dependency graph
Only transitions have transition tags.
Dependency graph
The state pins the transition's tag.
Dependency graph
The symbol read pins the transition's tag.
Dependency graph
Tag classes for the promise-exclusive alternatives.
Equations
Instances For
Dependency graph
Tag classes for the promise-exclusive alternatives.
Equations
Instances For
Dependency graph
Tag classes for the promise-exclusive alternatives.
Equations
Instances For
Dependency graph
Tag classes for the promise-exclusive alternatives.
Equations
Instances For
Dependency graph
Tag classes for the promise-exclusive alternatives.
Equations
Instances For
Dependency graph
Tag classes for the promise-exclusive alternatives.
Equations
Instances For
Dependency graph
Tag classes for the promise-exclusive alternatives.
Equations
Instances For
Dependency graph
The state and the symbol determine the transition's tag, up to the promise-exclusive alternatives: the two dispatches, the three ends of a return sweep, and the two ends of a verification sweep. A finite check over the tags.
Dependency graph
The lowest clause is unique.
Dependency graph
The highest clause is unique.
Dependency graph
The next clause is unique.
Dependency graph
The least element is unique.
Dependency graph
The successor of an element is unique.
Dependency graph
Equal tags force equal payloads: the source state and the symbol read pin two coordinates, the promises the rest.
Dependency graph
The promise-exclusive alternatives #
The two dispatches exclude each other.
Dependency graph
A clause with a next one is not the last.
Dependency graph
An element with a successor is not the greatest.
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Reading DescriptiveComplexity.HSrc off a concrete tag: the payload equations
all flow through this.
Dependency graph
Reading DescriptiveComplexity.HTr off a concrete tag.
Dependency graph
At most one transition applies, everywhere: the machine has no guess
phase, so this is the whole of transition-level determinism. The three
ambiguity classes left by DescriptiveComplexity.hTag_cases are separated by their
promises: a clause with a next one is not the last, an element with a
successor is not the greatest, and an instance either has a clause or has
none.
Dependency graph
A transition moves to exactly one state: the branching destinations are separated by their flags and their first-order tests, and the two relational destinations are pinned by uniqueness of the lowest clause.
Dependency graph
A transition writes exactly one symbol: the marking write's two branches are separated by the marking bit and the positive-literal test.
Dependency graph
The machine is deterministic – the promise
DescriptiveComplexity.DTMAccept folds into its yes-instances, discharged here for
every image of the reduction, Horn or not.
Dependency graph
The positions of the tape, concretely #
The dimension-3 mirror of stage 3's marker and cell lemmas: the left marker is the lowest position, cells follow in the order of their elements, the right marker closes the chain, and ranks are what the budget compares.
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Every tag other than the left marker's is above it.
Dependency graph
There is only one left marker.
Dependency graph
There is only one right marker.
Dependency graph
A cell is the cell of the element it carries.
Dependency graph
The left marker is the lowest position.
Dependency graph
Dependency graph
Dependency graph
Dependency graph
Cells are ordered as their elements are.
Dependency graph
Only the two lowest tags are at or below a cell's.
Dependency graph
Only the three bracketing tags are at or below the right marker's.
Dependency graph
Only the two highest bracketing tags lie between a cell's and the right marker's.
Dependency graph
The head's first move: the cell of the least element follows ⊢.
Dependency graph
The head moves from cell to cell along the instance.
Dependency graph
The head's last move of a sweep: ⊣ follows the last cell.
Dependency graph
The intended run: marks and tapes #
The machine's working state is a set of marked elements, as a Bool-valued
assignment. Processing one clause – a check sweep and a return sweep – applies
DescriptiveComplexity.procB to it: unconditionally, because when the check fails the
inner conjunction is false and nothing is added, exactly as the machine's
return sweep writes nothing when its marking bit is off.
One clause processed on a marked set: if every negative literal of c is
marked, its positive literals join the marks.
Equations
- DescriptiveComplexity.procB M c x = (M x || decide (DescriptiveComplexity.SatPos c x) && decide (∀ (y : A), DescriptiveComplexity.SatNeg c y → M y = true))
Instances For
Dependency graph
Processing a clause only adds marks.
Dependency graph
The tape carrying the marked set M: markers and blanks in place, the
cell of y holding (y, M y). A junk cell tuple reads its initial, unmarked
symbol forever – it is never written, so its value must not depend on M.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
The markers hold their symbols on every marked tape.
Dependency graph
Dependency graph
A real cell reads its element's mark.
Dependency graph
Marked tapes agree wherever the marks do – in particular junk cells never notice a change of marks.
Dependency graph
The tape during a return sweep of the clause c with the head at p,
moving left: the cells strictly above the head have been processed, the rest
still carry the old marks.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
Dependency graph
Dependency graph
The intended run: configurations #
The flag of a check sweep with the head at p: every negative literal of
c strictly below the head is marked.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
The configuration during the check sweep of clause c in round r.
Equations
- DescriptiveComplexity.confHChk M r c p = { state := DescriptiveComplexity.stHChk (DescriptiveComplexity.chkFlag M c p) r c, head := p, tape := DescriptiveComplexity.hTape M }
Instances For
Dependency graph
The configuration during the return sweep of clause c in round r,
with marking bit m.
Equations
- DescriptiveComplexity.confHMark M m r c p = { state := DescriptiveComplexity.stHMark m r c, head := p, tape := DescriptiveComplexity.markTape M c p }
Instances For
Dependency graph
The flag of a verification sweep, leftwards, with the head at p: some
cell strictly above the head satisfies c under the marks – stage 3's
DescriptiveComplexity.chkFlagL with the marks as valuation.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
The flag of a verification sweep, rightwards.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
The configuration during a leftward verification sweep.
Equations
- DescriptiveComplexity.confHVerL M c p = { state := DescriptiveComplexity.stHVer (DescriptiveComplexity.verFlagL M c p) false c, head := p, tape := DescriptiveComplexity.hTape M }
Instances For
Dependency graph
The configuration during a rightward verification sweep.
Equations
- DescriptiveComplexity.confHVerR M c p = { state := DescriptiveComplexity.stHVer (DescriptiveComplexity.verFlagR M c p) true c, head := p, tape := DescriptiveComplexity.hTape M }
Instances For
Dependency graph
The initial configuration: the dispatch state at the left marker, all cells unmarked.
Equations
- DescriptiveComplexity.confHInit = { state := DescriptiveComplexity.stHInit, head := DescriptiveComplexity.posHStart, tape := DescriptiveComplexity.hTape fun (x : A) => false }
Instances For
Dependency graph
The machine starts at the dispatch configuration: the unmarked tape is the initial tape.
Dependency graph
The flags and tapes along a sweep #
A check sweep starts with a vacuously true flag: no cell lies strictly below the first one.
Dependency graph
Stepping right folds one cell into the check flag.
Dependency graph
A completed check sweep has seen every cell: at the right marker the flag says every negative literal of the clause is marked.
Dependency graph
A leftward verification sweep starts with an empty flag.
Dependency graph
A rightward verification sweep starts with an empty flag.
Dependency graph
Stepping down folds one cell into the leftward verification flag.
Dependency graph
Stepping up folds one cell into the rightward verification flag.
Dependency graph
A completed leftward verification sweep has seen every cell.
Dependency graph
A completed rightward verification sweep has seen every cell.
Dependency graph
At the top of the return sweep nothing has been processed: the tape still carries the old marks.
Dependency graph
At the bottom of the return sweep everything has been processed: the tape carries the new marks.
Dependency graph
The return sweep only ever changes the cell under the head, exactly as stage 3's guess sweep: moving the head down brings its own cell into the processed region and nothing else.
Dependency graph
What the return sweep reads at its own head: the old mark.
Dependency graph
The intended run: single steps #
The dispatch, when a clause exists: into the first check sweep of the lowest round and clause, with everything unmarked.
Dependency graph
The dispatch, when there is no clause at all: accept.
Dependency graph
One step of a check sweep: fold the cell under the head into the flag and move right.
Dependency graph
The turn at the right marker: the check sweep is over, the return sweep begins with the accumulated verdict as its marking bit.
Dependency graph
One step of a return sweep: process the cell under the head – marking it if it is the positive literal of a successfully checked clause – and move left.
Dependency graph
The turn at the left marker, next clause: the processed marks become the working marks, and the next check sweep starts.
Dependency graph
The turn at the left marker, next round: last clause processed, the round counter advances and the checks restart at the lowest clause.
Dependency graph
The turn at the left marker, into verification: the last clause of the last round is processed, and the final marks are verified clause by clause, starting rightwards at the lowest clause.
Dependency graph
One step of a rightward verification sweep.
Dependency graph
One step of a leftward verification sweep.
Dependency graph
The verification turn at the right marker, another clause following: reverse into a leftward sweep of the next clause.
Dependency graph
The verification turn at the left marker – the mirror.
Dependency graph
Accepting at the right marker: the last clause is verified, and the instance is Horn – the gate.
Dependency graph
Accepting at the left marker – the mirror.
Dependency graph
Ranks, sweeps, and one whole clause #
The left marker has rank 0.
Dependency graph
The right marker sits one step above the last cell.
Dependency graph
The first cell has rank 1.
Dependency graph
A sweep is short: only the left marker and the cells lie below the
right marker, by injection into Option A.
Dependency graph
A whole check sweep, from the first cell to the right marker.
Dependency graph
A whole return sweep, from the last cell down to the left marker.
Dependency graph
A whole rightward verification sweep.
Dependency graph
A whole leftward verification sweep.
Dependency graph
One whole clause: check sweep, turn, return sweep, back at the left
marker with the processed marks, in exactly 2 R steps for R the right
marker's rank.
Dependency graph
The folds: what the rounds compute #
Processing the clauses from c to the last one, relationally: the marked
set each clause leaves behind.
- last {A : Type} [FirstOrder.Language.sat.Structure A] [LinearOrder A] {c : A} {M : A → Bool} : SatMaxCl c → ClauseFold c M (procB M c)
- step {A : Type} [FirstOrder.Language.sat.Structure A] [LinearOrder A] {c c' : A} {M M' : A → Bool} : SatNextCl c c' → ClauseFold c' (procB M c) M' → ClauseFold c M M'
Instances For
Dependency graph
Processing the rounds from r to the last one, each a pass over all the
clauses from c₀.
- last {A : Type} [FirstOrder.Language.sat.Structure A] [LinearOrder A] {c₀ r : A} {M M' : A → Bool} : MaxElt r → ClauseFold c₀ M M' → RoundFold c₀ r M M'
- step {A : Type} [FirstOrder.Language.sat.Structure A] [LinearOrder A] {c₀ r r' : A} {M M' M'' : A → Bool} : SuccElt r r' → ClauseFold c₀ M M' → RoundFold c₀ r' M' M'' → RoundFold c₀ r M M''
Instances For
Dependency graph
The clause fold only adds marks.
Dependency graph
The round fold only adds marks.
Dependency graph
Soundness of the fold: marks stay inside the propagation closure.
Dependency graph
Soundness for the rounds.
Dependency graph
One round dominates one propagation step: a clause whose negative literals are all marked at the start of the round has its positive literals marked at its end – the marks only grow until the clause's turn comes.
Dependency graph
The rounds reach every propagation stage: seed marks containing stage
j become, after the remaining rounds, marks containing stage j + #rounds.
Each round dominates one step because its marks only grow.
Dependency graph
The machine walks the folds #
Every element that is not the greatest has a successor.
Dependency graph
Passing to the next round removes exactly one round from those left.
Dependency graph
The machine processes the clauses from c to the last one: it
computes the clause fold, and then turns – to the next round if one follows,
into verification otherwise – in at most 2R + 1 steps per clause.
Dependency graph
The machine runs all the rounds: from any round to the start of the verification phase, computing the round fold.
Dependency graph
The verification phase #
Verifying c rightwards and moving on to the next clause.
Dependency graph
Verifying c leftwards and moving on to the next clause.
Dependency graph
Verifying the last clause rightwards, and accepting.
Dependency graph
Verifying the last clause leftwards, and accepting.
Dependency graph
The verification phase accepts: every remaining clause is satisfied by the marks, so the sweeps run through and the machine accepts after the last one – stage 3's clause induction, verbatim, with the marks as valuation.
Dependency graph
The machine accepts every Horn-satisfiable instance #
The final marks are exactly the propagation closure.
Dependency graph
The machine accepts every yes-instance of HORN-SAT, within the
budget: dispatch, n rounds of propagation, and a verification pass that the
closure – which satisfiability makes a model – lets run to acceptance.
Dependency graph
The machine accepts only Horn-satisfiable instances #
Determinism replaces stage 3's run-analysis induction: the run from the unique initial configuration is the intended trajectory, so it suffices that on a non-Horn-satisfiable instance the trajectory never carries an accepting state – either because no accept transition exists at all (the Horn gate), or because the trajectory gets stuck at the first failing verification sweep.
No transition applies in an accepting state: once accepted, the machine halts, so an accepting run cannot be a strict prefix of another.
Dependency graph
No transition applies in a failed verification state on a marker: the run dies there.
Dependency graph
The only transitions into an accepting state are the two accept transitions.
Dependency graph
A failed rightward verification sweep is stuck at the right marker.
Dependency graph
A failed leftward verification sweep is stuck at the left marker.
Dependency graph
The trajectory of an unsatisfiable Horn instance gets stuck: the verification sweeps run through the satisfied clauses and die at the first failing one, in a configuration that is not accepting and admits no step.
Dependency graph
Correctness of the unit-propagation machine: it accepts exactly the yes-instances of HORN-SAT.