Problem Solving with Constraints CSCE496/896, Fall2011: www.cse.unl.edu/~choueiry/F11496896 Berthe Y. Choueiry (Shuweri) Avery Hall, Room 360 [email protected] Intelligent Backtracking Algorithms. Reading. Required reading  PowerPoint PPT Presentation
Text of Problem Solving with Constraints CSCE496/896, Fall2011: cse.unl/~choueiry/F11496896
PowerPoint PresentationHybrid Algorithms for the Constraint
Satisfaction Problem [Prosser, CI 93]
Recommended reading
Tsang, Chapter 5
Available upon request
Problem Solving with Constraints
Hybrid backtracking algorithms
Hybrid backtracking algorithms
Problem Solving with Constraints
Backtracking:
Etc.
Problem Solving with Constraints
Theoretical: Kondrak & Van Beek 95
BT
BJ
CBJ
BM
BMJ
BMCBJ
FC
FCBJ
FCCBJ
Variables: Vi, i in [1, n]
Domain: Di = {vi1, vi2, …,viMi}
Constraint between Vi and Vj: Ci,j
Constraint graph: G
Language primitives: list, push, pushnew, remove, setdifference,
union, maxlist
Problem Solving with Constraints
v[i] gives the value assigned to ith variable
v[0]: pseudo variable (root of tree), backtracking to v[0]
indicates insolvability
domain[i]: a (1xn) array to store the original domains of
variables
currentdomain[i]: a (1xn) array to store the current domains of
variables
Upon backtracking, currentdomain[i] of future variables must be
refreshed
check(i,j): a function that checks whether the values assigned to
v[i] and v[j] are consistent
Problem Solving with Constraints
If i > n
Then status “solution”
End
End
Problem Solving with Constraints
btlabel:
When v[i] is assigned a value from currentdomain[i], we perform
backchecking against past variables (check(i,k))
If backchecking succeeds, btlabel returns i+1
If backchecking fails, we remove the assigned value from
currentdomain[i], assign the next value in currentdomain[i],
etc.
If no other value exists, consistent nil (btunlabel will be
called)
btunlabel
Current level is set to i1 (notation for current variable:
v[h])
For all future variables j: currentdomain[j] domain[j]
If domain[h] is not empty, consistent true (btlabel will be
called)
Note: for all past variables g, currentdomain[g] domain[g]
Problem Solving with Constraints
consistent false
For v[i] each element of currentdomain[i] while not
consistent
Do Begin
consistent true
Do consistent check(i,h)
If not consistent
End
END
Terminates:
consistent=false, currentdomain[i]=nil, returns i
Problem Solving with Constraints
consistent currentdomain[h] nil
Selects vh to backtrack to
(Uninstantiates all variables between vh and vi)
Uninstantiates v[h]: removes v[h] from currentdomain [h]:
Sets consistent to true if currentdomain[h] 0
Returns h
{1,2,3,4,5}
{1,2,3,4,5}
{1,2,3,4,5}
{1,2,3,4,5}
{1,2,3,4,5}
V2
V1
V3
V4
V5

