Exercises — Module 10 (Satisfiability, §7.2.2.2)
Self-contained problems on this module's material — the empty-clause/empty-formula edge cases, soundness of the unit rule, the van der Waerden number , at-most-one encodings and their clause counts, the soundness and completeness of DPLL, and Haken's exponential lower bound for pigeonhole. You can work every one without the books: each states the problem in full, gives a hint to peek at when stuck, and a worked answer sketch to check against after you try. Computational answers here are reproduced by the code you write in the lab (or a few lines at a REPL).
Ratings follow Knuth's scale (00–50; M = needs mathematics, ▶ = especially
instructive). Where a problem mirrors a TAOCP exercise, its number is noted for
readers who own Volume 4B.
Tracking
| # | Topic | Rating | Status |
|---|---|---|---|
| 1 | Empty clause is UNSAT, empty formula is valid | 10 | ⬜ |
| 2 | The unit-clause rule preserves the set of models | 15 | ⬜ |
| 3 | ▶ : an 8-witness, and why 9 is impossible | 22 | ⬜ |
| 4 | Pairwise vs sequential at-most-one: count clauses | 20 | ⬜ |
| 5 | ▶ DPLL is sound and complete | M30 | ⬜ |
| 6 | Haken's pigeonhole lower bound: read and outline | 40 | ⬜ |
Problems
1. Empty clause is UNSAT, empty formula is valid (rating 10 · cf. 7.2.2.2–1)
Problem. In CNF, a clause is a disjunction (OR) of literals and a formula is
a conjunction (AND) of clauses. Show that the empty clause [] is
unsatisfiable (so any formula containing it is UNSAT), while the empty formula
[] (no clauses) is valid — satisfied by every assignment. Relate both to how
evaluate must behave.
Hint. A disjunction is true iff at least one disjunct is true; a conjunction is true iff every conjunct is true. Apply each definition to a collection of size zero.
Answer sketch. The empty clause is an OR over no literals; an OR is true iff
some disjunct is true, and with no disjuncts there is none, so it is false
under every assignment — unsatisfiable. Since a formula is an AND of its clauses
and an AND is false as soon as one conjunct is false, any formula containing []
is unsatisfiable; indeed deriving the empty clause is exactly how a solver
proves UNSAT. Conversely the empty formula is an AND over no clauses; an AND is
true iff every conjunct is true, and vacuously there are none to fail, so it is
true under every assignment — valid. Accordingly evaluate must require
every clause to have at least one true literal: with an empty clause present
that clause has no true literal, so evaluate returns false; with no clauses
at all the "every clause" condition holds vacuously, so evaluate returns
true. These two conventions are what the Stage 1 tests pin down.
2. The unit-clause rule preserves the set of models (rating 15 · cf. 7.2.2.2–4)
Problem. The unit rule says: if, under the current partial assignment, a clause has no true literal and exactly one unassigned literal , then must be set true. Prove that forcing true does not change the set of full satisfying assignments that extend the current partial one — so unit propagation never loses (or gains) a model. This is the soundness that makes Stage 2 safe to run before search.
Hint. Take any full assignment that (i) extends the current partial one and (ii) satisfies the whole formula. What value must give in order to satisfy the clause ?
Answer sketch. Let be any model extending the current partial assignment.
must satisfy . By hypothesis every literal of other than is
already false under the partial assignment (no true literal, and is the
only unassigned one), and extends that partial assignment, so those literals
are still false under . The only way can make true is therefore
. Hence every model extending the current partial assignment
already sets true, so adding the constraint "" removes
no models. And it obviously adds none (it only restricts). Thus the set of
extending models is unchanged. Two consequences the README relies on: if the rule
ever forces a variable both true and false along a chain, the clause that becomes
all-false is a genuine conflict (no extending model exists); and running
propagation again at the fixed point forces nothing (idempotence,
Implied([])), since every unit has already been resolved.
3. ▶ : an 8-witness, and why 9 is impossible (rating 22 · cf. 7.2.2.2–13)
Problem. is the least such that every red/blue colouring of
contains a monochromatic 3-term arithmetic progression (AP)
. Show by (a) exhibiting a colouring of
with no monochromatic 3-AP, and (b) arguing that no colouring of
avoids one. The waerden_cnf(3,3,n) formula is SAT iff .
Hint. For (a) try the period-4 pattern from the README. For (b), you do not
need to check all colourings by hand: fix the colour of (the centre)
and chase the forced consequences through the APs through , or simply appeal
to the exhaustive check your solver performs — solve(&waerden_cnf(3,3,9))
returns None.
Answer sketch. (a) Witness. The colouring
(RRBBRRBB) has no monochromatic 3-AP. There are exactly twelve 3-APs inside ; listing their colour triples: , , , , , (step ); , , , (step ); , (step ). None is or , so is colourable — hence .
(b) No 9-colouring. An exhaustive search over all colourings of
finds that every one contains a monochromatic 3-AP; equivalently
waerden_cnf(3,3,9) is UNSAT, so solve returns None. Therefore
forces a monochromatic 3-AP while does not, giving exactly —
the smallest interesting van der Waerden number, and the Stage 3 SAT/UNSAT pair
(waerden(3,3;8) SAT, waerden(3,3;9) UNSAT).
4. Pairwise vs sequential at-most-one: count clauses (rating 20 · cf. 7.2.2.2–17)
Problem. "At most one of is true" can be encoded two ways. The pairwise (binomial) encoding adds a clause for each pair and no new variables. The sequential (ladder / Sinz counter) encoding introduces auxiliary variables to stay linear. Give the exact clause count of the pairwise encoding, and compare it with the sequential encoding's variable and clause counts. Why does the difference matter at scale?
Hint. The number of pairs of items is . For the sequential counter, introduce one "carry" variable per position (bar the last) and write the three implications that propagate a used slot forward.
Answer sketch. Pairwise. One clause per unordered pair, so exactly
clauses and zero auxiliary variables. E.g. , , , and clauses — the figure the README cites for one Sudoku row.
Sequential (Sinz counter). Introduce carries ( auxiliary variables) meaning "one of is already used," with clauses , , and for each the three clauses , , . That totals clauses and new variables — both (e.g. variables, clauses).
Why it matters. Pairwise is clauses, sequential is clauses at the cost of extra variables. At lab sizes the pairwise encoding wins on simplicity (no auxiliaries, and both give the same models on the original variables), but when is large — many at-most-one constraints, each over hundreds of literals — the quadratic blow-up dominates the formula size and can be the difference between a solver finishing in a second and choking. Encoding choice is a first-class performance decision, a recurring theme of §7.2.2.2.
5. ▶ DPLL is sound and complete (rating M30 · cf. 7.2.2.2–99)
Problem. Prove that the DPLL procedure (Algorithm D: propagate to a fixed
point, report a model if all clauses are satisfied, otherwise branch on a literal
trying both and , backtracking on
conflict) is sound (any model it reports really satisfies the formula) and
complete (it reports None only when the formula is genuinely
unsatisfiable). Include termination.
Hint. Three pieces. Soundness: when does D report a model, and what has it verified? Completeness: unit propagation preserves models (Problem 2), and branching on both values of partitions the remaining search space with no gaps. Termination: what strictly decreases down every branch?
Answer sketch. Soundness. D reports a model only at a node where every
clause has a true literal under the current (then completed) assignment — i.e. it
has verified satisfaction directly, exactly as evaluate would. So a reported
model is genuine; D never reports a wrong "SAT."
Completeness. Argue that at every node, the models of the formula that extend
the current partial assignment are exactly covered by the subtree below.
Propagation (Problem 2's unit rule) only assigns logically forced literals, so
it neither adds nor removes extending models; if it reaches a conflict
(all-false clause), there is provably no extending model, and pruning that
branch loses nothing. At a branch node the two children assign
and ; every completion of the current
partial assignment sets to one value or the other, so the union of the two
subtrees covers all completions — no model can slip between them. By induction
from the leaves up, a subtree returns None only when it contains no model, and
returns a model whenever one exists in its range. At the root this says: D
returns None iff the formula is unsatisfiable, and otherwise returns a genuine
model. Crucially, on backtrack D must undo everything propagation forced after
the guess (the README's snapshot/restore), else the "covers all completions"
invariant breaks.
Termination. Each branch node fixes one previously-unassigned variable, and
propagation only ever assigns variables, never unassigns; so the number of
unassigned variables strictly decreases down every path and the recursion depth
is at most num_vars. The tree is finite, so D halts. (This is the
argument the README sketches in §5; the toy trace there finds the model
after exactly one backtrack.)
6. Haken's pigeonhole lower bound: read and outline (rating 40 · cf. 7.2.2.2–176)
Problem. The pigeonhole formula — variables = "pigeon in hole ," clauses "each pigeon sits somewhere" and "no hole is shared" for — is unsatisfiable exactly because . Haken's theorem (1985) states that every resolution refutation of has size exponential in . Outline why this implies DPLL runs in exponential time on the pigeonhole family, and sketch the structure of the lower-bound argument. (Rating 40 — this is a "read the source and reproduce the outline" exercise, not a from-scratch proof.)
Hint. First connect DPLL to resolution: the trace of a DPLL refutation can be turned into a resolution proof of comparable size, so a lower bound on all resolution proofs is a lower bound on DPLL. Then recall the two-move shape of resolution lower bounds: show any short proof must contain a "wide" clause, then count how many wide clauses a proof must contain.
Answer sketch — the outline one reconstructs.
Step 1: DPLL reasoning is resolution. A DPLL search that proves UNSAT can be read as a tree-like resolution refutation: each conflict corresponds to resolving the clauses that became all-false, and the branching structure records the resolution steps. So the size of DPLL's search is lower-bounded by the size of the smallest resolution refutation. Any statement "every resolution refutation of is huge" therefore forces DPLL to be huge on — no branching heuristic can escape it, because the bound is on the whole proof system, not one search order. This is precisely why the README says the pigeonhole family drives DPLL "to its knees" as a matter of principle, not implementation.
Step 2: the shape of Haken's argument. Lower bounds of this kind follow a width / bottleneck pattern:
- Every short refutation must contain a wide clause. Using a restriction (random or adversarial fixing of some variables) one shows that any resolution refutation of must, at some point, derive a clause mentioning a large number — order — of the variables. Intuitively the pigeonhole contradiction is "global": no small set of variables carries it, so the proof cannot stay narrow.
- Wide clauses are expensive to accumulate. A counting ("bottleneck") argument then shows a refutation must pass through exponentially many distinct such wide clauses, because each one constrains only a small fraction of the exponentially many pigeon-to-hole matchings, and covering them all requires exponentially many clauses.
Multiplying the two gives size . The takeaway grounded in the
README: is "obviously" false to a human counting argument, yet
provably hard for resolution and hence for DPLL — an unconditional lower bound
that motivates conflict-driven clause learning (CDCL, Module 14). Even CDCL does
not fully escape pigeonhole, but learned clauses let it reason in ways plain
resolution search cannot on many other families. (The lab confirms only the
qualitative face of this: solve(&pigeonhole_cnf(4,3)) and pigeonhole_cnf(5,4)
return UNSAT, and the effort grows sharply with .)
Your solutions
Use this space to log your own work — a restated problem, your approach, and how it compared with the sketch above.
Exercise N (rating RR)
Approach. Answer / proof. Compared with the sketch: what you did differently, what you missed.