Part IV · trunk C · constraint programming and SAT · addendum

19b

Backjumping, and why search is complete

When a dead end has nothing to do with the last choice, go back to the choice that caused it. Why a search that skips subtrees this way still misses no solution, and why it always stops.

needs 19~1½ h slidesno lab

19b · overview

The route

1 · conflict sets and backjumping

Why chronological search thrashes; frames, closed values, reasons; Prosser's jump rule, step by step.

2 · completeness

Reasons are nogoods; one invariant; why an empty conflict set means "no solution"; learned nogoods.

3 · termination

A number that drops on every step, even when a jump sends the digits below it up.

4 · choosing the variable at each level

The heuristic's contract, and why both proofs survive it; orders against CBJ, measured; a jump-target bug that tests in the input order cannot show; restarts; where the argument stops; optimization.

getting around

Words with a dotted underline are glossary terms: click one for its definition. Solid-underlined names are pieces of the running example, or of the other small instances: hover to see them. 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

Conflict sets and backjumping

Go back to the choice that caused the failure.

19b · backjumping

Thrashing, on four variables

The running example: $a, b, c, d \in \{1, 2\}$, constraints $a \ne c$, $a \ne d$, $c \ne d$. $b$ is in no constraint. Unsatisfiable: $a, c, d$ form a triangle, which needs three colours. Static order $a, b, c, d$.

Chronological backtracking undoes the most recent choice first. When the $c, d$ part fails under $a = 1, b = 1$, it tries $b = 2$ and fails in exactly the same way: $b$ played no part. That is thrashing, the same failure rediscovered under an irrelevant choice.

Conflict-directed backjumping (CBJ) sees that the failure below $b$ only blames $a$, and jumps straight back to $a$.

same failure again: b changed nothing the failure, found once a=1 b=1c=1c=2d=1d=2✗ a≠c✗ a≠d✗ c≠db=2c=1c=2d=1d=2✗ a≠c✗ a≠d✗ c≠d chronological: next b CBJ: no rejection names b, so jump to a

Chronological search under $a = 1$. Red: rejected, with the constraint that rejected it. No rejection involves $b$, so trying $b = 2$ (shaded) replays the identical failure. CBJ jumps from the exhausted $c$ frame straight back to $a$ (step 8) and never enters it. Under $a = 2$ the same happens again, mirrored.

19b · backjumping

Frames, closed values, reasons, conflict sets

the search stack

A frame is one level of the stack: the variable chosen for that depth, its candidate values in order with a cursor at the current one, and a conflict set.

A value is closed at a frame when search is finished with it while the assignments above stay put: a constraint rejected it, a learned nogood matched it, or everything below it failed and a backjump landed here.

Each closed value has a reason: the earlier variables that caused it to be closed.

The conflict set of a frame starts empty when the frame is opened, and is the union of the reasons of its closed values.

closed becausereason
rejected by a constraintthe constraint's other variables (assigned, earlier)
a deeper frame was exhausted and jumped herethat frame's conflict set, minus this frame's variable
a stored nogood matchedthe nogood's other variables
after step 6 of the CBJ run

Stack $a = 1$, $b = 1$, $c = 2$, and a frame for $d$ with both values closed: $d = 1$ by $a \ne d$, reason $\{a\}$; $d = 2$ by $c \ne d$, reason $\{c\}$. Conflict set of $d$: $\{a, c\}$.

Frame $c$: $c = 1$ closed by $a \ne c$, reason $\{a\}$; cursor on $c = 2$. Frame $b$: nothing closed, conflict set empty. $b$ appears in no reason.

19b · backjumping

The backjump rule, and the example step by step

the backjump rule (Prosser 1993)

When every value of a frame is closed (the frame is exhausted), let $E$ be its conflict set.

  • If $E$ is empty, stop: unsatisfiable.
  • Otherwise jump to the deepest frame whose variable is in $E$, discard the frames below it, merge $E$ minus that variable into its conflict set, and close its current value.

Chronological backtracking is the same loop with the jump always going to the frame just above, and stopping only when the top frame is exhausted. It differs from step 8: "$c$ exhausted, back to $b$", and then it repeats the $c, d$ failure under $b = 2$, for $a = 1$ and again for $a = 2$.