Hybrid backtracking algorithms
Problem Solving with Constraints
Danger of BT: thrashing
BT assumes that the instantiation of v[i] was prevented by a bad
choice at (i1).
It tries to change the assignment of v[i1]
When this assumption is wrong, we suffer from thrashing (exploring
‘barren’ parts of solution space)
Backjumping (BT) tries to avoid that
Jumps to the reason of failure
Then proceeds as BT
Problem Solving with Constraints
Tries to reduce thrashing by saving some backtracking effort
When v[i] is instantiated, BJ remembers v[h], the deepest node of
past variables that v[i] has checked against.
Uses: maxcheck[i], global, initialized to 0
At level i, when check(i,h) succeeds
maxcheck[i] max(maxcheck[i], h)
If currentdomain[h] is getting empty, simple chronological
backtracking is performed from h
BJ jumps then steps!
bjunlabel, same as btunlabel but
Backtracks to h = maxcheck[i]
Resets maxcheck[j] 0 for j in [h+1,i]
Important: maxcheck is the deepest level we checked against, could
have been success or could have been failure
1
2
3
0
2
3
1
i
h1
h1
h
h
h2
0
0
0
V4=3, succeeds
V5=3, fails for V1
V5=4, fails for V1
V5=5, fails for V1
{1,2,3,4,5}
{1,2,3,4,5}
{1,2,3,4,5}
{1,2,3,4,5}
{1,2,3,4,5}
V2
V1
V3
V4
V5
jumps from v[i] to v[h],
but then, it steps back from v[h] to v[h1]
CBJ improves on BJ
Jumps from v[i] to v[h]
And jumps back again, across conflicts involving both v[i] and
v[h]
To maintain completeness, we jump back to the level of deepest
conflict
Backtracking
confset[i] are first initialized to {0}
At any point, confset[i] is a subset of past variables that are in
conflict with i
{0}
{0}
{0}
{0}
{0}
{0}
When currentdomain[i] empty
h in confset[i]
Primitive form of learning (while searching)
{x}
{3}
confset[6] = {1}
CBJ for finding all solutions
After finding a solution, if we jump from this last variable, then
we may miss some solutions and lose completeness
Two solutions, proposed by Chris Thiel (S08)
Using conflict sets
Rationale by Rahul Purandare (S08)
We cannot skip any variable without chronologically backtracking to
it at least once
In fact, exactly once
CBJ/All solutions without cbf
When a solution is found, force the last variable, N, to conflict
with everything before it
confset[N] {1, 2, ..., N1}.
*
CBJ/All solutions with cbf
Kondrak proposed to fix the problem using cbf (flag), a 1xn
vector
i, cbf[i] 0
In unlabel
Else h maxlist (confset[i])
*
Backjumping
Uses array of integers: maxcheck[i]
Conflictdirected backjumping
Uses array of sets: confset[i]
Problem Solving with Constraints
Hybrid backtracking algorithms
Problem Solving with Constraints
Situation:
v[i]k was checked against v[h]g
v[h] has not been modified
v[h] = g
BM: motivation
Two situations
Either (v[i]=k,v[h]=g) has failed it will fail again
Or, (v[i]=k,v[h]=g) was founded consistent it will remain
consistent
In either case, backchecking effort against v[h] can be
saved!
k
maximum checking level: mcl (n x m)
Minimum backup level: mbl (n x 1)
0
0
0
0
0
0
0
0
0
0
0
0
0
Maximum checking level
mcl[i,k] stores the deepest variable that v[i]k checked
against
mcl[i,k] is a finer version of maxcheck[i]
0
0
0
0
0
0
0
0
0
0
0
0
0
Minimum backup level
mbl[i] gives the shallowest past variable whose value has changed
since v[i] was the current variable
BM (and all its hybrid) do not allow dynamic variable
ordering
Number of variables n
Problem Solving with Constraints
v[i]
BM is aware that
The deepest variable that (v[i] k) checked against is v[j]
Values of variables in the past of v[j] (h<j) have not
changed
So
We do need to check (v[i] k) against the values of the variables
between v[j] and v[i]
We do not need to check (v[i] k) against the values of the
variables in the past of v[j]
k
Type a savings
When mcl[i,k] < mbl[i], do not check v[i] k because it will
fail
k
Problem Solving with Constraints
mcl[i,k]mbl[i]
When mcl[i,k] mbl[i], do not check (i,h<j) because they will
succeed
k
Mixing BJ & BM yields BMJ
avoids redundant consistency checking (types a+b savings) and
reduces the number of nodes visited during search (by
jumping)
Mixing BM & CBJ yields BMCBJ
Problem Solving with Constraints
v[m]
v[m]
v[g]
v[h]
v[i]
v[f]
Backmarking of v[h]:
When reconsidering v[h], v[h] will be checked against all f
[m,g)
effort could be saved
Problem fixed by Kondrak & van Beek 95
BMJ enjoys only some of the advantages of BM
Assume: mbl[h] = m and maxcheck[i]=max(mcl[i,x])=g
v[m]
v[g]
v[h]
v[i]
v[g]
v[h]
v[i]
v[h]
Forward checking (FC)
Looking ahead: from current variable, consider all future variables
and clear from their domains the values that are not consistent
with current partial solution
FC makes more work at every instantiation, but will expand fewer
nodes
When FC moves forward, the values in currentdomain of future
variables are all compatible with past assignment, thus saving
backchecking
FC may “wipe out” the domain of a future variable (aka, domain
annihilation) and thus discover conflicts early on. FC then
backtracks chronologically
Goal of FC is to fail early (avoid expanding fruitless
subtrees)
Problem Solving with Constraints
FC: data structures
When v[i] is instantiated, currentdomain[j] are filtered for all j
connected to i and I < j n
reduction[j] store sets of values remove from currentdomain[j] by
some variable before v[j]
reductions[j] = {{a, b}, {c, d, e}, {f, g, h}}
futurefc[i]: subset of the future variables that v[i] checks
against (redundant)
futurefc[i] = {k, j, n}
pastfc[i]: past variables that checked against v[i]
All these sets are treated like stacks
v[i]
v[k]
v[l]
v[n]
v[m]
v[j]
It performs Revise(j,i)
Returns false if currentdomain[j] is empty, true otherwise
Values removed from currentdomain[j] are pushed, as a set, into
reductions[j]
These values will be popped back if we have to backtrack over v[i]
(undoreductions)
Problem Solving with Constraints
currentdomain[i] domain[i] \ reductions[i]
actually, we have to iterate over reductions, which is a set of
sets
fclabel
Then filters domains of all future variables (push into
reductions)
Whenever currentdomain of a future variable is wipedout:
v[i] is uninstantiated and
domain filtering is undone (pop reductions)
Problem Solving with Constraints
FCBJ:
maxcheck is integrated in fcbjlabel and fcbjunlabel
Enjoys advantages of FC and BJ… but suffers malady of BJ (first
jumps, then steps back)
FCCBJ:
Forwardchecking
Uses: reductions[i], futurefc[i], pastfc[i]
Problem Solving with Constraints
Permutation of variable ordering yields new search spaces
Variable ordering: different bandwidth/induced width of graph
450 problem instances were generated
Each algorithm was applied to each instance
Experiments were carried out under static variable ordering
Problem Solving with Constraints
FCCBJ FCBJ BMCBJ FC CBJ BMJ BM BJ BT
Number of nodes visited (average)
FCCBJ FCBJ FC BMCBJ BMJ=BJ BM=BT
CPU time (average)
FCCBJ apparently the champion
Problem Solving with Constraints
Pseudotrees [Freuder 85]
Problem Solving with Constraints
Normalize all constraints ( fapp0102000 )
Interrupt as soon as you detect domain wipe out
Dynamic variable ordering
Apply domino effect