2

I wrote it as such. But it only succeed in finding till the grandparent, and not any further. How do I write it in such a way that it finds all possible ancestor. That is, finding greatgrandparent and even further if there exist such fact?

 ancestor(X, Y) :- parent(X, Y); parent(X,Z), parent(Z,Y).

Given

parent(greatgrand_parent, grand_parent).
parent(grand_parent, parent).
parent(parent, child).

Returns only

?- ancestor(What, child).
What = parent ;
What = grand_parent ;
false.
false
  • 10,264
  • 13
  • 101
  • 209
Gavin
  • 2,784
  • 6
  • 41
  • 78

2 Answers2

2

you forget the recursive call: try

ancestor(X, Y) :- parent(X, Y) ; parent(X,Z), ancestor(Z,Y).

and you get

?- ancestor(X,child).
   X = parent
;  X = greatgrand_parent
;  X = grand_parent
;  false.
false
  • 10,264
  • 13
  • 101
  • 209
CapelliC
  • 59,646
  • 5
  • 47
  • 90
2

Transitive closure is a frequently recurring problem in Prolog. So why not separate the specific - in your case the relation parent/2 from the general - a relation closure/3.

| ?- closure(parent, What, child).
What = greatgrand_parent ? ;
What = grand_parent ? ;
What = parent ? ;
no
Community
  • 1
  • 1
false
  • 10,264
  • 13
  • 101
  • 209