Craig interpolation
Craig's interpolation theorem, proved by William Craig in 1957, says that whenever a formula logically implies a formula , there is a formula such that implies , implies , and every non-logical symbol of occurs in both and [1]. The interpolant is an explanation of the implication in the shared vocabulary: it captures exactly what has to say that needs. The theorem holds for first-order and propositional logic. Its computational form made it a tool of automated verification: from a resolution refutation of an unsatisfiable conjunction , an interpolant can be read off in one pass[2][3]. Kenneth McMillan used such interpolants in 2003 to turn bounded model checking with a SAT solver into a complete method for proving safety properties[3].
Statement
In the refutation form used in automated reasoning, for unsatisfiable, an interpolant satisfies
This is the original statement applied to . In propositional logic, interpolants always exist and there are two extreme ones. Quantifying away the variables that occur only in gives the strongest interpolant, , and quantifying away those that occur only in from gives the weakest, . Every interpolant lies between them. Both can be exponentially large, and computing them requires eliminating quantifiers.
Interpolants from resolution proofs
Given a resolution refutation of , each clause of the refutation can be labelled with a partial interpolant . McMillan's system is[3]:
where the last two cases are for a resolvent of and on the pivot , and is the disjunction of the literals of whose variables occur in . By induction over the proof, each label satisfies and , a clause restricted to shared literals, so the label of the empty clause is an interpolant. The computation is linear in the size of the proof, and the interpolant, viewed as a circuit with shared subterms, is as well. Pudlák's earlier system is symmetric between and [2][10]; D'Silva and co-authors showed that these systems are instances of a family that yields interpolants of different logical strength from the same proof[5].
McMillan's labelling over the refutations produced by a small DPLL-based prover.
open Resproof(* Interpolants as formulas, simplified as they are built. *)type f = T | F | Lit of int | And of f * f | Or of f * flet conj a b = match a, b with F, _ | _, F -> F | T, x | x, T -> x | _ -> if a = b then a else And (a, b)let disj a b = match a, b with T, _ | _, T -> T | F, x | x, F -> x | _ -> if a = b then a else Or (a, b)let rec eval env = function| T -> true | F -> false | Lit l -> if l > 0 then env l else not (env (-l))| And (a, b) -> eval env a && eval env b | Or (a, b) -> eval env a || eval env blet rec vars = function T | F -> [] | Lit l -> [ abs l ] | And (a, b) | Or (a, b) -> vars a @ vars b(* McMillan's labelling of a refutation of A ∧ B. Input clauses withindex below na belong to A. *)let interpolant ~na (a_vars : int list) (b_vars : int list) (p : proof) =let a_local v = List.mem v a_vars && not (List.mem v b_vars) inlet rec label p =match p.step with| Input i when i < na -> (* A clause: its B-literals, disjoined *)List.fold_left (fun acc l -> if List.mem (abs l) b_vars then disj acc (Lit l) else acc) F p.clause| Input _ -> T (* B clause *)| Resolve (v, p1, p2) ->if a_local v then disj (label p1) (label p2) else conj (label p1) (label p2)inlabel plet rec show_with name = function| T -> "⊤" | F -> "⊥"| Lit l -> (if l < 0 then "¬" else "") ^ name (abs l)| And (a, b) -> "(" ^ show_with name a ^ " ∧ " ^ show_with name b ^ ")"| Or (a, b) -> "(" ^ show_with name a ^ " ∨ " ^ show_with name b ^ ")"let show = show_with (fun v -> String.make 1 (Char.chr (Char.code 'a' + v - 1)))
The example of the figure.
open Interp
Running it.
refutation with 7 clausesinterpolant: b
The interpolant is : implies it, it contradicts , and it is the only variable they share.
Checking the construction on random unsatisfiable pairs by brute force.
open Interp(* Random unsatisfiable pairs over variables 1-4 (A only), 5-7 (shared)and 8-11 (B only), checked by brute force over all assignments. *)let clause pool = List.init 3 (fun _ ->let v = List.nth pool (Random.int (List.length pool)) in if Random.bool () then v else -v)let sat_of cs env = List.for_all (List.exists (fun l -> if l > 0 then env l else not (env (-l)))) cs
Running it.
300 unsatisfiable pairs, 300 interpolants correct, average 8.0 literal occurrences
Model checking
Bounded model checking unrolls a transition system steps and asks a SAT solver whether a bad state is reachable within those steps; it finds errors but cannot prove their absence. McMillan observed that when the bounded check fails, the refutation contains an over-approximation of the reachable states that is still too weak to reach a bad state[3]. Split the unrolled formula into , the current approximation of the initial states and one transition, and , the remaining transitions and the bad states. The interpolant mentions only and describes a set of states that contains every successor of and from which no bad state is reachable in steps. Adding it to and repeating either reaches a fixed point, an inductive invariant that proves the property, or finds that the enlarged reaches a bad state, in which case the check is repeated with a larger .
Interpolation-based model checking of a 3-bit counter that starts at 0 and adds 2: can it reach an odd value?
open Interp(* A 3-bit counter that starts at 0 and adds 2 modulo 8. Is an odd statereachable? State bit j at time t is variable 3t + j + 1. *)let bit t j = (3 * t) + j + 1let trans t = (* state t+1 = state t + 2 *)let x j = bit t j and y j = bit (t + 1) j in[ [ -y 0; x 0 ]; [ y 0; -x 0 ]; (* bit 0 unchanged *)[ -y 1; -x 1 ]; [ y 1; x 1 ]; (* bit 1 flips *)[ -y 2; x 2; x 1 ]; [ -y 2; -x 2; -x 1 ]; [ y 2; -x 2; x 1 ]; [ y 2; x 2; -x 1 ] ] (* bit 2 ^= bit 1 *)(* A set of states over time 0, as clauses excluding every other state. *)let states_at t set =List.filter_map (fun s -> if List.mem s set then Noneelse Some (List.init 3 (fun j -> if s land (1 lsl j) <> 0 then - (bit t j) else bit t j)))(List.init 8 Fun.id)let states_of t f =List.filter (fun s -> eval (fun v -> let tt = (v - 1) / 3 and j = (v - 1) mod 3 intt = t && s land (1 lsl j) <> 0) f) (List.init 8 Fun.id)let show_set s = "{" ^ String.concat "," (List.map string_of_int s) ^ "}"(* McMillan's loop with k steps of lookahead: A is "R at time 0 and onestep", B is "k - 1 more steps and an odd state at some time 1..k". *)let check k =let rec loop r =let a = states_at 0 r @ trans 0 inlet b = List.concat (List.init (k - 1) (fun t -> trans (t + 1)))@ [ List.init k (fun t -> bit (t + 1) 0) ] inlet vars_of cs = List.sort_uniq compare (List.map abs (List.concat cs)) inmatch Resproof.refute (a @ b) with| None -> Printf.printf " R = %s reaches a bad state within %d steps\n" (show_set r) k; `Unknown| Some p ->let i = interpolant ~na:(List.length a) (vars_of a) (vars_of b) p inlet img = states_of 1 i inPrintf.printf " R = %-10s interpolant %s, the states %s\n" (show_set r)(show_with (fun v -> Printf.sprintf "s%d.bit%d" ((v - 1) / 3) ((v - 1) mod 3)) i) (show_set img);if List.for_all (fun s -> List.mem s r) img then `Safe relse loop (List.sort_uniq compare (r @ img))inloop [ 0 ]
Running it.
k = 1:R = {0} interpolant ¬s1.bit0, the states {0,2,4,6}R = {0,2,4,6} interpolant ¬s1.bit0, the states {0,2,4,6}fixed point: {0,2,4,6} is closed under a step and has no odd statek = 3:R = {0} interpolant ¬s1.bit0, the states {0,2,4,6}R = {0,2,4,6} interpolant ¬s1.bit0, the states {0,2,4,6}fixed point: {0,2,4,6} is closed under a step and has no odd state
The first interpolant is not the exact image of , which is , but the more general statement that the lowest bit is 0. That generalization is what makes the method converge: after one step, the approximation is closed under the transition and contains no odd state, so it is an invariant proving the property. Interpolants over theories, computed from SMT refutations, serve the same purpose in software model checking, where they supply the predicates for abstraction refinement[6][7].
Proof complexity
Because an interpolant can be computed from a resolution refutation as a circuit of linear size, lower bounds on circuits give lower bounds on proofs. This is feasible interpolation: Krajíček showed in 1997 that for resolution and several other proof systems, a refutation of size yields an interpolating circuit of size polynomial in , and when the shared variables occur only positively in , a monotone one[4]. Pudlák applied it to cutting planes[2]. Formulas whose interpolants must be large monotone circuits, such as those encoding the clique–colouring problem, therefore have no short refutations in these systems.
History
Craig proved the theorem for first-order logic in 1957 as a consequence of Gentzen's cut elimination[1]. Lyndon strengthened it in 1959 to preserve the polarity of predicate symbols[8], and Beth's definability theorem of 1953 follows from it[9]. Its use in proof complexity began with Krajíček and Pudlák in the 1990s[4][2], and Huang, Krajíček and Pudlák independently gave the symmetric labelling of resolution proofs[10][4][2]. McMillan's paper of 2003 made interpolation a mainstream verification technique[3], followed by interpolating SMT solvers and interpolation-based abstraction refinement for software[6][7].
see also
- ResolutionResolution is the inference rule that derives, from two clauses containing a variable with opposite signs, the clause of all their other literals: from C ∨ x and D ∨ ¬x, infer C ∨ D. It is sound and refutation complete for propositional logic, so a set of clauses is unsatisfiable exactly when the empty clause can be derived. Resolution is the proof system behind SAT solvers, whose runs on unsatisfiable formulas are resolution refutations, and behind first-order theorem provers and logic programming. Some formulas, such as the pigeonhole formulas, have only exponentially long resolution refutations.
- SATThe Boolean satisfiability problem, SAT, asks whether some assignment of true and false to the variables of a propositional formula makes the formula true. It was the first problem shown to be NP-complete, so every problem in NP reduces to it, and no polynomial-time algorithm is known. In practice SAT solvers based on conflict-driven clause learning decide industrial instances with millions of variables, which has made SAT a general-purpose engine for hardware and software verification, planning, scheduling and combinatorics.
- CDCLConflict-driven clause learning (CDCL) is the algorithm of modern SAT solvers. It extends DPLL backtracking search with three ideas: when propagation falsifies a clause, conflict analysis derives a new clause that explains the conflict and adds it to the formula; the solver then backjumps non-chronologically to the decision level at which the new clause forces a literal; and branching follows the variables involved in recent conflicts. With watched literals, restarts and clause deletion, CDCL solvers decide industrial formulas with millions of variables, and with restarts they are as strong as general resolution, exponentially stronger than DPLL.
- First-UIP conflict analysisConflict analysis is the step of a CDCL SAT solver that explains a conflict by a new clause. Starting from the clause that became false, the solver repeatedly resolves it with the reason clauses of literals assigned at the current decision level, in reverse order of assignment, until only one literal of that level remains. That literal is the first unique implication point (UIP), a node through which every path from the decision to the conflict passes in the implication graph. The resulting clause is learned; it is implied by the formula, it forbids the combination of assignments that caused the conflict, and after backjumping to the second-highest level in it, it immediately propagates the negation of the UIP.
- SMTSatisfiability modulo theories (SMT) is the problem of deciding whether a first-order formula is satisfiable when some of its symbols are interpreted by background theories, such as integer or real arithmetic, bit-vectors, arrays and uninterpreted functions. SMT solvers such as Z3 and cvc5 combine a SAT solver, which handles the Boolean structure, with specialized decision procedures for the theories, usually in the DPLL(T) architecture. They read the standard SMT-LIB language and are the reasoning engines of program verifiers, symbolic execution tools, test generators and many other analysis tools.
further reading
- [1]W. Craig, “Linear reasoning. A new form of the Herbrand–Gentzen theorem”, Journal of Symbolic Logic 22 (1957).
- [2]P. Pudlák, “Lower bounds for resolution and cutting plane proofs and monotone computations”, Journal of Symbolic Logic 62 (1997).
- [3]K. L. McMillan, “Interpolation and SAT-based model checking”, CAV (2003).
- [4]J. Krajíček, “Interpolation theorems, lower bounds for proof systems, and independence results for bounded arithmetic”, Journal of Symbolic Logic 62 (1997).
- [5]V. D'Silva, D. Kroening, M. Purandare, G. Weissenbacher, “Interpolant strength”, VMCAI (2010).
- [6]K. L. McMillan, “An interpolating theorem prover”, Theoretical Computer Science 345 (2005).
- [7]T. A. Henzinger, R. Jhala, R. Majumdar, K. L. McMillan, “Abstractions from proofs”, POPL (2004).
- [8]R. C. Lyndon, “An interpolation theorem in the predicate calculus”, Pacific Journal of Mathematics 9 (1959).
- [9]E. W. Beth, “On Padoa's method in the theory of definition”, Indagationes Mathematicae 15 (1953).
- [10]G. Huang, “Constructing Craig interpolation formulas”, COCOON, Lecture Notes in Computer Science 959 (1995).
last updated