Theory solver
A theory solver is the component of an SMT solver that understands one background theory[1][2]. The Boolean search of DPLL(T) treats every theory atom, such as or , as an opaque propositional variable, and relies on the theory solver to tell it which combinations of truth values make sense. For this the theory solver needs only to decide conjunctions of literals, which is often far easier than deciding arbitrary formulas: a conjunction of difference constraints is a shortest-path problem, and a conjunction of equalities is congruence closure. The search asserts literals as it assigns them, asks whether they are consistent, and retracts them when it backtracks. When they are inconsistent, the theory solver returns an explanation, a subset of the asserted literals that is already inconsistent, and its negation becomes a clause that the search learns, a theory lemma. A theory solver can also report literals that the asserted ones imply, theory propagation, saving the search from guessing them[5].
The interface
The exact interface differs between solvers, but the operations are the same[1][2]:
Assert adds a literal to the theory solver's set. Check decides whether the set is consistent; solvers often distinguish a cheap partial check, run after every propagation, from a complete final check, run when the Boolean assignment is total. Explain returns, for a conflict or a propagated literal, the asserted literals that justify it. Backtrack returns to the state at an earlier decision level. Model produces values for the theory's variables when the final check succeeds, and in combinations of theories the solver must also report equalities between shared variables that it entails[8][10].
The theory interface used by a small DPLL(T) implementation: the theory receives the assigned atoms and returns a model or an explanation.
(* DPLL(T): a DPLL search over Boolean atoms that consults a theorysolver whenever unit propagation reaches a fixed point. Literals arenon-zero integers: i stands for atoms.(i-1), -i for its negation. Thetheory accepts the assigned atoms or explains a conflict by a subset ofthem, whose negation is learned as a clause (a theory lemma). *)module type THEORY = sigtype atomtype modelval check : (atom * bool) list -> (model, (atom * bool) list) resultend
Explanations
An explanation is correct if it is inconsistent on its own; it is useful if it is small. The learned clause contains one literal per element of the explanation, and a short clause rules out every assignment that contains the same few literals, whereas a long one rules out little more than the current assignment. Minimal explanations, from which no literal can be dropped, are ideal but not always cheap to compute. For difference logic, a negative cycle in the constraint graph is a natural explanation[5]; for congruence closure, the equations along the proof of the violated equality[4]; for linear arithmetic, the rows of the simplex tableau that witness infeasibility[3].
A job-shop instance solved at its optimal makespan and one below, with three difference-logic theory solvers: one that explains conflicts by a negative cycle, one that blames every asserted literal, and the first with theory propagation.
(* The same DPLL(T) search with three difference-logic theory solvers:one that explains a conflict by its negative cycle, one that blamesevery asserted literal, and the first with theory propagation. *)module Cycle = Dpllt.Make (Dl.Theory)module Blame_all = Dpllt.Make (structinclude Dl.Theorylet check lits = match Dl.Theory.check lits with Ok m -> Ok m | Error _ -> Error litsend)
Decisions, learned theory lemmas and theory checks.
makespan theory solver result decisions lemmas checks32 cycle explanation feasible 55 30 8732 blame everything feasible 55 30 8732 cycle + propagation feasible 8 0 135831 cycle explanation no 161 75 23631 blame everything no 2633 2634 526731 cycle + propagation no 3 4 1626
When a schedule exists, the first two solvers behave alike, since the search finds it before explanations matter. When none exists, blaming every literal makes the search enumerate far more assignments, 2,633 decisions against 161, because each lemma excludes only the exact assignment that failed. Theory propagation nearly removes the search, at the price of many more theory checks, because the implementation here finds implied atoms by trial; real solvers compute them directly from their data structures, for instance from shortest paths in the constraint graph[5].
Incrementality and backtracking
The SAT search asserts one literal at a time and backtracks often, so a theory solver that starts from scratch at every check wastes most of its work. Practical solvers keep their state between calls and update it for each new literal: a congruence-closure solver merges two classes, a difference-logic solver repairs the potential function around one new edge, and a simplex-based solver adjusts the bounds of one variable and pivots only if needed[3]. Backtracking must restore the state of an earlier level cheaply; solvers keep a trail of changes and undo them in reverse, or, like the simplex solver of Dutertre and de Moura, arrange that backtracking only relaxes bounds and never needs to undo pivots[3].
Common theories
The theories most used in practice have well-understood solvers[2][9]. Equality with uninterpreted functions uses congruence closure[4]. Linear real arithmetic uses a variant of the simplex method specialized for incremental bound changes[3]; linear integer arithmetic adds branch-and-bound and cutting planes on top of it. Difference logic uses graph algorithms. Fixed-width bit-vectors are usually handled by bit-blasting into propositional clauses. Arrays are handled by instantiating their read-over-write axioms lazily, as lemmas when a candidate model violates them. Z3 and cvc5 provide dozens of such solvers[6].
History
Decision procedures for conjunctions of literals in particular theories predate SMT; Nelson and Oppen's combination method of 1979 already assumed theory solvers that report entailed equalities[8]. The modern interface took shape with DPLL(T), presented by Ganzinger, Hagen, Nieuwenhuis, Oliveras and Tinelli in 2004[7] and formalized by Nieuwenhuis, Oliveras and Tinelli in 2006[1], which separated a generic DPLL engine from theory solvers that assert, check, explain and backtrack. Exhaustive theory propagation for difference logic[5], proof-producing congruence closure[4] and the incremental simplex of Dutertre and de Moura[3] followed, and model-based theory combination replaced eager equality propagation in Z3[10][6].
see also
- DPLL(T)DPLL(T) is the architecture of lazy SMT solvers: a CDCL SAT solver searches over the Boolean structure of a formula, treating each theory atom as a propositional variable, and a theory solver for T checks the consistency of the atoms it assigns. When the theory solver finds the assigned literals inconsistent, it returns an explanation, whose negation the SAT solver learns as a clause before backjumping; it may also propagate literals the assignment implies. The approach separates a generic engine from pluggable theory solvers and is used by nearly all SMT solvers, including Z3, cvc5 and Yices.
- 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.
- Difference logicDifference logic is the fragment of linear arithmetic whose atoms bound the difference of two variables by a constant, x − y ≤ c, over the integers or the reals. A conjunction of such constraints is satisfiable exactly when the graph with an edge from y to x of weight c for each constraint has no negative cycle, so it can be decided by shortest-path algorithms such as Bellman–Ford, and a negative cycle is a short explanation of unsatisfiability. Boolean combinations of difference constraints are handled by SMT solvers through DPLL(T); they express scheduling problems and the timing constraints of timed automata.
- Congruence closureCongruence closure is the algorithm that decides whether an equation between terms follows from a set of ground equations, using only the laws of equality and the congruence rule that equal arguments give equal function applications. It maintains equivalence classes of subterms in a union–find structure and, whenever two classes merge, merges any applications of the same function whose arguments have become equal. It runs in O(n log n) time and decides the quantifier-free theory of equality with uninterpreted functions (EUF), which makes it a core theory solver in SMT; the same data structure, the e-graph, underlies equality saturation in compilers.
- Nelson–Oppen combinationThe Nelson–Oppen method decides satisfiability of quantifier-free formulas that mix several theories with disjoint signatures, such as linear arithmetic and uninterpreted functions, using only a decision procedure for each theory. The formula is first purified, by naming mixed subterms with fresh variables, so that every literal belongs to one theory; the theory solvers then agree on which of their shared variables are equal, either by propagating the equalities each entails (enough for convex theories) or by searching over all arrangements of the shared variables. It is complete for theories that are stably infinite, and it is how SMT solvers combine their theory solvers.
- Fourier–Motzkin eliminationFourier–Motzkin elimination removes a variable from a system of linear inequalities by combining every inequality that bounds the variable from below with every inequality that bounds it from above. The result has a solution exactly when the original system does, over the real or rational numbers, and describes the projection of the solution set. Eliminating all variables decides satisfiability, and back-substitution recovers a solution, but the number of inequalities can grow doubly exponentially.
- Refinement typeA refinement type is a base type paired with a logical predicate that its values must satisfy, such as {v : Int | v > 0}, the positive integers. Type checking generates verification conditions, implications between predicates, and discharges them with an SMT solver, so a program can be checked against preconditions, postconditions and invariants without the programmer writing proof terms. The predicates are restricted to a decidable logic, typically linear arithmetic with uninterpreted functions, which is what keeps checking automatic. LiquidHaskell, F* and Liquid Types are the best-known systems.
- Simplex methodThe simplex method solves linear programs, maximizing a linear function subject to linear inequalities, by walking along the edges of the feasible polyhedron from vertex to vertex, each step improving the objective, until no neighbouring vertex is better. Each step is a pivot on a tableau. It is fast in practice and in smoothed analysis, but takes exponential time on the Klee-Minty cubes with Dantzig's pivoting rule, and needs a rule such as Bland's to avoid cycling on degenerate problems. Its final tableau also gives a solution of the dual program, certifying optimality.
referenced by
further reading
- [1]R. Nieuwenhuis, A. Oliveras, C. Tinelli, “Solving SAT and SAT Modulo Theories: from an abstract Davis–Putnam–Logemann–Loveland procedure to DPLL(T)”, Journal of the ACM 53 (2006).
- [2]C. Barrett, R. Sebastiani, S. A. Seshia, C. Tinelli, “Satisfiability modulo theories”, in A. Biere et al. (eds.), Handbook of Satisfiability, IOS Press (2nd ed., 2021).
- [3]B. Dutertre, L. de Moura, “A fast linear-arithmetic solver for DPLL(T)”, CAV (2006).
- [4]R. Nieuwenhuis, A. Oliveras, “Fast congruence closure and extensions”, Information and Computation 205 (2007).
- [5]R. Nieuwenhuis, A. Oliveras, “DPLL(T) with exhaustive theory propagation and its application to difference logic”, CAV (2005).
- [6]L. de Moura, N. Bjørner, “Z3: an efficient SMT solver”, TACAS (2008).
- [7]H. Ganzinger, G. Hagen, R. Nieuwenhuis, A. Oliveras, C. Tinelli, “DPLL(T): fast decision procedures”, CAV (2004).
- [8]G. Nelson, D. C. Oppen, “Simplification by cooperating decision procedures”, ACM Transactions on Programming Languages and Systems 1 (1979).
- [9]D. Kroening, O. Strichman, Decision Procedures: An Algorithmic Point of View, Springer (2nd ed., 2016).
- [10]L. de Moura, N. Bjørner, “Model-based theory combination”, Electronic Notes in Theoretical Computer Science 198 (2008).
last updated