当一个存在时,prolog不会给我一个解决方案

时间:2016-10-02 08:33:37

标签: prolog prolog-dif logical-purity

我正在通过七周的七种语言工作,但有一些我对prolog不了解。我有以下程序(基于他们的华莱士和格罗米特计划):

/* 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.

是什么给出了?

2 个答案:

答案 0 :(得分:6)

你做了很好的观察!事实上,情况更糟,因为即使是最常见的查询也会失败

?- teamMate(X, Y).
false.

声明地说,这意味着“没有任何解决方案”,这显然是错误,而不是我们期望关系如何表现:如果有解决方案,那么更通用查询一定不能失败

你得到这种奇怪且逻辑上不正确的行为的原因是(\+)/1只有在其参数充分实例化时才会发出声音。

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

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

team_mate(X, Y) :- dif(X, Y), on_team(X, Z), on_team(Y, Z).

您的查询现在完全符合预期:

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

最常见的查询当然也可以正常运行:

?- team_mate(X, Y).
X = a,
Y = b ;
X = b,
Y = a ;
X = b,
Y = c ;
etc.

因此,使用dif/2来表达不平等会保留您关系的 :系统现在不再简单地说false 即使有溶液。相反,你会得到你期望的答案!请注意,与之前相比,无论您拨打电话的位置都可以使用

答案 1 :(得分:3)

answer by mat为您提供了一些高级考虑因素和解决方案。我的答案更多地是关于潜在的原因,可能会或可能不会让你感兴趣。

(顺便说一句,在学习Prolog的过程中,我几乎问了the same question并得到了同一个用户very similar answer。很棒。)

证明树

你有一个问题:

  

两名球员是队友吗?

要从Prolog获得答案,请制定一个查询:

?- team_mate(X, Y).

其中X和Y都可以是自由变量或绑定。

基于您的谓词数据库(事实和规则),Prolog尝试查找证明并为您提供解决方案。 Prolog searches for a proof by doing a depth-first traversal of a proof tree

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

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

(考虑到证明树,试着想出一种实现dif/2的方法:你认为没有a)在dif/2\+ (X = Y)的参数中添加某种状态是可能的吗? b)改变决议策略?)

最后,如果你将X放在最后,并注意Y和{{1}}在评估时都是基础的,那么统一就会变得更像一个简单的比较,可能会失败,因此否定可以成功