序言:一个人是自己的兄弟?

我有一些麻烦,理解为什么我的代码在序言中做了一些基于我把我的规则的顺序。

这是我的数据库:

parent(tom, bob). parent(tom, liz). parent(mary, bob). parent(mary, liz). male(tom). male(bob). female(mary). female(liz). 

这里是规则:

 %difference(X, Y) ==> Predicate to check if two people X and Y are not the same person. difference(X, Y) :- \==(X, Y). father(X, Y) :- male(X), parent(X, Y), difference(X, Y). mother(X, Y) :- female(X), parent(X, Y), difference(X, Y). sibling(X, Y) :- difference(X, Y), mother(M, X), mother(M, Y), father(F, X), father(F, Y). 

问题是,当我这样做时,

 ?- sibling(bob, X). 

我明白了

 X = bob ; X = liz ; false. 

但是当我改变顺序时(我把最后一部分的差异(X,Y))

 sibling(X, Y) :- mother(M, X), mother(M, Y), father(F, X), father(F, Y), difference(X, Y). 

我打电话

 ?- sibling(bob, X). 

我明白了

 X = liz; false. 

这是我想要的。

到目前为止,我只看到了recursion时规则的顺序。 所以我不明白鲍勃是不是自己的兄弟姐妹,因为我先把差异检查。

感谢您的帮助!

这是因为统一的方式。 如果先把差值放在一起,则X和Y的值还没有统一到任何值。 考虑一下痕迹:

  goal list: [sibling(bob, Z)] goal: sibling(bob, Z). X-> bob, Y -> Z goal list: [difference(bob, Y), mother(M, bob), mother(M, Y), father(F, bob), father(F, Y).] goal: difference(bob, Y) --SUCCESS goal list: [mother(M, bob), mother(M, Y), father(F, bob), father(F, Y).] goal: mother(M, bob) ... 

当你最后调用差异时,X和Y都是统一的,如果它们是相同的值,则差异将失败。 然后回溯将发生。

使用您的prolog环境的跟踪function来查看在执行过程中一步一步发生的事情。

你的问题的实际原因是(\==)/2different/2 。 它成功的经常。 dif/2 ,你会得到预期的行为。 dif/2可用于许多Prolog系统,如SICStus,YAP,B,SWI。 您也可以在ISO-Prolog中定义一个安全的近似值,如下所示:

 iso_dif(X, Y) :- X \== Y, ( X \= Y -> true ; throw(error(instantiation_error,iso_dif/2)) ). 

现在,如果参数没有被充分实例化,你会得到一个实例化错误。 Prolog放弃计算,并说:我不知道! 这比假装它有一个想法,而没有一个更好。

使用iso_dif/2你仍然必须把它放在规则的末尾。 但是这一次,Prolog将会关注它的正确用法。

 | ?- iso_dif(a,b). yes | ?- iso_dif([a,_],[b,_]). (8 ms) yes | ?- iso_dif([a,X],[X,b]). yes | ?- iso_dif([a,X],[a,X]). no | ?- iso_dif([a,X],[X,X]). uncaught exception: error(instantiation_error,iso_dif/2)