Computational Logic Constraint Programming: Finite Domains

## Introduction

• Constraint domains in which the possible values that a variable can take are restricted to a finite set.

• Examples: Boolean constraints, or integer constraints in which each variable is constrained to lie in within a finite range of integers.

• Widely used in constraint programming.

• Many real problems can be easily represented using constraint domains, e.g.: scheduling, routing and timetabling.

• They involve choosing amongst a finite number of possibilities.

• Commercial importance to many businesses: e.g. deciding how air crews should be allocated to aircraft flights.

• Developed methods by different research communities:
• Arc and node consistency techniques (artificial intelligence).

• Bounds propagation techniques (constraint programming).

• Integer programming (operations research).

## Constraint Satisfaction Problems

• In the artificial intelligence community, satisfaction of constraint problems over finite domains has been studied under the name of constraint satisfaction problems''.

• A constraint satisfaction problem (CSP) consists on:

• a constraint over variables , where be of the form (each is a primitive constraint), and

• a domain that maps each variable to a finite set of values, written , which is allowed to take.

• The CSP is understood to represent the constraint .

• Examples of CSPs: map coloring and N-queens problem.

• Binary CSPs: the primitive constraints have at most two variables (e.g. map coloring).

## A Simple Backtracking Solver

• It is always possible to determine the satisfiability of a CSP by brute force search'': trying all combinations of different values (finite number).

• However, this can be prohibitively expensive.

• Simplest techniques for determining satisfiability of an arbitrary CSP is chronological backtracking:

• choosing a variable, and then, for each value in its domain, determining satisfiability of the constraint which results by replacing the variable with that value.

• This is done by calling the backtracking algorithm recursively.

• It uses the parametric function satisfiable(c), which takes the primitive constraint c which involve no variables and returns true or false indicating whether c is satisfiable or not.

## Chronological Backtracking Solver

INPUT: a CSP with constraint and domain .
OUTPUT: Returns if is satisfiable (has one or more solutions), otherwise .
METHOD:


back_solve()

if  then return partial_satisfiable()

else choose

for each values  do

let  be obtained from  by replacing  by

if partial_satisfiable() then

if back_solve() then return  endif

endif

endfor

return

endif


## Chronological Backtracking Solver (Contd.)


partial_satisfiable()

let  be of the form  (each  is aprimitive constraint)

for  := 1 to  do

if  then

if satisfiable()  then return  endif

endif

endfor

return


Exercise: apply the algorithm to the CSP with constraint

and domain , such that .

## Node and Arc Consistency

• There are solvers for CSPs which have polynomial worst case complexity, but are incomplete.

• These solvers are based in the observation that if the domain for any variable in the CSP is empty, then the CSP is unsatisfiable.

• Idea: transform the CSP into an equivalent'' CSP but one in which the domains of the variables are decreased.

• Equivalent'' means that the constraints represented by the CSPs have the same set of solutions.

• If any of the domains become empty, then this CSP, and also the original, are unsatisfiable.

• These solvers work by considering each primitive constraint in turn, and using information about the domain of each variable in the constraint to eliminate values from the domains of the other variables.

## Node and Arc Consistency (Contd.)

• The solvers are said to be consistency'' based since they propagate information about allowable domain values from one variable to another until the domains are consistent'' with the constraint.

• Two special domains may result after application of a consistency based solver:

• False domain: if some variable in the domain is mapped to the empty set.

• Valuation domain: if every variable is mapped to a singleton set.

• The function takes a constraint and a valuation domain and returns true or false, indicating whether is satisfiable or not under this valuation (i.e. whether the constraint evaluates to true or false). Examples:

• The domain , in which and is a false domain.

• The domain , in which , , and is a valuation domain.

• , where is , is false.

## Node and Arc Consistency: Definitions

• A primitive constraint is node consistent with domain if either or, if , then, for each , is a solution of .

• A CSP with constraint and domain is node consistent if each primitive constraint is node consistent with for .

• A primitive constraint is arc consistent with domain if either or, if , then,

• for each , there is some , such that is a solution of , and

• for each , there is some , such that is a solution of .

• A CSP with constraint and domain is arc consistent if each primitive constraint is arc consistent with for .

## Node and Arc Consistency: Examples

• The CSP with

• constraint and

• domain , such that

is node and arc consistent.

• It is also satisfiable (a solution is ).

• The CSP with the same constraint and domain is also node and arc consistent.

• However, it is not satisfiable! (it has no solutions).

• The CSP with constraint and domain , such that is node consistent but is not arc consistent.

• The CSP with constraint and domain , such that is neither node nor arc consistent.

## Algorithm for Node Consistency

