Documentation

Complexitylib.SAT.Encoding

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)

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 #

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.

Unary encoding of n: n consecutive true bits. encode 0 = [].

Equations
Instances For
    @[simp]

    The unary encoding of n has length exactly n.

    @[simp]

    Zero encodes to the empty bit list.

    Every bit in a unary encoding is true.

    Raw literal encoding: [sign] ++ unary(var). Produces a list of single (undoubled) bits; the doubling happens at the clause level.

    Equations
    Instances For
      @[simp]

      The raw literal encoding has length ℓ.var + 1: one sign bit plus a unary var.

      The raw encoding of a literal has ℓ.var ≤ |encodeRaw| - 1. Key for maxVar ≤ |encode|.

      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
      Instances For
        @[simp]

        Doubling the empty bit list yields the empty list.

        @[simp]

        Doubling a cons prepends the head bit twice: doubleBits (b :: bs) = b :: b :: ….

        @[simp]

        Doubling exactly doubles the length: |doubleBits bs| = 2 * |bs|.

        Encoded clause: each literal's raw bits doubled, followed by [0,1].

        Equations
        Instances For
          @[simp]

          The empty clause encodes to the empty bit list.

          Unfolding lemma: encoding ℓ :: ℓs emits the doubled raw literal, the [false, true] literal separator, then the encoded tail.

          theorem Complexity.SAT.Clause.length_encode (c : Clause) :
          c.encode.length = List.foldr (fun ( : Lit) (acc : ) => 2 * .encodeRaw.length + 2 + acc) 0 c

          Length bound on the encoded clause: each literal contributes at most 2 * |encodeRaw| + 2 bits (doubling + separator).

          Encoded CNF: each clause followed by [1,0].

          Equations
          Instances For
            @[simp]

            The empty CNF encodes to the empty bit list.

            Unfolding lemma: encoding c :: cs emits the encoded clause, the [true, false] clause separator, then the encoded tail.

            theorem Complexity.SAT.CNF.length_encode (φ : CNF) :
            φ.encode.length = List.foldr (fun (c : Clause) (acc : ) => c.encode.length + 2 + acc) 0 φ

            Length bound: each clause contributes |c.encode| + 2 bits to the CNF.

            theorem Complexity.SAT.CNF.encode_append (φ ψ : CNF) :
            (φ ++ ψ).encode = φ.encode ++ ψ.encode

            CNF.encode is a ++-homomorphism — the per-family reduction emitters compose by output concatenation.

            Doubling a run of trues doubles its length.

            theorem Complexity.SAT.Clause.encode_cons' ( : Lit) (ℓs : Clause) :
            encode ( :: ℓs) = [.sign, .sign] ++ List.replicate (2 * .var) true ++ [false, true] ++ ℓs.encode

            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.

            Every variable in a clause has index ≤ |c.encode|. Immediate from unary.

            Key bound for PolyBalanced. Every variable mentioned in φ has index at most |φ.encode|. Hence any satisfying assignment α (with unused positions truncated) has length at most |φ.encode| + 1.

            theorem Complexity.SAT.doubleBits_pair_eq (bs : List Bool) (k : ) (h : 2 * k + 1 < (doubleBits bs).length) :
            (doubleBits bs)[2 * k]? = (doubleBits bs)[2 * k + 1]?

            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}.