Prolog taller than - prolog

What is the easiest way to find who is the tallest in Prolog:
height(lisa,1.65).
height(sam,1.70).
height(luke,1.92).
height(nicole,1.54).
I want to write
tallest(X) :- Y is bigger than other Y's

SWI-Prolog has some different ways to solve this problem, for instance by means of library(solution_sequences)
?- order_by([desc(H)],height(P,H)).
H = 1.92,
P = luke ;
...
or using library(aggregate):
?- aggregate(max(H,P),height(P,H),max(_,P)).
P = luke.
less sophisticate Prologs probably will offer setof/3 and last/2:
?- setof(H:P,height(P,H),L),last(L,_:P).
P = luke,
L = [1.54:nicole, 1.65:lisa, 1.7:sam, 1.92:luke].
and still more basic engines, lacking setof/3, will offer
?- height(P,H),\+((height(_,L),L>H)).
P = luke,
H = 1.92 ;

Supposing that tallest(X) succeeds if, and only if, person X is taller than all other persons, I think that a correct answer would be:
tallest(X) :-
height(X, H),
forall((height(Y, H1),
X \= Y),
H > H1), !.
First scenario:
height(lisa,1.65).
height(sam,1.70).
height(luke,1.92).
height(nicole,1.54).
?- tallest(X).
X = luke.
Second scenario:
height(lisa, 1.65).
height(sam, 1.70).
height(luke, 1.92).
height(nicole, 1.54).
height(bob, 1.92). % Bob is as tall as Luke!
?- tallest(X).
false.

height(lisa,1.65).
height(sam,1.70).
height(luke,1.92).
height(nicole,1.54).
max_height(Person, Height, [[Person, Height]]).
max_height(P , H , [[P, H]|Tail]) :- max_height(_ , H2, Tail), H > H2.
max_height(P2, H2, [[_, H]|Tail]) :- max_height(P2, H2, Tail), H =< H2.
tallest(X) :- findall([P, H], height(P, H), Bag), max_height(X, _, Bag).
There are ways to avoid writing max_height : Prolog, find minimum in a list

Related

Why is my prolog program stucked in endless recursion

I have the following experimental code
s(a,b).
s(b,c).
s(c,b).
r(a).
r(c).
r(d).
p(X,Y) :- s(X,Y), not(r(Y)).
q(X,Y) :- q(Y,X), r(X).
q(X,Y) :- p(Y,X), s(X,Y).
t(X,Y) :- r(X), q(X,Y).
Querying for t(X,Y) will result in a endless recursion blowing up the stack. But I can actually think of X=c,Y=b being the solution because
t(c,b) <- r(c), q(c,b)
q(c,b) <- q(b,c), r(c)
q(b,c) <- p(c,b), s(b,c)
p(c,b) <- s(c,b), not(r(b))
Can someone explain to me, why prolog doesn't come to this solution and gets caught in an endless recursion around q(c,b) and q(b,c)
Many thanks!
In SWI-Prolog, you can solve the problem using tabled execution.
:- table q/2.
s(a,b).
s(b,c).
s(c,b).
r(a).
r(c).
r(d).
p(X,Y) :- s(X,Y), not(r(Y)).
q(X,Y) :- q(Y,X), r(X).
q(X,Y) :- p(Y,X), s(X,Y).
t(X,Y) :- r(X), q(X,Y).
Examples:
?- t(X,Y).
X = c,
Y = b ;
false.
?- q(X,Y).
X = c,
Y = b ;
X = b,
Y = c.

Evaluating expressions with indexicals in SICStus Prolog