INPUT: a CSP with constraint and domain .
OUTPUT: a domain such that the CSP with constraint and domain is node consistent and is equivalent to the input CSP.
METHOD: := node_consistent().


node_consistent() ( is a constraint and  a domain)

let  be of the form  (each  is aprimitive constraint)

for  := 1 to  do
:= node_consistent_primitive()

endfor

return

node_consistent_primitive()

if  then

let  ( is a variable)
:=  is a solution of ( is a domain value).

endif

return


## Algorithm for Arc Consistency

INPUT: a CSP with constraint and domain .
OUTPUT: a domain such that the CSP with constraint and domain is arc consistent and is equivalent to the input CSP.
METHOD: := arc_consistent().


arc_consistent() ( is a constraint and  a domain)

let  be of the form  (each  is aprimitive constraint)

repeat  :=

for  := 1 to  do              := arc_consistent_primitive() endfor

until

return



arc_consistent_primitive()

if  then

let  ( and  are variables)
:=  for some ,  is a solution of
:=  for some ,  is a solution of

endif

return


## Incomplete Node and Arc Consistency Solver

INPUT: a CSP with constraint and domain .
OUTPUT: Returns true, false or unknown. true if the CSP is satisfiable (has one or more solutions); false if the CSP is unsatisfiable (has no solutions); and unknown if the algorithm is not able of determining the satisfaction of the CSP.

METHOD:


arc_solv()
:= node_arc_consistent()

if  is a false domain then return false

elseif  is a valuation domain then return

else return unknown

endif


node_arc_consistent()
:= node_consistent()
:= arc_consistent()

return


## Incomplete Node and Arc Consistency Solver: Example

• Consider the CSP with constraint and domain , such that .

## Complete Node and Arc Consistency Solver

INPUT: a CSP with constraint and domain .
OUTPUT: Returns if the CSP is satisfiable (has one or more solutions), otherwise return .
METHOD: if back_arc_solv() returns , then return , otherwise return .


back_arc_solv()
:= node_arc_consistent()

if  is a false domain then return

elseif  is a valuation domain then

if  then return  else return  endif

endif

Choose a variable  such that

for each value  do
:= back_arc_solv()

if  then return  endif

endfor

return


## Hyper-Arc Consistency

• Node and Arc work well for pruning the domains in binary CSPs.

• However, they do not work well if the problem contains primitive constraints that involve more than two variables, since they are ignored when performing consistency checks.

• A primitive constraint is hyper-arc consistent with domain if for each variable and each value , there are values for the remaining variables in , say , such that for and is a solution of .

• A CSP with constraint and domain is hyper-arc consistent if each primitive constraint is hyper-arc consistent with for .

• hyper-arc consistency is a true generalization of arc and node consistency.

• hyper-arc consistency is equivalent to arc (node) consistency in the case when a primitive constraint has two (one) variables.

• Unfortunately, testing for hyper-arc consistency can be very expensive even for fairly simple constraints that involve more than two variables.

## Bounds Consistency

• The restriction to integer and arithmetic constraints allows us to define a new type of consistency: bounds consistency.

• A CSP is arithmetic if each variable in the CSP ranges over a finite domain of integers and the primitive constraints are arithmetic constraints.

• The most important class of CSPs (most problems of commercial interest).

• Two ideas behind bounds consistency.

• Approximate the domain of a variable using a lower and upper bound.

• Use real number consistency of primitive constraints rather than integer consistency.

• A range represents the set of values if , otherwise it represents the empty set.

• If is a domain over integers, and are the minimum and maximum elements in respectively.

## Bounds Consistency (Contd.)

• An arithmetic primitive constraint is bounds consistent with domain if for each variable there is:

• an assignment of real numbers, say , to the remaining variables in , say , such that:

is a solution of , and for each .

• another assignment of real numbers, say , to the remaining variables in , say , such that:

is a solution of , and for each .

• An arithmetic CSP with constraint and domain is bounds consistent if each primitive constraint is bounds consistent with for .

• Since bounds consistency only depends on the upper and lower bounds of the domains of the variables, when testing bounds consistency, we need only consider domains that assign ranges to each variable.

## Bounds Consistency: Example

• Consider the constraint: , with domain , where:

the constraint is NOT bounds consistent with .

• Reason: if we consider , the left hand side can take a maximum value of , however the left hand side can take a maximum value of .

• Hence the domain can be changed (changing the range of ), obtaining another domain such that the constraint is bounds consistent with

## Propagation Rules

• Propagation rules methods: are efficient methods so that given a current range for each of the variables in a primitive constraint, they calculate a new range for each variable in the constraint, which makes the constraint to be bounds consistent with the new domain.

• Example: consider the simple constraint: .

• It can be written in three forms:

