Prolog and ancestor relationship

落花浮王杯 提交于 2019-12-18 06:58:20

问题


I have to write a small prolog program which checks if a given person is a ancestor of a second one. These are the facts and rules:

mother(tim, anna).
mother(anna, fanny).
mother(daniel, fanny).
mother(celine, gertrude).
father(tim, bernd).
father(anna, ephraim).
father(daniel, ephraim).
father(celine, daniel).

parent(X,Y) :- mother(X,Y).
parent(X,Y) :- father(X,Y).

The test if a person is an ancestor of another person is easy:

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

But now I have to write a method ancestor(X,Y,Z) which also prints out the relationship between two persons. It should look like this

?- ancestor(ephraim, tim, X).
false.
?- ancestor(tim, ephraim, X).
X = father(mother(tim)).

And that is the problem: I have no clue how do to this.


回答1:


You can use an accumulator to adapt @Scott Hunter's solution :

mother(anna, fanny).
mother(daniel, fanny).
mother(celine, gertrude).
father(tim, bernd).
father(anna, ephraim).
father(daniel, ephraim).
father(celine, daniel).

ancestor(X, Y, Z) :- ancestor(X, Y, X, Z).
ancestor(X, Y, Acc, father(Acc)) :- father(X, Y).
ancestor(X, Y, Acc, mother(Acc)) :- mother(X, Y).
ancestor(X, Y, Acc, Result) :-
    father(X, Z),
    ancestor(Z, Y, father(Acc), Result).
ancestor(X, Y, Acc, Result) :-
    mother(X, Z),
    ancestor(Z, Y, mother(Acc), Result).

edit : as Scott Hunter showed in his edit, there's no need for an explicit accumulator here, since we can left the inner part of the term unbound easily at each iteration. His solution is therefore better !




回答2:


A term manipulation alternative to the accumulator tecnique by @Mog:

parent(X, Y, mother(X)) :- mother(X, Y).
parent(X, Y, father(X)) :- father(X, Y).

ancestor(X, Y, R) :-
    parent(X, Y, R).
ancestor(X, Y, R) :-
    parent(X, Z, P),
    ancestor(Z, Y, A),
    eldest(A, P, R).

eldest(A, P, R) :-
    A =.. [Af, Aa],
    (   atom(Aa)
    ->  T = P
    ;   eldest(Aa, P, T)
    ),
    R =.. [Af, T].

To test, I made tim a father: father(ugo, tim).

?- ancestor(tim, ephraim, X).
X = father(mother(tim)) .

?- ancestor(ugo, ephraim, X).
X = father(mother(father(ugo))) .



回答3:


Simply add a term which tracts what kind of parent is used at each step (edited to get result in proper order):

ancestor(X,Y,father(X)) :- father(X,Y).
ancestor(X,Y,mother(X)) :- mother(X,Y).
ancestor(X,Y,father(Z2)) :- father(Z,Y), ancestor(X,Z,Z2).
ancestor(X,Y,mother(Z2)) :- mother(Z,Y), ancestor(X,Z,Z2).


来源:https://stackoverflow.com/questions/8966488/prolog-and-ancestor-relationship

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!