You need to define another predicate that will act as transitive relation. The code below works just as fine (notice the predicate progenyt
that is the actual transitive relation).
progeny(dexter, mark).
progeny(mark, bill).
progeny(bill, lisa).
progenyt(X, Y) :- progeny(X, Y).
progenyt(X, Y) :- progeny(X, Z), progenyt(Z, Y).
Clarification
When you write progeny(X, Y) :- progeny(X, Z), progeny(Z, Y).
, you will, at some point, have prolog trying to match progeny(dexter, Y) :- progeny(dexter, lisa), progeny(lisa, Y).
, which is the moment where prolog gets 'confused'.
Namely, it will try to match progeny(lisa, Y)
with some fact, which will fail for all entries. Then, prolog will try rule progeny(lisa, Y) :- progeny(lisa, Z), progeny(Z, Y).
, which calls for evaluating progeny(lisa, Z)
. Here you are met with stack overflow, because for progeny(lisa, Y)
to succeed, progeny(lisa, Z)
has to succeed as well, which induces sort of infinite loop, and that is why your query never terminates.
In the solution I've posted, that can never happen, because for progenyt(lisa, Y)
to succeed, progeny(lisa, Z)
has to, and that never happens (it fails for all facts). Therefore, it will produce only those three results and will terminate immediately afterwards.
Note that, if progeny
and progenyt
were to be swapped in the last line, the query will also run into the same problem as before (for progenyt(lisa, Y)
to succeed, progenyt(lisa, Z)
has to succeed as well first, will causes the infinite loop).