Cook–Levin theorem: Satisfiability is -complete (Cook 1971, Levin 1973)
OpenPvsNP.cook_levinCook (p. 4–5): "in 1971 the present author [9] introduced a notion of -completeness ... The main results in [9] are that several natural problems, including Satisfiability and 3-SAT (defined below) and subgraph isomorphism are -complete. ... Meanwhile Levin [23], independently of Cook and Karp, defined the notion of 'universal search problem', similar to the -complete problem, and gave six examples, including Satisfiability." And (p. 5): "This problem was shown in [9] to be -complete essentially by showing that, for each polynomial-time Turing machine that recognizes a checking relation for an language , there is a polynomial-time algorithm that takes as input a string and produces a propositional formula (describing the computation of on input , with variables representing the unknown string ) such that is satisfiable iff accepts the input for some with ."
Theorem (Cook–Levin). is -complete in the sense of Cook's Definition 4: , and for every language there is a polynomial-time computable function such that for all , where is the set of codes of satisfiable CNF formulas.
Formalization Note Reductions are many-one (Karp) reductions as in Cook's Definition 3; Cook's 1971 paper used polynomial-time Turing reductions, and the many-one form stated here is the one Cook's description adopts as standard. Satisfiability is CNF satisfiability, as in Cook's 1971 paper. The reduction must output the specific code encodeCNF F_x of a CNF formula, so a proof requires an explicit multi-stack machine that, given , writes down the tableau formula of the checking machine's computation on with , within a polynomial step bound. A machine-checked proof of the Cook–Levin theorem exists in Coq (Gäher and Kunze, ITP 2021); none exists in Lean.
import Definitions.Def_PvsNP import Mathlib
namespace PvsNP theorem cook_levin : NPComplete SAT := by sorry end PvsNP
Read-back
What the Lean code literally says, in plain math · claude-fable-5-1
Read-back: PvsNP.cook_levin
Statement. The theorem asserts a single closed proposition with no free variables, hypotheses or typeclass assumptions:
i.e. the set of binary strings defined below belongs to the class defined below, and every language in that class is polynomial-time reducible (in the sense defined below) to . Everything named here is a custom definition from the accompanying file; each is unfolded below down to standard notions.
Strings and languages
A string is a finite list of booleans (a word over the two-letter alphabet , i.e. ); denotes its length. A language is an arbitrary set of such strings (no computability or decidability is imposed on a language as such), and is ordinary set membership.
The machine model (Mathlib's bundled two-stack-style machine "TM2")
A machine consists of:
- a type of stack names which is finite and has decidable equality, together with two distinguished names (input stack) and (output stack) — is allowed;
- for each stack name a type of stack symbols; only is required to be finite (the other are arbitrary types);
- a finite type of labels with a distinguished label ;
- a finite type of internal states with a distinguished initial state ;
- a program assigning to each label a statement .
A statement is a finite tree built from the constructors: push a symbol (depending on the current internal state ) onto stack and continue; peek at the top of stack (an optional symbol) and update the internal state by an arbitrary function , then continue; pop the top of stack and update the state likewise, then continue; load, i.e. replace the state by for an arbitrary , then continue; branch on a boolean function of the state to one of two continuations; goto a label depending on the state; or halt. All the functions occurring in statements are arbitrary (set-theoretic) functions; no effectiveness is required of them.
A configuration is a triple (current label or "halted", internal state , and for each a finite list of symbols of — the stacks, top of stack first). The step function is: a halted configuration has no successor; a configuration with label has exactly one successor, obtained by executing the entire statement (all its pushes, pops, peeks, loads and branches, however many) until it reaches a goto (which sets the new label) or a halt (which sets the label to "halted"). Thus one "step" is the execution of one whole statement block.
For an input list of symbols of , the initial configuration has label , state , stack equal to , and every other stack empty. For an output list of symbols of , the halting configuration has label "halted", state (the initial state), stack equal to , and every other stack empty.
" outputs on input within steps" means: there is a natural number such that iterating the step function exactly times starting from (where "no successor" is absorbing) yields exactly the configuration . In particular the machine must stop with its internal state reset to , with all stacks other than empty, and with stack holding exactly .
Polynomial-time computability of a function relative to encodings
Given types , alphabets , encodings and (lists of letters), and a function , the structure " is TM2-computable in polynomial time w.r.t. " consists of:
- a machine as above;
- a bijection between the input-stack alphabet and , and a bijection between the output-stack alphabet and ;
- a polynomial with natural-number coefficients;
- for every : outputs (the letter-by-letter preimage of the encoded output) on input within steps, where is the length of the encoded input.
Every use below is of the form "there exists at least one such structure" (mere existence, no particular machine is fixed).
The encodings used are:
- on strings: a string is its own code, alphabet ;
- : a boolean is coded as the one-letter string , alphabet ;
- for a pair of strings: the letters of each tagged "left" followed by the letters of each tagged "right", a string over the four-letter alphabet ; its length is .
Hence:
- is a polynomial-time decider (): there exist a machine, alphabet bijections , , and a polynomial such that for every string the machine, started on , halts (in the strict sense above) with output stack holding exactly the single letter within steps.
- is a polynomial-time checker (): the same with input alphabet in bijection with , input , output the single letter , within steps.
- is polynomial-time computable (): the same with both alphabets in bijection with , input , output exactly the string , within steps.
The classes and reducibility
- iff there exist a function and a natural number (with allowed) such that is a polynomial-time checker and, for every string ,
Here is natural-number exponentiation with (including ); for and the empty string the only admissible certificate is the empty string.
- is polynomial-time reducible to (written ) iff there exists which is polynomial-time computable in the above sense and such that for every string ,
- is NP-complete iff and for every language with , .
(The file also defines a class , a class and a language ; none of these occurs in the theorem.)
Formulas and their string coding
- A literal is a pair with a boolean (sign) and (variable index). A clause is a finite list of literals. A CNF formula is a finite list of clauses. Duplicates and any ordering are allowed; the empty clause and the empty formula are allowed.
- For an assignment : the literal evaluates to and to ; a clause evaluates to iff some literal in it does (the empty clause evaluates to ); evaluates to iff every clause in it does (the empty formula evaluates to ).
- is satisfiable iff there exists (an arbitrary function, defined on all of ) under which evaluates to .
The coding of formulas as binary strings, writing for and for :
- is the binary expansion of written least-significant bit first with no leading zeros, so (empty), , , , and for the last bit is .
- A literal is coded by taking the list (sign first, then the bits), replacing each of its entries by the two letters , and then appending the terminator :
For example and .
- A clause is coded by concatenating the codes of its literals in order and appending the terminator ; the empty clause is coded as .
- A formula is coded by concatenating the codes of its clauses in order, with no further delimiter; the empty formula is coded as the empty string.
Finally,
Thus a string is in iff it is the exact code of some satisfiable formula; strings that are not codes of any formula are not in ; the empty string is in (it codes the empty formula, which is satisfiable); the string (code of the formula consisting of one empty clause) is not.
The assertion, assembled
The theorem asserts both of the following:
-
: there exist and , such that some machine of the kind described (with input alphabet in bijection with , output alphabet in bijection with , some polynomial ) computes on every tagged pair within steps, halting exactly in the configuration with output stack , all other stacks empty and internal state reset to the initial state, and such that for every string : is the code of a satisfiable CNF formula iff there is a string with and .
-
Every reduces to : for every set of binary strings for which there exist as in the definition of , there exists a function , computed by some machine of the kind described (both stack alphabets in bijection with ) within steps for some polynomial on every input (halting exactly with output stack , other stacks empty, state reset), such that for every string : iff is the code of a satisfiable CNF formula.