\(%\usepackage{color}\) \(%\usepackage{tcolorbox}\) \(%\tcbuselibrary{skins}\) \(\usepackage{pifont}\) \(\) \(%\definecolor{aaltoblue}{RGB}{00,101,189} % 0065BD\) \(%\definecolor{aaltored}{RGB}{237,41,57} % ED2939\) \(\) \(\definecolor{MyBoxBackground}{rgb}{0.98,0.98,1.0}\) \(\definecolor{MyBoxBorder}{rgb}{0.90,0.90,1.0}\) \(%\definecolor{backgroundred}{rgb}{1.0,0.98,0.98}\) \(%\definecolor{shadowred}{rgb}{1.0,0.90,0.90}\) \(\) \(%\newcommand{\subheading}[1]{\textbf{\large\color{fakeaaltobluel}#1}}\) \(\newcommand{\subheading}[1]{\large{\usebeamercolor[fg]{frametitle}\sc #1}}\) \(\) \(\newcommand{\AAccess}[1]{{\footnotesize[\href{https://libproxy.aalto.fi/login?url=#1}{Aalto lib access}]}}\) \(%\newtcbox{\mybox}[1][red]{on line,arc=0pt,outer arc=0pt,colback=#1!10!white,colframe=#1!50!black,boxsep=0pt,left=1pt,right=1pt,top=2pt,bottom=2pt,boxrule=0pt,bottomrule=1pt,toprule=1pt}\) \(%\newtcbox{\mybox}[1][MyBoxBackground]{on line,arc=0pt,outer arc=0pt,colback=#1!10!white,colframe=#1!50!black,boxsep=0pt,left=1pt,right=1pt,top=2pt,bottom=2pt,boxrule=0pt,bottomrule=1pt,toprule=1pt}\) \(\) \(\newtcolorbox{MyBoxTitled}[1]{colback=MyBoxBackground!100!black,colframe=MyBoxBorder!100!black,boxsep=2pt,left=0pt,right=0pt,top=2pt,bottom=0pt,%enhanced,%\) \( coltitle=red!25!black,title=#1,boxrule=1pt}\) \(\) \(\newtcolorbox{MyBox}[1][]{colback=MyBoxBackground!100!black,colframe=MyBoxBorder!100!black,boxsep=0pt,left=2pt,right=0pt,top=0pt,bottom=0pt,%enhanced,%\) \( coltitle=red!25!black,boxrule=1pt,#1}\) \(\) \(\newenvironment{EqnBox}[1]{\begin{adjustbox}{valign=t}\begin{minipage}{#1}\begin{MyBox}[colback=italyGreen!10!white,colframe=italyGreen!100!black]}{\end{MyBox}\end{minipage}\end{adjustbox}}\) \(\) \(\newenvironment{topbox}[1]{\begin{adjustbox}{valign=t}\begin{minipage}{#1}}{\end{minipage}\end{adjustbox}}\) \(\) \(\newcommand{\Blue}[1]{{\color{finnishBlue}#1}}\) \(\newcommand{\Red}[1]{{\color{italyRed}#1}}\) \(%\newcommand{\Emph}[1]{\emph{\color{aaltoblue}#1}}\) \(\newcommand{\Emph}[1]{\emph{\usebeamercolor[fg]{structure} #1}}\) \(%\newcommand{\Emp}{\usebeamercolor[fg]{structure}}\) \(\newcommand{\Emp}{\color{italyRed}}\) \(\newcommand{\TextDef}[1]{{\bf\usebeamercolor[fg]{structure} #1}}\) \(\) \(\newcommand{\todo}[1]{\textbf{\Red{\Pointer #1}}}\) \(\newcommand{\TODO}[1]{\todo{#1}}\) \(\) \(\newcommand{\Pointer}{\raisebox{-1ex}{\huge\ding{43}}\ }\) \(\) \(%\newcommand{\Follows}{\Pointer}\) \(\newcommand{\Follows}{\color{finnishBlue}\rightsquigarrow}\) \(\newcommand{\Property}{{\color{italyGreen}\bf Property}}\) \(\) \(\) \(%\) \(% Common math definitions\) \(%\) \(\newcommand{\Set}[1]{\{#1\}}\) \(\newcommand{\Setdef}[2]{\{{#1}\mid{#2}\}}\) \(\newcommand{\PSet}[1]{\mathcal{P}(#1)}\) \(\newcommand{\Pair}[2]{(#1,#2)}\) \(\newcommand{\Card}[1]{{\vert{#1}\vert}}\) \(\newcommand{\Tuple}[1]{(#1)}\) \(\newcommand{\Seq}[1]{[#1]}\) \(\newcommand{\bbZ}{\mathbb{Z}}\) \(\newcommand{\Ints}{\mathbb{Z}}\) \(\newcommand{\Reals}{\mathbb{R}}\) \(\newcommand{\bbQ}{\mathbb{Q}}\) \(\newcommand{\Rats}{\bbQ}\) \(\) \(\newcommand{\False}{\textsf{F}}\) \(\newcommand{\True}{\textsf{T}}\) \(\) \(\newcommand{\Implies}{\rightarrow}\) \(\newcommand{\Iff}{\leftrightarrow}\) \(%\newcommand{\Implies}{\Rightarrow}\) \(%\newcommand{\Iff}{\Leftrightarrow}\) \(\newcommand{\Xor}{\oplus}\) \(\) \(\newcommand{\Equiv}{\equiv}\) \(\) \(\newcommand{\Oh}[1]{O(#1)}\) \(%\newcommand{\Theta}[1]{\Theta(#1)}\) \(\) \(\newcommand{\PHP}[2]{\mathrm{php}_{#1,#2}}\) \(\newcommand{\PH}[2]{\mathit{x}_{#1,#2}}\) \(\) \(\newcommand{\NP}{\textbf{NP}}\) \(\newcommand{\coNP}{\textbf{co-NP}}\) \(\) \(\newcommand{\bnfdef}{\mathrel{\textup{::=}}}\) \(\newcommand{\bnfor}{\mathrel{\mid}}\) \(\)
\(\newcommand{\Vars}{X}\) \(\newcommand{\VarsOf}[1]{\mathop{vars}(#1)}\) \(\) \(\newcommand{\Bool}{\Bbb{B}}\) \(\) \(\newcommand{\FF}{\bot} % Formula "False"\) \(\newcommand{\TF}{\top} % Formula "True"\) \(%\newcommand{\FF}{\mathbf{F}} % Formula "True"\) \(%\newcommand{\TF}{\mathbf{T}} % Formula "False"\) \(\) \(\newcommand{\LHS}{\alpha}\) \(\newcommand{\RHS}{\beta}\) \(\newcommand{\EHS}{\gamma}\) \(\) \(\newcommand{\Res}[2]{{#1} \otimes {#2}}\) \(\) \(\newcommand{\Gates}{{\mathcal G}}\) \(\newcommand{\Eqns}{{\mathcal D}}\) \(\newcommand{\Circuit}{{\mathcal C}}\) \(\newcommand{\GDef}{\mathrel{\mathrm{:=}}}\) \(\newcommand{\Gate}{g}\) \(\newcommand{\GateL}{g'}\) \(\newcommand{\GateR}{g''}\) \(\newcommand{\GateVar}[1]{v_{#1}}\) \(\newcommand{\ORf}{\mathbf{or}}\) \(\newcommand{\ANDf}{\mathbf{and}}\) \(\newcommand{\NOTf}{\mathbf{not}}\) \(\newcommand{\OR}[1]{\mathbf{or}(#1)}\) \(\newcommand{\AND}[1]{\mathbf{and}(#1)}\) \(\newcommand{\NOT}[1]{\mathbf{not}(#1)}\) \(\newcommand{\FG}{\mathbf{f}} % Input gate "False"\) \(\newcommand{\TG}{\mathbf{t}} % Input gate "True"\) \(\newcommand{\Tseitin}[1]{\mathop{\textrm{cnf}}(#1)}\) \(\newcommand{\Trans}{\mathrel{\rightsquigarrow}}\) \(\) \(\newcommand{\SUD}[3]{x_{#1,#2,#3}}\) \(\newcommand{\SUDClues}{H}\) \(\) \(\newcommand{\PseudoDPLL}{\mathop{\mathit{dpll}}}\) \(\newcommand{\PseudoAsgn}{\mathrel{\leftarrow}}\) \(\newcommand{\PseudoUnsat}{\mathbf{unsat}}\) \(\newcommand{\PseudoSat}{\mathbf{sat}}\) \(\newcommand{\TA}{\tau}\) \(\newcommand{\Undef}{\mathit{undef}}\) \(%\newcommand{\PseudoPropagate}{\textit{propagate}}\)
\(\newcommand{\Asgn}{\leftarrow}\) \(\newcommand{\PseudoDPLL}{\mathop{\textrm{DPLL}}}\) \(\newcommand{\PseudoCDCL}{\mathop{\textrm{CDCL}}}\) \(\newcommand{\PseudoAsgn}{\mathrel{\leftarrow}}\) \(\newcommand{\PseudoUnsat}{\mathbf{unsat}}\) \(\newcommand{\PseudoSat}{\mathbf{sat}}\) \(\newcommand{\PseudoUP}{\mathop{\textit{unit-propagate}}}\) \(\newcommand{\PseudoAnalyze}{\mathop{\textit{analyze-conflict}}}\) \(\) \(%\newcommand{\Neg}[1]{\overline{#1}}\) \(\newcommand{\Neg}[1]{\neg #1}\) \(\newcommand{\Vars}{X}\) \(\newcommand{\VarsOf}[1]{\mathop{vars}(#1)}\) \(\) \(\newcommand{\TA}{\tau}\) \(\newcommand{\Undef}{\mathit{undef}}\) \(\) \(%\newcommand{\Form}{\phi}\) \(\newcommand{\Models}{\models}\) \(\) \(\newcommand{\Trail}{\pi}\) \(\newcommand{\Anno}[2]{#1^{#2}}\) \(\newcommand{\Lit}{l}\) \(\newcommand{\Reason}{r}\) \(\newcommand{\Dec}{\textsf{dec}}\) \(\) \(\newcommand{\IG}[1]{G_{#1}}\) \(\newcommand{\IGVerts}{V}\) \(\newcommand{\IGEdges}{E}\) \(\newcommand{\IGEdge}[2]{\Pair{#1}{#2}}\) \(\newcommand{\IGConflict}{\bot}\) \(\newcommand{\Cut}{W}\) \(\) \(\newcommand{\ResOp}[1]{\mathrel{\otimes_{#1}}}\) \(\newcommand{\Res}[3]{#1 \ResOp{#3} #2}\)

SAT Solvers for CNF Formulas: common preliminaries

Recall that a SAT solver is an algorithm/tool that takes as input a propositional formula and then finds out whether the formula is satisfiable or not.


After providing some common preliminary definitions below, we will learn the fundamentals of how most modern SAT solvers work:

  1. In the section The DPLL backtracking search procedure, we review the classic, basic DPLL search procedure for solving satisfiability.

  2. In Conflict-driven clause learning (CDCL) SAT solvers, we see how that basic search procedure is extended with a reasoning technique that allows learning from mistakes.

  3. In the section Preprocessing, we see some basic techniques for simplifying the formula before the search phase.

  4. Finally, in the section The resolution proof system we introduce the classic method for producing machine-verifiable proofs of unsatisfiability.

Observe that we will omit several crucial parts needed to make SAT solvers to really work in practise. Some links to extra material explaining these aspects are provided in the relevant sections.

Partial truth assignments

The DPLL and CDCL search procedures for SAT both try to build a satisfying truth assignment incrementally, heuristically extending a truth assignment for some subset of the variables to a larger subset. This is continued until a satisfying truth assignment is found or some clause is falsified. In the former case, the search ends in the verdict “the formula is satisfiable”. In the latter case, the algorithms backtrack by removing some parts of the assignment and then continue the search with different assignment values. We next introduce some notation and definitions used in expressing such search procedures.

  1. Given a CNF formula \(\phi\) over a set \(\VarsOf{\phi}\) variables, a partial truth assignment for it is a function \(\TA : X \to \Set{\False,\True}\) for some subset \(X \subseteq \VarsOf{\phi}\).

    If \(y \notin X\), then the value of \(y\) is undefined in \(\TA : X \to \Set{\False,\True}\).

    As earlier, for a negation \(\Neg{x}\) of a variable \(x \in X\), \(\TA(\Neg{x}) = \False\) when \(\TA(x) = \True\) and \(\TA(\Neg{x}) = \True\) when \(\TA(x) = \False\).

  2. For convenience, we often see a partial truth assignment \(\TA\) as the set of literals

    \[\Setdef{x}{x \in X\text{ and }\TA(x) = \True} \cup \Setdef{\Neg{x}}{x \in X\text{ and }\TA(x) = \False}\]

    Observe that such a set can never contain a variable and its negation. Using this set notation for truth assignments, one can use the standard set operations to build new truth assignments.

  3. A clause \((l_1 \lor ... \lor l_k)\) is

    • satisfied by \(\TA\) if \(\TA(l_i) = \True\) for at least one \(i \in [1..k]\)

    • falsified by \(\TA\) if \(\TA(l_i) = \False\) for all \(i \in [1..k]\)

  4. A CNF formula \(\phi\) is satisfied by \(\TA\) if \(\TA\) satisfies all the clauses in \(\phi\).


  • ​ A partial truth assignment \(\TA = \Set{a \mapsto\False, d \mapsto\True, e\mapsto\False}\)

  • ​ In the set-of-literals notation: \(\TA = \Set{\Neg{a},d,\Neg{e}}\)

  • ​ The value of \(b\) is undefined in \(\TA\)

  • ​ The clause \((b \lor \Neg{c} \lor d)\) is satisfied by \(\TA\)

  • ​ The clause \((a \lor \Neg{d})\) is falsified by \(\TA\)

  • ​ The clause \((a \lor \Neg{b} \lor c)\) is neither satisfied nor falsified by \(\TA\)

  • \(\TA \cup \Set{\Neg{b}}\) means the truth assignment \(\Set{a \mapsto\False, b\mapsto\False, d \mapsto\True, e\mapsto\False}\)

Unit clause propagation

The DPLL and CDCL search procedures are always incorporated with a constraint propagation technique called “unit clause propagation” (or “unit propagation” for short). In general, “constraint propagation” means that we study the constraints (clauses in this case) under the current partial solution candidate (partial truth assignment in this case) and try to deduce new facts that help in pruning the search space.

Assume a CNF formula \(\phi\) and a partial truth assignment \(\TA\). A clause \(C =(l_1 \lor ... \lor l_k)\) in \(\phi\) is a unit clause under \(\TA\) (or simply unit) if \(\TA\) evaluates all the literals in it to false except for one literal whose value is undefined in \(\TA\). Formally, \(C\) is unit if

  • \(\TA(l_j)\) is undefined for some \(j \in [1 .. k]\), and

  • \(\TA(l_i) = \False\) for all \(i \in [1..k]\) with \(i \neq j\).

In such a case, we say that \(l_j\) is implied by \(C\) and \(\TA\) and may extend \(\TA\) to \(\TA \cup \Set{l_j}\). This step is called a unit clause propagation step and it preserves all the satisfying truth assignments: if there is a satisfying truth assignment that is an extension of \(\TA\), then it is also an extension of \(\TA \cup \Set{l_j}\). The reason for this is simple: extending \(\TA\) with \(\neg l_j\) would make the clause \(C\) falsified and thus \(\TA \cup \Set{\neg l_j}\) cannot be extended to any satisfying truth assignment.


Consider the CNF formula \((a \lor \neg b) \land (a \lor c \lor \neg d) \land (\neg c \lor \neg e) \land (\neg c \lor e) \land (c \lor d)\).

  • ​ In the truth assignment \(\TA = \Set{\neg a}\), the clause \((a \lor \neg b)\) is unit and we can extend \(\TA\) to \(\Set{\neg a, \neg b}\).

  • ​ On \(\TA = \Set{\neg a,\neg b,\neg c}\), the clause \((a \lor c \lor \neg d)\) is unit and we can extend \(\TA\) to \(\Set{\neg a, \neg b,\neg c,\neg d}\). Now the clause \((c \lor d)\) is falsified.

Observe that a single unit propagation step can

  • ​ make some other clause falsified, or

  • ​ make some other clauses unit so that further unit propgation is possible.

The unit clause propagation (or simply unit propagation) is the process of applying unit clause propagation steps until (i) a clause becomes falsified, or (ii) there are no unit clauses. Given a CNF formula \(\phi\) and a partial truth assignment \(\TA\), we use \(\PseudoUP(\phi, \TA)\) to denote a partial truth assignment produced by applying the unit propagation process on \(\TA\). Observe that \(\PseudoUP(\phi, \TA)\) is (i) uniquely defined when the resulting truth assignment does not falsify any clauses but (ii) can have different outcomes when the resulting truth assignments falsify some clauses because the propagation order between different unit clauses is not defined and we stop propagation when a clause becomes falsified.


Consider a CNF formula

\[\phi = (a \lor b) \land (a \lor \Neg{b} \lor \Neg{c}) \land (\Neg{b} \lor c) \land {}...\]

Let us apply unit propagation on the partial truth assignment \(\TA = \Set{\Neg{a}}\).

  • ​ First, \(b\) is implied by \((a \lor b)\) and we set \(\TA = \Set{\Neg{a}, b}\).

  • ​ Now \(\Neg{c}\) is implied by \((a \lor \Neg{b} \lor \Neg{c})\) and we set \(\TA = \Set{\Neg{a}, b, \Neg{c}}\).

  • ​ But now \(\TA\) falsifies the clause \((\Neg{b} \lor c)\) and the propagation stops.