I'm trying to write a predicate in SICStus Prolog such that given an expression, I can evaluate it (possible several times). The following works as expected:
?- A is 1, H = A+2+2, C is H.
C = 5 ?
yes
And so does this more elaborate code:
testing(Variables, Updates, Values, Result):-
assert(temp(Variables, Updates)),
temp(Values, Result),
abolish(temp/2).
evaluate([],[]).
evaluate([Term|T1],[H|T2]):-
H is Term,
evaluate(T1,T2).
Now, if instead A is an indexical, say A in 1..3, it doesn't work anymore. Any ideas about how to fix it?
The longer code is supposed to be used as follows:
?- testing([A,B,C], [A+1,B+C,max(A,B)], [0,0,0], Result), evaluate(Result, R).
Result = [0+1,0+0,max(0,0)],
R = [1,0,0] ?
yes
But is suffers from the same problem as the small example: I can't provide ranges of values in this way:
?- Val1 in 1..2, Val2 in 3..10, testing([A,B], [A+1,B+A], [Val1,Val2], Result), evaluate(Result, R).
Any suggestions?
My current solution requires replacing is/2 with val_of/2. It works, but I still believe there should be a better/faster implementation.
testing(Variables, Updates, Values, Result):-
assert(temp(Variables, Updates)),
temp(Values, Result),
abolish(temp/2).
evaluate([],[]).
evaluate([Term|T1],[H|T2]):-
val_of(H,Term),
evaluate(T1,T2).
val_of(E,E):- number(E),!.
val_of(E,E):- var(E),!.
val_of(V,E1+E2):- !, val_of(V1,E1), val_of(V2,E2), V #= V1+V2.
val_of(V,E1-E2):- !, val_of(V1,E1), val_of(V2,E2), V #= V1-V2.
val_of(V,max(E1,E2)):- !, val_of(V1,E1), val_of(V2,E2), V #= max(V1,V2).
val_of(V,min(E1,E2)):- !, val_of(V1,E1), val_of(V2,E2), V #= min(V1,V2).
val_of(V,abs(E1,E2)):- !, val_of(V1,E1), val_of(V2,E2), V #= abs(V1,V2).
A test example:
| ?- X in 1..3, testing([A,B], [A+1,B], [X,0], R), evaluate(R,R1).
R = [X+1,0],
R1 = [_A,0],
X in 1..3,
_A in 2..4 ?
yes
I think that all you need is just
evaluate([],[]).
evaluate([Term|T1],[H|T2]):-
H #= Term,
evaluate(T1,T2).
but the temp/2 relation is unnecessary, so a real simplification could be:
testing(Variables, Updates, Values, Result):-
maplist(#=, Updates, Values), Result=Variables.
results in
?- testing([A,B,C], [A+1,B+C,max(A,B)], [0,0,0], Result).
A = -1,
B = C, C = 0,
Result = [-1, 0, 0].
(note: tested in SWI-Prolog, after ?- [library(clpfd)].)
My final solution is a modified version of my original code based on the useful answers and comments provided by #CapelliC and #false:
testing(Variables, Updates, Values, Result):-
copy_term(Variables-Updates, Values-Result).
evaluate([],[]).
evaluate([Term|T1],[H|T2]):-
call(H #= Term),
evaluate(T1,T2).
The main issue in my original code was the missing call/1 in evaluate/2.
A test example in SICStus Prolog looks like this:
?- A in 1..3, testing([C,D,R],[C+1,max(D,5),R],[A,0,0],Res), evaluate(Res,T).
Res = [A+1,max(0,5),0],
T = [_A,5,0],
A in 1..3,
_A in 2..4 ?
yes

(SWI)Prolog: Order of sub-goals

I have two, slightly different, implementations of a predicate, unique_element/2, in Prolog. The predicate succeeds when given an element X and a list L, the element X appears only once in the list. Below are the implementations and the results:
Implementation 1:
%%% unique_element/2
unique_element(Elem, [Elem|T]) :-
not(member(Elem, T)).
unique_element(Elem, [H|T]) :-
member(Elem, T),
H\==Elem,
unique_element(Elem, T),
!.
Results:
?- unique_element(X, [a, a, b, c, c, b]).
false.
?- unique_element(X, [a, b, c, c, b, d]).
X = a ;
X = d.
Implementation 2:
%%% unique_element/2
unique_element(Elem, [Elem|T]) :-
not(member(Elem, T)).
unique_element(Elem, [H|T]) :-
H\==Elem,
member(Elem, T),
unique_element(Elem, T),
!.
In case you didn't notice at first sight: H\==Elem and member(Elem, T) are flipped on the 2nd impl, rule 2.
Results:
?- unique_element(X, [a, a, b, c, c, b]).
X = a.
?- unique_element(X, [a, b, c, c, b, d]).
X = a ;
X = d.
Question: How does the order, in this case, affect the result? I realize that the order of the rules/facts/etc matters. The two specific rules that are flipped though, don't seem to be "connected" or affect each other somehow (e.g. a cut in the wrong place/order).
Note: We are talking about SWI-Prolog here.
Note 2: I am aware of, probably different and better implementations. My question here is about the order of sub-goals being changed.
H\==Elem is testing for syntactic inequality at the point in time when the goal is executed. But later unification might make variables identical:
?- H\==Elem, H = Elem.
H = Elem.
?- H\==Elem, H = Elem, H\==Elem.
false.
So here we test if they are (syntactically) different, and then they are unified nevertheless and thus are no longer different. It is thus just a temporary test.
The goal member(Elem, T) on the other hand is true if that Elem is actually an element of T. Consider:
?- member(Elem, [X]).
Elem = X.
Which can be read as
(When) does it hold that Elem is an element of the list [X]?
and the answer is
It holds under certain circumstances, namely when Elem = X.
If you now mix those different kinds of goals in your programs you get odd results that can only explained by inspecting your program in detail.
As a beginner, it is best to stick to the pure parts of Prolog only. In your case:
use dif/2 in place of \==
do not use cuts - in your case it limits the number of answers to two. As in
unique_element(X, [a,b,c])
do not use not/1 nor (\+)/1. It produces even more incorrectness. Consider unique_element(a,[a,X]),X=b. which incorrectly fails while X=b,unique_element(a,[a,X]) correctly succeeds.
Here is a directly purified version of your program. There is still room for improvement!
non_member(_X, []).
non_member(X, [E|Es]) :-
dif(X, E),
non_member(X, Es).
unique_element(Elem, [Elem|T]) :-
non_member(Elem, T).
unique_element(Elem, [H|T]) :-
dif(H,Elem),
% member(Elem, T), % makes unique_element(a,[b,a,a|Xs]) loop
unique_element(Elem, T).
?- unique_element(a,[a,X]).
dif(X, a)
; false. % superfluous
?- unique_element(X,[E1,E2,E3]).
X = E1, dif(E1, E3), dif(E1, E2)
; X = E2, dif(E2, E3), dif(E1, E2)
; X = E3, dif(E2, E3), dif(E1, E3)
; false.
Note how the last query reads?
When is X a unique element of (any) list [E1,E2,E3]?
The answer is threefold. Considering one element after the other:
X is E1 but only if it is different to E2 and E3
etc.
TL;DR: Read the documentation and figure out why:
?- X = a, X \== a.
false.
?- X \== a, X = a.
X = a.
I wonder why you stop so close from figuring it out yourself ;-)
There are too many ways to compare things in Prolog. At the very least, you have unification, which sometimes can compare, and sometimes does more; than you have equvalence, and its negation, the one you are using. So what does it do:
?- a \== b. % two different ground terms
true.
?- a \== a. % the same ground term
false.
Now it gets interesting:
?- X \== a. % a free variable and a ground term
true.
?- X \== X. % the same free variable
false.
?- X \== Y. % two different free variables
true.
I would suggest that you do the following: figure out how member/2 does its thing (does it use unification? equivalence? something else?) then replace whatever member/2 is using in all the examples above and see if the results are any different.
And since you are trying to make sure that things are different, try out what dif/2 does. As in:
?- dif(a, b).
or
?- dif(X, X).
or
?- dif(X, a).
and so on.
See also this question and answers: I think the answers are relevant to your question.
Hope that helps.
Here is another possibility do define unique_element/2 using if_/3 and maplist/2:
:- use_module(library(apply)).
unique_element(Y,[X|Xs]) :-
if_(Y=X,maplist(dif(Y),Xs),unique_element(Y,Xs)).
In contrast to #user27815's very elegant solution (+s(0)) this version does not build on clpfd (used by tcount/3). The example queries given by the OP work as expected:
?- unique_element(a,[a, a, b, c, c, b]).
no
?- unique_element(X,[a, b, c, c, b, d]).
X = a ? ;
X = d ? ;
no
The example provided by #false now succeeds without leaving a superfluous choicepoint:
?- unique_element(a,[a,X]).
dif(a,X)
The other more general query yields the same results:
?- unique_element(X,[E1,E2,E3]).
E1 = X,
dif(X,E3),
dif(X,E2) ? ;
E2 = X,
dif(X,E3),
dif(X,E1) ? ;
E3 = X,
dif(X,E2),
dif(X,E1) ? ;
no
Can you not define unique_element like tcount Prolog - count repetitions in list
unique_element(X, List):- tcount(=(X),List,1).

Prolog need to get it fix

The solution
ppath(X,Y,M,Path,[Y|Path]) :- edge(X,Y,M),
\+ memberchk(Y,Path).
path(X,Y,P,SoFar,Path) :- edge(X,W,M), \+
memberchk(W,SoFar),
path(W,Y,N,[W|SoFar],Path), P is M+N.
pravilo(X,Y,Z) :-
aggregate(min(W), P^path(X,Y,W,[],P),
Z).
After that i am trying to use ?- pravilo(a,z,M). get the result. but it says false.
My version SWI-Prolog (Multi-threaded, 64 bits, Version 6.4.1)
Thank You
You should avoid assert/retract as far as possible.
Your graph has a loop between f and g, then you can't use the naive path/4 predicate, or your program will loop.
To avoid looping, you should invert the path construction (now it's 'bottom up'), to 'top down' adding a further argument (an accumulator) to path/4, and check that a node isn't already visited before recursing.
You can use memberchk for the test.
edit: here is the code
path(X,Y,M,Path,[Y|Path]) :- edge(X,Y,M), \+ memberchk(Y,Path).
path(X,Y,P,SoFar,Path) :- edge(X,W,M), \+ memberchk(W,SoFar),
path(W,Y,N,[W|SoFar],Path), P is M+N.
this yields
?- path(a,z,W,[],P).
W = 27,
P = [z, e, j, b] ;
W = 26,
P = [z, g, b] ;
...
let's use library(aggregate) to complete the assignment:
pravilo(X,Y,Z) :-
aggregate(min(W), P^path(X,Y,W,[],P), Z).
now I get
?- pravilo(a,z,M).
M = 24.
edit To get (full) ordered paths, these changes are necessary in recursion base
path(X,Y,M,Path,FullPath) :-
edge(X,Y,M), \+ memberchk(Y,Path), reverse([Y|Path], FullPath).
and in top level predicate:
pravilo(X,Y,Z) :-
aggregate(min(W), P^path(X,Y,W,[X],P), Z).

Don't repeat solutions in Prolog

Suppose you have a database with the following content:
son(a, d).
son(b, d).
son(a, c).
son(b, c).
So a and b are sons of d and c. Now you want to know, given a bigger database, who is brother to who. A solution would be:
brother(X, Y) :-
son(X, P),
son(Y, P),
X \= Y.
The problem with this is that if you ask "brother(X, Y)." and start pressing ";" you'll get redundant results like:
X = a, Y = b;
X = b, Y = a;
X = a, Y = b;
X = b, Y = a;
I can understand why I get these results but I am looking for a way to fix this. What can I do?
Prolog will always try to find every possible solution available for your statements considering your set of truths. The expansion works as depth-first search:
son(a, d).
son(b, d).
son(a, c).
son(b, c).
brother(X, Y) :-
son(X, P),
son(Y, P),
X \= Y.
brother(X, Y)
_______________________|____________________________ [son(X, P)]
| | | |
X = a, P = d X = b, P = d X = a, P = c X = a, P = b
| | | |
| ... ... ...
|
| (X and P are already defined for this branch;
| the algorithm now looks for Y's)
|__________________________________________ [son(Y, d)]
| |
son(a, d) -> Y = a son(b, d) -> Y = b
| |
| | [X \= Y]
X = a, Y = a -> false X = a, Y = b -> true
|
|
solution(X = a, Y = b, P = d)
But, as you can see, the expansion will be performed in all the branches, so you'll end up with more of the same solution as the final answer. As pointed by #Daniel Lyons, you may use the setof built-in.
You may also use the ! -- cut operator -- that stops the "horizontal" expansion, once a branch has been found to be valid, or add some statement that avoids the multiple solutions.
For further information, take a look at the Unification algorithm.
First, I would advise against updating the Prolog database dynamically. For some reasons, consider the article
"How to deal with the Prolog dynamic database?".
You could use a combination of the builtin setof/3 and member/2, as #DanielLyons has suggested in his answer.
As yet another alternative, consider the following query which uses setof/3 in a rather unusual way, like this:
?- setof(t,brother(X,Y),_).
X = a, Y = b ;
X = b, Y = a.
You can eliminate one set with a comparison:
brother(X, Y) :-
son(X, P),
son(Y, P),
X \= Y, X #< Y.
?- brother(X, Y).
X = a,
Y = b ;
X = a,
Y = b ;
false.
Since X and Y will be instantiated both ways, requiring X be less than Y is a good way to cut the solutions in half.
Your second problem is that X and Y are brothers by more than one parent. The easiest solution here would be to make your rules more explicit:
mother(a, d).
mother(b, d).
father(a, c).
father(b, c).
brother(X, Y) :-
mother(X, M), mother(Y, M),
father(X, F), father(Y, F),
X \= Y, X #< Y.
?- brother(X, Y).
X = a,
Y = b ;
false.
This method is very specific to this particular problem, but the underlying reasoning is not: you had two copies because a and b are "brothers" by c and also by d—Prolog was right to produce that solution twice because there was a hidden variable being instantiated to two different values.
A more elegant solution would probably be to use setof/3 to get the solutions. This can work even with your original code:
?- setof(X-Y, (brother(X, Y), X #< Y), Brothers).
Brothers = [a-b].
The downside to this approach is that you wind up with a list rather than Prolog generating different solutions, though you can recover that behavior with member/2.
This should work. But I think it can be improved (I am not a Prolog specialist):
brother(X, Y) :-
son(X, P1),
son(Y, P1),
X #< Y,
(son(X, P2), son(Y, P2), P1 #< P2 -> false; true).
If you're using Strawberry Prolog compiler,you won't get all the answers by typing this:
?- brother(X, Y),
write(X), nl,
write(Y), nl.
In order to get all the answers write this:
?- brother(X, Y),
write(X), nl,
write(Y), nl,
fail.
I hope it helps you.:)
I got to an answer.
% Include the dictionary
:- [p1]. % The dictionary with sons
:- dynamic(found/2).
brother(X, Y) :-
% Get two persons from the database to test
son(X, P),
son(Y, P),
% Test if the two persons are different and were not already used
testBrother(X, Y).
% If it got here it's because there is no one else to test above, so just fail and retract all
brother(_, _) :-
retract(found(_, _)),
fail.
testBrother(X, Y) :-
X \= Y,
\+found(X, Y),
\+found(Y, X),
% If they were not used succed and assert what was found
assert(found(X, Y)).
It always returns fails in the end but it succeeds with the following.
brother(X, Y). % Every brother without repetition
brother('Urraca', X). % Every brother of Urraca without repetition
brother('Urraca', 'Sancho I'). % True, because Urraca and Sancho I have the same father and mother. In fact, even if they only had the same mother or the same father it would return true. A little off context but still valid, if they have three or more common parents it would still work
It fails with the following:
brother(X, X). % False because it's the same person
brother('Nope', X). % False because not is not even in the database
brother('Nope', 'Sancho I'). % False, same reason
So like this I can, for example, ask: brother(X, Y), and start pressing ";" to see every brother and sister without any repetition.
I can also do brother(a, b) and brother(b, a), assuming a and b are persons in the database. This is important because some solutions would use #< to test things and like so brother(b, a) would fail.
So there it is.

Resources