swi-prolog abs operator not working in clpfd module - prolog

I am doing some toy tests with the CLPFD library in swi-prolog.
Does anybody know why the program below does not work?
start(X,Y):-
Vars = [X,Y],
Vars ins 1..3,
abs(X-Y) #>= 2,
X #>= Y,
nl,
write([X,Y]), nl.
The expected answer for start(X,Y) would be X=3 and Y=1. However, swi-prolog indicates me multiple answers. The program works properly if I replace
abs(X-Y) #>= 2
by
X-Y #>= 2
My question is whether I am using the abs operator in the right way.

First of all, constraints and side-effects do not flock together. Instead, simply stick to the pure part of your program:
start(X,Y):-
Vars = [X,Y],
Vars ins 1..3,
abs(X-Y) #>= 2,
X #>= Y.
And now, query your relation:
?- start(X,Y).
X in 1..3, X#>=Y, abs(X-Y)#>=2, Y in 1..3.
The answer is a conditional one:
Yes, there are solutions for X and Y provided all these conditions hold.
To get actual values, you have to eliminate all these conditions. You have several options:
In this case, you can use labeling/2:
?- start(X,Y), labeling([], [X,Y]).
X = 3, Y = 1.
So there is exactly one solution. The clpfd-solver alone was not powerful enough to come to this conclusion, it needed some extra help.
Even better would be to use contracting/1:
?- start(X,Y), clpfd:contracting([X,Y]).
X = 3, Y = 1.
In contrast to labeling, contracting tries to reduce the size of the domain without (visible) search. This makes the solver a bit stronger.
Reasons why the solver is not powerful enough
in the very general case solving such arithmetic problems is undecidable.
in more specific cases the algorithms would be extremely costly. In fact, there is more than one diophant in the room.
even simpler algorithms are very costly in terms of both implementation effort and runtime.
for many situations, the solver boils down to maintaining consistencies within one constraint1. So the only way to "communicate" between different constraints are the domains of variables.
In your case, the abs-constraint admits more solutions!
?- [X,Y]ins 1..3, abs(X-Y)#>=2, labeling([],[X,Y]).
X = 1, Y = 3
; X = 3, Y = 1.
?- [X,Y]ins 1..3, X-Y#>=2, labeling([],[X,Y]).
X = 3, Y = 1.
What you expect is that the extra constraint X #>= Y would help. Alas, the concrete consistency mechanisms are too weak. And not even X #> Y helps:
?- [X,Y]ins 1..3, abs(X-Y)#>=2, X#>Y.
X in 2..3, Y#=<X+ -1, abs(X-Y)#>=2, Y in 1..2.
However, if you switch from SWI to SICStus, things are a bit different:
| ?- assert(clpfd:full_answer).
| ?- X in 1..3, Y in 1..3, abs(X-Y)#>=2.
Y+_A#=X, X in 1..3, Y in 1..3, _A in{-2}\/{2}.
| ?- X in 1..3, Y in 1..3, abs(X-Y)#>=2, X#>Y.
X = 3, Y = 1.
Please note how abs is resolved!
And using SICStus with library(clpz) has the same strength:
| ?- X in 1..3, Y in 1..3, abs(X-Y)#>=2, X#>Y.
X = 3, Y = 1.
1 Note that I avoid to use the notion of local consistency as opposed to global consistency, since quite often also global consistency only refers to consistency within one "global" constraint.

Related

Prolog: How do I list the different values that X and Y could be using prolog's clpfd library?

