Circuit satisfiability
DefinitionCertificate position of a wire#✓fully proved
For a wire that refers to one of \(n\) inputs or one of \(g\) gates, its position in \(\{0, \dots, n + g - 1\}\) is \(k\) if it is input \(k\) and \(n + j\) if it is gate \(j\), so the inputs come first and the gates follow.
@[expose] public def toFin {i g : Nat} (wire : Wire i g) : Fin (i + g) :=
finSumFinEquiv (Wire.equiv i g wire)
Used by 6
DefinitionBoolean certificate verifier#✓fully proved
Let \(c\) be a circuit over the Boolean signature with \(n\) inputs, \(s\) gates and one output, and let \(b = (b_0, \dots, b_{m-1})\) be an array of truth values, read as a value for each wire: input \(k\) at position \(k\) and gate \(j\) at position \(n + j\). The verifier is a computation with a counted cost. It first checks whether \(m = n + s\), at cost \(1\); if not, it returns false. Otherwise, for each gate \(j < s\) in order, it reads the entries of \(b\) at the positions of the argument wires of gate \(j\), at cost \(1\) per argument, and compares the Boolean interpretation of the operation of gate \(j\) on these values with \(b_{n+j}\), at cost \(1\); finally it reads the entry at the position of the output wire, at cost \(1\). It returns true exactly when every comparison succeeds and that output entry is true.
public def verifyBooleanCertificate {i : Nat}
(c : Circuit booleanSignature i 1) (cert : Array Bool) : TimeM Nat Bool := do
TimeM.tick 1
if cert.size = i + c.size then
let gatesOK ← checkProgram c.program cert
TimeM.tick 1
let output := cert.getD (c.outputs 0).toFin.val false
pure (gatesOK && output)
else
pure false
def booleanSignature : Signature where
Op := BooleanGate
Arity
| .not => 1
| .and a => a + 1
| .or a => a + 1
CSLibExt/Computability/Circuit/Boolean.lean:33
private def checkProgram {i : Nat} :
{g : Nat} → Program booleanSignature i g → Array Bool → TimeM Nat Bool
| _, .empty, _ => pure true
| _, .gate p line, cert => do
let prior ← checkProgram p cert
let equal ← checkLine line cert
pure (prior && equal)
CSLibExt/Algorithms/Lean/Circuit/Verification.lean:95
Uses 3 · Used by 6
TheoremCharacterization of accepted certificates#✓fully proved
Let \(c\) be a circuit over the Boolean signature with \(n\) inputs, \(s\) gates and one output, and let \(b = (b_0, \dots, b_{m-1})\) be an array of truth values, where an entry at a position at or beyond \(m\) is read as false and the position of a wire is \(k\) for input \(k\) and \(n + j\) for gate \(j\). The Boolean certificate verifier accepts \(b\) if and only if \(m = n + s\), for every gate \(j < s\) the Boolean interpretation of the operation of gate \(j\) applied to the entries of \(b\) at the positions of its argument wires equals \(b_{n+j}\), and the entry of \(b\) at the position of the output wire is true.
public theorem verifyBooleanCertificate_iff {i : Nat}
(c : Circuit booleanSignature i 1) (cert : Array Bool) :
(verifyBooleanCertificate c cert).ret = true ↔
cert.size = i + c.size ∧
(∀ j : Fin c.size, booleanInterpretation (c.program.lines j).op
(fun k => cert.getD ((c.program.lines j).wires k).toFin.val false) =
cert.getD (i + j.val) false) ∧ cert.getD (c.outputs 0).toFin.val false = true
def booleanSignature : Signature where
Op := BooleanGate
Arity
| .not => 1
| .and a => a + 1
| .or a => a + 1
CSLibExt/Computability/Circuit/Boolean.lean:33
public def verifyBooleanCertificate {i : Nat}
(c : Circuit booleanSignature i 1) (cert : Array Bool) : TimeM Nat Bool := do
TimeM.tick 1
if cert.size = i + c.size then
let gatesOK ← checkProgram c.program cert
TimeM.tick 1
let output := cert.getD (c.outputs 0).toFin.val false
pure (gatesOK && output)
else
pure false
CSLibExt/Algorithms/Lean/Circuit/Verification.lean:104
def booleanInterpretation : Interpretation booleanSignature Bool
| .not, f => !(f ⟨0, by decide⟩)
| .and a, f => Fin.foldl (a + 1) (fun acc k => acc && f k) true
| .or a, f => Fin.foldl (a + 1) (fun acc k => acc || f k) false
CSLibExt/Computability/Circuit/Boolean.lean:41
Uses 4 · Used by 2
TheoremSoundness of the Boolean certificate verifier#✓fully proved
Let \(c\) be a circuit over the Boolean signature with \(n\) inputs, \(s\) gates and one output, and let \(b = (b_0, \dots, b_{m-1})\) be an array of truth values, where an entry at a position at or beyond \(m\) is read as false and the position of a wire is \(k\) for input \(k\) and \(n + j\) for gate \(j\). If the Boolean certificate verifier accepts \(b\), then, writing \(x = (b_0, \dots, b_{n-1})\), the value of every wire of \(c\) on input \(x\) under the Boolean interpretation equals the entry of \(b\) at the position of that wire, and the output of \(c\) on input \(x\) is true.
public theorem verifyBooleanCertificate_sound {i : Nat}
(c : Circuit booleanSignature i 1) (cert : Array Bool)
(h : (verifyBooleanCertificate c cert).ret = true) :
(∀ w : Wire i c.size, c.program.trace booleanInterpretation
(fun k => cert.getD k.val false) w = cert.getD w.toFin.val false) ∧
c.eval booleanInterpretation (fun k => cert.getD k.val false) 0 = true
def booleanSignature : Signature where
Op := BooleanGate
Arity
| .not => 1
| .and a => a + 1
| .or a => a + 1
CSLibExt/Computability/Circuit/Boolean.lean:33
public def verifyBooleanCertificate {i : Nat}
(c : Circuit booleanSignature i 1) (cert : Array Bool) : TimeM Nat Bool := do
TimeM.tick 1
if cert.size = i + c.size then
let gatesOK ← checkProgram c.program cert
TimeM.tick 1
let output := cert.getD (c.outputs 0).toFin.val false
pure (gatesOK && output)
else
pure false
CSLibExt/Algorithms/Lean/Circuit/Verification.lean:104
def booleanInterpretation : Interpretation booleanSignature Bool
| .not, f => !(f ⟨0, by decide⟩)
| .and a, f => Fin.foldl (a + 1) (fun acc k => acc && f k) true
| .or a, f => Fin.foldl (a + 1) (fun acc k => acc || f k) false
CSLibExt/Computability/Circuit/Boolean.lean:41
Uses 5 · Used by 1
TheoremCompleteness of the Boolean certificate verifier#✓fully proved
Let \(c\) be a circuit over the Boolean signature with \(n\) inputs, \(s\) gates and one output, and let \(x = (x_0, \dots, x_{n-1})\) be truth values on which the output of \(c\) under the Boolean interpretation is true. Let \(b\) be the array \((x_0, \dots, x_{n-1}, v_0, \dots, v_{s-1})\), where \(v_j\) is the value of gate \(j\) of \(c\) on input \(x\). Then \(b\) has length \(n + s\) and the Boolean certificate verifier accepts \(b\).
public theorem verifyBooleanCertificate_complete {i : Nat}
(c : Circuit booleanSignature i 1) (input : Fin i → Bool)
(h : c.eval booleanInterpretation input 0 = true) :
let cert := Array.ofFn (Fin.addCases input (c.program.eval booleanInterpretation input))
cert.size = i + c.size ∧ (verifyBooleanCertificate c cert).ret = true
def booleanSignature : Signature where
Op := BooleanGate
Arity
| .not => 1
| .and a => a + 1
| .or a => a + 1
CSLibExt/Computability/Circuit/Boolean.lean:33
def booleanInterpretation : Interpretation booleanSignature Bool
| .not, f => !(f ⟨0, by decide⟩)
| .and a, f => Fin.foldl (a + 1) (fun acc k => acc && f k) true
| .or a, f => Fin.foldl (a + 1) (fun acc k => acc || f k) false
CSLibExt/Computability/Circuit/Boolean.lean:41
public def verifyBooleanCertificate {i : Nat}
(c : Circuit booleanSignature i 1) (cert : Array Bool) : TimeM Nat Bool := do
TimeM.tick 1
if cert.size = i + c.size then
let gatesOK ← checkProgram c.program cert
TimeM.tick 1
let output := cert.getD (c.outputs 0).toFin.val false
pure (gatesOK && output)
else
pure false
CSLibExt/Algorithms/Lean/Circuit/Verification.lean:104
Uses 5 · Used by 1
TheoremShort accepted certificates exist exactly for satisfiable circuits#✓fully proved
Let \(c\) be a circuit over the Boolean signature with \(n\) inputs, \(s\) gates and one output. The Boolean certificate verifier accepts some array of at most \(n + 2s\) truth values if and only if there are truth values \(x_0, \dots, x_{n-1}\) on which the output of \(c\) under the Boolean interpretation is true.
public theorem verifyBooleanCertificate_satisfiable_iff {i : Nat}
(c : Circuit booleanSignature i 1) :
(∃ cert : Array Bool, (verifyBooleanCertificate c cert).ret = true ∧
cert.size ≤ i + 2 * c.size) ↔
∃ input : Fin i → Bool, c.eval booleanInterpretation input 0 = true
def booleanSignature : Signature where
Op := BooleanGate
Arity
| .not => 1
| .and a => a + 1
| .or a => a + 1
CSLibExt/Computability/Circuit/Boolean.lean:33
public def verifyBooleanCertificate {i : Nat}
(c : Circuit booleanSignature i 1) (cert : Array Bool) : TimeM Nat Bool := do
TimeM.tick 1
if cert.size = i + c.size then
let gatesOK ← checkProgram c.program cert
TimeM.tick 1
let output := cert.getD (c.outputs 0).toFin.val false
pure (gatesOK && output)
else
pure false
CSLibExt/Algorithms/Lean/Circuit/Verification.lean:104
def booleanInterpretation : Interpretation booleanSignature Bool
| .not, f => !(f ⟨0, by decide⟩)
| .and a, f => Fin.foldl (a + 1) (fun acc k => acc && f k) true
| .or a, f => Fin.foldl (a + 1) (fun acc k => acc || f k) false
CSLibExt/Computability/Circuit/Boolean.lean:41
TheoremCost of the Boolean certificate verifier#✓fully proved
Let \(c\) be a circuit over the Boolean signature with \(n\) inputs, \(s\) gates and one output, and let \(b\) be an array of \(m\) truth values. The cost counted by the Boolean certificate verifier on \(b\) is \(2 + s + \sum_{j < s} a_j\) if \(m = n + s\), where \(a_j\) is the number of arguments of gate \(j\), and \(1\) otherwise.
public theorem verifyBooleanCertificate_time {i : Nat}
(c : Circuit booleanSignature i 1) (cert : Array Bool) :
(verifyBooleanCertificate c cert).time =
if cert.size = i + c.size then
2 + c.size + ∑ j : Fin c.size, booleanSignature.Arity (c.program.lines j).op
else 1
def booleanSignature : Signature where
Op := BooleanGate
Arity
| .not => 1
| .and a => a + 1
| .or a => a + 1
CSLibExt/Computability/Circuit/Boolean.lean:33
public def verifyBooleanCertificate {i : Nat}
(c : Circuit booleanSignature i 1) (cert : Array Bool) : TimeM Nat Bool := do
TimeM.tick 1
if cert.size = i + c.size then
let gatesOK ← checkProgram c.program cert
TimeM.tick 1
let output := cert.getD (c.outputs 0).toFin.val false
pure (gatesOK && output)
else
pure false
CSLibExt/Algorithms/Lean/Circuit/Verification.lean:104
Uses 4 · Used by 1
TheoremLinear cost of the Boolean certificate verifier#✓fully proved
Let \(K\) be a natural number and let \(c\) be a circuit over the Boolean signature with \(n\) inputs, \(s\) gates and one output in which every gate has at most \(K\) arguments. Then for every array \(b\) of truth values, the cost counted by the Boolean certificate verifier on \(b\) is at most \(2 + (K + 1)s\).
public theorem verifyBooleanCertificate_time_le_of_fanInAtMost {i K : Nat}
(c : Circuit booleanSignature i 1) (cert : Array Bool) (hfan : c.FanInAtMost K) :
(verifyBooleanCertificate c cert).time ≤ 2 + (K + 1) * c.size
def booleanSignature : Signature where
Op := BooleanGate
Arity
| .not => 1
| .and a => a + 1
| .or a => a + 1
CSLibExt/Computability/Circuit/Boolean.lean:33
public def verifyBooleanCertificate {i : Nat}
(c : Circuit booleanSignature i 1) (cert : Array Bool) : TimeM Nat Bool := do
TimeM.tick 1
if cert.size = i + c.size then
let gatesOK ← checkProgram c.program cert
TimeM.tick 1
let output := cert.getD (c.outputs 0).toFin.val false
pure (gatesOK && output)
else
pure false
CSLibExt/Algorithms/Lean/Circuit/Verification.lean:104
Uses 3
AbbreviationCircuit-satisfiability instances#✓fully proved
An instance of circuit satisfiability is a pair \((n, G)\) of a natural number \(n\), the number of variables, and a finite list \(G\) of gates, each gate a triple \((o, a, b)\) of natural numbers: an operation code \(o\), a first input \(a\) and a second input \(b\).
abbrev CircuitSatInstance := ℕ × List (ℕ × ℕ × ℕ)
DefinitionResolving a circuit input#✓fully proved
Given an assignment \(x = (x_0, \dots, x_{n-1})\) of booleans to the variables and the list \(v = (v_0, \dots, v_{k-1})\) of the values of the gates evaluated so far, an input index \(r\) resolves to \(x_r\) if \(r < n\), to \(v_{r-n}\) if \(n \le r < n + k\), and to false if \(r \ge n + k\).
def CircuitRef (assign : List Bool) (vals : List Bool) (idx : ℕ) : Bool :=
if idx < assign.length then assign.getD idx false
else vals.getD (idx - assign.length) false
Used by 1
DefinitionValue of a gate#✓fully proved
Let \(x = (x_0, \dots, x_{n-1})\) be an assignment of booleans to the variables and \(v\) the list of values of the earlier gates. An input index \(r\) resolves to \(x_r\) if \(r < n\), and otherwise to \(v_{r-n}\), or to false if that entry does not exist. The value of a gate \((o, a, b)\) is the conjunction of the resolved inputs \(a\) and \(b\) if \(o = 0\), their disjunction if \(o = 1\), the negation of the resolved input \(a\) if \(o = 2\), \(x_a\) (false if \(a \ge n\)) if \(o = 3\), true if \(o = 4\), and false if \(o \ge 5\).
def GateValue (assign : List Bool) (vals : List Bool) (gate : ℕ × ℕ × ℕ) : Bool :=
match gate.1 with
| 0 => CircuitRef assign vals gate.2.1 && CircuitRef assign vals gate.2.2
| 1 => CircuitRef assign vals gate.2.1 || CircuitRef assign vals gate.2.2
| 2 => !CircuitRef assign vals gate.2.1
| 3 => assign.getD gate.2.1 false
| 4 => true
| _ => false
def CircuitRef (assign : List Bool) (vals : List Bool) (idx : ℕ) : Bool :=
if idx < assign.length then assign.getD idx false
else vals.getD (idx - assign.length) false
WantedExt/Complexity/NPComplete/CircuitSatWanted.lean:55
Uses 1 · Used by 1
DefinitionEvaluating a circuit#✓fully proved
Given an assignment of booleans to the variables and a list of gates \(g_1, \dots, g_m\), circuit evaluation returns the list \((v_1, \dots, v_m)\) of gate values, where \(v_k\) is the value of the gate \(g_k\) under the assignment and the earlier values \((v_1, \dots, v_{k-1})\).
def EvalCircuit (assign : List Bool) (gates : List (ℕ × ℕ × ℕ)) : List Bool :=
gates.foldl (fun vals gate => vals ++ [GateValue assign vals gate]) []
def GateValue (assign : List Bool) (vals : List Bool) (gate : ℕ × ℕ × ℕ) : Bool :=
match gate.1 with
| 0 => CircuitRef assign vals gate.2.1 && CircuitRef assign vals gate.2.2
| 1 => CircuitRef assign vals gate.2.1 || CircuitRef assign vals gate.2.2
| 2 => !CircuitRef assign vals gate.2.1
| 3 => assign.getD gate.2.1 false
| 4 => true
| _ => false
WantedExt/Complexity/NPComplete/CircuitSatWanted.lean:60
Uses 1 · Used by 1
DefinitionWell-formed circuit-satisfiability instances#✓fully proved
An instance \((n, G)\) with gates \(G = (g_0, \dots, g_{m-1})\) is well formed when every gate \(g_j = (o, a, b)\) satisfies \(o \le 5\), and moreover: if \(o = 0\) or \(o = 1\) then \(a < n + j\) and \(b < n + j\); if \(o = 2\) then \(a < n + j\); and if \(o = 3\) then \(a < n\).
def WellFormed (i : CircuitSatInstance) : Prop :=
(∀ p ∈ i.2.zipIdx, p.1.1 ≤ 5 ∧
((p.1.1 = 0 ∨ p.1.1 = 1) → p.1.2.1 < i.1 + p.2 ∧ p.1.2.2 < i.1 + p.2) ∧
(p.1.1 = 2 → p.1.2.1 < i.1 + p.2) ∧
(p.1.1 = 3 → p.1.2.1 < i.1))
abbrev CircuitSatInstance := ℕ × List (ℕ × ℕ × ℕ)
WantedExt/Complexity/NPComplete/CircuitSatWanted.lean:51
Uses 1 · Used by 1
DefinitionSatisfiable circuit instances#✓fully proved
An instance \((n, G)\) is satisfiable when there is an assignment \(x \in \{\mathrm{true}, \mathrm{false}\}^n\) of booleans to the \(n\) variables such that the evaluation of the circuit \(G\) under \(x\) has a last gate value and that value is true. In particular an instance with no gates is not satisfiable.
def CircuitSatFeasible
(i : CircuitSatInstance) : Prop :=
∃ assign : List Bool, assign.length = i.1 ∧
(EvalCircuit assign i.2).getLast? = some true
abbrev CircuitSatInstance := ℕ × List (ℕ × ℕ × ℕ)
WantedExt/Complexity/NPComplete/CircuitSatWanted.lean:51
def EvalCircuit (assign : List Bool) (gates : List (ℕ × ℕ × ℕ)) : List Bool :=
gates.foldl (fun vals gate => vals ++ [GateValue assign vals gate]) []
WantedExt/Complexity/NPComplete/CircuitSatWanted.lean:70
Uses 2 · Used by 1
DefinitionThe CIRCUIT SAT decision problem#✓fully proved
CIRCUIT SAT is the decision problem that accepts a bitstring \(s\) exactly when \(s\) decodes, under the canonical bitstring encoding of circuit-satisfiability instances, to an instance that is well formed and satisfiable. Bitstrings that fail to decode are rejected.
noncomputable def circuitSatDec :
MetaMathlibExt.ComplexityTheory.DecisionProblem := fun x =>
match MetaMathlibExt.BitstringEncoding.bitDecode
(α := CircuitSatInstance) x with
| some i => decide (WellFormed i ∧ CircuitSatFeasible i)
| none => false
abbrev DecisionProblem := List Bool → Bool
MathlibExt/Computability/Complexity.lean:170
def bitDecode [BitstringEncoding α] (l : List Bool) : Option α := toEncoding.decode l
MathlibExt/Computability/Complexity.lean:58
abbrev CircuitSatInstance := ℕ × List (ℕ × ℕ × ℕ)
WantedExt/Complexity/NPComplete/CircuitSatWanted.lean:51
def WellFormed (i : CircuitSatInstance) : Prop :=
(∀ p ∈ i.2.zipIdx, p.1.1 ≤ 5 ∧
((p.1.1 = 0 ∨ p.1.1 = 1) → p.1.2.1 < i.1 + p.2 ∧ p.1.2.2 < i.1 + p.2) ∧
(p.1.1 = 2 → p.1.2.1 < i.1 + p.2) ∧
(p.1.1 = 3 → p.1.2.1 < i.1))
WantedExt/Complexity/NPComplete/CircuitSatWanted.lean:75
def CircuitSatFeasible
(i : CircuitSatInstance) : Prop :=
∃ assign : List Bool, assign.length = i.1 ∧
(EvalCircuit assign i.2).getLast? = some true
WantedExt/Complexity/NPComplete/CircuitSatWanted.lean:82
Uses 12 · Used by 1
TheoremCIRCUIT SAT is NP-complete#●ready to prove
The CIRCUIT SAT decision problem on bitstrings belongs to the class NP, and every decision problem in NP reduces to it by a polynomial-time many-one reduction.
public theorem_wanted circuitSat_npComplete :
circuitSatDec ∈ MetaMathlibExt.ComplexityTheory.NP ∧
∀ L : MetaMathlibExt.ComplexityTheory.DecisionProblem,
L ∈ MetaMathlibExt.ComplexityTheory.NP →
Cslib.CookLevin.PolyManyOneRed L circuitSatDec
noncomputable def circuitSatDec :
MetaMathlibExt.ComplexityTheory.DecisionProblem := fun x =>
match MetaMathlibExt.BitstringEncoding.bitDecode
(α := CircuitSatInstance) x with
| some i => decide (WellFormed i ∧ CircuitSatFeasible i)
| none => false
WantedExt/Complexity/NPComplete/CircuitSatWanted.lean:89
def NP : DecisionComplexityClass :=
{ L | ∃ (p : Polynomial ℕ), ∃ R : (List Bool × List Bool) → Bool,
IsPolyTime R ∧
∀ x, L x ↔ ∃ w : List Bool, w.length ≤ p.eval x.length ∧ R (x, w) }
MathlibExt/Computability/Complexity.lean:200
abbrev DecisionProblem := List Bool → Bool
MathlibExt/Computability/Complexity.lean:170
def PolyManyOneRed (L₁ L₂ : MetaMathlibExt.ComplexityTheory.DecisionProblem) : Prop :=
∃ reduce : List Bool → List Bool,
MetaMathlibExt.ComplexityTheory.IsPolyTime reduce ∧ ∀ x, L₁ x = L₂ (reduce x)
CSLibExt/Computability/CookLevin.lean:396
Sources
- M. R. Garey and D. S. Johnson, Computers and Intractability: A Guide to the Theory of NP-Completeness (1979), CIRCUIT SATISFIABILITY; S. A. Cook, "The complexity of theorem-proving procedures" (1971).
Uses 5
Loading dependency explorer…
The dependency explorer needs JavaScript and its graph data.