Prolog:程序中的统一或回溯错误
我有一个简单的知识库,可以对家谱进行编码。此表述中的一些重要规则如下:Prolog:程序中的统一或回溯错误,prolog,backtracking,unification,family-tree,Prolog,Backtracking,Unification,Family Tree,我有一个简单的知识库,可以对家谱进行编码。此表述中的一些重要规则如下: % fathers father(michael,cathy). father(michael,sharon). father(charles_gordon,michael). father(charles_gordon,julie). father(charles,charles_gordon). father(jim,melody). father(jim,crystal). father(elmo,jim). fath
% fathers
father(michael,cathy).
father(michael,sharon).
father(charles_gordon,michael).
father(charles_gordon,julie).
father(charles,charles_gordon).
father(jim,melody).
father(jim,crystal).
father(elmo,jim).
father(greg,stephanie).
father(greg,danielle).
% mothers
mother(melody,cathy).
mother(melody,sharon).
mother(hazel,michael).
mother(hazel,julie).
mother(eleanor,melody).
mother(eleanor,crystal).
mother(crystal,stephanie).
mother(crystal,danielle).
% parents
parent(X,Y) :- father(X,Y).
parent(X,Y) :- mother(X,Y).
% men
male(michael).
male(charles_gordon).
male(charles).
male(jim).
male(elmo).
male(greg).
% women
female(cathy).
female(sharon).
female(julie).
female(hazel).
female(eleanor).
female(melody).
female(crystal).
female(stephanie).
female(danielle).
person(X) :- male(X) ; female(X).
parent(X,Y) :- father(X,Y) ; mother(X,Y). % X is parent of Y
child(X,Y) :- parent(Y,X).
elder(X,Y) :- parent(X,Y). % X is an elder of Y, meaning X is a parent or an ancestor of Y
elder(X,Y) :- parent(X,Z), elder(Z,Y).
junior(X,Y) :- child(X,Y). % X is a junior of Y, meaning X is a child or some descendant of Y
junior(X,Y) :- child(X,Z), junior(Z,Y).
我试图在两个人之间找到最近的长者(谓词ne(X,Y,Z)
)。这个人Z
是X
和Y
中的长者,而Z
中的下级也不是X
和Y
中的长者
我的尝试如下所示:
ne(X,Y,Z) :- person(X),
person(Y),
X \= Y,
elder(Z,X),
elder(Z,Y),
junior(A,Z),
not(elder(A,X)),
not(elder(A,Y)).
但这在某种程度上是不正确的,因为每当我运行?-ne(stephanie,cathy,Z)。
Z = jim ;
Z = jim ;
Z = jim ;
Z = jim ;
Z = elmo ;
Z = elmo ;
Z = elmo ;
Z = elmo ;
Z = eleanor ;
Z = eleanor ;
Z = eleanor ;
Z = eleanor ;
但我只能得到一个答案,我不知道怎么回事。谢谢 从这个图中
看来这个答案是正确的
?- ne(stephanie,cathy,A).
A = eleanor ;
A = jim.
这是我尝试的ne/3
ne(X,Y,Z) :-
setof(A, (
elder(A, X),
elder(A, Y),
X \= Y,
\+ (elder(A, T), elder(T, X) , elder(T, Y) ))
, As), member(Z, As).
不确定这是不是更好的方式
Setof/3(与member/2连接)用于消除重复答案,因为
?- aggregate(count,A^ne(stephanie,cathy,A),N).
N = 32.
有了这个核心逻辑
ne(X,Y,A) :-
elder(A, X),
elder(A, Y),
X \= Y,
\+ (elder(A, T), elder(T, X) , elder(T, Y)).
注:变量A局部替换原始Z
编辑
我没有考虑@Boris的精明评论,但在删除重复的parent/2定义后,
setof/3+member/2
技巧变得毫无用处。您的程序中有相当多的冗余。您已经定义了两次parent/2
。同样,“人”是“男性”或“女性”,但为什么你有父亲/2
和母亲/2
,而不仅仅是父母/2
?或者同一个“人”可以是“男性”和“母亲”?无论哪种方式,跟踪你的程序,你都可能“发现”出了什么问题。不要忽略编译时警告。谢谢你的评论。我想我应该研究一下单例变量警告以及类似的答案。我的尝试是错误的,因为它打印了埃莉诺、吉姆和埃尔莫,他们都是他们(斯蒂芬妮和凯西)的共同长者(埃莉诺、吉姆和埃尔莫)。它应该做的就是打印埃莉诺和吉姆。我尝试了您的实现,但它似乎没有绑定任何变量?(它无限打印“true”)。