Controlling Search (Cont)

Minimisation and Search Control

Recall that we are handling minimisation (so far) by assuming that our underlying system has a predicate minimise(G,E) which minimises the value of E over all valuations which satisfy E

Since we are relying on a built-in minimise predicate, there is not a great deal we can do to make its search more efficient

But we can ensure that our goal G is efficiently implemented

We can use the tricks we have already discussed to make G more efficient in the required mode

But what is the required mode?

The important point is that in most implementations, minimise will call G in the form

E < m, G.

(where m is a fixed number) - that is, G is rather more constrained than in the context in which minimise was called

Example

%leaflevel(BTree,Leaf,Depth) if Leaf is a leaf

%at depth Depth in binary tree BTree

leavlevel(node(null,X,null),X,0).

leaflevel(node(TL,_,_),X,D+1) :-

leaflevel(TL,X,D).

leaflevel(node(_,_,TR),X,D+1) :-

leaflevel(TR,X,D).

given the above tree and the goal minimise(leaflevel(ta,X,D),D) (ie return the node of minimum depth)

the goal leaflevel(ta,X,D) will be executed in a mode where D is subject ot the constraint D<n for some fixed n

However the implementation of leaflevel can not make use of this constraint, and the goal will only fail when the search reaches a leaf

Adding the redundant constraint D>=0 will stop search once the minimum depth already discovered has been passed:

%leaflevel(BTree,Leaf,Depth) if Leaf is a leaf

%at depth Depth in binary tree BTree

leavlevel(node(null,X,null),X,0).

leaflevel(node(TL,_,_),X,D+1) :-

D >= 0,

leaflevel(TL,X,D).

leaflevel(node(_,_,TR),X,D+1) :-

D >= 0,

leaflevel(TR,X,D).

 

Specifying Deterministic Search

There are sometimes situations where there is potential backtracking in a constraint, where we as the model builders are sure that the backtracking will not be productive (note that if we are wrong, the model may well produce incorrect answers)

If-then-else

The first case is closely analogous to a construct which occurs almost everywhere in traditional programming languages:

(Gtest -> Gthen

; Gelse)

If Gtest succeeds, then Gthen is evaluated; backtracking may occur in Gthen

If Gtest fails then Gelse is evaluated; backtracking may occur in Gelse

But in neither case is there any backtracking in Gtest; if backtracking reaches Gtest, it fails

 

Examples

abs(X,Y) :-

(X >= 0 -> Y = X

; Y = -X).

gives no backtracking in modes where X is fixed, compared with

abs(X,X) :-

X >= 0.

abs(X,-X) :-

X < 0.

which may give rise to backtracking

But note that the first form may not give correct answers in other modes; for example, the query

abs(X, 2), X < 0.

will incorrectly return the answer 'no', whereas

X < 0, abs(X, 2).

will return the answer X = -2

far_or_equal(X,Y) :-

(apart(X,Y,4) -> true

; X = Y).

apart(X,Y,D) :-

X >= Y + D.

apart(X,Y,D) :-

Y >= X + D.

again

far_or_equal(1,6).

succeeds, and

far_or_equal(1,3).

fails, but

far_or_equal(1,Y), Y = 6.

also fails

 

Once

The other main restriction constraint specifies that only one solution to the goal is of interest

It is usually used where (the model designer believes that) any one solution is equivalent to any other

Again, if this is wrong, or if the goal is called in unexpected modes, the model may give incorrect answers

Example

intersect(L1, L2) :-

member(X,L1),

member(X, L2).

Given the goal

intersect([a,b,e,g,h], [b,e,f,g,i]).

The predicate will return a first success answer having used X = b

If some later part of the program fails and causes backtracking, the goal will re-evaluate, and after some searching, produce two further success answers using X = e and X = g

Since X is not available outside intersect, it follows that the rest of the program will behave exactly the same, and simply cause two further failures

This can be avoided by

intersect(L1, L2) :-

once ( member(X,L1),

member(X, L2)).

But note that the behaviour of this new version may be incorrect if L1 and L2 are not full instantiated

intersect([a,b], [X1,X2]), X1 = b.

will fail because the first solution has X1 = a

 

Extended Example

Omitted

Design

Omitted

 

Finite Constraint Domains

(Chapter 3)

Examples

Map Colouring Problem

Colour a map of Australia using only the colours red, yellow, blue given the constraint that no two adjacent states have the same colour

N Queens Problem

Place N queens on an N*N chessboard in such a way that no queen is attacking another

Matching Problems

As discussed in the graph theory part of the course

Backtracking Solver

Essentially the solver we have discussed in chapters 5 & 7

 

Node & Arc Consistency

Node Consistency

A primitive constraint c is node consistent with domain D if either it has more than one variable, or if every element of D is a solution of c (and a general constraint is node consistent if all its primitive constraints are)

Node Consistency Algorithm

For each single-variable primitive constraint p in turn

restrict the values in the current domain to those which provide solutions to p

Example

consider the constraint

X < Y, Y < Z, Z <= 2

and domain {1,2,3}

This is not node-consistent, since Z = 3 is inconsistent with the third primitive constraint

Applying the algorithm we get

D(X) = {1,2,3}, D(Y) = {1,2,3}, D(Z) = {1,2}

 

Arc Consistency

A primitive constraint c is arc consistent with domain D unless it has exactly two variables X and Y, and for some value of X in D, there is no value of Y in D which satisfies the constraint (and a general constraint is arc consistent if all its primitive constraints are)