stepwhat happensreason, or $E$
1–2descend $a = 1$, $b = 1$
3reject $c = 1$ by $a \ne c$$\{a\}$
4descend $c = 2$
5reject $d = 1$ by $a \ne d$$\{a\}$
6reject $d = 2$ by $c \ne d$$\{c\}$
7$d$ exhausted: jump to $c$$E = \{a, c\}$
8$c$ exhausted: jump to $a$, skipping $b$$E = \{a\}$
9–13$a = 2$, $b = 1$, $c = 1$; $d = 1$, $d = 2$ rejected$\{c\}$, $\{a\}$
14$d$ exhausted: jump to $c$$E = \{a, c\}$
15reject $c = 2$ by $a \ne c$$\{a\}$
16$c$ exhausted: jump to $a$$E = \{a\}$
17$a$ exhausted: unsatisfiable$E = \emptyset$

All 17 steps: hover the CBJ run; compare the chronological run.

section 2

Completeness

Skipping a subtree is safe when the reason says it must fail.

19b · completeness

Reasons are nogoods, and one invariant

what a reason says

A reason $R$ for closing value $v$ of frame variable $x$, under the current assignment $A$: no solution agrees with $A$ on $R$ and has $x = v$.

Equivalently, $\{y = A(y) : y \in R\} \cup \{x = v\}$ is a nogood in unit 19's sense. That is what makes it safe to store.

the invariant

Every closed value of every frame has a valid reason that names only variables of frames above it.

the combining lemma

If every value of $x$ is closed, with reasons $R_v$, then no solution agrees with $A$ on $E = \bigcup_v R_v$.

Why: a solution gives $x$ some value $v$ of its domain, and agrees with $A$ on $R_v \subseteq E$: exactly what the reason for $v$ rules out.

So $E$ minus the jump target's variable is a valid reason for closing the target's value. Discarding the frames below the target breaks nothing: reasons mention only variables above their own frame, and those keep their values.

full proof in the notes (N)

step 7

$d = 1$ has reason $\{a\}$, $d = 2$ has $\{c\}$, so no solution has $a = 1$ and $c = 2$. Closing $c = 2$ with reason $\{a\}$ says exactly that.

19b · completeness

Why an empty conflict set means "no solution"

the stopping rule, justified

Take $E = \emptyset$ in the combining lemma: no solution agrees with $A$ on nothing, that is, there is no solution at all.

two different empty sets

A conflict set is also empty when its frame is opened, and then it claims nothing. The conclusion needs both: every value closed, and $E$ empty.

At the top frame $E$ is necessarily empty, since there are no variables above it. It can also become empty deeper, and search stops there.

unit 20's empty clause

CDCL's learned clause is the same kind of object: a nogood written as a clause. Both go back past decisions it does not mention: CBJ to the deepest variable of $E$, closing its value; CDCL further up, to the second-highest level, asserting the flipped UIP. The empty clause is $E = \emptyset$.

in the example

Step 17: $a$'s two values were closed at steps 8 and 16, each with reason $\{a\} \setminus \{a\} = \emptyset$. Every value closed, $E = \emptyset$: unsatisfiable.

Fine print. "Every value" means every value of the domain. A value propagation removed under the current assignment is closed only if its reason goes into the conflict set; if not, $E = \emptyset$ can be reported on a satisfiable problem (notes).

19b · completeness

Learned nogoods

  • A nogood store starts empty.
  • A reason written out as values is an absolute nogood: it holds whatever the rest of the assignment is. So recording it is sound.
  • A store hit is one more way to close a value, with the nogood's other variables as the reason.
  • Forgetting is safe for soundness, and for termination of a single run: a store is only a source of closings. With restarts, see section 4. Only adding needs a proof, and the reason invariant is that proof.

The invariant and the measure of section 3 do not care where a closing came from, so a store changes neither soundness nor the termination of a single run.

what the run could record

Step 7 closes $c = 2$ with reason $\{a\}$ under $a = 1$: the nogood $\{a = 1, c = 2\}$.

Step 8 closes $a = 1$ with reason $\emptyset$: the nogood $\{a = 1\}$, so $a = 1$ is in no solution.

back to unit 19: decision against reason

The decision nogood at step 7 is $\{a = 1, b = 1, c = 2\}$: every choice above. It does not fire under $b = 2$. The reason form $\{a = 1, c = 2\}$ leaves $b$ out, so it does: the difference between the two is exactly the thrashing.

section 3

Termination

One number that goes down on every step.

19b · termination

