Encoding fidelity: a model of the CNF is a light logical operator #
Reflect/LRAT.lean turns successful kernel replay into unsatisfiability of a CNF.
This module supplies Boolean semantic soundness of the encoder; Reflect/Complete
proves the converse, and Reflect/Distance connects these semantics to binary matrices
and Hamming weight. Concrete solver output and replay data are outside this import.
What the encoder asserts is (see the module note of the external encoder)
exists x, w with x in ker(Hker), w in ker(Hpair), x.w = 1, wt(x) <= k
The three parts are each realised by one class of clauses, and for each class this module establishes soundness ("all clauses satisfied implies that the semantics holds"):
| part | clauses | soundness |
|---|---|---|
xorChain | a Tseitin chain plus one fixing clause | dotS σ xs = want (dotS is the GF(2) |
dot product over a support set) |
| atMostK | a sequential counter (Sinz) | cntS σ xs ≤ k |
The product variables (a Tseitin conjunction of three clauses) are given in a later section
of this same file.
The fact that "x is not in the row space of Hpair" follows from x.w = 1 together with
w ∈ ker(Hpair): if x = Σ c_r r is a combination of rows, then x.w = Σ c_r (r.w) = 0,
contradicting x.w = 1. This step uses only the one half row space ⊆ (ker)⊥; the
converse inclusion (ker)⊥ ⊆ row is not needed.
The GF(2) dot product over a support set, and the support size #
The GF(2) dot product Σ_{j ∈ s} σ j over the support set s (with XOR of Bool as
the addition).
Equations
- QECCertificates.LRAT.dotS σ [] = false
- QECCertificates.LRAT.dotS σ (j :: s) = (σ j ^^ QECCertificates.LRAT.dotS σ s)
Instances For
The support size: the number of variables that σ assigns true.
Equations
- QECCertificates.LRAT.cntS σ l = (List.filter (fun (t : ℕ) => σ t) l).length
Instances For
General clause lemmas #
Tseitin chain: Σ xs = want #
The four clauses of one Tseitin step, pinning nxt = cur ⊕ x.
The polarities of the four clauses must not be swapped: dropping the negation of nxt in
the first two leaves the chain computing an equivalence rather than an XOR, which detaches
the UNSAT result from the physical assertion (a self-check on a small example in the
external encoder guards against exactly this).
Equations
- One or more equations did not get rendered due to their size.
Instances For
The complete chain (xs nonempty; an empty list can only come from an empty support
set, in which case no clause is emitted at all, since the encoder never produces an
empty support set and a [-start] clause would create a constraint out of nothing).
Equations
- QECCertificates.LRAT.xorChain [] want start = ([], start)
- QECCertificates.LRAT.xorChain (j :: s) want start = QECCertificates.LRAT.xorChainAux s want j start
Instances For
Soundness of the chain for an arbitrary nonempty list of variables; used when a
definition such as prodVars does not reduce syntactically.
Sequential counter: wt ≤ k #
The slot convention: s i j is the variable number meaning "at least j of the first
i variables are true"; none marks the slot as a constant (true when j = 0, false
when j > min i (k + 1)).
The external encoder writes 0 for those two constant slots, and it must discharge them
before emitting clauses: 0 is the clause terminator in DIMACS, so writing it out would
split one clause into two.
Instances For
The three or four clauses of the slot (i,j), transcribed verbatim from the encoder
none slots are discharged as constants (always false or always true).
Equations
- One or more equations did not get rendered due to their size.
Instances For
All clauses of the i-th row (which processes the variable x), expanded over
j = 1..min i (k + 1).
Equations
- QECCertificates.LRAT.rowClauses s k i x = List.flatMap (fun (j' : ℕ) => QECCertificates.LRAT.slotClauses s i (j' + 1) x) (List.range (min i (k + 1)))
Instances For
The sequential counter: pre holds the variables already processed (the slot numbers
are computed from its length) and suf the remaining ones. When k+1 ≤ pre.length, that is
on reaching the last row, one further clause is emitted pinning s n (k + 1) to false.
Equations
- QECCertificates.LRAT.atMostKAux s k pre [] = if k + 1 ≤ pre.length then match s pre.length (k + 1) with | some v => [[(v, false)]] | none => [] else []
- QECCertificates.LRAT.atMostKAux s k pre (j :: s_1) = QECCertificates.LRAT.rowClauses s k (pre.length + 1) j ++ QECCertificates.LRAT.atMostKAux s k (pre ++ [j]) s_1
Instances For
Soundness of the counter: all clauses satisfied implies that the number of true
variables is at most k.
The invariant is: at least j of the first i variables are true implies that the slot
(i,j) is true. The induction runs along the list of variables (pre is the prefix already
processed and suf the remainder), so the step needs only List.filter_append and not the
index bookkeeping of List.take.
Soundness of the counter (the prefix-free form): the existence of a σ satisfying
all clauses implies that the number of true variables is at most k.
Assembly, matching build_pair of the external encoder #
SatFormula is a def and does not unfold automatically at implicit transparency; use
this to obtain the ∀ C ∈ F form.
The block of product variables: a_j ↔ x_j ∧ w_j, with three clauses each.
Equations
- One or more equations did not get rendered due to their size.
Instances For
A sequence of xorChains, one per row, returning the clauses and the next variable
number.
Equations
Instances For
The slot base: the number of slots allocated before the i-th row (agreeing with the
row-major allocation order of the encoder).
Equations
- QECCertificates.LRAT.slotBase k i = (List.map (fun (i' : ℕ) => min i' (k + 1)) (List.range i)).sum
Instances For
The slot variable numbers of the sequential counter (none marks a constant
slot).
Equations
Instances For
The kernel-constraint section (the rows of x, with variable number = column + 1),
together with the counter that follows it.
Equations
- QECCertificates.LRAT.kerClauses Rker n = (QECCertificates.LRAT.chainsFrom (fun (j : ℕ) => j) Rker (2 * n)).fst
Instances For
First unused auxiliary variable after the kernel constraints.
Equations
- QECCertificates.LRAT.c1Of Rker n = (QECCertificates.LRAT.chainsFrom (fun (j : ℕ) => j) Rker (2 * n)).snd
Instances For
The pairing-constraint section (the rows of w, with variable number =
n + column + 1).
Equations
- QECCertificates.LRAT.pairClauses Rker Rpair n = (QECCertificates.LRAT.chainsFrom (fun (j : ℕ) => n + j) Rpair (QECCertificates.LRAT.c1Of Rker n)).fst
Instances For
First unused auxiliary variable after the pairing constraints.
Equations
- QECCertificates.LRAT.c2Of Rker Rpair n = (QECCertificates.LRAT.chainsFrom (fun (j : ℕ) => n + j) Rpair (QECCertificates.LRAT.c1Of Rker n)).snd
Instances For
The product-variable section, together with the chain for x·w = 1.
Equations
- QECCertificates.LRAT.prodVars Rker Rpair n = List.map (fun (j : ℕ) => QECCertificates.LRAT.c2Of Rker Rpair n + j) (List.range n)
Instances For
Clauses asserting that the componentwise product has odd parity.
Equations
- QECCertificates.LRAT.xwClauses Rker Rpair n = (QECCertificates.LRAT.xorChain (QECCertificates.LRAT.prodVars Rker Rpair n) true (QECCertificates.LRAT.c2Of Rker Rpair n + n)).fst
Instances For
First unused auxiliary variable after the odd-pairing chain.
Equations
- QECCertificates.LRAT.c3Of Rker Rpair n = (QECCertificates.LRAT.xorChain (QECCertificates.LRAT.prodVars Rker Rpair n) true (QECCertificates.LRAT.c2Of Rker Rpair n + n)).snd
Instances For
The encoding used by this package's pipeline, transcribed verbatim from build_pair
of the external encoder.
Rows are given as lists of column indices (the form before to_masks):
x_j ↔ variable j+1 and w_j ↔ variable n+j+1. The order of assembly must match verbatim
as well, otherwise the instance identity checked by by decide does not go through.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Encoding fidelity (the soundness direction): every satisfying assignment yields
- an
xof weight at mostk(cntScounts the true positions) xin the kernel ofRkerandwin the kernel ofRpairx.w = 1(a pointwise conjunction followed by an XOR).
Together with x.w = 1, the third and fourth items make it impossible for x to lie in the
row space of Rpair (row space ⊆ (ker)⊥), that is, x is a light logical operator.