我有这些事实和规则:
male(roelof).
male(mans).
male(ronald).
male(jan).
female(chantal).
female(marie).
female(gerda).
female(dagmar).
female(denise).
female(kimberly).
parent(mans,gerda).
parent(mans,roelof).
parent(marie,gerda).
parent(marie,roelof).
parent(dagmar,denise).
parent(dagmar,kimberly).
parent(ronald,denise).
parent(ronald,kimberly).
parent(chantal,tamara).
parent(roelof,tamara).
parent(jan,chantal).
parent(jan,dagmar).
father_child(Father, Child) :-
parent(Father, Child),
male(Father).
mother_child(Mother, Child) :-
parent(Mother, Child),
female(Mother).
child_father_mother(Child, Father, Mother) :-
father_child(Father, Child),
mother-child(Mother, Child).
same_father(Child, Sibling) :-
father_child(Father, Child),
father_child(Father, Sibling).
same_mother(Child, Sibling) :-
mother_child(Mother, Child),
mother_child(Mother, Sibling).
siblings(Child, Sibling) :-
same_father(Child, Sibling),
Child \= Sibling.
siblings(Child, Sibling) :-
same_mother(Child, Sibling),
Child \= Sibling.
display_siblings(X,Y) :-
setof(X-Y, (siblings(X,Y), \+X=Y), Sibs),
member((X-Y,Y), Sibs),
\+ (Y@<X, member((Y,X), Sibs)).
但是当我display_siblings
时,我希望看到roelof-gerda
。
但输出仅为x=roelof
我做错了什么。 我是Prolog的初学者,并尝试了解它是如何工作的。
鲁洛夫
编辑1:这可能是一个解决方案:How can I prevent duplicates in prolog
编辑2:我会这样做,但我仍然不明白为什么'setof(X-Y,(兄弟姐妹(X,Y),X @&lt; Y),Sibs),写(同胞)。是错的。它适用于display_'siblings(gerda,X)'和'display_siblings(X,Y)'
两种情况答案 0 :(得分:1)
您的大部分问题都在于display_siblings
谓词:
display_siblings(X,Y) :-
setof(X-Y, (siblings(X,Y), \+X=Y), Sibs),
member((X-Y,Y), Sibs),
\+ (Y@<X, member((Y,X), Sibs)).
在第二行中,\+X=Y
是多余的,因为siblings
已经强制它们不同。这可以是:
setof(X-Y, siblings(X,Y), Sibs),
下一行是查询(X-Y,Y)
是否是Sibs
的成员。但是,Sibs
由X-Y
个字词组成,这些字词永远不会与(X-Y,Y)
字词匹配。因此,对member
的此调用将始终失败。应该是:
member(X-Y, Sibs),
然后最后一行过于复杂,如果你想做的就是消除对称重复。您可以简单地使用X @< Y
并提高效率,将其作为setof
支票的一部分:
display_siblings(Sibs) :-
setof(X-Y, (siblings(X,Y), X @< Y), Sibs).
这将产生:
?- display_siblings(Sibs).
Sibs = [chantal-dagmar, denise-kimberly, gerda-roelof].
如果您想为给定的人选择所有兄弟姐妹并仍然避免对称冗余,您可能需要在setof
之后处理这些冗余:
display_siblings(X, Sibs) :-
setof(A-B, ((X = A ; X = B), siblings(A,B)), SibPairs),
pack(SibPairs, Sibs).
pack([X-Y|T], Sibs) :-
pack(T, SibList),
( member(Y-X, SibList)
-> SibList = Sibs
; Sibs = [X-Y|SibList]
).
pack([], []).
?- display_siblings(gerda, Sibs).
Sibs = [roelof-gerda].