SAT: Encoding Layer #
This file pins down how CNFs and literals are written as List Bool, which
is the bit-string format that the TM verifier will actually parse.
Format summary #
data bit b ↦ [b, b] (doubled)
literal separator "|" ↦ [false, true] (one undoubled pair)
clause separator "#" ↦ [true, false] (one undoubled pair)
- A variable index
v : ℕis encoded in unary asreplicate v true— that is,vconsecutive1-bits.Unary.encode 0 = []. Unary is chosen (over binary) so that|encode v| ≥ v, which makesmaxVar φ ≤ |φ.encode|automatic. This is what powers thePolyBalancedstep in the NP-membership proof. - A literal
(sign, var)is encoded as[sign] ++ Unary.encode var— call this the raw literal encoding (a list of single bits). - A clause is a list of raw-encoded literals, each doubled bit-by-bit,
separated (and terminated) by
|. An empty clause is the empty list. - A CNF is a list of encoded clauses, each terminated by
#. An empty CNF is the empty list.
Inside a clause, every bit is doubled, so the only pairs that appear are
00, 11 (data), 01 (lit sep), 10 (clause sep). The four patterns
cover all four two-bit combinations and are mutually exclusive, giving a
well-defined token stream for any valid encoding.
Why this format #
|and#can't collide with data because all data bits are doubled.- No length prefixes — parsing is a single pass over the input.
- Unary variables give
|encodeRaw ℓ| = ℓ.var + 1, which propagates tomaxVar φ ≤ |φ.encode|(key forPolyBalanced). - Distinguishes
[](true CNF) from[[]](one unsatisfiable clause): the former encodes to[], the latter to[true, false].
No decode function is provided. The verifier's correctness theorem is
stated directly against encode; we don't need an inverse as a Lean
function to prove NP membership.
The raw literal encoding is injective: sign and var are recoverable.
Double each bit: b ↦ [b, b]. The image consists only of 00 and 11
two-bit patterns, so 01 and 10 cannot appear in doubled data.
Equations
- Complexity.SAT.doubleBits bs = List.flatMap (fun (b : Bool) => [b, b]) bs
Instances For
Doubling the empty bit list yields the empty list.
Doubling a cons prepends the head bit twice: doubleBits (b :: bs) = b :: b :: ….
Doubling exactly doubles the length: |doubleBits bs| = 2 * |bs|.
Encoded clause: each literal's raw bits doubled, followed by [0,1].
Equations
Instances For
CNF.encode is a ++-homomorphism — the per-family reduction emitters
compose by output concatenation.
Doubling a run of trues doubles its length.
The encoded form of one literal inside a clause: doubled sign, doubled unary variable index, separator — exactly the word the reduction's literal emitter appends.
doubleBits bs contains no [false, true] or [true, false] pair at
an even-index boundary. Concretely: every pair (b_{2k}, b_{2k+1}) in
doubleBits bs has b_{2k} = b_{2k+1}.