我有一个简单的知识库,可以对家谱进行编码。该表示中的一些重要规则如下:
% 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 ;
但我只能得到一个答案,而我无法弄清楚出了什么问题。谢谢!
答案 0 :(得分:2)
来自此图
似乎这个答案是正确的
?- 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的精明评论,但在删除重复的父/ 2定义后,setof/3+member/2
技巧变得无用。