序言:一个人是自己的兄弟?
我有一些麻烦,理解为什么我的代码在序言中做了一些基于我把我的规则的顺序。
这是我的数据库:
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来查看在执行过程中一步一步发生的事情。
你的问题的实际原因是(\==)/2
在different/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)