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

Ale*_*502 2 prolog prolog-dif logical-purity

我正在七周的七种语言中工作,但有一些我对prolog不了解.我有以下程序(基于他们的华莱士和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).
Run Code Online (Sandbox Code Playgroud)

并像这样加载它

?- ['teams.pl'].
true.
Run Code Online (Sandbox Code Playgroud)

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

?- teamMate(a, X).
false.
Run Code Online (Sandbox Code Playgroud)

它可以解决更简单的东西(在书中显示):

?- onTeam(b, X).
X = aTeam ;
X = superTeam.
Run Code Online (Sandbox Code Playgroud)

有解决方案:

?- teamMate(a, b).
true ;
false.
Run Code Online (Sandbox Code Playgroud)

我错过了什么?我尝试了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).
Run Code Online (Sandbox Code Playgroud)

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

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

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

?- teamMate(b, X).
X = a ;
X = c.
Run Code Online (Sandbox Code Playgroud)

是什么赋予了?

mat*_*mat 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 即使有解决方案,系统现在也不再简单地说.相反,你会得到你期望的答案!请注意,与之前相比,无论您拨打电话的地方,这也都有效!