test(X, Y) :-
X ins 1..3,
Y ins 1..3,
X #\= Y.
Here is my attempt at doing it. The goal would be to type this into SWI-Prolog so that this output comes out.
?- test(X, Y).
X = 1
Y = 2 ;
X = 2,
Y = 1;
X = 3,
Y = 1 ;
... etc.
I'm actually trying to solve the 8-queens problem using prolog and have this so far.
eight_queens(Qs, L) :-
Qs = [ [X1,Y1], [X2, Y2], [X3, Y3], [X4, Y4], [X5, Y5], [X6, Y6], [X7, Y7], [X8, Y8], [X9, Y9] ],
Qs ins 1..9,
X1 #\= X2,
X1 #\= X3,
...
etc.
But I keep getting this error: "Arguments are not sufficiently instantiated" for both the test function and the eight_queens problem.
Besides the observation about in/2 and ins/2 posted by #coder, that solve your imminent problem, I would add the following points that are good to keep in mind when using CLP(FD):
1. Always make labeling the last goal
First let's observe the answers for the variant marked as 2nd way using ins in #coder's post but without the goal label/1:
test(X, Y) :-
[X,Y] ins 1..3,
X #\= Y.
?- test(X,Y).
X in 1..3, % residual goal
X#\=Y, % residual goal
Y in 1..3. % residual goal
Since there is no unique answer to the query, Prolog answers with residual goals (see section A.8.8 of the CLP(FD) manual) for more information). These residual goals are constraints that are being propagated and with every additional (non-redundant) constraint the domain is narrowed. If this does not lead to a unique solution like in the example above you can get concrete values by labeling the constrained variables (e.g. with label/1). This observation suggests to use labeling as the last goal:
?- test(X,Y), label([X,Y]).
X = 1,
Y = 2 ;
X = 1,
Y = 3 ;
X = 2,
Y = 1 ;
X = 2,
Y = 3 ;
X = 3,
Y = 1 ;
X = 3,
Y = 2.
This is obviously the same result as with #coders version but the three pairs (X,Y) = (1,1) ∨ (2,2) ∨ (3,3) are not considered when labeling due to the constraint X#\=Y being posted before the goal label([X,Y]). In #coder's version it is the other way around: label([X,Y]) is delivering all three pairs as possible solutions and the last goal X#\=Y is eliminating them subsequently. To see this just leave the last goal as a comment and query the predicate:
test(X,Y):- [X,Y] ins 1..3, label([X,Y]). %, X#\=Y.
?- test(X,Y).
X = Y, Y = 1 ; % <- (1,1)
X = 1,
Y = 2 ;
X = 1,
Y = 3 ;
X = 2,
Y = 1 ;
X = Y, Y = 2 ; % <- (2,2)
X = 2,
Y = 3 ;
X = 3,
Y = 1 ;
X = 3,
Y = 2 ;
X = Y, Y = 3. % <- (3,3)
The difference is minuscule in this example, so there's nothing wrong with #coder's version. But in general this might lead to a big difference if the constraints posted after labeling exclude a lot of candidates. So it's good practice to always put labeling as the last goal.
2. Separate labeling from the actual relation
Coming from the previous observations it is opportune to divide the predicate into a core relation that is posting all the constraints and labeling. Consider the restructured predicate test/2 as a template:
test(X,Y) :-
test_(X,Y,L), % the core relation
label(L). % labeling
test_(X,Y,L) :-
L=[X,Y], % variables to be labeled in a flat list
L ins 1..3,
X#\=Y.
The predicate test_/3 is describing the actual relation by posting all the necessary constraints and has a list as an additional argument that contains all the variables to be labeled. Obtaining the latter might not be trivial, depending on the data structures your arguments come with (consider for example a list of lists as an argument that you want to turn into a flat list for labeling). So the predicate test/2 is only calling test_/3 and subsequently the labeling goal. This way you have a clean and easily readable separation.
3. Try different labeling strategies
The goal label(L) is the simplest way to do labeling. It is equivalent to labeling([],L). The first argument of labeling/2 is a list of options that gives you some control over the search process, e.g. labeling([ff],L) labels the leftmost variable with the smallest domain next, in order to detect infeasibility early. Depending on the problem you are trying to solve different labeling strategies can lead to results faster or slower. See the documentation of labeling/2 for available labeling strategies and further examples.
ins is used for lists, in is used for single variable so in your example:
test(X, Y) :-
X ins 1..3,
Y ins 1..3,
X #\= Y.
X,Y are assumed to be lists. This does not produces a syntax error, but produces error when trying to run it with X,Y not being lists.
Also when using in Low..High doesn't mean that the variable is int just X=<High and X>=Low. In order to put the constraint to be integers use label/1:
:- use_module(library(clpfd)).
%using in/
test(X,Y):- X in 1..3,Y in 1..3,label([X,Y]), X#\=Y.
%2nd way using ins
test(X,Y):- [X,Y] ins 1..3, label([X,Y]), X#\=Y.
Example:
?- test(X,Y).
X = 1,
Y = 2 ;
X = 1,
Y = 3 ;
X = 2,
Y = 1 ;
X = 2,
Y = 3 ;
X = 3,
Y = 1 ;
X = 3,
Y = 2 ;
false.

How to determine the outcome of queries for constraint logic programming

