wiki

CNF

Conjunctive normal form: a conjunction of clauses, each a disjunction of literals, where a literal is a variable or its negation, . It is the input format of SAT solvers. Every formula has an equivalent CNF, but it can be exponentially larger; the Tseitin transformation gives an equisatisfiable one of linear size instead.

A clause is satisfied when one of its literals is true, and the formula when every clause is. Solvers are built around that shape: a clause whose literals are all false but one forces the last one, which is unit propagation, and a clause whose literals are all false is a conflict.

An equivalent CNF comes from pushing negations down to the variables with De Morgan's laws and then distributing disjunction over conjunction:

Distribution is where the size goes. For each clause of the result picks one of from every term, which gives clauses, and no equivalent CNF has fewer.

Negation normal form, then distribution. Clauses are lists of nonzero ints, as in DIMACS: -3 is the negation of variable 3.

type f = Var of int | Not of f | And of f * f | Or of f * f
let rec nnf = function
| Var v -> Var v
| Not (Var v) -> Not (Var v)
| Not (Not a) -> nnf a
| Not (And (a, b)) -> Or (nnf (Not a), nnf (Not b))
| Not (Or (a, b)) -> And (nnf (Not a), nnf (Not b))
| And (a, b) -> And (nnf a, nnf b)
| Or (a, b) -> Or (nnf a, nnf b)
let rec distribute = function
| Var v -> [ [ v ] ]
| Not (Var v) -> [ [ -v ] ]
| And (a, b) -> distribute a @ distribute b
| Or (a, b) ->
let ca = distribute a and cb = distribute b in
List.concat_map (fun c -> List.map (fun d -> c @ d) cb) ca
| Not _ -> assert false

Clause counts for the formula above, by distribution and by the Tseitin transformation.

n distributed tseitin (clauses, variables)
1 2 4, 3
2 4 10, 7
5 32 28, 19
10 1024 58, 39
15 32768 88, 59

Two restricted forms are decidable in polynomial time. In 2-CNF every clause has at most two literals; each clause gives the implications and , and the formula is unsatisfiable exactly when some variable and its negation lie in the same strongly connected component of the resulting graph, which is a linear-time check. In Horn CNF every clause has at most one positive literal, and unit propagation alone decides it. With three literals per clause the problem is already NP-complete.

see also

further reading

  1. [1]S. A. Cook, “The complexity of theorem-proving procedures”, STOC (1971).
  2. [2]B. Aspvall, M. F. Plass, R. E. Tarjan, “A linear-time algorithm for testing the truth of certain quantified Boolean formulas”, Information Processing Letters 8 (1979).