and

• We can see that:

,

,

,

• It is easy to implement an algorithm for the propagation rules for the constraint .

## Propagation Rules for the Constraint

INPUT: a domain .
OUTPUT: a domain which is bounds consistent with the constraint .
METHOD:


:=
:=
:=
:=
:=
:=
:=
:=
:=

return


## Example of Propagation Rules for the Constraint

• Consider the domain:

• We can determine that:

, using ,

, using ,

, using .

• Therefore we can update the domain to:

without removing any solutions to the constraint.

• If we apply the propagation rules to the new domain we obtain:

• Thus, is bounds consistent with the new domain.

• We need only apply these propagation rules once to any domain to obtain a domain which is bounds consistent with the constraint .

## Propagation Rules for More Complicated Linear Arithmetic Constraints

• Example: consider the constraint:

• We can rewrite this into three forms:

, ,

• and obtain the inequalities:

,

,

• Given the initial domain:

we can determine that , ,

• Note that instead of we can use (i.e. , since takes integer values only).

• Using the propagation rules (to be explained later), we update the domain:

## Propagation Rules for the Constraint

INPUT: a domain .
OUTPUT: a domain which is bounds consistent with the constraint
.
METHOD:


:=
:=
:=
:=
:=
:=

return


## Propagation Rules for Nonlinear Constraints

• Example:

• Propagation rules follow directly from:

## Bounds Consistency Algorithm

• INPUT: an arithmetic CSP with constraint and domain .

• OUTPUT: a domain such that the CSP with constraint and domain is bounds consistent and is equivalent to the input CSP.

• METHOD: := bounds_consistent().

## Bounds Consistency Algorithm (Contd.)


bounds_consistent() ( is a constraint and  a domain)

let  be of the form  (each  is aprimitive constraint)
:=

while  do

choose
:=
:= bounds_consistent_primitive()

if  is a false domain then return  endif

for  := 1 to  do

if there exists  such that            then  :=

endif

endfor
:=

endwhile

return


## Bounds Consistency Algorithm (Contd.)

bounds_consistent_primitive()

• Applies the propagation rules for primitive constraint to the domain and returns the new domain.

• We assume that the original CSP has been transformed into a CSP containing only legitimate primitive constraints.

## Bounds Consistency Algorithm: Example of Execution

• Consider the execution of this solver with the constraint:

and the domain

, , .

