5

我正在阅读“七周内七种语言”的自动取款机,但我对一些我不理解“否”响应的 Prolog 查询感到困惑。

friends.pl文件如下所示:

likes(wallace, cheese).
likes(grommit, cheese).
likes(wendolene, sheep).

friend(X, Y) :- \+(X = Y), likes(X, Z), likes(Y, Z).

我可以对其进行一些简单的查询,例如:

| ?- ['friends'].
compiling /home/marc/btlang-code/code/prolog/friends.pl for byte code...
/home/marc/btlang-code/code/prolog/friends.pl compiled, 12 lines read - 994 bytes written, 8 ms

yes
| ?- friend(wallace,grommit).

yes
| ?- friend(wallace,wendolene).

no

这一切都在预料之中。现在,我想在查询中引入一个变量。我的意图是 Prolog 会给我一份华莱士所有朋友的名单。我期待X = grommit,但我得到no

| ?- trace.
The debugger will first creep -- showing everything (trace)

yes
{trace}
| ?- friend(wallace,X).
      1    1  Call: friend(wallace,_16) ?
      2    2  Call: \+wallace=_16 ?
      3    3  Call: wallace=_16 ?
      3    3  Exit: wallace=wallace ?
      2    2  Fail: \+wallace=_16 ?
      1    1  Fail: friend(wallace,_16) ?

no
{trace}

它甚至没有尝试将X( _16) 与grommit. 为什么?

4

4 回答 4

4

这是朋友的定义:

friend(X, Y) :- \+(X = Y), likes(X, Z), likes(Y, Z).

这里重要的是你从\+(X = Y)通常定义为:

\+ Goal :- Goal,!,fail

请注意,这意味着如果目标成功,您肯定会失败。自由变量(那些没有被赋值的)总是统一的,因此是相等的,所以你总是会因为一个自由变量而失败。因此,如果 X 或 Y 还没有值,它将永远不会为 X 或 Y 赋值。

反而

friend(X, Y) :-  likes(X, Z), likes(Y, Z), \+(X = Y)

将表现得更符合您的预期。

这里的问题是 prolog 为您提供了控制程序流的强大方法,但这些方法与它更面向逻辑的设计并不完全吻合。应该可以用一种不会产生这些问题的方式来表达“否定为失败”类型的约束。由于这个原因,我不是一个巨大的序言粉丝。

于 2011-05-12T00:27:24.077 回答
4

关于 Philip JF 的上述评论:

应该可以用一种不会产生这些问题的方式来表达“否定为失败”类型的约束。

这是可能的:此类问题的现代解决方案是约束。在这种情况下,例如dif/2,在所有严肃的 Prolog 系统中都可用。

于 2011-05-12T07:07:59.963 回答
3

的第一个子目标friend/2\+(X = Y)。这是通过首先尝试找到 的解决方案X = Y,然后否定该结果来执行的。谓词=/2大致相当于unify/2,即它试图将左操作数与右操作数统一。现在,当您使用 eg 进行查询时friend(wallace, gromit),这两个原子wallace并不gromit统一;但是当一个自由变量被加入到混合中时,它总是与给定的任何项结合起来,所以X = Y总是成功的,因此\+(X = Y)总是失败的,并且执行永远不会超过第一个子目标。

于 2011-05-12T00:20:41.297 回答
1

首先具有不等式约束的另一个问题是:无法找到未绑定的绑定X(暂时不包括将其与 grommit 统一的琐碎情况)。Prolog 通过运行它的数据库找到绑定,试图统一未绑定的变量。这就是为什么likes(grommit, Z)会找到一些绑定,Z然后可以对其进行进一步处理,因为likes数据库中有子句。但是对于 grommit 与某物的不等式没有这样的子句,所以 Prolog 不能产生任何绑定。就目前的情况而言,friend谓词必须确保在测试不等式之前所有变量都是绑定的。

于 2011-06-04T20:37:30.813 回答