The measure

$n$ variables, $D_{\max}$ the largest domain, radix $B = D_{\max} + 2$. For depth $d < n$, $r_d$ counts the values of its frame not yet closed, the current one included, or is $\top = B - 1$ if depth $d$ has no frame.

$$\mu = \sum_{d<n} r_d \, B^{\,n-1-d}$$

The termination measure: the counts read as one number in base $B$, shallowest digit first.

the CBJ run: $n = 4$, $D_{\max} = 2$, $B = 4$
after stepdigits, depth 0 1 2 3$\mu$
start2 3 3 3191
62 2 1 0164
7, jump to $c$2 2 0 3163
8, jump to $a$1 3 3 3127
9, descend1 2 3 3111
16, jump to $a$0 3 3 363
every step lowers $\mu$

Each step lowers the shallowest digit it changes, and changes only digits below it.

  • Reject: $r_d - 1$.
  • Descend: $r_{d+1}$ from $\top$ to $|\mathrm{dom}\,x| \le D_{\max}$.
  • Jump to $j$: $r_j - 1$, and every digit below $j$ reset to $\top$.
  • Stop ends it.
$$\sum_{d>j} (B-1)\,B^{\,n-1-d} = B^{\,n-1-j} - 1 < B^{\,n-1-j}$$

Lowering digit $j$ by one outweighs anything below it.

Why $+2$: $\top$ must exceed every open frame's $r_d \le D_{\max}$, so that opening a frame is a decrease.

full proof in the notes (N)

In the table, step 8: depths 1 and 2 go up (2 → 3, 0 → 3), but depth 0 drops from 2 to 1, which outweighs them: $163 \to 127$. Digits are per depth, not per variable.

section 4

Choosing the variable at each level, and why the proofs survive it

Any variable, as long as it is a new one.

19b · variable ordering

The heuristic's contract

the contract

In dynamic variable ordering the heuristic is consulted each time a frame opens. It may read anything: the assignments so far, the conflict history, unit 19's weights, randomness. Its one obligation: return an unassigned variable whenever one exists.

what breaks it

Returning a variable already on the stack: the stack's variables stop being distinct, the depth is no longer bounded by $n$, and $\mu$ is undefined.

why neither proof looks at the choice

The measure counts values per depth. On a descend, the new frame's digit drops from $\top$ to at most $D_{\max}$, whichever variable it holds. On a jump, the digits that change sit below the one that decreases.

The invariant names variables, not depths: "above" means above on the stack as it is now.

full proof in the notes (N)

first-fail, with no propagation

Plain CBJ never shrinks a domain, so "smallest domain first" is a static order. A dynamic first-fail counts the live domain: the values still consistent with the assignments so far, computed only for choosing; the frame still opens on the full domain. dom/wdeg also reads the history, bumping the constraint that rejected a value: on the Mycielski graph (next slide) CBJ with dom/wdeg puts 10 different variables at depth 5 in one run, with dom 3. Both stop with the right answer.

19b · variable ordering

Ordering against backjumping, measured

five orders, ties by input order
  • input: as the model lists the variables.
  • max-cardinality (static): most already-ordered neighbours, ties by degree.
  • dom: smallest live domain.
  • dom/deg: live domain over the number of constraints to unassigned variables.
  • dom/wdeg: live domain over the summed weights of those constraints; weights start at 1, a rejection bumps the rejecting one.

All four instances are unsatisfiable. Every run checks $\mu$ at every step, and its answer against brute force.

stepsexampleMycielskipigeonsrandom
chron.CBJchron.CBJchron.CBJchron.CBJ
input331718881175325325468174
max-card.15151312105032532516491
dom15155685683253257264
dom/deg15156526523253256868
dom/wdeg15157006593253256868
what the numbers say

Under the input order CBJ saves 16, 713 and 294 steps on the example, the Mycielski graph and the random CSP; under dom, 0, 0 and 8. Ordering and backjumping attack the same waste: a good order leaves CBJ less to save. On the pigeons there is nothing to skip under any order.

19b · variable ordering

The jump-target pitfall

two readings of "the deepest frame whose variable is in E"

By stack position: the deepest frame on the stack whose variable is in $E$. This is the rule the proofs use.

By index: the variable of $E$ that comes last in the input order. A CBJ written to search in the input order may do this, since there index order is depth order.

the index rule under any other order

