2
sisters(mary,catherine).
sisters(catherine,mary).
brothers(john,simone).
brothers(simone,john).
marriage(john,mary,2010).
marriage(mary,john,2010).
marriage(kate,simone,2009).
marriage(simone,kate,2009).
marriage(catherine,josh,2011).
marriage(josh,catherine,2011).
birth(mary,johnny).
birth(mary,peter).
birth(catherine,william).
birth(kate,betty).
givebirthyear(mary,peter,2015).
givebirthyear(mary,johnny,2012).
givebirthyear(catherine,william,2012).
givebirthyear(kate,betty,2011).
siblings(X,Y) :-
    birth(Parent,X),
    birth(Parent,Y).
cousins(X,Y) :-
    birth(Xparent,X),
    birth(Yparent,Y),
    sisters(Xparent,Yparent).
cousins(X,Y) :-
    X \= Y,
    birth(Xmom,X),
    birth(Ymom,Y),
    marriage(Xmom,Xdad,_),
    marriage(Ymom,Ydad,_),
    brothers(Xdad,Ydad).

我不知道我的代码中发生了什么。当我输入

cousins(betty,johnny).

cousins(william,johnny).

序言说的是真的。但是当我进入

cousins(S,johnny).

序言说S = william但没有告诉我S = betty。我真的不知道发生了什么。需要帮忙。

这是我得到的序言结果。

?- cousins(S,johnny).
S = william ;
false.

?- cousins(betty,johnny).
true.

?- cousins(william,johnny).
true .
4

1 回答 1

1

问题

发生这种情况的原因是因为

X \= Y,

实际上意味着:

\+(X = Y).

现在\+not在 Prolog 中与逻辑上的 not 相比有一些奇怪的行为。\+意味着否定作为有限的失败。这意味着\+(G)被认为是true在 Prolog 查询的情况下G,并且找不到满足的方法G,并且这G是有限的(最终满足的追求G结束)。

现在,如果我们查询\+(X = Y),Prolog 将因此旨在统一XY。如果XY是(不接地的)变量,则X可以等于Y。因此X \= Y,万一失败,X并且Y是自由变量。

所以基本上我们可以使用另一个谓词,例如对两个变量施加约束,当变量接地时触发,或者我们可以重新排序子句的主体,这样在我们调用之前XY已经接地了X \= Y

例如,如果我们可以假设XandY将在调用 之后接地birth/2,我们可以将子句重新排序为:

cousins(X,Y) :-
    birth(Xmom,X),
    birth(Ymom,Y),
    X \= Y,
    marriage(Xmom,Xdad,_),
    marriage(Ymom,Ydad,_),
    brothers(Xdad,Ydad).

然而,Prolog 有一个谓词dif/2,它对两个变量施加约束,并且从这两个变量接地的那一刻起,如果两者相等,它将失败。所以我们可以像这样使用它:

cousins(X,Y) :-
    dif(X,Y),
    birth(Xmom,X),
    birth(Ymom,Y),
    marriage(Xmom,Xdad,_),
    marriage(Ymom,Ydad,_),
    brothers(Xdad,Ydad).

让事情变得更简单

话虽如此,我认为您使程序过于复杂。我们可以从几个定义开始:

两个人slibings/2brothers/2sisters/2

slibings(X,Y) :-
    brothers(X,Y).
slibings(X,Y) :-
    sisters(X,Y).

然而,有可能brothers/2并且sisters/2不提供所有信息。如果两个人有同一个母亲,那么两个人也是slibing(我们假设人们在这里不离婚,或者至少在他们再婚后不生其他孩子)。

slibings(X,Y) :-
    dif(X,Y),
    birth(Mother,X),
    birth(Mother,Y).

a parent/2of a person 是该人的母亲或父亲(与母亲结婚的人)。

所以我们可以写:

parent(Mother,X) :-
    birth(Mother,X).
parent(Father,X) :-
    birth(Mother,X),
    marriage(Father,Mother,_).

根据您的示例,marriage/3谓词是双向的:在 casemarriage(X,Y,Z).中,还有一个 fact marriage(Y,X,Z).

现在我们可以定义:

如果有父母是slibings,两个人是堂兄弟:

cousins(X,Y) :-
    parent(MF1,X),
    parent(MF2,Y),
    slibings(MF1,MF2).

就是这样。

于 2017-10-11T21:09:40.657 回答