-
Conjunctive normal form
A literal names a natural-number variable and its sign. A CNF formula is a list of clauses, each a list of literals. Empty clauses are false and the empty conjunction is true. Satisfiability quantifies over Boolean assignments.
1 import Lax434930.PolynomialTime 2 … module docstring, 9 lines 12 13 namespace Lax429075.CNF 14 15 structure Literal where 16 index : ℕ 17 positive : Bool 18 deriving DecidableEq 19 20 abbrev Clause := List Literal 21 abbrev Formula := List Clause 22 abbrev Assignment := ℕ → Bool 23 24 def Literal.eval (l : Literal) (ρ : Assignment) : Bool := 25 if l.positive then ρ l.index else !(ρ l.index) 26 27 def eval (F : Formula) (ρ : Assignment) : Bool := 28 F.all fun C => C.any fun l => l.eval ρ 29 30 def Satisfiable (F : Formula) : Prop := ∃ ρ, eval F ρ = true 31 32 end Lax429075.CNF 33 -
Binary encoding of CNF formulas
Lists use a one-bit continuation marker and a zero-bit terminator. A literal consists of its variable index in unary, a zero terminator, and its sign. This encoding gives every formula a unique binary word and bounds each variable index by the word length.
1 import Lax429075.CNF 2 … module docstring, 10 lines 13 14 namespace Lax429075.Encoding 15 16 open CNF Lax434930.PolynomialTime 17 18 def encodeList {α : Type} (encode : α → Word) : List α → Word 19 | [] => [false] 20 | a :: as => true :: (encode a ++ encodeList encode as) 21 22 def encodeNat (n : ℕ) : Word := List.replicate n true ++ [false] 23 24 def encodeLiteral (l : Literal) : Word := encodeNat l.index ++ [l.positive] 25 26 def encodeClause : Clause → Word := encodeList encodeLiteral 27 28 def encodeCNF : Formula → Word := encodeList encodeClause 29 30 def parseNat : Word → Option (ℕ × Word) 31 | [] => none 32 | false :: w => some (0, w) 33 | true :: w => do 34 let (n, rest) ← parseNat w 35 pure (n + 1, rest) 36 37 def parseLiteral (w : Word) : Option (Literal × Word) := do 38 let (n, rest) ← parseNat w 39 match rest with 40 | [] => none 41 | sign :: tail => pure (⟨n, sign⟩, tail) 42 43 def parseList {α : Type} (parse : Word → Option (α × Word)) : 44 ℕ → Word → Option (List α × Word) 45 | 0, _ => none 46 | _ + 1, [] => none 47 | _ + 1, false :: w => some ([], w) 48 | fuel + 1, true :: w => do 49 let (a, rest) ← parse w 50 let (as, tail) ← parseList parse fuel rest 51 pure (a :: as, tail) 52 53 def parseClause (w : Word) : Option (Clause × Word) := parseList parseLiteral w.length w 54 55 def decodeCNF (w : Word) : Option Formula := do 56 let (F, rest) ← parseList parseClause w.length w 57 if rest = [] then pure F else none 58 59 end Lax429075.Encoding 60 -
Decoding an encoded formula
The binary decoder recovers every encoded CNF formula.
-
no assumptions
Decode unary indices, then literals, clauses, and the outer list.
-
The satisfiability language and verifier
SAT contains precisely the encodings of satisfiable CNF formulas. A certificate is a finite list of truth values, extended by false outside its length. The verifier accepts a paired formula encoding and certificate when every clause is satisfied. Malformed encodings are outside the language.
1 import Lax429075.Encoding 2 import Lax434930.Certificates 3 … module docstring, 10 lines 14 15 namespace Lax429075.Satisfiability 16 17 open CNF Encoding Lax434930.PolynomialTime Lax434930.Certificates 18 19 def assignment (y : Word) : Assignment := fun i => (y[i]?).getD false 20 21 def SAT : Language := {w | ∃ F, encodeCNF F = w ∧ Satisfiable F} 22 23 def Verifier : Language := 24 {z | ∃ (F : Formula) (y : Word), z = pair (encodeCNF F) y ∧ eval F (assignment y) = true} 25 26 end Lax429075.Satisfiability 27 -
Satisfiability and binary encodings
An encoded formula belongs to the SAT language exactly when the formula is satisfiable.
1 import Lax429075.Satisfiability 2 … module docstring, 7 lines 10 11 namespace Lax429075.SATEncoding 12 13 open CNF Encoding Satisfiability 14 15 axiom correct (F : Formula) : encodeCNF F ∈ SAT ↔ Satisfiable F 16 17 end Lax429075.SATEncoding 18 -
The decoder's left-inverse property makes the binary encoding injective.
-
A bounded satisfying assignment
A satisfiable formula has a certificate whose length is at most the length of its binary encoding. Only variables occurring in the formula matter.
1 import Lax429075.Satisfiability 2 … module docstring, 8 lines 11 12 namespace Lax429075.FiniteWitness 13 14 open CNF Encoding Satisfiability Lax434930.PolynomialTime 15 16 axiom bounded (F : Formula) : 17 Satisfiable F ↔ ∃ y : Word, y.length ≤ (encodeCNF F).length ∧ eval F (assignment y) = true 18 19 end Lax429075.FiniteWitness 20 -
no assumptions
Restrict a satisfying assignment to the input-length prefix containing every variable.
-
Correctness of the SAT verifier
Membership in SAT is equivalent to the existence of an accepted certificate of length at most the input length.
1 import Lax429075.Satisfiability 2 … module docstring, 8 lines 11 12 namespace Lax429075.VerifierCorrect 13 14 open Satisfiability Lax434930.PolynomialTime Lax434930.Certificates 15 16 axiom correct (w : Word) : 17 w ∈ SAT ↔ ∃ y : Word, y.length ≤ w.length ∧ pair w y ∈ Verifier 18 19 end Lax429075.VerifierCorrect 20 -
Use the bounded assignment and the injective encoding of input-certificate pairs.
-
Polynomial time for CNF verification
A finite stack machine decodes the paired input and checks the supplied assignment. Its running time is polynomial in the input length, including on malformed encodings, using the machine model of lax-434930.
1 import Lax429075.Satisfiability 2 … module docstring, 10 lines 13 14 namespace Lax429075.VerifierTime 15 16 open Satisfiability Lax434930.PolynomialTime 17 18 axiom polynomial : Verifier ∈ P 19 20 end Lax429075.VerifierTime 21 -
no assumptions
Decode the pair, evaluate the formula against the certificate, and clear the work stacks. The finite stack program takes at most steps on every input, including malformed encodings.
-
SAT belongs to NP
A polynomial time verifier checks a satisfying assignment of polynomial length.
1 import Lax429075.Satisfiability 2 import Lax434930.NondeterministicPolynomialTime 3 … module docstring, 7 lines 11 12 namespace Lax429075.SATinNP 13 14 open Satisfiability Lax434930.NondeterministicPolynomialTime 15 16 axiom membership : SAT ∈ NP 17 18 end Lax429075.SATinNP 19 -
Use the identity polynomial as the certificate-length bound.
-
Boolean circuits
A circuit is a finite sequence of input, constant, negation, conjunction, and disjunction gates. Every wire refers to an earlier gate, and the output is a gate of the circuit. A satisfying wire assignment respects every gate and makes the output true.
1 import Lax429075.CNF 2 … module docstring, 10 lines 13 14 namespace Lax429075.Circuits 15 16 open CNF 17 18 inductive Gate 19 | input 20 | constant (value : Bool) 21 | neg (a : ℕ) 22 | conj (a b : ℕ) 23 | disj (a b : ℕ) 24 deriving DecidableEq 25 26 def Gate.inputs : Gate → List ℕ 27 | .input | .constant _ => [] 28 | .neg a => [a] 29 | .conj a b | .disj a b => [a, b] 30 31 structure Circuit where 32 gates : List Gate 33 output : Fin gates.length 34 ordered : ∀ g i, (g, i) ∈ gates.zipIdx → ∀ j ∈ g.inputs, j < i 35 36 def Gate.check (ρ : Assignment) (i : ℕ) : Gate → Bool 37 | .input => true 38 | .constant b => ρ i == b 39 | .neg a => ρ i == !(ρ a) 40 | .conj a b => ρ i == (ρ a && ρ b) 41 | .disj a b => ρ i == (ρ a || ρ b) 42 43 def check (C : Circuit) (ρ : Assignment) : Bool := 44 ρ C.output && C.gates.zipIdx.all (fun gi => gi.1.check ρ gi.2) 45 46 def Satisfiable (C : Circuit) : Prop := ∃ ρ, check C ρ = true 47 48 end Lax429075.Circuits 49 -
Gate clauses
The Tseitin encoding assigns one variable to each gate. At most three clauses enforce a gate's truth table, and a unit clause requires a true output. Input gates have no constraints.
1 import Lax429075.Circuits 2 … module docstring, 9 lines 12 13 namespace Lax429075.Tseitin 14 15 open CNF Circuits 16 17 def positive (i : ℕ) : Literal := ⟨i, true⟩ 18 def negative (i : ℕ) : Literal := ⟨i, false⟩ 19 20 def gateClauses (i : ℕ) : Gate → Formula 21 | .input => [] 22 | .constant b => [[⟨i, b⟩]] 23 | .neg a => [[positive i, positive a], [negative i, negative a]] 24 | .conj a b => [[negative i, positive a], [negative i, positive b], 25 [positive i, negative a, negative b]] 26 | .disj a b => [[positive i, negative a], [positive i, negative b], 27 [negative i, positive a, positive b]] 28 29 def encode (C : Circuit) : Formula := 30 [[positive C.output]] ++ C.gates.zipIdx.flatMap (fun gi => gateClauses gi.2 gi.1) 31 32 end Lax429075.Tseitin 33 -
Correctness of gate clauses
The clauses for one gate hold exactly when its output agrees with its Boolean operation.
1 import Lax429075.Tseitin 2 … module docstring, 8 lines 11 12 namespace Lax429075.GateCorrect 13 14 open CNF Circuits Tseitin 15 16 axiom correct (i : ℕ) (g : Gate) (ρ : Assignment) : 17 eval (gateClauses i g) ρ = g.check ρ i 18 19 end Lax429075.GateCorrect 20 -
no assumptions
Check the finite truth tables of the five gate forms.
-
Correctness of the circuit encoding
The gate clauses and output clause are satisfiable exactly when the circuit is satisfiable.
1 import Lax429075.Tseitin 2 … module docstring, 7 lines 10 11 namespace Lax429075.TseitinCorrect 12 13 open Circuits 14 15 axiom correct (C : Circuit) : CNF.Satisfiable (Tseitin.encode C) ↔ Satisfiable C 16 17 end Lax429075.TseitinCorrect 18 -
Conjoin the gate equivalences with the unit output clause.
-
Polynomial many-one reductions and NP-completeness
A polynomial many-one reduction is one polynomial time computable function on binary words that preserves membership. A language is NP-complete if it belongs to NP and every language in NP reduces to it.
1 import Lax434930.NondeterministicPolynomialTime 2 … module docstring, 9 lines 12 13 namespace Lax429075.Reductions 14 15 open Lax434930.PolynomialTime Lax434930.NondeterministicPolynomialTime 16 17 def ManyOne (A B : Language) : Prop := 18 ∃ f : Word → Word, Nonempty (Turing.TM2ComputableInPolyTime id id f) ∧ 19 ∀ x, x ∈ A ↔ f x ∈ B 20 21 def NPComplete (B : Language) : Prop := B ∈ NP ∧ ∀ A : Language, A ∈ NP → ManyOne A B 22 23 end Lax429075.Reductions 24 -
Polynomial circuit simulation of a verifier
For a fixed polynomial time verifier and polynomial certificate bound, construct a circuit whose free inputs represent the certificate. The circuit is satisfiable exactly when some bounded certificate is accepted. Its encoded gate clauses are produced in polynomial time. The machine simulation and time bound follow from a finite stack program that emits the initial layer, the transition layers, and the final acceptance constraint.
1 import Lax429075.Tseitin 2 import Lax429075.Encoding 3 import Lax434930.NondeterministicPolynomialTime 4 … module docstring, 12 lines 17 18 namespace Lax429075.CircuitMachine 19 20 open Lax434930.PolynomialTime Lax434930.Certificates Circuits Encoding 21 22 axiom compile (V : Language) (hV : V ∈ P) (p : Polynomial ℕ) : 23 ∃ circuits : Word → Circuit, 24 Nonempty (Turing.TM2ComputableInPolyTime id id 25 (fun x => encodeCNF (Tseitin.encode (circuits x)))) ∧ 26 ∀ x, Satisfiable (circuits x) ↔ 27 ∃ y : Word, y.length ≤ p.eval x.length ∧ pair x y ∈ V 28 29 end Lax429075.CircuitMachine 30 -
Unroll the bounded verifier and emit its gate clauses with polynomially bounded loops.
-
NP-hardness of SAT
Every language in NP has a polynomial many-one reduction to the binary language of satisfiable CNF formulas.
1 import Lax429075.Satisfiability 2 import Lax429075.Reductions 3 … module docstring, 8 lines 12 13 namespace Lax429075.SATHard 14 15 open Satisfiability Reductions Lax434930.PolynomialTime Lax434930.NondeterministicPolynomialTime 16 17 axiom hardness (A : Language) : A ∈ NP → ManyOne A SAT 18 19 end Lax429075.SATHard 20 -
Compile the verifier, impose the gate clauses, and encode the resulting formula.
-
The Cook–Levin theorem
Satisfiability of CNF formulas is NP-complete under polynomial many-one reductions.
1 import Lax429075.Satisfiability 2 import Lax429075.Reductions 3 … module docstring, 7 lines 11 12 namespace Lax429075.CookLevin 13 14 open Satisfiability Reductions 15 16 axiom np_complete : NPComplete SAT 17 18 end Lax429075.CookLevin 19 -
- lem✓
Lax429075.SATHard - lem✓
Lax429075.SATinNP
Combine membership in NP with polynomial many-one hardness.
- lem✓
Loading the paper…