You are on page 1of 10

Constraint Logic Programming (CLP)

using Constraint Solving

Like Logic Programming, CLP uses the resolution


principle. However, unification has been replaced by
constraint solving over an application domain.

Depending on the particular CLP language and


computation domain, different constraint solvers and
techniques may be employed.

These might include symbolic AI methods, simplex and


branch-and-bound methods from the Operations Research
world, as well as techniques for symbolic equation
solving developed by the Computer Algebra community.

Of key importance in the design and implementation of


constraint-solvers for these languages has been:

• efficiency in dealing with simple constraints, which


are the most commonly occurring,

• incrementality, so that solving extra constraints does


not involve re-solving the original set,

• a internal representation that facilitates efficient


backtracking.
CLP improves on Logic Programming when dealing with
constrained search problems, by providing:

• more expressive languages in which a user can work


directly with objects from the intended domain and
employ the natural constraints for that domain, and

• far more efficient execution employing specialized


methods and algorithms.

Jaffar and Lassez have given the formal definition of a


general framework or schema from which many
constraint logic programming languages can be derived.
Each instance of this scheme is obtained by specifying a
particular structure of computation <D, F, R>,
comprising:

• a computation domain D (e.g., natural numbers, reals,


booleans, strings);
• a collection of functions (i.e., operators) F in D (e.g.,
+, -, *, &);
• a collection of relations (i.e., constraints) R in D (e.g.,
= , >, =<).

together with a constraint solver for R over F in D (for


deciding the satisfiability of the constraints).

Jaffar and Michaylov developed the language CLP(),


Constraint Logic Programming over the Reals, mainly
as a demonstrator of their broader Constraint Logic
Programming schema.
CLP()

The domain of computation comprises the reals and trees


of reals.

Real constants and variables are arithmetic terms.

If t1, t2 are arithmetic terms,


then so are: (t1 + t2), (t1 - t2), (t1 * t2) and (t1 / t2).

Arithmetic terms, uninterpreted constants and variables


are all terms.

If f is an n-ary uninterpreted functor and t 1,..., tn are


terms, then so is the tree f(t1,..., tn).

An equation or inequality between arithmetic terms is an


arithmetic constraint, solvable when there exists a
substitution for its variables that makes it true in the
obvious way.

Two trees are equal when they share the same root
functor and the corresponding subtrees are equal.
A CLP(R) program consists of a finite number of rules:

A0 :- C1, C2, ..., Cn, A1, A2, ..., Am.

where n, m  0 ,

Ci are arithmetic constraints


Ai are "atoms" of the form p(X1, ..., Xn)
where p is a predicate symbol, the Xi are terms

A CLP(R) goal is of the form:

?- C1, C2, ..., Cn, A1, A2, ..., Am

where n, m  0 , n + m  1 ,

Ci are arithmetic constraints


Ai are atoms

An atom or subcollection of atoms in a goal is a:


subgoal.

If A, B are two atoms with the same predicate symbol, A


= B is used to signify the collection of equations between
corresponding arguments in these two atoms.

For example:
if A is resistor(X, Y, 5) and
B is resistor(2, 8, Z) ,

then A = B denotes {X = 2, Y = 8, Z = 5} .

The CLP(R) operational model:

Let P denote a CLP(R) program.

Let G1, G2 be two goals containing the collections C1,


C2 of constraints.

Assume that both C1 and C2 are solvable.

There is a derivation step from G1 to G2 if:

• G1 is of the form
?- C1, A1, A2, ..., Am , where m  1

• P contains a rule of the form


B0 :- C2, D1, D2, ..., Dk , where k  0

• G2 is of the form
?- C1, C2, Ai = B0, A1, A2, ..., Ai-1, Ai+1, ..., Am,
D1, D2, ..., Dk ,
where 1  i  m

Ai in G1 is called the selected subgoal,


or the subgoal in G1 chosen to be reduced.
A derivation sequence is a (possibly infinite) sequence
of goals in which there is a derivation step to each goal
from the preceding goal.

A derivation sequence is successful if it is finite and its


last goal contains only arithmetic constraints.

Such constraints are called answer constraints.

Answer constraints constitute the output of a CLP(R)


program, facilitating symbolic output.

A finitely-failed derivation sequence is a non-successful


finite sequence, where no derivation step is possible from
its last goal.

A CLP(R) program and goal are executed by a process


of continually reducing any remaining atoms in the
subgoal.

In obtaining a derivation sequence the CLPR()


interpreter:

• employs Prolog’s left-to-right atom selection rule


• employs Prolog’s top-to-bottom depth-first search
strategy,

Consider the following CLP() program for the factorial


of a number:

fact(0, 1).
fact(N, N*F) :-
N > 0,
fact(N-1,F).

Steps in the computation of the goal ?- fact(N0, 6):

?- fact(N0, 6).

?- N1 > 0, N0 = N1, 6 = N1*F1,


fact(N1-1, F1).

(tries first clause and fails, then tries second clause)

?- N1 > 0, N0 = N1, 6 = N1*F1,


