2

我正在七周内完成七种语言,但是我对 prolog 有一些不明白的地方。我有以下程序(基于他们的 wallace 和 grommit 程序):

/* teams.pl */

onTeam(a, aTeam).
onTeam(b, aTeam).
onTeam(b, superTeam).
onTeam(c, superTeam).

teamMate(X, Y) :- \+(X = Y), onTeam(X, Z), onTeam(Y, Z).

并像这样加载它

?- ['teams.pl'].
true.

但它没有给我以下任何解决方案

?- teamMate(a, X).
false.

它可以解决更简单的问题(如书中所示):

?- onTeam(b, X).
X = aTeam ;
X = superTeam.

并且有解决方案:

?- teamMate(a, b).
true ;
false.

我错过了什么?我已经尝试过使用 gnu prolog 和 swipl。

...还有更多...

当您将“不能成为自己的队友”限制移动到然后结束时:

/* teams.pl */

onTeam(a, aTeam).
onTeam(b, aTeam).
onTeam(b, superTeam).
onTeam(c, superTeam).

teamMate(X, Y) :- onTeam(X, Z), onTeam(Y, Z), \+(X = Y).

它给了我我期望的解决方案:

?- ['teams.pl'].
true.

?- teamMate(a, X).
X = b.

?- teamMate(b, X).
X = a ;
X = c.

是什么赋予了?

4

2 回答 2

7

你的观察非常好!事实上,情况更糟,因为即使是最一般的查询也会失败

?- 队友(X,Y)。
的。

声明式地,这意味着“没有任何解决方案”,这显然是错误的,而不是我们期望关系的行为方式:如果有解决方案,那么更一般的查询一定不会失败

您得到这种奇怪且逻辑上不正确的行为的原因是,(\+)/1只有当它的参数被充分实例化时,它才是合理的。

要以更一般的方式表达术语的不等式,无论参数是否被实例化,都可以正常工作使用dif/2,或者,如果您的 Prolog 系统不提供它, iso_dif/2您可以在 标记中找到安全的近似值.

例如,在您的情况下(note_that_I_am_using_underscores_for_readability而不是tuckingTheNamesTogetherWhichMakesThemHarderToRead):

team_mate(X,Y):-差异( X,Y),on_team(X,Z),on_team(Y,Z)。

您的查询现在完全按预期工作:

?- team_mate(a, X)。
X = 乙

最一般的查询当然也可以正常工作:

?- 队友(X,Y)。
X = 一个,
Y = b;
X = b,
Y = 一个;
X = b,
Y = c;
等等

因此,使用dif/2来表达不等式保留了关系的:系统现在不再简单地说false ,即使有解决方案。相反,你会得到你期望的答案!请注意,与以前相比,无论您在哪里拨打电话,这都有效!

于 2016-10-02T08:46:47.500 回答
3

mat的回答给了你一些高层次的考虑和解决方案。我的回答更多地是关于潜在原因,这对您来说可能感兴趣也可能不感兴趣。

(顺便说一句,在学习 Prolog 时,我问了几乎相同的问题,并得到了同一个用户非常相似的答案。太好了。)

证明树

你有一个问题:

两名球员是队友吗?

要从 Prolog 获得答案,您可以制定一个查询:

?- team_mate(X, Y).

其中 X 和 Y 都可以是自由变量或有界变量。

Prolog 会根据您的谓词数据库(事实和规则)尝试找到证明并为您提供解决方案。Prolog通过深度优先遍历证明树来搜索证明

在您的第一个实现中,\+ (X = Y)它位于树的根节点之前,因此它位于树的根节点,并将在以下目标之前进行评估。如果其中一个X或是Y自由变量,则X = Y 必须成功,这意味着\+ (X = Y) 必须失败。所以查询一定会失败

另一方面,如果其中一个XY是一个自由变量,将成功,但稍后将它们相互统一的尝试必须失败。到那时,Prolog 将不得不在证明树的另一个分支下寻找证明,如果还有的话。dif(X, Y)

(考虑到证明树,试着找出一种实现方式dif/2:你认为没有a)向参数添加某种状态dif/2或b)改变解析策略是否可行?)

最后,如果你把它放在\+ (X = Y)最后,并在评估时注意两者XY都是接地的,那么统一变得更像是一个简单的比较,它可能会失败,因此否定会成功

于 2016-10-03T06:13:17.793 回答