为什么这不能显示正确的答案

时间:2014-03-16 21:11:29

标签: prolog

我有这些事实和规则:

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)'

两种情况

1 个答案:

答案 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的成员。但是,SibsX-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].