Arc Consistency Algorithm

For each two-variable primitive constraint p in turn

restrict the values in the current domain to those which provide solutions to p

Example

consider the constraint

X < Y, Y < Z, Z <= 2

and domain {1,2,3}

This is not arc-consistent, since X = 3 is inconsistent with the first primitive constraint

Applying the algorithm we get

D(X) = {1, 2}, D(Y) = {1,2,3}, D(Z)={1,2,3}

Applying it to variable Y, we get

D(X) = {1, 2}, D(Y) = {2}, D(Z)={1,2,3}

Finally, applying it to variable Z, we get

D(X) = {1, 2}, D(Y) = {2}, D(Z)={3}

 

Node-Arc Solver

Applying the node and arc consistency algorithms together allows us to solve problems which cannot be solved by either separately

 

Node-Arc Algorithm

Apply the node and arc consistency algorithms indeterminately until the constraints are both node and arc consistent

Example

consider the constraint

X < Y, Y < Z, Z <= 2

and domain {1,2,3}

Applying arc consistency as before, we get

D(X) = {1, 2}, D(Y) = {2}, D(Z)={3}

Applying node consistency, we get

D(X) = {1, 2}, D(Y) = {2}, D(Z)=f

A further application of arc consistency (checking X before Y) gives

D(X) = {1}, D(Y) = f , D(Z)=f

Applying node consistency again gives no further simplification, but a further application of arc consistency gives

D(X) = f , D(Y) = f , D(Z)=f

 

Bounds Consistency

Hyper-Arc Consistency

One obvious extension of arc consistency (hpyer-arc consistency) is to extend it to primitive constraints with more than two variables

For example, consider the constraint

X = 3Y + 5Z

with D(X) = {2,3,4,5,6,7}, D(Y) = {0,1,2}, D(Z) = {-1,0,1,2}

The first check we would perform would substitute 2 for X and test for solutions (in the domain) for

2 = 3Y + 5Z

In general, this problem (diophantine equations) is too expensive to be built into a constraint solver

A better approach takes into account the fact that the domains of X, Y and Z are in fact continuous domains of integers

An arithmetic primitive constraint c is bounds consistent with integer domain D unless there is a variable x in c for which either c(x® minD(x)) or c(x® maxD(x)) is unsatisfiable for real values

(note that checking for real values is much simpler than for integer values, but if there are no real values, then there are no integer values as a consequence)

Depending on the form of the constraints, we may be able to devise propagation rules, which given a current set of ranges for the variables, generate a new set of ranges which are bounds consistent

 

Monotonic Bounds Consistency Algorithm

(eg for linear inequalities)

Until constraint c is bounds consistent with domain D

Choose a variable x in a primitive constraint c' of

c giving rise to a bounds inconsistency

If there is no real value minD(x) < x < maxD(x)

for which c' can be satisfied

return "unsatisfiable"

else

If x is minimum bound inconsistent

increase minD(x) until bounds

consistency is restored

else

decrease maxD(x) until bounds

consistency is restored

Example: Smuggler's Knapsack

Smuggler's knapsack has a capacity of 9 units

Size and profit of smuggle-able items are:

item

size

profit

whiskey

4

15

perfume

3

10

cigarettes

2

7

The minimum profit (ie risk premium) for a trip is 30; what are acceptable cargoes?

Capacity: 4W + 3P + 2C <= 9

Profit: 15W + 10P + 7C >= 30

Domain is initially [0..¥ ] for each variable

Applying bounds consistency for capacity to W, P and C in turn gives

D(W) = [0..2], D(P) = [0..3], D(C)=[0..4]

The profit constraint is bounds-consistent with this domain

 

 

Propagation rules for particular classes of constraint can be quite difficult to find; most solvers have built-in linear inequalities and a limited range of other classes

The applicability of a particular propagation rule will depend directly on the particular primitive form the solver rewrites the initial constraint to

Thus it can be hard to predict which bounds reductions will be achieved by the solver

 

Some Special Consistency Predicates

If you have looked at the eclipse libraries, you may have wondered why each library has so many special predicates

It relates to the point above, namely that each particular primitive constraint may have specific bounds consistency propagation rules

In many cases, complex constraints may have stronger propagation rules than the rules which could have been derived from more primitive constraints in terms of which they could have been defined

Example: alldifferent

alldifferent([V1,...,Vn])

asserts that the elements of the list are all distinct

It could be modeled by a conjunction of pairwise inequalities

Apart from the efficiency issue that n2 inequalities are required, there is also a constraint propagation issue

A propagation rule for alldifferent can require that a valid domain for currently free variables has at least as many values as the number of variables remaining free

On the other hand, if the problem is specified in terms of pairwise inequalities, there is no equivalent constraint which can be specified in terms of any particular primitive constraint

 

Example: cumulative

cumulative([S1,...,Sm],[D1,...,Dm],[R1,...Rm],L)

specifies that there are m tasks

The ith task starts at time Si, and requires Ri resources for duration Di; at any instant, only L resources are available

Cumulative could be defined more simply as a set of multiplicative equalities and inequalities, but propagation rules for cumulative could not be derived from those for the primitive constraints

Example: element

element(i,[V1,...,Vm],X)

specifies that X is the ith element of [V1,...,Vm] (it may also be required that the Vi are ordered)

The obvious propagation rules then permit the domains for i and for X to be closely linked, in ways which would not be possible if the constraint were re-rewritten in terms of primitive constraints

Optimisation for Arithmetic CSPs

Omitted