prolog returns 值两次

prolog returns value twice

我只是在学习序言,我 运行 遇到了一个问题,在询问侄女和侄子时,我得到了两次相同的答案。我只是不能全神贯注。有谁知道我做错了什么?也许每个堂兄都有两个规则?但是求兄弟姐妹的时候就没问题了..

更新:我尝试了一些东西,回到我在这里写下的代码后,侄女只能是女性的规则不再适用。和侄子 returns false.

所以我有代码:

male( ted  ).
male( john ).
male( aron ).
male( nico ).
male( gio  ).

female( liza   ).
female( sophie ).
female( lily   ).
female( elin   ).
female( daisy  ).
    
parent_of( lily   , aron ).
parent_of( john   , aron ).
parent_of( john   , elin ).
parent_of( lily   , elin ).
parent_of( sophie , gio  ).
parent_of( sophie , nico ).
parent_of( daisy  , liza ).
parent_of( ted    , liza ).
    
father_of(X,Y):- male(X),
    parent_of(X,Y).

mother_of(X,Y):- female(X),
    parent_of(X,Y).

sister_of( X , Y ) :- % (X,Y or Y,X) %
  female(X),
  father_of(F,Y),
  father_of(F,X),
  X \= Y.
sister_of( X , Y ) :-
  female(X),
  mother_of(M,Y),
  mother_of(M,X),
  X \= Y.
    
brother_of(X,Y):- %(X,Y or Y,X)%
  male(X),
  father_of(F,Y),
  father_of(F,X),
  X \= Y.
brother_of(X,Y):- male(X),
  mother_of(M,Y),
  mother_of(M,X),
  X \= Y.

niece_of(X,Y):-
  dif(X,Y),
  female(X), 
  parent_of(W,Y),
  parent_of(P,X), 
  brother_of(P,W).
niece_of(X,Y) :-
  dif(X,Y),female(X), 
  parent_of(W,Y),
  parent_of(P,X), 
  sister_of(P,W).

nephew_of(X,Y) :-
  dif(X,Y),
  male(X), 
  parent_of(W,Y),
  parent_of(P,X),
  brother_of(P,W).
nephew_of(X,Y):-
  dif(X,Y),
  male(X), 
  parent_of(W,Y),
  parent_of(D,X),
  sister_of(D,W).

我得到的输出是

?- niece_of(X,liza).
X = aron ;
X = aron ;
X = nico ;
X = nico ;
X = gio ;
X = gio ;
false.

?- nephew_of(X,liza).
false.

首先是一些简化和扩展的家谱

male(ted).
male(john).
male(aron).
male(nico).
male(gio).
male(ken).
male(vladimir).

female(liza).
female(sophie).
female(lily).
female(elin).
female(daisy).
female(barbie).

parent(lily, aron).
parent(john, aron).
parent(john, elin).
parent(lily, elin).
parent(sophie, gio).
parent(sophie, nico).
parent(vladimir, gio).
parent(vladimir, nico).
parent(daisy, liza).
parent(ted, liza).

% grandfathers
parent(ken, lily).
parent(ken, daisy).
parent(ken, sophie).
parent(barbie, lily).
parent(barbie, daisy).
parent(barbie, sophie).



father(Father, Child) :-
    male(Father),
    parent(Father, Child).

mother(Mother, Child) :-
    female(Mother),
    parent(Mother, Child).

sibling(X, Y) :-
    father(Father, Y),
    father(Father, X),
    X\=Y.

sister(Sister, Sibling) :-
    female(Sister),
    sibling(Sister, Sibling).
    
brother(Brother, Sibling) :-
    male(Brother),
    sibling(Brother, Sibling).

niece(Niece, ParentsSibling) :-
    female(Niece),
    parent(NiecesParent, Niece),
    sibling(NiecesParent, ParentsSibling).

nephew(Nephew, ParentsSibling) :-
    male(Nephew),
    parent(NephewParent, Nephew),
    sibling(NephewParent, ParentsSibling).

我添加了 sibling/2 谓词以删除一些重复使用的代码。

为什么你的侄子有重复?