I am doing some revision for constraint logic programming and wanted to know how I can read the following queries in order to predicate their results correctly.
Basically there is a question which asks whether or not the answer provided by the following query is correct or not.
So this is the question
Consider the following queries and answers. Some answers coincide
with what SWI-Prolog would infer whereas others are erroneous.
Indicate which answers are genuine and which ones are fake (no
explanation is required).
(i) ?- [X, Y, Z] ins 0 .. 4, X #= Y + 1.
X in 1..4, Y in 0..3, Z in 0..4.
(ii) ?- [X, Y, Z] ins 0 .. 4, X #= Y + Z.
X in 0..4, Y in 0..2, Z in 0..2.
(iii) ?- [X, Y, Z] ins 0 .. 4, X #= Z - Y.
X in 0..4, Y in 0..4, Z in 0..4.
(iv) ?- [X, Y, Z] ins 0 .. 4, X #= Y * Y, Z #= -Y.
Y = 0, Z = 0.
My question is what is the best way to read the query in order to determine whether the answer is correct or not.
Several steps:
Is the shown answer a syntactically valid Prolog goal? If not, then the answer is definitely fake, because the actual toplevel only emits syntactically valid residual goals.
Moving on: Are there any solutions of the original query that are precluded by the shown residual goals? If yes (= incompleteness), then the answer is fake, because the actual toplevel only emits residual goals that are semantically equivalent to the original query.
Conversely, do the residual goals admit a solution that the initial query does not? If yes (= overly general), then the answer is fake. Exercise: Why?
In your case, the shown answer is a syntactically valid conjunction, so it is definitely a candidate for a correct solution. However, the answer admits solutions (exercise: which?) that the original query does not, and so the answer is not correct.

Residual constraints with reification in clpfd

I defined reified variants of the
clpfd constraints (#<)/2, (#=<)/2, (#>=)/2 and (#>)/2:
:- use_module(library(clpfd)).
ltA(X,Y,Truth) :- X #< Y #<==> B, bool01_truth(B,Truth).
ltB(X,Y, true) :- X #< Y.
ltB(X,Y,false) :- X #>= Y.
lteA(X,Y,Truth) :- X #=< Y #<==> B, bool01_truth(B,Truth).
lteB(X,Y, true) :- X #=< Y.
lteB(X,Y,false) :- X #> Y.
gteA(X,Y,Truth) :- X #>= Y #<==> B, bool01_truth(B,Truth).
gteB(X,Y, true) :- X #>= Y.
gteB(X,Y,false) :- X #< Y.
gtA(X,Y,Truth) :- X #> Y #<==> B, bool01_truth(B,Truth).
gtB(X,Y, true) :- X #> Y.
gtB(X,Y,false) :- X #=< Y.
Of course, ltA/3 and ltB/3 are logically equivalent, as are
lteA/3 and lteB/3, gteA/3 and gteB/3, and gtA/3 and gtB/3.
The answers I get using these predicates, however, differ regarding size and readability. I ran the following queries with SWI-Prolog 7.1.37:
Good news, first!
?- lteA(X,Y,Truth).
Truth = false, Y#=<X+ -1 ;
Truth = true, Y#>=X.
?- lteB(X,Y,Truth).
Truth = true, Y#>=X ;
Truth = false, Y#=<X+ -1.
?- gteA(X,Y,Truth).
Truth = false, X#=<Y+ -1 ;
Truth = true, X#>=Y.
?- gteB(X,Y,Truth).
Truth = true, X#>=Y ;
Truth = false, X#=<Y+ -1.
Ok! But what about the other two?
?- ltA(X,Y,Truth).
Truth = false, X+1#=_G968, Y#=<_G968+ -1 ;
Truth = true, X+1#=_G912, Y#>=_G912.
?- ltB(X,Y,Truth).
Truth = true, X#=<Y+ -1 ;
Truth = false, X#>=Y.
?- gtA(X,Y,Truth).
Truth = false, X#=<_G1301+ -1, Y+1#=_G1301 ;
Truth = true, X#>=_G1243, Y+1#=_G1243.
?- gtB(X,Y,Truth).
Truth = true, Y#=<X+ -1 ;
Truth = false, Y#>=X.
Not quite!
How do I get compact answers with ltA/3 and gtA/3---just like with lteA/3 and gteA/3?
It runs counter the basic idea of CLP(FD) to have compact
answers. Since CLP(FD) usually doesn't do gauss elimination and
similar things. Its not like a Computer Algebra System (CAS).
In CLP(FD), you basically model your problem by entering
inequations, and the system is allowed to do nothing with this
inequations as long as you don't call labeling.
Some CLP(FD) realizations already check consistency to some
degree when entering inequations and/or already do simplifications
and propagations. But this isnt mandatory.
In your example you have E #= X where E is an expression and
X is a variable. There is no guarantee that occurences
of X are replaced by E when entering a model.
Usually this is not done in CLP(FD), since it would blow
up the entered model. You can directly test that this
is not simplified:
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.4)
Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam
?- use_module(library(clpfd)).
true.
?- A#=X+1, Y#=<A+ -1.
Y#=<A+ -1,
X+1#=A.
The same also happens in Jekejeke Prolog. The CLP(FD) of
Jekejeke Prolog is open source here. Refification itself
is planned but not yet implemented:
Jekejeke Prolog, Runtime Library 1.0.7
(c) 1985-2015, XLOG Technologies GmbH, Switzerland
?- use_module(library(finite/clpfd)).
% 11 consults and 0 unloads in 513 ms.
Yes
?- A#=X+1, Y#=<A+ -1.
A #= 1+X,
-1+A #>= Y
Typicall an equation E #= X only leads to substitutions when
E is also a variable or constant. This might explain why your
examples look different from case to case.
Here you see SWI-Prolog simplifying A #= X. I just modified
the above example slightly so that E is a variable:
?- A#=X, Y#=<A+ -1.
A = X,
Y#=<X+ -1.
And here you see Jekejeke Prolog doing it (Todo bug fix: I
guess I need to reorder the rules a little bit, so that it
gives A = X and not X = A as here):
?- A#=X, Y#=<A+ -1.
X = A,
-1+A #>= Y
The case of E #= X where E is a constant and where this
value is propagated is called forward checking. This is the
minimum requirement a CLP(FD) must be able to do, otherwise
labeling would not work.
But already the case of E #= X where E is a variable a
propagation isn't mandatory. But the testing above shows
that many CLP(FD) do it. Propagating variables leads to
union find algorithms and the like.
Bye