It can jump to a frame above the deepest frame in $E$. Then it merges $E$ minus the target's variable into the target's conflict set: a set naming a variable below the target, whose frame the jump discards. The invariant is broken.

trial 291, one random dynamic order

Stack $v_5, v_3, v_0, v_2, v_4, v_1$. Step 10: $v_1$ is exhausted with $E = \{v_0, v_3\}$.

  • Stack rule: jump to $v_0$, at depth 2. It finds a solution at step 30.
  • Index rule: jump to $v_3$, at depth 1, discarding $v_0$; $v_3$'s set becomes $\{v_0\}$. Step 11: $v_3$, which has one value, is exhausted. Dropping the discarded $v_0$ leaves $E = \emptyset$: "unsatisfiable".
index rule, 3 000 random CSPsinput orderrandom order
the jump looks for a discarded variable: crash0319
such variables dropped: a satisfiable instance called unsatisfiable031

A static order is not enough: under max-cardinality, static but not the input order, 159 crashes and 12 wrong answers.

19b · variable ordering

The correction: jump by stack position

the stack-position rule

Keep an array depth[$x$], set when $x$ is assigned and cleared when it is unassigned. The jump target is the frame at the largest depth[$x$] over $x \in E$.

a cheap invariant check

After each step, assert: every variable in a frame's conflict set is on the stack above that frame. On trial 291 the index rule trips it at step 10: $v_3$'s set, at depth 1, is $\{v_0\}$, and above it is only $v_5$.

the lesson

When the search follows the input order the two rules coincide, so tests that always search in index order cannot see the bug. Test with other orders, dynamic ones included, and assert the invariant.

3 000 random CSPsinput orderrandom order
index rule: the check fires0417
index rule, dropping: wrong answers031
stack rule: wrong answers00
stack rule: the check fires00

With the check on, the index rule is stopped in all 31 wrong-answer runs before it answers. It also fires on runs that crash, and on runs that break the invariant and still, by luck, answer correctly.

19b · variable ordering

Restarts with a dynamic order

assumed

Each run starts from a fresh stack; a cutoff counts steps; the instance is fixed, so $n$ and $B$ never change. Dom/wdeg's weights, and a store of nogoods written out as values, may carry over.

the restart loop ends, and is complete

A restart sends $\mu$ back up. But a run that is not cut off stops within $B^n$ steps, whatever the order. The Luby sequence (unit 19) is unbounded, so some run gets a cutoff of at least $B^n$, and that run finishes. Every answer is sound, so the loop is complete.

full proof in the notes (N)

one box per step: descend (value tried), rejected (red), jump (→ target), stoprun 1cut 4a=1b=1b=2c=1cut offrun 2cut 4a=1b=1b=2c=1cut offrun 3cut 8a=1b=1b=2c=1c=2d=1d=2→ccut offrun 4cut 4a=1c=1c=2d=1cut offrun 5cut 4a=1c=1c=2d=1cut offrun 6cut 8a=1c=1c=2d=1d=2→c→aa=2cut offrun 7cut 16a=1c=1c=2d=1d=2→c→aa=2c=1d=1d=2→cc=2→aE=∅unsatisfiable, step 15 of 16

A triangle $a, c, d$, plus $a \ne b$ and $b \ne e$, all in $\{1, 2\}$; CBJ with dom/wdeg, weights kept, Luby cutoffs times 4. Each run restarts at $\mu = 767$. From run 4 the weights make the order open $c$ after $a$, not $b$; run 7 has room for its 15 steps.

19b · scope

Where the argument stops

restarts with bounded cutoffs

If the cutoffs stay below $B^n$, no run need finish, and the last slide's argument says nothing. Termination then needs the learned nogoods: if every run adds one the store did not have and none is forgotten, there can be only finitely many runs.

dynamic backtracking (Ginsberg 1993)

Reordering the assigned variables is a different algorithm. It moves the culprit variable without erasing the assignments in between, so the per-depth counters no longer decrease. Its termination argument rests on the recorded nogoods instead.

what this deck proved, and for what

For any search that keeps a stack of frames, closes values only with valid reasons that point upwards, jumps by Prosser's rule, opens frames on unassigned variables in any order, and restarts, if at all, with unbounded cutoffs: sound in both answers, terminating, hence complete.

19b · optimization

Optimization: the bound is one more constraint

branch and bound, as one search

