Satisfiability Modulo Theories (SMT) extends SAT solving to formulas involving richer logical structures: integer and real arithmetic, arrays, bitvectors, strings, and uninterpreted functions. An SMT solver combines a CDCL-based SAT engine with specialized theory solvers (decision procedures) for each supported theory. The dominant architecture, DPLL(T), uses the SAT engine to handle the Boolean structure of the formula while delegating theory-specific reasoning to the appropriate solvers. When multiple theories appear in the same formula, the Nelson-Oppen combination method ensures that theory solvers cooperate correctly by exchanging equalities over shared variables. SMT solvers like Z3, CVC5, and MathSAT are the primary back-end engines for program verification, symbolic execution, and constraint solving.
Pure SAT solving operates on propositional formulas: variables are Boolean, and the only operations are AND, OR, NOT. But verification problems involve richer data -- integers, arrays, pointers, floating-point numbers. Encoding these directly into Boolean variables (bit-blasting) is possible but produces enormous formulas that overwhelm even the best SAT solvers. Satisfiability Modulo Theories (SMT) solves this by reasoning about formulas that mix Boolean structure with theory atoms -- predicates interpreted in specific mathematical theories. The formula `(x > 0 AND y = x + 1) OR (y < 0 AND a[i] = 3)` combines linear integer arithmetic and array theory within a Boolean structure.
The standard SMT architecture is DPLL(T), proposed by Nieuwenhuis, Oliveras, and Tinelli (2006). The idea is to reuse the powerful CDCL SAT engine for Boolean reasoning while delegating theory-specific questions to specialized theory solvers (also called decision procedures). The SAT engine treats each theory atom as an opaque Boolean variable. It makes decisions, propagates, and learns clauses exactly as in pure CDCL. Periodically (typically after each propagation fixpoint), it sends the current set of true theory literals to the theory solver, which checks whether they are jointly satisfiable in the background theory. If the theory solver detects an inconsistency, it returns a theory conflict clause -- a minimal unsatisfiable subset of the current theory literals. The SAT engine treats this as a learned clause, triggering backjumping and further search. If no conflict is found and all variables are assigned, the formula is satisfiable with a combined Boolean and theory model.
Each supported theory has its own decision procedure. Linear real arithmetic (LRA) uses the simplex algorithm. Linear integer arithmetic (LIA) extends simplex with branch-and-bound or Gomory cuts. Bitvector arithmetic (BV) can be solved by bit-blasting to SAT or through word-level reasoning. Arrays use the read-over-write axioms: `read(write(a, i, v), j) = if i = j then v else read(a, j)`. Uninterpreted functions (EUF) enforce the congruence axiom: `a = b implies f(a) = f(b)`, solved efficiently using union-find with congruence closure. When a formula involves atoms from multiple theories -- such as array accesses with integer indices and arithmetic comparisons -- the Nelson-Oppen combination method enables cooperation. Each theory solver handles its own literals independently, and they exchange equalities over shared variables until they agree or one detects a conflict. The method requires theories to be signature-disjoint (no shared function symbols beyond equality) and stably infinite (every satisfiable formula has an infinite model).
Modern SMT solvers incorporate many optimizations beyond basic DPLL(T). Theory propagation lets the theory solver proactively inform the SAT engine about implied literals, reducing unnecessary decisions. Preprocessing simplifies formulas through rewriting, Gaussian elimination on linear constraints, and symmetry breaking. Incremental solving allows pushing and popping assertions efficiently, which is critical for verification tools that issue many related queries (e.g., symbolic execution checking path conditions incrementally). Quantifier handling through E-matching and model-based quantifier instantiation (MBQI) extends SMT beyond quantifier-free decidable fragments, though without completeness guarantees.
SMT solvers are the universal back end of formal methods. Bounded model checkers (CBMC) encode programs as SMT formulas. Symbolic execution engines (KLEE, angr) query SMT solvers for path feasibility. Deductive verifiers (Boogie, Why3, Dafny) discharge verification conditions to SMT. Refinement type checkers (Liquid Haskell) send subtyping obligations to SMT. Understanding SMT solver architecture -- the DPLL(T) split, theory solver capabilities and limitations, quantifier handling boundaries -- is essential for anyone building or using formal verification tools, because the formulation of the problem for the solver often determines whether verification succeeds or times out.