SWI Prolog Clpfd Library - Reification - prolog

I have an upcoming Logic exam and have been studying some past papers from my course. I've come across a question regarding reification and have posted it below;
Illustrate reification by using it to express the property that a variable B can
either take the value of 1 or 8.
After reading some resources and looking at the SWI Prolog manual, I still find the concept of reification quite confusing (primarily studying Java so the switch to learning Prolog has been difficult). It's quite confusing having to use boolean logic within the prolog query.
Without reification, I would have to write the following code (which I know is far too long to be the correct answer);
B in 1..8, B #\= 2,B #\= 3,B #\= 4,B #\= 5,B #\= 6,B #\= 7.
Would really appreciate if someone could show me the above query, but using reification.

From the documentation:
The constraints in/2, #=/2, #\=/2, #/2, #==/2 can be reified, which means reflecting their truth values into Boolean values represented by the integers 0 and 1. Let P and Q denote reifiable constraints or Boolean variables, then:
...
P #\/ Q True iff either P or Q
...
For you, it seems P is B #= 1 and Q is B #= 8, so you end up with:
?- B #= 1 #\/ B #= 8.
B in 1\/8.
As you see, you are not really using the reified values. You are just using reification as a round-about way of declaring the domain of your variable. The answer to your query, B in 1 \/ 8, is what you would probably use directly if you wanted to say that "B is either 1 or 8". If you look carefully at the documentation of in/2, you should see that the domain can be either an integer, a range Lower .. Upper, or the union of Domain1 \/ Domain2. In your case both domains are a single integer, 1 and 8.
PS: Once you go down that road, why not:
?- B in 1..8 #/\ #\ B in 2..7.
B in 1\/8.
B is in [1,8] AND B is not in [2,7].
The possibilities are endless :)

First, try out your query:
?- B in 1..8, B #\= 2,B #\= 3,B #\= 4,B #\= 5,B #\= 6,B #\= 7.
B in 1\/8.
This tells you that your query is equivalent to the single goal B in 1\/8.
From this, you see that you don't need reification to express that a finite domain variable is either equal to 1 or 8.
Reification allows you to reify the truth value of the constraint. For example, you can say:
?- T #<==> B in 1\/8.
T in 0..1,
B in 1\/8#<==>T.
?- T #<==> B in 1\/8, B = 3.
T = 0,
B = 3.
From the second query, you see that if B = 3, then T = 0, because the constraint B in 1\/8 doesn't hold in that case.
Reifying a constraint can be useful if you want to reason about constraints themselves. For example, this allows you to express that a certain number of list elements must be equal to a given integer. I leave solving this as a more meaningful exercise to understand reification.

