3

Given a set of facts that represent parent-child relationships via the predicate parent/2, what are the differences when defining the relation "progenitor"(ancestor) with the predicates pred1/2 and pred2/2 as shown below?

pred1(X,Z) :- parent(X,Z).
pred1(X,Z) :- parent(X,Y), pred1(Y,Z).

pred2(X,Z) :- parent(X,Z).
pred2(X,Z) :- parent(Y,Z), pred2(X,Y).
false
  • 10,264
  • 13
  • 101
  • 209
Da Mike
  • 447
  • 4
  • 17

1 Answers1

5

The major difference are the termination properties of both, provided there are some cycles in the relation. To understand this, I will use a failure-slice which cuts down the program to its essence w.r.t. termination.

pred1(X,Z) :- false, parent(X,Z).
pred1(X,Z) :- parent(X,Y), pred1(Y,Z). % Z has no influence

pred2(X,Z) :- false, parent(X,Z).
pred2(X,Z) :- parent(Y,Z), pred2(X,Y). % X has no influence

For pred1/2, the second argument has no influence on termination at all, whereas in pred2/2, the first argument has no influence. To see this, try the original definitions with the fact:

parent(a,a).

?- pred1(b, _), false.
   false. % terminates
?- pred2(b, _), false.
   loops.
?- pred1(_, b), false.
   loops.
?- pred2(_, b), false.
   false. % terminates

See closure/3 for a general approach to avoid such loops.

For completeness, here is another variation of transitive closure which has some conceptual advantages:

pred3(X,Z) :- parent(X,Z).
pred3(X,Z) :- pred3(X,Y), pred3(Y,Z).

Alas, its termination properties are worst. In fact, it never terminates, as is testified by the following fragment:

pred3(X,Z) :- false, parent(X,Z).
pred3(X,Z) :- pred3(X,Y), false, pred3(Y,Z).

In this fragment, the first argument is only passed on. So, no matter, what the arguments are, the program will always loop!

?- pred3(b,b), false.
   loops.
false
  • 10,264
  • 13
  • 101
  • 209