你在尝试定义侄子 parent 的姐姐时确实使用了 parent 谓词,在这种情况下,你会得到每个兄弟姐妹两次(一次是因为与母亲的评估,一次是因为和父亲一起评估)。您可以使用 trace[=12=].

进行验证

解决方法

在查找兄弟姐妹时,我正在查找具有同一父亲的 2 个人(检查 sibling/2 谓词)。

如果出于某种原因,您的亲戚能够拥有人类可以在没有父亲的情况下生存的情况,那将行不通。在这种情况下,您需要修改 sibling/2 谓词并使用 parent,生成所有值(例如 findall),然后生成 return 个不同的值。

首先,根据你的数据库,没有人是任何人的侄女或侄子。当您绘制关系 parent_of/2.

的图形时,可以清楚地看到这一点

female(lily).
female(sophie).
female(daisy).
female(elin).
female(liza).

male(john).
male(ted).
male(aron).
male(gio).
male(nico).

parent_of(lily, aron).
parent_of(lily, elin).
parent_of(john, aron).
parent_of(john, elin).
parent_of(sophie, gio).
parent_of(sophie, nico).
parent_of(daisy, liza).
parent_of(ted, liza).

现在,考虑定义关系 siblings0/2:

的规则的第一个版本
siblings0(Person1, Person2) :-
    dif(Person1, Person2),
    parent_of(Parent, Person1),
    parent_of(Parent, Person2).

使用这个规则,有两种不同的方法可以证明 AronElin 是兄弟姐妹(首先,因为他们都有同一个母亲;其次,因为他们都有同一个父亲)。然而,只有一种方法可以证明 GioNico 是兄弟姐妹(因为没有关于谁是每个人的父亲的信息他们)。

?- siblings0(aron, elin).
true ;  % <== same mother
true ;  % <== same father
false.

?- siblings0(gio, nico).
true.   % <== same mother

为了避免冗余,我们可以使用ISO内置谓词once/1:

siblings(Person1, Person2) :-
    dif(Person1, Person2),
    person(Person1),
    person(Person2),
    once( ( parent_of(Parent, Person1),
            parent_of(Parent, Person2) ) ).

person(Person) :-
    (   female(Person)
    ;   male(Person) ).

现在,我们对每个查询只得到一个答案:

?- siblings(aron, elin).
true.

?- siblings(gio, nico).
true.

因此,扩展您的数据库并使用谓词 siblings/2 来定义其他关系,一切都会正常进行!

female(lily).
female(sophie).
female(daisy).
female(elin).
female(liza).
female(pat).   % <== add

male(john).
male(ted).
male(aron).
male(gio).
male(nico).
male(coy).     % <== add

parent_of(lily, aron).
parent_of(lily, elin).
parent_of(john, aron).
parent_of(john, elin).
parent_of(sophie, gio).
parent_of(sophie, nico).
parent_of(daisy, liza).
parent_of(ted, liza).
parent_of(elin, pat ). % <== add
parent_of(elin, coy).  % <== add
parent_of(gio, pat).   % <== add
parent_of(gio, coy).   % <== add

siblings(Person1, Person2) :-
    dif(Person1, Person2),
    once( ( parent_of(Parent, Person1),
            parent_of(Parent, Person2) ) ).

mother_of(Mother, Child):-
    female(Mother),
    parent_of(Mother, Child).

father_of(Father, Child):-
    male(Father),
    parent_of(Father, Child).

sister_of(Sister, Person) :-
    dif(Sister, Person),
    female(Sister),
    siblings(Sister, Person).

brother_of(Brother, Person) :-
    dif(Brother, Person),
    male(Brother),
    siblings(Brother, Person).

niece_of(Niece, Person):-
    female(Niece),
    parent_of(Parent, Niece),
    siblings(Parent, Person).

nephew_of(Nephew, Person):-
    male(Nephew),
    parent_of(Parent, Nephew),
    siblings(Parent, Person).

示例:

?- niece_of(Niece, Person).
Niece = pat,
Person = aron ;
Niece = pat,
Person = nico.

?- nephew_of(Nephew, Person).
Nephew = coy,
Person = aron ;
Nephew = coy,
Person = nico.