4

我是 Prolog 的新手,我只是在想,为什么这条规则在一次为真之后给了我错误的结果。

likes(1,banana).
likes(1,mango).

test :- likes(1,banana),likes(1,mango).

?- test.  
true;  
false.

我想知道这个错误背后的原因。

4

1 回答 1

6

prolog 的工作方式是评估查询,直到否定失败。

在这里,您已经确定了两个事实:

likes(1, banana).上面写着“1 喜欢香蕉”

likes(1, mango).上面写着“1 喜欢芒果”

然后你建立了一个规则,它基本上评估为:

left_hand_side :- right_hand_side. left_hand_side 如果 right_hand_side

将规则评估为查询尝试匹配事实,如果可以则返回true,如果无法匹配则返回 false。需要注意的一件重要事情是,如果指定,只要规则评估为 ,prolog 将继续匹配事实true

所以让我们一步一步来test :- likes(1,banana),likes(1,mango).

如果test作为查询运行,prolog 首先尝试likes(1,banana)这是一个先前确定的事实,并且是真的。然后,它继续前进,likes(1,mango)这又是一个事实,而且是真的。然后 Prolog 到达规则的末尾,并输出true.

此时,如果您不搜索更多匹配项,则可以缩短查询并只使用 true。但是,如果您正在寻找更多(所有)匹配项,prolog会回溯并尝试再次评估规则,以搜索更多匹配项。

但是,由于您的规则仅匹配“喜欢香蕉和喜欢芒果”并且我们已经匹配likes(1,banana),所以当 prolog 回溯并尝试再次评估likes(1,banana)时,由于我们之前已经匹配它,所以这次没有另一个事实(换句话说,1 不能“像“香蕉不止一次,除非已经定义)来匹配。这就是它的false来源。

在您的 prolog 解释器中,您可以通过键入trace.然后运行查询来跟踪程序的执行。我的踪迹如下:

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

(1 ms) yes
{trace}
| ?- test.
      1    1  Call: test ? 
      2    2  Call: likes(1,banana) ? 
      2    2  Exit: likes(1,banana) ? 
      3    2  Call: likes(1,mango) ? 
      3    2  Exit: likes(1,mango) ? 
      1    1  Exit: test ? 

true ? ;
      1    1  Redo: test ? 
      2    2  Redo: likes(1,banana) ? 
      2    2  Fail: likes(1,banana) ? 
      1    1  Fail: test ? 

(1 ms) no
{trace}
| ?-

最后要注意的一件事:如果不是;true ?提示符下按,而是按<ENTER>,脚本将仅以true.

我很高兴你问了这个问题,因为它让我对 prolog 有一个小小的复习,我真的很喜欢,但很长时间没有使用过。

于 2011-02-16T07:55:11.723 回答