N2 > 0, N1-1 = N2, F1 = N2*F2,
fact(N2-1,F2).

(tries first clause and fails, then tries second clause)

?- N1 > 0, N0 = N1, 6 = N1*F1, N2 > 0,


N1-1 = N2, F1 = N2*F2, N2-1 = N3,
F2 = N3*F3, fact(N3-1,F3).

(tries first clause)

?- N1 > 0, N0 = N1, 6 = N1*F1, N2 > 0,


N1-1 = N2, F1 = N2*F2, N3 > 0,
N2-1 = N3, F2 = N3*F3, N3-1 = 0,
F3 = 1.

Solving the final constraint set, with respect to N0, we


obtain: N0 = 3.

The following mortgage calculation CLP() program:

mortgage(Principal, Time, Rate, Balance, Payment) :-


0 < Time, Time <= 1,
Balance + Payment = Principal * (1 + Rate * Time).
mortgage(Principal, Time, Rate, Balance, Payment) :-
1 < Time,
mortgage(Principal * (1 + Rate) - Payment, Time - 1, Rate, Balance, Payment).

will yield the following answers to queries:

?- mortgage(120000, 120, 0.01, 0, Payment)


Payment = 1721.65

?- mortgage(Principal, 120, 0.01, 0, 1721.65)


Principal = 120000

?- mortgage(Principal, 120, 0.01, 0, Payment)


Payment = 0.0143471 * Principal

?- mortgage(Principal, 120, 0.01, Balance, Payment)


Balance = (3.30039 * Principal) - (230.039 * Payment)
?- mortgage(999, 3, Rate, 0, 400)
400 = (-400 + (599 + 999 * Rate) * (1 + Rate)) * (1 + Rate)

The third and fourth cases are examples of partial evaluation. In the fifth case CLP() cannot determine whether the
answer constraint is solvable or not. Actually, the answer is not entirely useless, since the polynomial is solvable
and yields the correct solution for Rate.

The following CLP() program for selecting components in an electrical circuit:


ohmlaw(V, I, R) :-
V = I * R.

kirchoff(L) :-
sum(L, 0). Voltage V2
R1

sum([ ], 0).
sum([H|T], N) :-
N = H + M,
sum(T, M).
V
availres(10).
availres(14). R2
availres(27).
availres(60).
availres(100).

availcell(10).
availcell(20).

Consider the query:

?- 14.5 < V2, V2 < 16.25,


availres(R1),
availres(R2),
availcell(V),
ohmlaw(V1, I1, R1),
ohmlaw(V2, I2, R2),
kirchoff([I1, -I2]),
kirchoff([-V, V1, V2])

The constraint in the first line is found to be solvable and the system proceeds to expand the atoms in the goal. Each
possible expansion of the first three atoms gives an instance a, b, c or R1, R2 and V. To the problem:
14.5 < V2 < 16.26, V1/a - V2/b = 0, V1 + V2 = c

CLP() computes the three sets of solutions: V = 20, R1 = 10, R2 = 27,


V = 20, R1 = 14, R2 = 60,
V = 20, R1 = 27, R2 = 100.

A CLP(R) program for loan(P, I, S) which means that the series of (not necessarily uniform) payments S - expressed
as a list - exactly repays loan P, at rate of interest I.
loan(0, I, []).
loan(P, I, [X|Y]) :-
loan((1+I)*P - X, I, Y).

A program in CLP(R) for the predicate power(X, N, P) meaning that P is the value of number X raised to
the power of positive integer N:
power(X, 0, 1).
power(X, N, X*Y) :-
N > 0,
power(X, N-1, Y).

Here are the execution steps involved when the query


?- power(3, 2, P)
is posed in CLP(R):

?- power(3, 2, P)
?- X1 = 3, N1 = 2, X1 * Y1 = P, N1 > 0,
power(X1, 1, Y1)

?- X1 = 3, N1 = 2, X1 * Y1 = P, N1 > 0,
X2 = X1, N2 = 1, X2 * Y2 = Y1, N2 > 0,
power(X2, 0, Y2)

?- X1 = 3, N1 = 2, X1 * Y1 = P, N1 > 0,
X2 = X1, N2 = 1, X2 * Y2 = Y1, N2 > 0,
X2 = X3, Y2 = 1

The final constraint set can be solved for P, and yields P = 9.

Newton’s method of finding a numerical solution to the equation xn = a , where n is a positive integer, involves
making an initial guess x0, and then iteratively calculating a series of values xi, where:

until the value of xin is sufficiently close to a.

Here is a program in CLP(R) that uses this method to find the nth root of a real number, to any given precision:

root(Y, N, R, R, E) :-
power(R, N, P),
P < Y + E,
P > Y - E.
root(Y, N, R1, R2, E) :-
power(R1, N, P),
(P >= Y + E ; P <= Y - E),
power(R1, N-1, P1),
R3 = ((N-1)*R1 + Y/P1)/N,
root(Y, N, R3, R2, E).

where the equation is of the form X N = Y , E represents the required degree of precision (the largest permitted error), R1 is
the current value and R2 the next value.

You might also like