Reputation: 575
i write this programm for give me this result : "X=john" "Y=jane"
likes(john,mary).
likes(mary,jane).
likes(l,k).
likes(X,Y) :- likes(X,Z), likes(Z,Y).
but if run this programm such that this result: i think the programm get in loop ! i want to stop after true answer !
1 ?- likes(X,Y).
X = john,
Y = mary ;
X = mary,
Y = jane ;
X = l,
Y = k ;
X = john,
Y = jane ;
ERROR: Out of local stack
i have the error ! how solving this problem ?
by debugging :
[debug] 3 ?- likes(john,Y).
T Call: (6) likes(john, _G2162)
T Exit: (6) likes(john, mary)
Y = mary ;
T Redo: (6) likes(john, _G2162)
T Call: (7) likes(john, _G2267)
T Exit: (7) likes(john, mary)
T Call: (7) likes(mary, _G2162)
T Exit: (7) likes(mary, jane)
T Exit: (6) likes(john, jane)
Y = jane ;
T Redo: (7) likes(mary, _G2162)
T Call: (8) likes(mary, _G2267)
T Exit: (8) likes(mary, jane)
T Call: (8) likes(jane, _G2162)
T Call: (9) likes(jane, _G2267)
T Call: (10) likes(jane, _G2267)
T Call: (11) likes(jane, _G2267)
T Call: (12) likes(jane, _G2267)
T Call: (13) likes(jane, _G2267)
T Call: (14) likes(jane, _G2267)
T Call: (15) likes(jane, _G2267)
and so on .. why likes(jane, _G2267) ??????
Upvotes: 3
Views: 194
Reputation: 71065
Your code:
likes(john,mary). % {1}
likes(mary,jane). % {2}
likes(l,k). % {3}
likes(X,Y) :- % {4}
likes(X,Z), % {5}
likes(Z,Y). % {6}
The query likes(john,Y)
proceeds as follows:
likes(john,Y)?
%% {1} Y = mary. ; redo
%% {4} likes(john,Y) :-
%% {5} likes(john,Z)?
%% {1} Z=mary.
%% {6} likes(mary,Y)?
%% {2} Y=jane. ; redo
%% {4} likes(mary,Y) :-
%% {5} likes(mary,Z2)?
%% {2} Z2=jane,
%% {6} likes(jane,Y)?
%% {4} likes(jane,Y):-
%% {5} likes(jane,Z3)?
%% {4} likes(jane,Z3):-
%% {5} likes(jane,Z4)?
............
and that's what you see in the debugger.
To prevent this behaviour, rename your transitive closure predicate, as follows:
likes(john,mary). % {1b}
likes(mary,jane). % {2b}
likes(l,k). % {3b}
pals(X,Y) :- % {4b}
likes(X,Z), % {5b}
pals(Z,Y). % {6b}
Upvotes: 2
Reputation: 3180
Your query (both X
and Y
are variables) is far too "broad" for the way you defined likes/2
Try
?- likes(john, Y).
What does the prolog engine do? Well, it searches in its facts database.
First it finds that (1st rule)
likes(john, mary).
so john likes mary.
Then it finds that
likes(john,Y) :-
likes(john,Z),
likes(Z,Y).
so it asks itself: for what Z is it true that likes(john,Z)
? Well, the database says that likes(john, mary)
, so Z = mary
. Let's put it in the rule:
likes(john,Y) :-
likes(john,mary),
likes(mary,Y).
so it asks itself: for what Y is it true that likes(mary,Y)
? Well, the database says that likes(mary, jane)
, so Y = jane
. Let's put it in the rule:
likes(john,jane) :-
likes(john,mary),
likes(mary,jane).
so john likes jane.
Now we have a problem. Look closely to the second query:
likes(john,Y) :-
likes(john,Z),
.....
uh-oh.
John likes someone if john likes someone (and, .....)
well, on the first try we were lucky: the Prolog engine found Y = jane, Z = mary
because we have the following rules
likes(john,mary).
likes(mary,jane).
and it stopped. But then it asked itself, again:
likes(john,Y) ?
we already used the first two rules, so let's try with the third one:
likes(X,Y) :-
likes(X,Z),
likes(Z,Y).
troubles!
likes(john,Someone) :-
likes(john,Someone2), .....
likes(john,Someone2) :-
likes(john,Someone3), .....
likes(john,Someone3) :-
likes(john,Someone4), .....
and so on..
Upvotes: 3
Reputation: 2868
If you need "X=john" "Y=jane" then you have to rename:
likes(X,Y) :- likes(X,Z), likes(Z,Y).
for other name, example:
likestransitive(X,Y) :- likes(X,Z), likes(Z,Y).
Thus you can obtain the solution that you need:
1 ?- transitivelikes(X,Y).
X = john,
Y = jane;
false.
Upvotes: 3