To minimise $f$, keep the best solution found so far, the incumbent, and its cost $U$. Treat $f < U$ as a constraint that tightens each time a solution is found.

  • All variables assigned: record the incumbent, set $U$ to its cost, and close the last value, since it now breaks $f < U$.
  • A value breaks $f < U$: close it with reason the other variables $f$ depends on, as for any constraint.
  • $E = \emptyset$ at an exhausted frame means what it always meant: no solution of the constraints, now including $f < U$. With an incumbent, it is optimal; with none, $U = +\infty$ and this is plain unsatisfiable.
why the proofs carry over

A reason found under $f < U$ says: no solution agrees with $A$ on $R$, has $x = v$ and costs less than $U$. $U$ only goes down, so that stays true under every later bound. The invariant holds, and the combining lemma with it.

Recording a solution closes a value like any rejection, so the measure of section 3 still drops on every step.

what changes

Reasons from the bound, and nogoods learned from them, are true relative to the bound, not of the problem. They are safe to keep while $U$ only decreases; not if the objective or the question changes.

19b · optimization

Optimization on three variables

the instance

$a, b, c \in \{1, 2\}$, constraint $a \ne c$, minimise $f = a + 2c$. As in the running example, $b$ is in nothing. Static order $a, b, c$.

Optimum: $a = 2$, $c = 1$, cost $4$ (the only other option, $a = 1$, $c = 2$, costs $5$).

CBJ stops after 11 steps, chronological branch and bound after 21: it tries $b = 2$ under both values of $a$, and fails on $c$ in the same way each time.

Step 5: the closing of $a = 1$ carries reason $\emptyset$ under $U = 5$. It is still true at $U = 4$: there is no solution with $a = 1$ and cost below 4 either.

a=1b=1c=1✗ a≠cc=2★ 5: U=5b=2c=1✗ a≠cc=2✗ f<5a=2b=1c=1★ 4: U=4c=2✗ a≠cb=2c=1✗ f<4c=2✗ a≠c chronological onlychronological only CBJ: E = {a} at c, jump to a

The tree chronological branch and bound visits. Green: a solution, which sets $U$ and closes its value with reason $\{a\}$. Red: rejected, by $a \ne c$ or by the bound. Once $c$ is exhausted (steps 5 and 10), CBJ jumps straight back to $a$ and never enters the shaded subtrees.

19b · scope

CBJ with a nogood store, against CDCL

the same idea

Explain each dead end by a nogood that names only the choices that caused it; go back past the choices it does not name; an empty nogood proves there is no solution. Unit 20's learned clause is such a nogood, written as a clause.

when, and what is learned

CBJ jumps only when a frame is exhausted, and what it carries up is that frame's conflict set: the union of the reasons of its closed values.

CDCL analyses every conflict at once, resolving back through the implication graph to the first UIP: one literal of the current level, the rest from earlier levels.

where it lands

CBJ goes to the deepest variable of $E$ and closes its value; the next value is a new choice.

CDCL goes to the second-deepest level of the clause, where the clause is unit and forces the flipped UIP: an implication, not a decision.

how learned nogoods are used

This deck's store is checked when a value is tried: a hit closes that value. CDCL's clauses join unit propagation, so they fix values before anything is tried, and serve as reasons in later conflict analysis.

Around that, CDCL adds propagation at every node, VSIDS, frequent restarts that keep what was learned, and LBD deletion (unit 20). Unit 21 brings the whole engine back to CP.

19b · checkpoint

Done when

checkpoint
  • You can explain, on the example, why CBJ takes 17 steps and chronological search 33.
  • You can say why $E = \emptyset$ at an exhausted frame means unsatisfiable, and at a new frame nothing.
  • You can show $\mu$ decreasing on a jump, although the digits below it go up.
  • You can state the heuristic's contract, why neither proof looks at the choice, and why Luby restarts still end.
  • You can say why a jump target by index fails under any order but the input order, and how to test for it.

Reading

Prosser, "Hybrid algorithms for the constraint satisfaction problem", Computational Intelligence 9(3), 1993.
Ginsberg, "Dynamic backtracking", JAIR 1, 1993.
Dechter, Constraint Processing, 2003, the look-back chapter.
Chen & van Beek, "Conflict-directed backjumping revisited", JAIR 14, 2001.

Next

20 SAT and CDCL: the same ideas with clauses, where the reasons come from unit propagation and the nogoods are kept.