• Initially is set to the set { .

• A primitive constraint , say , is removed from .

• The function bounds_consistent_primitive() is called and returns the updated domain (evaluating the propagation rules for ):

, , .

• Since the range of variable has changed, the constraint is added to (although this is unnecessary since its propagation rules ensure consistency with respect to itself).

• Another primitive constraint, say , is removed from .

## Bounds Consistency Algorithm: Example of Execution (Contd.)

• The call to the function bounds_consistent_primitive() removes the value from the range of giving the updated domain:

, , .

• The constraint is added to , since the range of variable has changed.

• Another primitive constraint, say , is removed from , and its propagation rules are applied yielding the domain:

, , .

• Since the range of variable has changed, the constraint is added to .

• Further processing of the of the constraints, and , in does not change the domain so the function terminates returning this domain which is bounds consistent with the constraint.

## Incomplete Bounds Consistency Solver

INPUT: an arithmetic CSP with constraint and domain .
OUTPUT: Returns true, false or unknown. true if the CSP is satisfiable (has one or more solutions); false if the CSP is unsatisfiable (has no solutions); and unknown if the algorithm is not able of determining the satisfaction of the CSP.

METHOD:


bounds_solv()
:= bounds_consistent()

if  is a false domain then return false

elseif  is a valuation domain then return

else return unknown

endif


## Incomplete Bounds Consistency Solver: Example

• Consider the CSP with constraint and domain , such that .

• The call to bounds_consistent() sets to .

• Considering the primitive constraint we obtain:

, , .

• The constraint is added to .

• Considering we obtain:

, , .

• The constraint is added to .

## Incomplete Bounds Consistency Solver: Example (Contd.)

• Reconsidering the constraint we obtain:

, , .

• The constraint is added to .

• Further processing of the of the constraints, and , in does not change the domain so the function bounds_consistent returns:

, , .

• Thus, bounds_solv returns unknown.

## Complete Bounds Consistency Solver

INPUT: an arithmetic CSP with constraint and domain .
OUTPUT: Returns if the CSP is satisfiable (has one or more solutions), otherwise return .
METHOD: if back_bounds_solv() returns , then return , otherwise return .


back_bounds_solv()
:= bounds_consistent()

if  is a false domain then return

elseif  is a valuation domain then

if  then return  else return  endif

endif

Choose a variable  such that

for each value  do
:= back_bounds_solv()

if  then return  endif

endfor

return


## Complete Bounds Consistency Solver: Example

• Consider the previous CSP (with constraint and domain , such that ).

• The call to bounds_consistent() returns:

, , .

• The (complete) solver selects a variable, say , and tries different values in its domain.

• First, the (complete) solver calls itself recursively with the constraint:

and the domain:

, , .

• The function bounds_consistent is evaluated with this new constraint and domain.

## Complete Bounds Consistency Solver: Example

• Examining gives .

• Examining gives .

• Examining gives .

• No more propagation is performed, so the resulting domain is:

, , .

• This is returned by bounds_consistent and, since this is a valuation domain which satisfies the constraint, the solver back_bounds_solv returns true.

## Example Problem: The Smuggler's Knapsack

• Knapsack of limited capacity: units.

• It can smuggle bottles of whiskey of size units, bottles of perfume of size units, and cartons of cigarettes of size units.

• The profit for a bottle of whiskey, a bottle of perfume, and a cartons of cigarettes are dollars, dollars, and dollars respectively.

• The smuggler will only take a trip if he makes a profit of dollars or more.

• What can he take ?

## Example Problem: The Smuggler's Knapsack

• Constraint:

• Domain:

• Using the complete bounds propagation solver, we begin by calling the bounds_consistent function with this constraint and domain. This gives the domain:

• Then, choosing a branch on , we first try adding .

• Applying bounds_consistent returns:

• Now, choosing to branch on , we add the constraint . Applying bounds_consistent we get:

• So, we have found a solution: , , .

• Note: this is not the optimal solution!

## Generalized Consistency

• We have seen three consistency based approaches to solving CSPs: arc, node and bounds consistency.

• These can be combined with each other and also with specialized consistency methods for complex'' primitive constraints:

• For constraints involving only two variables, we can use the stronger arc consistency tests to remove values from the domain.

• For constraints involving more than two variables, we can use the weaker, but more efficiently computable, bounds consistency approach.

• One of the weaknesses of the consistency based approaches is that primitive constraints are examined in isolation from each other.

• Sometimes, knowledge about other primitive constraints can dramatically improve domain pruning.

• For this reason, it is common to provide complex'' primitive constraints which are understood as conjunction of simpler primitive constraints but which have specialized propagation rules.

## Generalized Consistency (Contd.)

• For example, the specialized primitive'' constraint:

alldifferent( )

holds whenever each of the variables takes a different value from the others.

• Instead of this constraint, we could use a conjunction of primitive constraints.

• For example, the primitive constraint alldifferent() can be replaced by: , but this is a weaker approach.

• Example: the constraint

with domain

has no solutions (there are two possible values for the three variables).

• But, arc consistency techniques cannot determine this!

## A Consistency Method for the alldifferent Primitive Constraint


alldifferent_consistent_primitive() ( is a single alldifferent primitive constraint)

let  be of the form alldifferent()

while exists  with  for some
:=

for each  do  :=  endfor

endwhile
:=
:=

for each  do  :=  endfor

if  then return false endif

return


## Optimization for Arithmetic CSPs

• For many problems, the aim is not simply to find any solution, but rather, to find the optimal solution.

• The simplest approach to finding an optimal solution to an arithmetic CSP is to make use of a complete solver for these problems, and use it iteratively to find better and better solutions to the problems:

• Use the solver to find any solution to the CSP.

• Add a constraint to the problem which excludes solutions that are not better than this solution.

• The new constraint is solved recursively, giving rise to a better solution.

## Integer Optimizer Based on Retrying

INPUT: an arithmetic CSP with constraint and domain and an arithmetic expression which is the objective function.
OUTPUT: an optimal solution or false if the CSP is unsatisfiable.
METHOD: The answer is the result of evaluating retry_int_opt( ).


retry_int_opt() ( is either asolution or false)
:= int_solv() ( is a valuation domain or false)

if   then

return

else

let  be the solution corresponding to

return retry_int_opt()

endif


## Integer Optimizer Based on Backtracking

INPUT: an arithmetic CSP with constraint and domain and an arithmetic expression which is the objective function.
OUTPUT: an optimal solution or false if the CSP is unsatisfiable.
METHOD: The answer is the result of evaluating back_int_opt( ).


back_int_opt() ( is either asolution or false)
:= int_consistent(, )

if  is a false domain then return

elseif  is a valuation domain then return the solutioncorresponding to

endif

choose a variable  for which
:=

for each  do

if  then  :=  else  := true endif
:= back_int_opt()

endfor

return



Last modification: Wed Nov 22 23:44:17 CET 2006 <webmaster@clip.dia.fi.upm.es>