General
Material
Lecture 1
 Slides Practical Session
Lecture 2
 Slides Practical Session
Lecture 3
 Slides Practical Session
Lecture 4
 Slides Practical Session
Lecture 5
 Slides Practical Session

Hint

The predicate `grandparent_of/2` could be defined as follows:

```grandparent_of(X,Y) :- parent_of(X,Z),
parent_of(Z,Y).
```
The predicate `greatgrandparent_of/2` could be defined as follows:
```greatgrandparent_of(X,Y) :- parent_of(X,Z),
parent_of(Z,A),
parent_of(A,Y).
```
And the predicate `greatgreatgrandparent_of/2` could be defined analogously by simply adding one more `parent_of` step to the definition of `greatgrandparent/2`. However, `ancestor_of/2` cannot be defined in this way, as we don't know how many 'parents we have to go back' to find an ancestor. Anybody who is an arbitrary number of parent relations back is an ancestor.

So, how can we express what `ancestor_of` means? Well, obviously if I am the parent of somebody, I also belong to his ancestors. Furthermore, if I am the parent of somebody and that somebody is an ancestor of a third person, I am also an ancestor of this third person.