I cannot figure out why the following query from the given Prolog code generates the error Out of local stack
.
Prolog code:
likes(g,c).
likes(c,a).
likes(c,b).
likes(b,a).
likes(b,d).
likes(X,Z) :- likes(X,Y), likes(Y,Z).
the query
?- likes(g,X).
results in
X = c ;
X = a ;
X = b ;
ERROR: Out of local stack
Edit 1 This is the way I think that Prolog should deal with this query,
likes(g,c) is a fact, so X={c}
likes(g,b) <= likes(g,c) and likes(c,b), so X={c,b}
likes(g,a) <= likes(g,b) and likes(b,a), so X={c,b,a}
likes(g,d) <= likes(g,b) and likes(b,d), so X={c,b,a,d}
likes(g,a) and false, so nothing to add to X
likes(g,d) and false, so nothing to add to X
end of backtracking search.
Edit 2 I managed to get what I was looking for by the following modification of the code:
likes(g,c).
likes(c,a).
likes(c,b).
likes(b,a).
likes(b,d).
indirect_likes(A,B):- likes(A,B).
indirect_likes(A,C):- likes(B,C), indirect_likes(A,B).
the query
?- indirect_likes(g,Which).
results in
Which = c ;
Which = a ;
Which = b ;
Which = a ;
Which = d ;
false.
However, there is still something which I cannot figure out the rationale behind. If I change the last rule to be
indirect_likes(A,C):- indirect_likes(A,B), likes(B,C).
Then I get ERROR: Out of local stack
! As far as I know, logical conjunction is commutative.
You spin off into infinite recursion.
Once you get to
likes(b,a)
, you calllikes(a,_G4382)
, which has no fact defined so it switches to the rulelikes(X,Z) :- likes(X,Y), likes(Y,Z).
So it callslikes(a,_G4383)
which callslikes(X,Z) :- likes(X,Y), likes(Y,Z).
over and over and over.You might want to define and auxillary predicate
aux_likes/2
that hosts all your facts. This will only work if there are no circular relationships, i.e.aux_likes(b,c)
andaux_likes(c,b)
. You would also need to definelikes(X,X).
This is essentially a graph problem and in graph theory a node has to be connected to itself. If you use it as a generator, it will go off into into infinite recursion (if you have cycles) unless you addcuts
which are not ideal.If using
swi-prolog
, feel free to enter thedebug
orspy
query to see what's going on.Code:
Output with new predicate:
This says
g
can likea
throughc
or throughb
. It likesd
throughb
, it likesb
throughc
and it likesc
directly. It also must like itself inorder to query like this. If you would rather have the usage mode(+,+)
meaning you supply it with both terms and no variables (as a checker) you can do