Prolog: How can I implement the sum of squares of two largest numbers out of three?

Exercise 1.3 of the book Structure and Interpretation of Computer Programs asks the following:
Define a procedure that takes three numbers as arguments and returns the sum of the squares of the two larger numbers.
I'm learning Prolog. Here's the function I tried to implement:
square(X, Y) :- Y is X * X.
squareTwoLargest(X, Y, Z, R) :-
R is square(L1) + square(L2), L1 = max(X, Y), L2 = max(min(X, Y), Z).
However, when I run it, it gives the following error: ERROR: is/2: Arguments are not sufficiently instantiated. I think I'm not only not getting Prolog's syntax, but I'm also not getting the logic programming paradigm yet. So, how could I implement this function in good logic programming style?
To get the two largest numbers out of three (V1, V2, and V3) you can proceed as follows: Sort the list [V1,V2,V3] and take the last two list items [_,X,Y], square and sum them.
:- use_module(library(lists)).
:- use_module(library(clpfd)).
squareTwoLargest(V1,V2,V3, R) :-
Zs = [_,X,Y],
chain(Zs, #=<),
permutation([V1,V2,V3],Zs),
R #= X*X + Y*Y.
Sample query:
?- squareTwoLargest(20,30,10, R).
R = 1300
Better implementation
Above code is based on "permutation sort", which makes it inefficient in more than one way.
The goal squareTwoLargest(X,Y,Z, R) succeeds multiple times and gives redundant answers, if two or more of X, Y, and Z are equal. This is shown by the following two queries:
?- squareTwoLargest(0,10,10, R).
R = 200 ;
R = 200 ;
false.
?- squareTwoLargest(10,10,10, R).
R = 200 ;
R = 200 ;
R = 200 ;
R = 200 ;
R = 200 ;
R = 200 ;
false.
We can eliminate the redundant answers by using a sorting network of size 3. For details, look at this answer to the question
ordering lists with constraint logic programming.
list_sorted__SN3([A0,A1,A2], [D0,D1,C2]) :-
B1 #= min(A1,A2), B2 #= max(A1,A2),
C0 #= min(A0,B2), C2 #= max(A0,B2),
D0 #= min(C0,B1), D1 #= max(C0,B1).
squareTwoLargest__SN(V1,V2,V3, R) :-
list_sorted__SN3([V1,V2,V3],[_,X,Y]),
R #= X*X + Y*Y.
Consider the following queries:
?- squareTwoLargest__SN(20,30,10, R).
R = 1300. % works like it did before
?- squareTwoLargest__SN(20,20,10, R).
R = 800. % succeeds deterministically
?- squareTwoLargest__SN(20,20,20, R).
R = 800. % succeeds deterministically
Note that all redundant answers of the corner cases shown above have been eliminated.
Unfortunately, max function you are using, is built-in arithmetic function and does not behave as a predicate, this may trick you into thinking that you will write your predicates in the same way.
In Prolog, what you will be writing is predicates. Predicate does not return any value, it just holds or does not hold (you can think of it as if it returned true or false). Your predicate square is a good example, what it square(X,Y) really means is 'Y is square of X'. If you ask Prolog console square(4, 16)., it will tell you true. If you ask square(4, 44), it will tell you false. So how do you find out square root of some number? You ask Prolog a question with free (unknown) variable square(4,R)., then Prolog will tell you that R=16. That is the important part of logical programming, you do not explain Prolog, how to calculate square, you only tell Prolog what square is in terms of logic and then you ask Prolog question and it will find answer by itself.
Soo what if you try instead of
R is square(L1) + square(L2)
something like
square(L2, L2SQUARED), square(L1, L1SQUARED), ...
which will give you square of L1 in L1SQUARED
However, L1 must not be free variable, Prolog must be able to deduce some value for it based on some other predicates (...), so that it can answer to square(L1, L1SQUARED). Imagine question square(SOMETHING1, SOMETHING2), where both arguments are unknown, what will the answer be? There is infinite number of correct answers, for example [2, 4] or [3, 9] etc.
Note: yes, it can be onliner with arithmetics, but if you want to learn logical programming, try more 'logical programming' like approach. In some flavours of Prolog, you do not get arithmetics and they are still useful...
my bet, using the 'if-then-else' construct.
squareTwoLargest(X, Y, Z, R) :-
( X > Y -> A = X, B = Y ; A = Y, B = X ),
R is A + max(B, Z).
Two temp variables are needed.

Prolog Beginner: How to unify with arithmetic comparison operators or how to get a set var to range of values

I am new to Prolog. I need to write an integer adder that will add numbers between 0-9 to other numbers 0-9 and produce a solution 0-18. This is what I want to do:
% pseudo code
add(in1, in2, out) :-
in1 < 10,
in2 < 10,
out < 18.
I would like to be able to call it like this:
To check if it is a valid addition:
?- add(1,2,3).
true.
?- add(1,2,4).
false.
With one missing variable:
?- add(X,2,3).
X = 1.
?- add(1,4,X).
X = 5.
With multiple missing variables:
?- add(X,Y,Z).
% Some output that would make sense. Some examples could be:
X=1, Y=1, Z=2 ;
X=2, Y=1, Z=3 ......
I realize that this is probably a pretty simplistic question and it is probably very straightforward. However, according to the Prolog tutorial I am using:
"Unlike unification Arithmetic Comparison Operators operators cannot be used to give values to a variable. The can only be evaluated when every term on each side have been instantiated."
All modern Prolog systems provide finite domain constraints, which are true relations that can (in contrast to more low-level arithmetic predicates like is/2 and >/2) be used in all directions. In SWI-Prolog:
:- use_module(library(clpfd)).
plus(X, Y, Z) :-
[X,Y] ins 0..9,
X + Y #= Z.
Results for your examples:
?- plus(1,2,3).
true.
?- plus(1,2,4).
false.
?- plus(X,2,3).
X = 1.
?- plus(1,4,X).
X = 5.
?- plus(X,Y,Z).
X in 0..9,
X+Y#=Z,
Y in 0..9,
Z in 0..18.
Since the predicate can be used in all directions, it does no longer make sense to call it "add/3", as that would imply a direction, but the predicate truly describes when the relation holds and is thus more general.
What about this?:
add(X,Y,Z) :-
Z is X + Y,
X < 10,
Y < 10,
Z < 19.
Problem: this works nicely for queries of the form add(1,1,X) because Z's instantiated before the < calls, but fails when you ask add(X,1,2). You could use var/1 to distinguish the kind of query (var/1 tells you whether a variable's uninstantiated or not), but that sounds like a lot of pain.
Solution:
lessThanTen(9).
lessThanTen(8).
lessThanTen(7).
lessThanTen(6).
lessThanTen(5).
lessThanTen(4).
lessThanTen(3).
lessThanTen(2).
lessThanTen(1).
lessThanTen(0).
addSimple(Add1,Add2,Sol) :-
lessThanTen(Add1),
lessThanTen(Add2),
Sol is Add1+Add2.

Resources