Prolog中的感叹号

时间:2013-02-25 11:13:01

标签: prolog

鉴于以下事实和谓词:

sound(time1).
sound(time2).
sun(time3).
relax(X):-sound(X),!,sun(X).
relax(_):-sun(_).

执行relax(S).时,由于S=time1,我希望得到!,如果我错了,请说明(如果我错了),如果满足'X',然后停止回溯。

这是跟踪:

3 ?- trace.
true.

[trace] 3 ?- relax(S).
   Call: (6) relax(_G1831) ? creep
   Call: (7) sound(_G1831) ? creep
   Exit: (7) sound(time1) ? creep
   Call: (7) sun(time1) ? creep
   Fail: (7) sun(time1) ? creep
   Fail: (6) relax(_G1831) ? creep
false.

那么为什么Prolog也会检查sun(time1),即使它在被sound(X)满意后遇到感叹号(因为sound(time1)是事实)。

3 个答案:

答案 0 :(得分:26)

!符号可以防止左侧的条款向后移动,它就像一个单向门,因此它不会在切割之后回溯。

sound(time1)为真时,将评估下一个句子sun(time1),然后只有prolog会发现sun(time1)false(通过搜索知识库,它实际上并不知道这是事实。)

然后,由于剪切,prolog不会在第一个子句中尝试值time2time3

关于剪切的更多信息:

Prolog从左到右评估谓词的子句。它将值绑定到最左边子句中的变量。如果该子句是true,则它将移至下一个子句。如果它是false,prolog也会尝试其他值。

如果任何值都不能满足任何条款,那么它将是false,因此将是整个谓词(因为子句由AND连接)。

整个事物作为树的深度优先遍历,其中子句是节点,边表示其变量的不同值。如果遍历发现一个子句为false,它将返回其前一个子句并尝试不同的值。

这是剪辑。如果你在两个子句之间放置一个剪切(!),这意味着如果一个剪切后的子句成为false,那么只有在评估时才会尝试新值切割后运行。这意味着在剪切之前使用的变量的值已锁定,并且当评估越过剪切时,它们无法更改。

答案 1 :(得分:21)

为了更清楚地说明这一点,如果有人仍在努力解决感叹号运算符的工作方式(就像我做的那样),这里有一个例子:

sound(time3).
sound(time1).
sun(time1).
relax(X):-sound(X),!,sun(X).

对于这个特定的例子,如果您向Prolog询问?-relax(S).,则结果为 false 。我们可以用这样的方式描述Prolog:

  1. Prolog搜索被叫谓词(放松(SOMEVARIABLE统一 在我们的例子中使用S))
  2. Prolog发现谓词放松(X)。变量 X和S现在绑定了。
  3. Prolog开始评估条款:
    • 声音(X)
      • Prolog在文件中搜索哪个事实 满足声音(X)。
      • 它找到事实声音(时间3)。并将其与我们的变量X = S = time3统一起来。
    • <!/强>
      • Prolog继续下一个clausule,这是运营商!所以他不会回溯这个运营商。
    • 太阳(X)
      • Prolog在文件中搜索满足sun(X)的事实。 X已被绑定,因此它会搜索 sun(time3),但不会 存在。
  4. 结论
    • 此时,如果没有!运算符Prolog会将(回溯)返回到声音(X),它会将变量X = S重新分配为X = S = time1。哪个最终会导致 true ,因为事实 sun(time1)存在。
    • Prolog返回false,因为他无法匹配任何规则的放松(S)。
  5. 反对,就像我在4.中所说的那样!运营商会导致成功

    sound(time3).
    sound(time1).
    sun(time1).
    relax(X):-sound(X),sun(X).
    

    如果我在某些方面错了,请随时纠正我。

答案 2 :(得分:4)

它仍然会尝试满足规则的其余部分,它不会在感叹号之前回溯。也就是说,如果sun(X)失败,它将不会回溯并尝试将不同的对象与sound(X)匹配,但无法完全匹配该规则。