Chapter 5
Constraint Satisfaction Problem
A CSP comprise of three components:
Set of variables: $X$: { $x_1, x_2, \ldots , x_n$}
Set of domains(D) belonging to each variable { $D_1, D_2, \ldots , D_n$ } where $D_i=domain(x_i)$
Set of constraints(C) that specifies the valid combinations of values assigned to each of the variable.
Backtracking Search
We can describe the CSP as follows:
Variables: { $x_1, x_2, x_3, x_4$}, where each $x_i$ represent the variable for $i^{th}$ column in $4 \times 4$ grid.
For each variable $x_i$: $D_{x_i}$={$1,2,3,4$}, $D_{x_i}$ represent the value of the row, i.e. each variable $x_i$ can possibly take a value of the row.
Constraints: Let NOATTACK($x_i,x_j$) return True if the queen at $x_i$ cannot attack the queen at $x_j$, and False otherwise.
NOATTACK($x_1,x_2$)
NOATTACK($x_1,x_3$)
NOATTACK($x_1,x_4$)
NOATTACK($x_2,x_3$)
NOATTACK($x_2,x_4$)
NOATTACK($x_3,x_4$)
We can specify the constraints fully for each NOATTACK($x_i,x_j$) in a huge truth table as seen in Table below:
$x_1$ | $x_2$ | NOATTACK |
---|---|---|
1 | 1 | False |
1 | 2 | False |
1 | 3 | True |
1 | 4 | True |
2 | 1 | False |
... | ... | ... |
Our goal is to choose the values of all $x$ so that none of the queens in their respective positions can attack each other.
Backtracking Search Algorithm
Algorithm 1 BacktrackingSearch(prob,assign)
- If AllVarsAssigned(prob,assign) then
- $~~~~~$If IsConsistent(assign) then
- $~~~~~~~~~~$ Return assign
- $~~~~~$Else
- $~~~~~~~~~~$ Return failure
- var$\gets$PickUnassignedVar(prob,assign)
- For value$\in$ OrderDomainValue(var,prob,assign) Do
- $~~~~~$ assign$\gets$ assign $\cup$ (var = value)
- $~~~~~$ result $\gets$ BacktrackingSearch(prob,assign)
- $~~~~~$If result != failure then Return result
- $~~~~~$ assign $\gets$ assign $\setminus$ (var=value)
- Return failure
Figure 1: Board state at various steps of naive Backtracking Search. |
Let be the $i^{th}$ functional call, and $j^{th}$ operation in that functional call. The execution of the algorithm goes as follows:
1.1 Pick variable $x_1$; 1.2 Set $x_1=1$
2.1 Pick variable $x_2$; 2.2 Set $x_2=1$
3.1 Pick variable $x_3$; 3.2 Set $x_3=1$
4.1 Pick variable $x_4$; 4.2 Set $x_4=1$
5.1 IsConsistent(assign)=False, thus back track; 4.3 Set $x_4=2$
5.1 IsConsistent(assign)=False, thus back track; 4.4 Set $x_4=3$
5.1 IsConsistent(assign)=False, thus back track; 4.5 Set $x_4=4$
5.1 IsConsistent(assign)=False, thus back track
4.6 Finished ‘for’ loop, thus back track; 3.3 Set $x_3=2$
4.1 Pick variable $x_4$; 4.2 Set $x_4=1$
5.1 IsConsistent(assign)=False, thus back track; 4.3 Set $x_4=2$
5.1IsConsistent(assign)=False, thus back track; 4.4 Set $x_4=3$
5.1 IsConsistent(assign)=False, thus back track; 4.5 Set $x_4=4$
5.1 IsConsistent(assign)=False, thus back track
4.6Finished ‘for’ loop, thus back track
$\cdots$
Improved Backtracking Search
Algorithm 2 BacktrackingSearch(prob,assign)
- If AllVarsAssigned(prob,assign) then
- var$\gets$PickUnassignedVar(prob,assign)
- For value$\in$ OrderDomainValue(var,prob,assign) Do
- $~~~~~~~$If ValIsConsistentWithAssignment(value,assign) then
- $~~~~~~~~~~~~~~$ assign$\gets$ assign $\cup$ (var = value)
- $~~~~~~~~~~~~~~$ result $\gets$ BacktrackingSearch(prob,assign)
- $~~~~~~~~~~~~~~$If result != failure then Return result
- $~~~~~~~~~~~~~~$ assign $\gets$ assign $\setminus$ (var=value)
- Return failure
Let us try to execute the Algorithm 2 step by step for 4-Queen puzzle. Figure 2 represents the board overview of backtracking algorithm to solve 4-Queen puzzle.
Figure 2: Board state at various steps of improved BacktrackingSearch |
The execution of the algorithm goes as follows:
1.1 Pick $x_1$; 1.2 Set $x_1=1$
2.1 Pick $x_2$; 2.2 Set $x_2=3$ as ${1,2}$ is attackable
3.1 Pick $x_3$; Return $failure$ as $ {1,2,3,4}$ are attackable
2.3 Set $x_1=4$ as $ {1,2}$ is attackable and ${3}$ had been assigned
3.1 Pick $x_3$; 3.2 Set $x_3=2$ as $ {1,3,4}$ are attackable
4.1 Pick $x_4$
4.2 Return $failure$ as $ {1,2,3,4}$ are attackable
3.3 Return $failure$ as $ {1,3,4}$ are attackable and ${2}$ had been assigned
2.4 Return $failure$ as $ {1,2}$ are attackable and ${3,4}$ had been assigned
1.3 Set $x_1=2$
2.1 Pick $x_2$; 2.2 Set $x_2=4$ as $ {1,2,3}$ are attackable
3.1 Pick $x_3$; 3.2 Set $x_3=1$ as $ {2,3,4}$ are attackable
4.1 Pick $x_4$; 4.2 Set $x_4=3$ as $ {1,2,4}$ are attackable
5.1 Return $assign$ because all variables are assigned
Backtracking Search with Inference
Algorithm 3 represents the improved backtrack algorithm with inference.
Algorithm 3 BacktrackingSearch_with_Inference(prob,assign)
- If AllVarsAssigned(prob,assign) then
- var$\gets$PickUnassignedVar(prob,assign)
- For value$\in$ OrderDomainValue(var,prob,assign) Do
- $~~~~~~~$If ValIsConsistentWithAssignment(value,assign) then
- $~~~~~~~~~~~~~~$ assign$\gets$ assign $\cup$ (var = value)
- $~~~~~~~~~~~~~~$ inference$\gets$ Infer(var,prob,assign)
- $~~~~~~~~~~~~~~$ assign$\gets$ assign $\cup$ inference
- $~~~~~~~~~~~~~~$ If inference != failure then
- $~~~~~~~~~~~~~~~~~~~~~~~~$ result $\gets$ BacktrackingSearch(prob,assign)
- $~~~~~~~~~~~~~~~~~~~~~~~~$If result != failure then Return result
- $~~~~~~~~~~~~~~$ assign $\gets$ assign $\setminus$ {(var=value) $\cup$ inference
- Return Failure
Below is the execution of Algorithm3 for $4-Queen$ problem:
1.1 Pick $x_1$; 1.2 Set $x_1=1$
1.3 $inference$ returned as $failure$, remove assignment $x_1=1$
1.4 Set $x_1=2$
1.5 $inference$ returned as ${x_2=4, x_3=1, x_4=3}$
2.1 Return $assign$ because all variables are assigned
Inference Function Logic at Step 3
Figure 3: Board state at various steps of improved BacktrackingSearch with Inference |
Then, the inference function looks at each and every constraint to infer restrictions on rest of the variables.
Constraint 1:NOATTACK($x_1,x_2$)
- Observation from Figure 3: $x_1=1 \Rightarrow x_2 \notin {1,2}$
Constraint 2:NOATTACK($x_1,x_3$)
- Observation from Figure 3: $x_1=1 \Rightarrow x_3 \notin {1,3}$
Constraint 3:NOATTACK($x_1,x_4$)
- Observation from Figure 3: $x_1=1 \Rightarrow x_4 \notin {1,4}$
Constraint 4:NOATTACK($x_2,x_4$)
Because $x_2 \in {3,4}$,
If $x_2=3 \Rightarrow x_4=2$
If $x_2=4 \Rightarrow x_4=3$
Constraint 5:NOATTACK($x_2,x_3$)
Deduction: $x_2 \in {3,4} \Rightarrow x_3 \notin {3,4}$
Deduction: $x_3 \notin {3,4} \wedge x_3 \notin {1,3} \Rightarrow x_3 \notin {1,3,4} \Rightarrow x_3=2$
Constraint 6:NOATTACK($x_3,x_4$)
Deduction: $x_3=2 \Rightarrow x_4 \notin {1,2,3}$
Deduction: $x_4 \notin {1,2,3} \wedge x_4 \notin {1,4} \Rightarrow x_4 \notin {1,2,3,4}$
Therefore,with no possible value to assign to $x_4$, $x_1=1$ is not going to work as a solution, return failure and backtrack
Inference Function Logic at Step 5
At step 5, because $x_1=2$, the inference function is able to deduce that the red squares in the Figure 4 are within a queens attacking range and no other queens can be placed there.
Figure 4: Board state at various steps of improved BacktrackingSearch with Inference |
Then, the inference function looks at each and every constraint to infer restrictions on rest of the variables.
Constraint 1:NOATTACK($x_1,x_2$)
- Observation from Figure 4 : $x_1=2 \Rightarrow x_2 \notin {1,2,3} \Rightarrow x_2=4$
Constraint 2:NOATTACK($x_1,x_3$)
- Observation from 4: $x_1=2 \Rightarrow x_3 \notin {2,4}$
Constraint 3:NOATTACK($x_1,x_4$)
- Observation from 4: $x_1=2 \Rightarrow x_4 \notin {2}$
Constraint 4:NOATTACK($x_2,x_4$)
Deduction: $x_2=4 \Rightarrow x_4 \notin {2,4}$
Deduction: $x_4 \notin {2,4} \wedge x_4 \notin {4} \Rightarrow x_4 \notin {2,4}$
Constraint 5:NOATTACK($x_2,x_3$)
Deduction: $x_2=4 \Rightarrow x_3 \notin {3,4}$
Deduction: $x_3 \notin {3,4} \wedge x_3 \notin {2,4} \Rightarrow x_3 \notin {2,3,4} \Rightarrow x_3=1$
Constraint 6:NOATTACK($x_3,x_4$)
Deduction: $x_3=1 \Rightarrow x_4 \notin {1,2}$
Deduction: $x_4 \notin {1,2} \wedge x_4 \notin {2,4} \Rightarrow x_4 \notin {1,2,4} \Rightarrow x_4=3$
Therefore,the function returns ${x_2=4, x_3=1, x_4=3}$
Now, the important question is How to implement the Infer functions? Let us discuss important questions related to functions:
Representation of data-structure: It stores each of the variable $x_i$, and set of values that $x_i$ is not supposed to take, such a set of values grows as Infer makes deductions based on the current assignment and constraints. For example: $x_1 \notin{1,2}, x_2 \notin {1,3,4}\ldots$
Store the constraints: The naive approach to store the constraints could be storing them as a truth-table described in Table 1, but we know that it is not efficient to use truth-tables for larger data; hence the more efficient way of storing the constraints is to come-up with some function that can returns true/false depending on the current values of the argument variables. Definitions of such a function depend on the application, for example for $n-Queen$ problem, such a function can be $f(x_1,x_2) { if {|val(x_1)-val(x_2)| > 1} \; \text{return True else False} }$.
ComputeDomain($\boldsymbol{x,assign,inference}$):In addition to above discussed questions, we also need an way to compute the domain of a variable x given an assignment and inference. We use a function ComputeDomain$(x,assign,inference)$ to return the domain of variable x given assignment and inference. Again, the definition of ComputeDomain function is not fixed and mainly depends on the application and inference definition. For example: if we have the assignment, ${x_1 = 1}$ and the inference, ${x_1 \notin {2,3}}$, then the ComputeDomain${(x_1,assign,inference)}$ should output the domain of $x_1$ as ${1}$. In another example for the assignment, ${x_2 = 1}$ and the inference, ${x_1 \notin {2,3}}$ the ComputeDomain${(x_1,assign,inference)}$ should output the domain of $x_1$ as ${1,4}$.>
Algorithm 4 represents function of Algorithm 3.
Algorithm 4 Infer(prob,var,assign) function of Algorithm 3
- inference $\gets \emptyset$
- varQueue $\gets$ [var]
- While varQueue is not empty Do
- $~~~~~~~$ y $\gets$ varQueue.pop()
- $~~~~~~~$ For each constraint C in prob where y $\in$ Vars(C) Do
- $~~~~~~~~~~~~~$ For all x $\in$ Vars(C)$\setminus$y Do
- $~~~~~~~~~~~~~~~~~~~~~$ S $\gets$ ComputeDomain(x,assign,inference)
- $~~~~~~~~~~~~~~~~~~~~~$ For each value v $\in$ S Do
- $~~~~~~~~~~~~~~~~~~~~~~~~~~~$ If no valid value exists $\forall$ var $\in$ Vars(C)$\setminus$ x s.t. C[x $\vdash$ v] is satisfied then
- $~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~$ inference $\gets$ inference $\cup$ (x $\not \in {v})
- $~~~~~~~~~~~~~~~~~~~~$ T $\gets$ ComputeDomain(x,assign,inference)
- $~~~~~~~~~~~~~~~~~~~~$ If T $= \emptyset$ then Return faliure
- $~~~~~~~~~~~~~~~~~~~~$ IF S $\neq$ T then varQueue.add(x)
- Return inference
Example in N-queen problem
Alternative Implementation of Inference
The alternative implementations are as follows:
Don’t add any variable to $varQueue$ at each iteration. This is the equivalent of deleting Line 13 of the Algorithm4.
This ensures that the inference will rule out only some of the values of variable.
This variant of inference is also known as Forward Checking.
Although forward checking can rule out many inconsistencies, it does not infer further ahead to ensure arc consistency for all the other variables.
Replace the $S\neq T$ condition in Line 13, replace with $|T|=1$.
This goes one step further from forward checking, and allows for further inferences for the variables that have one valid value in the domain.
Depending on the complexity of the application, the condition can be set to any particular value, e.g $|T|\leq 3$.
Minimum Remaining Value Heuristic: In PickUnassignedVar function of the backtracking search always choose the next unassigned variable that have the smallest domain size. The idea behind this heuristic is to assign values to variables that is most likely to cause failure quickly, thus allowing for pruning of larger branches in the search tree.
Least Constraining Value Heuristic: In OrderDomainValue function of the backtracking search always pick a value in the domain that rules out the least domain values of other neighboring variables in the constraint. This allows for the maximum flexibility for subsequent variable assignments. This heuristic is only relevant if we are interested in a single solution. If we want to find all (multiple) solutions to the problem, then the all values for an assignment to a variable will be iterated through in any case, thus it is not relevant here.
How Hard is Constraint Satisfaction Problem?
There are some special variants of CSP as listed below:
Binary CSP: Every constraint is defined over two variables(NP-complete).
Boolean CSP(SAT): The domain of every variable is 0,1(NP-complete).
2-SAT: Combination of Binary CSP and Boolean CSP, that is, every constraint is defined over two variables and the domain of every variable is 0,1(Polynomial time(P)-solvable).