Solving constraint satisfaction problems
Constraint Satisfaction Problem (CSP)
Defined by a set of variables, set of domains for each variable and set of constraints for each variables
Variables(X) :
A finite set of variablesX = {x1,x2,x3...}Domains(D) :
D = {D1,D2,D3,...}WhereDiis set of possible values for variablexi. That isxi ∈ Di.Constraints(C) :
A set of constraints C={c1,c2,…,cm} where each constraintcj involves a subset of variablesXj ⊆ Xand specifies a relationRj that must be satisfied. The relation RjRj defines the set of allowable tuples of values for the variables inXj.
A solution to a CSP is an assignment of values to all variables x1,x2,…,xn such that : xi ∈ Di for all i ∈ {1,2,…,n} and All constraints cj ∈ C are satisfied.
CSP as a Graph
Nodes: Each variable in the CSP is represented as a node (or vertex) in the graph.
Edges: An edge is drawn between two nodes (variables) if there is a direct constraint between them.
Example:
Constraints:
X ≠ Y
Y < Z
X > 1
Graph Representation:
Nodes: X, Y, Z
Edges:
X -- Y (due to the constraint X ≠ Y)
Y -- Z (due to the constraint Y < Z)
Node consistency
- Node consistency is achieved when, for every variable, each value in its domain is consistent with the variable’s unary constraints.
- To make a variable
xnode consistent : from the domain of variablex, remove a valuevthat doesn’t satisfy the constraint (length in case of crossword)
Arc Consistency
xis arc consistent withywhen every value in the domain ofxhas a possible value in the domain ofythat does not cause a conflict. (A conflict in the context of the crossword puzzle is a square for which two variables disagree on what character value it should take on.)- To make
xarc consistent withy, remove any value from the domain ofxthat does not have a corresponding possible value in the domain ofy. The domain ofyshould be left unmodified.
AC3 Algorithm
Maintains a queue of arcs to process.
- To implement AC3,
revise(make a variable x arc consistent with another variable y) each arc in the queue one at a time. Any time you make a change to a domain, though, you may need to add additional arcs to your queue to ensure that other arcs stay consistent. - When trying to enforce arc consistency , we remove all values from domain, it is impossible to solve the problem
Crossword as a CSP
Each variable(word) in a crossword is represented by 4 values:
{
i : coordinate of square of starting row
j : coordinate of square of starting column
length : some number
direction : down or across
}
Domain : Initially the domain for each variable is set of all words in corpus.
Unary constraints : length
Binary constraints : intersecting/overlapping letter with neighbour words(variables)
Code Implemetation
enforce_node_consistency:
- remove values from domain of a variable if it doesnt satisfy unary constraint (length of variable)
revise :
- To make
xarc consistent withy, remove any value from the domain ofxthat does not have a corresponding possible value in the domain ofy. - for every value in domain of
X, check if it has possible values inY, if not remove that value fromX
ac3 :
- Maintain queue of arcs
- enforce arc consistency using
revisefunction - when a domain of a variable is changed to enforce arc consistency, other arcs may be affected. so add other arcs in the queue
function AC-3(csp):
queue = all arcs in csp
while queue non-empty:
(X, Y) = DEQUEUE(queue)
if REVISE(csp, X, Y):
if size of X.domain == 0:
return false
for each Z in X.neighbors - {Y}:
ENQUEUE(queue, (Z, X))
return true
assignment_complete :
- An
assignmentis a dictionary where the keys areVariableobjects and the values are strings representing the words those variables will take on. - An
assignmentis complete if every crossword variable is assigned to a value (regardless of what that value is).
consistent :
- An
assignmentis consistent if it satisfies all of the constraints of the problem: that is to say, all values are distinct, every value is the correct length, and there are no conflicts between neighboring variables.
order_domain_values :
- returns a list of all of the values in the domain of
var, ordered according to theleast-constraining valuesheuristic. - if assigning var to a particular value results in eliminating
npossible choices for neighboring variables, you should order your results in ascending order ofn. In other words, we should choose a value for a given variable that keeps more options for other variables. - any variable present in assignment already has a value, and therefore shouldn’t be counted when computing the number of values ruled out for neighboring unassigned variables.
- Arbitrary choice of unassigned variable may also produce correct crossword.
select_unassigned_variable :
returns single
Variablein the crossword puzzle not yet assigned , By usingMinimum remaining valueheuristic and thendegreeheuristic.Minimum remaining value: Select a unassigned
Variablesuch that the variable has fewest values in its domain. This is done to quickly eliminate a branch of possible options.
This may sound counterintuitive toorder_domain_valueswhich tried to select a least constraining value But we are talking about different things here. Theorder_domain_valuestries to select avaluefor a specificVariableto keep the other variables with more choices, whileMinimum remaining valueselects aVariable(notValue) that prunes the unnecessary solution space quickly.Degree : If there is tie between variables by having same number of values in the domains, select the variable that has most neighbours. This is done because , by choosing such variable, it is likely to rule out more choices for other variables.
If it is still tie, choose arbitrary variable.Arbitrary choice of unassigned variable will also be correct for generating crossword, this is just for optimization
backtrack :
- Given a partial
assignmentdictionary , returns a complete satisfactoryassignmentif possible. - Interleaving search with inference (as by maintaining arc consistency every time you make a new assignment) makes it more efficient
backtrack starts with a assignment and recursively calls itself by passing the updated assignment disctionary with newly added assignment.
function BACKTRACK(assignment, csp):
if assignment complete:
return assignment
var = SELECT-UNASSIGNED-VAR(assignment, csp)
for value in DOMAIN-VALUES(var, assignment, csp):
if value consistent with assignment:
add {var = value} to assignment
result = BACKTRACK(assignment, csp)
if result ≠ failure:
return result
remove {var = value} from assignment
return failure
remove {var = value} from assignment, is where backtracking actually occurs as we return to previous state of assignment.
Optimimzed Backtracing Search
When we assign a value to a variable , we can check arc consistency on other nodes(variable) to quickly find out values other nodes could take. this inference procedure makes the algorithm more efficient as we do not need to solely assign values in the search(backtrack) process, but also can infer other values.
whenever we assign a value to a variable we check if other inferences can be made. those inferences are added to the assignment.
inferences = INFERENCE(assignment, csp)add inferences to assignmentIf later , that choice of value results in failure, we remove not only the value but also the inferences made from that value in the assignment
remove {var = value} and inferences from assignment
function BACKTRACK(assignment, csp):
if assignment complete:
return assignment
var = SELECT-UNASSIGNED-VAR(assignment, csp)
for value in DOMAIN-VALUES(var, assignment, csp):
if value consistent with assignment:
add {var = value} to assignment
inferences = INFERENCE(assignment, csp)
if inferences ≠ failure:
add inferences to assignment
result = BACKTRACK(assignment, csp)
if result ≠ failure:
return result
remove {var = value} and inferences from assignment
return failure