parent(jill, john).
parent(john, pam).
parent(pam, bob).
parent(tom, bob).
parent(tom, liz).
parent(bob, ann).
parent(bob, pat).
parent(pat, jim).
female(jill).
female(pam).
female(liz).
female(ann).
female(pat).
male(jim).
male(john).
male(tom).
male(bob).
mother(X,Y) :- female(X) , parent(X,Y).
father(X,Y) :- male(X), parent(X,Y).
offspring(X,Y) :- parent(Y,X).
sister(X,Y) :- female(X), female(Y), parent(Z,X), parent(Z,Y), not(X=Y).
ancestor(X, Y) :- parent(X,Z), ancestor(Z,Y).
这是整个代码以及与祖先部分无关的其他内容。当我尝试在swipl中对其进行测试时,祖先代码给我错误的提示。我正在尝试祖先(pat,jim)。和ancestor(X,jim)
。如果我在祖先代码中使用;
而不是,
,则可以工作,但是当一个人的父母双方都在列表中时,名字会重复。
答案 0 :(得分:0)
在这种情况下,trace
是您的朋友:
?- trace.
true.
[trace] ?- ancestor(pat, jim).
Call: (8) ancestor(pat, jim) ? creep
Call: (9) parent(pat, _3162) ? creep
Exit: (9) parent(pat, jim) ? creep
Call: (9) ancestor(jim, jim) ? creep
Call: (10) parent(jim, _3162) ? creep
Fail: (10) parent(jim, _3162) ? creep
Fail: (9) ancestor(jim, jim) ? creep
Fail: (8) ancestor(pat, jim) ? creep
false.
看看会发生什么?您将ancestor(X,Y)
定义为有两个要求:首先,X
必须是某个中间人Z
的父级,然后Z
也必须是{{1}的祖先}。由于Y
是pat
的父母,因此要求jim
是他自己的祖先,而他不是。
一种可能的解决方案是将祖先定义为 的直接父系或另一个祖先的父系:
jim
让我们测试一下
ancestor(X, Y) :- parent(X, Y).
ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y).
因此,我们对[trace] ?- ancestor(pat, jim).
Call: (8) ancestor(pat, jim) ? creep
Call: (9) parent(pat, jim) ? creep
Exit: (9) parent(pat, jim) ? creep
Exit: (8) ancestor(pat, jim) ? creep
和pat
很满意,因为它们是直接的jim
关系。递归情况如何?
parent