Initially I was thinking along the same lines as #Boris and #mat. But after pondering the question for a while, another possible interpretation of the task occured to me. However, keep in mind that I am not familiar with your course material, so this is highly speculative. That being said, maybe the task description is asking to write a predicate that evaluates to true if the above property holds or to false otherwise. A predicate like that could be defined as:
val_either_or_t(X,Y,Z,true) :-
( X#=Y ; X#=Z).
val_either_or_t(X,Y,Z,false) :-
X #\= Y,
X #\= Z.
I admit the name is a little clumsy but I couldn't really come up with a better one. Anyway, it does the job according to the task interpretation I described above:
?- val_either_or_t(X,1,8,T).
T = true,
X = 1 ? ;
T = true,
X = 8 ? ;
T = false,
X in inf..0\/2..7\/9..sup
?- val_either_or_t(X,Y,Z,T).
T = true,
X = Y,
X in inf..sup ? ;
T = true,
X = Z,
X in inf..sup ? ;
T = false,
X#\=Z,
X#\=Y
I came up with this idea because lately I was playing around with some reifying predicates that I found on Stackoverflow, and it popped into my mind that the task might be aimed in a direction where the described property could be used as a condition with such predicates. For example with if_/3 that I used a lot with (=)/3 in the condition, but why not use it with something like val_either_or_t/4. Consider the following minimal example:
a(condition_was_true).
b(condition_was_false).
somepredicate(X,Y) :-
if_(val_either_or_t(X,1,8),a(Y),b(Y)).
With the respective query:
?- somepredicate(X,Y).
X = 1,
Y = condition_was_true ? ;
X = 8,
Y = condition_was_true ? ;
Y = condition_was_false,
X in inf..0\/2..7\/9..sup
This example is of course not very meaningful and only intended to illustrate how reification of the given property might be used. Also, I am using the atoms true and false to reify the thruth values with regard to using them with if_/3. However, you can also use 1 and 0 to reify truth values like in #mat's example. Just replace the 4th argument in the definition of val_either_or_t/4 by 1 and 0 respectively. Furthermore you might find the refinement of this idea that was suggested by #repeat in the comments interesting as well.

Related

Prolog - Constraint Library - Variable Scope

I'm working on trying to solve an LSAT logic problem with Prolog. I'm trying to get Prolog to tell me whether possible values for actors in a line are valid.
I wrote the following:
:- use_module(library(clpfd)).
actor("Jeff",A) :-
A #>= 0,
A #<5.
actor("Rich",C) :-
C #>= 0,
C #<5,
actor("Jeff",A),
A #< C.
When I query:
?- actor("Rich",0).
false.
Which is right since Jeff is < than Rich and Jeff is => 0 so Rich cannot be 0.
But, when I query:
?- actor("Jeff",1), actor("Rich",1).
true
I also get true, which is impossible because Rich > Jeff.
I feel the problem is because of something going on with my variable. I don't understand how
actor("Jeff",A),
A #< C.
is evaluating. It seems to me that actor("Jeff",A) should be set to actor("Jeff",1) and then 1 #< 1 should fail.
Variables within a clause or local to that clause.
In your case, to understand the issue, consider first the following query:
?- actor("Rich", C),
C = 1.
C = 1.
This does not tell us a lot, so we apply the following purely algebraic reasoning: For the goal actor("Rich", C), we substitute the body of the single matching clause:
?- C #>= 0,
C #< 5,
actor("Jeff",A),
A #< C,
C = 1.
The answer is:
C = 1,
A = 0.
This shows that when C is 1, then A is 0. However, on the toplevel, you did not see this because this variable only occurs within the clause for "Rich". Making this explicit shows that there is a solution that satisfies the constraint within that clause, but it is not linked to the variable we want.
There are several ways out. One of them is to make A available as an argument so that you can explicitly refer to it from the toplevel. In general, to link the relevant entities together, you will have to introduce arguments for each of your clauses, so that you can refer to the variables you need to reason about, instead of introducing new ones within each clause.
For example, in your case, this could look as follows:
actor("Jeff", A, _) :-
A #>= 0,
A #< 5.
actor("Rich", A, C) :-
C #>= 0,
C #< 5,
actor("Jeff", A, C),
A #< C.
I have used A to refer to Jeff, and C to refer to Rich.
While we are at at, let us tidy up the code, and use the following essentially equivalent version:
actor(jeff, A, _) :- A in 0..4.
actor(rich, A, C) :- C in 0..4, actor(jeff, A, C), A #< C.
Make sure you understand the following answer:
?- actor(jeff, 1, C), actor(rich, C, 1).
C = 0.
Your original example now yields false, exactly as expected:
?- actor(rich, 1, 1).
false.
Thus, you should be able to solve your task in principle.
However, there is a much simpler way to solve all this, which avoids the reification overload.
Instead of painstakingly keeping track of connections between names and corresponding variables, let us use the variables directly with the intended names. For example, what do you say about this:
?- Jeff in 0..4,
Rich in 0..4,
Jeff #< Rich.
This uses Prolog variables to denote the people, and makes the work a lot simpler. In this representation, your query becomes:
?- Jeff in 0..4,
Rich in 0..4,
Jeff #< Rich,
Jeff = 1,
Rich = 1.
And this obviously results in false.

swi-prolog abs operator not working in clpfd module

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.

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.

What paradigm is this?

I have a question regarding different paradigms, I have this code example in Prolog
fib(0, 0).
fib(1, 1).
fib(V, VF) :­-
    B is V ­- 1, C is V ­- 2,
    fib(B, BF), fib(C, CF),
    VF is BF + CF.
can someone please tell me what paradigm this is and why it is that?
Thank you in advance!
Let me first make the program easier to understand and also more general by using true arithmetic relations between integers instead of low-level arithmetic:
:- use_module(library(clpfd)).
fib(0, 0).
fib(1, 1).
fib(V, VF) :-
V #> 1,
B #= V - 1,
C #= V - 2,
VF #= BF + CF,
fib(B, BF),
fib(C, CF).
Notice that since we are stating the solution in terms of true relations, we can also freely move the goals.
The following queries now make it pretty clear why this is called logic programming:
First, you can ask: Is there any solution?
?- fib(X, Y).
X = Y, Y = 0 .
Yes, there is!
Then, you can ask for example: What is the 20-th Fibonacci number?
?- fib(20, Y).
Y = 6765 .
Further, you can ask: Which Fibonacci number(s) equal 233?
?- fib(X, 233).
X = 13 .
Further, you can ask: Is it true that the 10th Fibonacci number is 54?
?- fib(10, 54).
false.
No, it is not true.
Thus, since we can ask logical questions and describe solutions by stating what holds in terms of logical relations, it is called logic programming.

SWI-Prolog Creating/Printing lists, Recursion etc

I'm trying to teach myself some Prolog, however right now i'm really struggling just adapting to the declarative style having never done declarative programming before.
I'm attempting to get my program to come up with a two positive integer numbers, A & B, where A + B =< 50 and B > A. Obviously there are lots of solutions (e.g. A = 5 & B = 12 or A = 15 & B = 17) and i want my program to print all the different solutions.
I honestly don't really know where to begin and would appreciate some guidance or some example code of how to do something as explained above.
Cheers!
Looks like a good problem to use constraint logic programming:
:- use_module(library(clpfd)).
model(A, B) :-
A #> 0, B #> 0,
A + B #=< 50,
B #> A.
(I assume you want only positive integer solutions, otherwise there will be infinite number of them). Look how the model code directly reflects the problem statement.
After you have the model you can use it to find all solutions:
?- findall(_, (model(A, B), label([A, B]), writeln([A, B])), _).
[1,2]
[1,3]
[1,4]
[1,5]
[1,6]
... skipped many lines ...
[24,25]
[24,26]
true.
A more traditional Prolog solution without constraint programming (with the same results):
model2(A, B) :-
between(1, 50, A),
between(1, 50, B),
A + B =< 50,
B > A.
?- findall(_, (model2(A, B), writeln([A, B])), _).
You could do something like this:
combos(A,B) :-
between(1,50,A) ,
between(1,50,B) ,
S is A+B ,
S =< 50
.
This, on backtracking, will successively find all the solutions.
Use findall/3 to collect the results into a list:
findall(A+B,combos(A,B),X).

Resources