Part IV · trunk C · constraint programming and SAT · branch
Propagators that explain themselves as clauses, a CDCL engine that learns from them, and a linear relaxation running alongside: the hybrid that ate the field.
needs 19, 20~1½ h slides + 2½ h lablab: uv run co lab 21
21 · overview
The order encoding; propagators that return clauses; learning from propagation.
SMT and DPLL(T); logic-based Benders.
LCG + LP relaxation + LNS portfolio, read off its log.
MIP, CP, SAT, CP-SAT: a decision table with reasons.
Words with a dotted underline are glossary terms: click one for its definition. G lists every term in the unit, N shows the notes. Optional extra: interactive figures, linked from the slides they support by a small ▸ chip; skip them freely.
section 1
Tell the SAT solver why.
21 · explanations
The order encoding: for $x \in [\ell, u]$, one Boolean (a bound literal) per threshold:
$$[x \le \ell],\ [x \le \ell + 1],\ \dots,\ [x \le u - 1]$$ $$[x \le v] \rightarrow [x \le v + 1]$$Direct $[x = v]$: good for ≠ and tables, and bad for bounds. Log (binary digits): compact, and propagation is weak. The order encoding is what makes bounds reasoning into unit propagation. It's the right choice for scheduling and arithmetic, and LCG solvers often keep both $[x \le v]$ and $[x = v]$, linked by clauses.
Tamura et al.'s Sugar (2009) showed the order encoding makes pure SAT competitive on scheduling. LCG keeps the encoding and removes the need to write out the constraints.
21 · explanations · example
$x \in \{0, 1, 2, 3\}$: three literals $[x \le 0]$, $[x \le 1]$, $[x \le 2]$, and two clauses
$\lnot[x \le 0] \lor [x \le 1], \qquad \lnot[x \le 1] \lor [x \le 2]$
| $x$ | $[x \le 0]$ | $[x \le 1]$ | $[x \le 2]$ |
|---|---|---|---|
| 0 | true | true | true |
| 1 | false | true | true |
| 2 | false | false | true |
| 3 | false | false | false |
Of the $2^3 = 8$ assignments, the two clauses allow exactly these 4: one per value.
$x \ge 2$ is $\lnot[x \le 1]$: set $[x \le 1]$ false. Unit propagation on the first clause then makes $[x \le 0]$ false too: $x \ge 1$ follows for free.
$x \le 2$ is $[x \le 2]$ itself. Both together leave only the row $x = 2$.
A domain with a hole, $x \ne 1$, is not one literal here: that is what the direct encoding's $[x = 1]$ is for.
21 · explanations
A propagator narrows a bound. LCG requires it to also return an explanation: a clause
Task $i$ surely runs during $[lst, ect)$ (latest start, earliest completion), so task $j$ can't overlap it:
$[s_i \le lst] \land [s_i \ge ect - d_i] \land [s_j \ge lst - d_j + 1] \rightarrow [s_j \ge ect]$
CDCL treats explanation clauses exactly like input clauses (an explained propagator is just a clause source): as reasons in the implication graph. Conflict analysis resolves through them, and a learned clause mixes Boolean decisions with integer bounds, in this shape:
¬[s₃ ≥ 12] ∨ ¬b₃,₇ ∨ [makespan ≥ 58]
"If operation 3 starts at 12 or later and precedes operation 7 on their machine, the makespan is at least 58." A nogood like that would take unit 17's engine an entire subtree to rediscover, every time.
Lab steps 2–3's tests decode every returned clause back to integers and check it against every feasible assignment.
21 · explanations · example
$x + 3 \le y$ with $x \in 0..3$, $y \in 0..6$.
| moment | propagation | explanation clause |
|---|---|---|
| root | $y \ge 3$ | $[y \ge 3]$ alone: true in every solution, since $x \ge 0$ |
| decide $x \ge 2$ | $y \ge 5$ | $\lnot[x \ge 2] \lor [y \ge 5]$ |
In order-encoding literals the second clause is $[x \le 1] \lor \lnot[y \le 4]$. It mentions only $x$'s bound that caused the push, not the decision's history, so it is valid forever and can be learned from.
Two tasks of length 3, starts $a, c \in 0..4$, on one machine. A Boolean $b$ picks the order: $b \Rightarrow a + 3 \le c$, and $\lnot b \Rightarrow c + 3 \le a$.
Level 1: decide $a \ge 2$. Level 2: decide $b$. The precedence needs $c \ge 5$, but $c \le 4$: its explanation $\lnot b \lor \lnot[a \ge 2]$ is all false, a conflict.
Learned: $\lnot b \lor [a \le 1]$, "if $a$ starts at 2 or later, $a$ can't go first". Backjump to level 1, where it forces $\lnot b$.
21 · explanations
Lab then, job-shop makespan, same kind of propagation in both:
| instance | unit 18 CP | LCG |
|---|---|---|
| ft06 | 55, not proven in 100 000 nodes | 55 proven, 154 conflicts |
| random 6×4 | 47, not proven | 44 proven, 94 |
| random 8×4 | no solution in 100 000 | 58 proven, 293 |
| random 8×5 | 53, not proven | 52 proven, 290 |
Ablation on ft06:
| variant | conflicts | s |
|---|---|---|
| disjunctions + explained timetable | 154 | 3.8 |
| disjunctions only | 286 | 5.2 |
| no restarts | 154 | 3.7 |
Stronger propagation halves the proof. Learning turns an unfinished search into a proof. It is not a constant factor: nogoods cut every symmetric and repeated subtree the CP search would re-enter.
section 2
A theory explains; a SAT solver learns.
21 · elsewhere
A CDCL solver over Boolean abstractions of theory atoms ($x - y \le 3$, $f(a) = b$). A theory solver checks the current atoms for consistency and returns a theory explanation (a clause) on conflict or propagation. Z3, CVC5 and Yices work this way.
LCG is DPLL(T) with CP propagators as the theory, arriving from the CP side. SMT is the same idea arriving from verification.
Unit 12's Benders with any subproblem solver: the subproblem returns an inference, a no-good or bound cut, about the master's decision. Same shape: one solver decides, another explains, and the first learns.
Decide, check, explain: decide in one representation. Check or propagate in a richer one. Hand back a certificate of why in the first representation. Units 09 (separation), 10 (pricing), 12 (Benders cuts) and 21 are all this pattern.
section 3
Every component, by name.
21 · CP-SAT
Lab then, 15×15 job-shop, 5 s, 8 workers (352 log lines):
| log section | what it is | built in |
|---|---|---|
| Presolve summary | simplification rules applied | 27 |
| subsolvers list | portfolio: default_lp, no_lp, max_lp, quick_restart, … | 19 |
| Search stats | conflicts, branches, restarts, Bool/int propagations | 17–21 |
| SAT stats | learned literals, minimisation | 20 |
| Clause deletion | learned clauses removed | 20 |
| Lp stats, Lp Cut | LP relaxation; CG, MIR, no-overlap cuts | 02–08 |
| LNS stats | graph_*, rnd_*, scheduling_* neighbourhoods | 19 |
max_lp, reduced_costs), cutting planes included, used for bounds and reduced-cost fixing (unit 11's idea).Makespan 1211 against a bound of 1162 after 5 s: not proven, which is typical for 15×15 job-shops.
section 4
Defend it with structure, not taste.
21 · choosing
| if the problem has… | reach first for | because |
|---|---|---|
| a strong LP relaxation (flows, covering, assignment with costs) | MIP | the bound does the proving (Part II) |
| big-M disjunctions, scheduling, sequencing | CP-SAT | no-overlap propagation + learning beats weak big-M LPs (units 05, 18, 21) |
| pure feasibility, Boolean structure, verification | SAT | CDCL, proofs, and preprocessing (unit 20) |
| huge instances, need good solutions not proofs | CP-SAT LNS, or a metaheuristic | unit 19; unit 26 |
| counting / cardinality at the core (pigeonhole-like) | MIP or a global constraint, not plain SAT | resolution can't count (unit 20) |
| nonlinear continuous parts | MINLP / a spatial B&B solver | outside this course's solvers |
Then measure, on several instances (unit 28). CP-SAT's portfolio is an admission that nobody can answer these questions in advance for every instance.
21 · lab
uv run co test 21
CO_MINE=20 uv run co test 21 # on your own CDCL
uv run co then 21 # learning vs not · ablation · CP-SAT's log by name
21 · checkpoint
Ohrimenko, Stuckey & Codish, Constraints 14 (2009).
Feydy & Stuckey, CP 2009.
Nieuwenhuis, Oliveras & Tinelli, JACM 53 (2006).
Perron, Didier & Gay, "The CP-SAT-LP solver", CP 2023.
Part V: 22 hardness and what's possible · 23 approximation · 26 metaheuristics.