我在理解为什么我的序言中的代码为什么会根据我放置规则的顺序执行某些操作时遇到了麻烦。

这是我的数据库:

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.


这就是我想要的。

到目前为止,我只看到规则的顺序在进行递归时很重要。
所以我不明白鲍勃仍然只是他自己的兄弟姐妹,因为我把差异检查放在首位。

谢谢你的帮助!

最佳答案

这是因为统一的工作方式。如果先放差异,则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都已统一,并且如果它们的值相同,则差异将失败。然后将发生回溯。

使用序言环境的跟踪功能可以查看执行过程中逐步发生的情况。

07-24 13:50