I began to study Prolog recently and faced one strange problem. Here you can see a code example (I use SWI-Prolog 7.2.3) which gives a tree of relationships and my solution of 2 tasks.
/* File: ancestors.pl
Author: Dave Robertson
Purpose: Relationships in a family tree
Suppose we have a family tree like this :
alan andrea bruce betty eddie elsie fred freda
| | | | | | | |
|_____| |_____| |_____| |_____|
| | | |
clive clarissa greg greta
| |__________|___| | |
|__________|__| |_____________|
| | |
dave doris henry
which is defined in Prolog by the following 3 sets of predicates:
*/
% parent(Parent, Child).
% Parent is the parent of Child.
parent(alan, clive).
parent(andrea, clive).
parent(bruce, clarissa).
parent(betty, clarissa).
parent(clive, dave).
parent(clarissa, dave).
parent(clive, doris).
parent(clarissa, doris).
parent(eddie, greg).
parent(elsie, greg).
parent(fred, greta).
parent(freda, greta).
parent(greg, henry).
parent(greta, henry).
%% PROBLEM 1
%% How do you find out if someone is the ancestor of someone else ?
ancestor(X,Y) :- parent(X,Y).
ancestor(X,Y) :- parent(X,Z), ancestor(Z,Y).
%% PROBLEM 3
%% How do you know if someone is related to someone else ?
relative(X,Y) :- ancestor(X,Y).
relative(X,Y) :- ancestor(Y,X).
relative(X,Y) :- ancestor(Z,X), ancestor(Z,Y), X\==Y.
When I want to get the relatives of dave I do:
relative(dave,X).
X = clive ;
X = clarissa ;
X = alan ;
X = andrea ;
X = bruce ;
X = betty ;
X = doris ;
X = doris ;
X = clive ;
X = doris ;
X = clive ;
X = doris ;
X = clarissa ;
X = doris ;
X = clarissa ;
X = doris ;
false.
And then I change my definition of relative next way:
relative(X,Y) :- ancestor(X,Y).
relative(X,Y) :- ancestor(Y,X).
relative(X,Y) :- X\==Y, ancestor(Z,X), ancestor(Z,Y).
I simply change the order of goals in the last statement. And now I have the following output:
relative(dave,X).
X = clive ;
X = clarissa ;
X = alan ;
X = andrea ;
X = bruce ;
X = betty ;
X = dave ;
X = doris ;
X = dave ;
X = doris ;
X = clive ;
X = dave ;
X = doris ;
X = clive ;
X = dave ;
X = doris ;
X = clarissa ;
X = dave ;
X = doris ;
X = clarissa ;
X = dave ;
X = doris ;
false.
I see dave in the output! How did this happen? I wrote that X \== Y... Can anybody give me a good explanation of this?
And one more question. How do I make my program not to write the same answers?
Thank you!
(\==)/2
is not a pure relation and can only be understood operationally. If you use it, exchanging the order of goals may yield declaratively wrong results:
?- X \== Y, X = Y. X = Y.
Please use dif/2
instead for a pure and completely declarative way to state disequality of terms.
?- dif(X, Y), X = Y. false.
See prolog-dif for more information.