Prolog中的感叹号

JAN*_*JAN 15 prolog

鉴于以下事实和谓词:

sound(time1).
sound(time2).
sun(time3).
relax(X):-sound(X),!,sun(X).
relax(_):-sun(_).
Run Code Online (Sandbox Code Playgroud)

执行时,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.
Run Code Online (Sandbox Code Playgroud)

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

060*_*002 26

这个!标志可以防止左边的条款向后移动,这就像一个单向的门,这样它就不会在切割之后回溯.

如果sound(time1)是真的,在下一项sun(time1)进行评估,然后才序言会发现,sun(time1)false(通过搜索知识库,它实际上并不知道,这是一个事实).

然后,由于削减,prolog将不会尝试值time2time3第一个条款.

更多关于切割:

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

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

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

这是削减.如果!在两个子句之间放置一个cut(),则意味着如果切割的子句变为false,则只有在评估后的评估运行时,尝试新值才会继续.这意味着在切割之前使用的变量的值被锁定,并且当评估越过切割时它们不能被改变.

  • @ron你误解了切割的作用.它不会停止评估,它只是意味着所有选择点累积直到`!`被丢弃.当达到'sound(X)`时,可能的时间是`time1`和`time2`.prolog解释器选择第一个(`time1`)并创建一个选择点,它可以回溯到该子句的其余部分失败,因此它可以用`time2`重新评估.除了丢弃这个选择点之外,`!`什么都不做.Prolog现在评估谓词的其余部分,但不能在`!`之前回溯并再次使用`time2`进行测试. (3认同)

Sma*_*y77 24

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

sound(time3).
sound(time1).
sun(time1).
relax(X):-sound(X),!,sun(X).
Run Code Online (Sandbox Code Playgroud)

对于这个特定的例子,如果你问Prolog ?-relax(S).这个结果是假的.我们可以用这样的方式描述Prolog:

  1. Prolog 在我们的例子中搜索被要求的谓词(放松(SOMEVARIABLE与S统一)).
  2. Prolog发现谓词放松(X).变量X和S现在绑定.
  3. Prolog开始评估条款:
    • 声音(X)
      • Prolog在文件中搜索满足声音(X)的事实.
      • 它找到了事实声音(time3).并将它与我们的变量X = S = time3统一起来.
    • !
      • Prolog继续下一个clausule,这是运营商!所以他不会回溯这个运营商.
    • 太阳(X)
      • Prolog在文件中搜索满足sun(X)的事实.X已被绑定,因此它搜索不存在的sun(time3).
  4. 结论
    • 在这一点上,如果没有!运算符Prolog将返回(回溯)到声音(X),它将重新分配变量X = S,因为X = S = time1.由于存在太阳(time1),因此最终会导致真实.
    • Prolog返回false,因为他无法匹配任何规则的放松(S).

反对就像我在4.中所说的那样!运营商取得成功.

sound(time3).
sound(time1).
sun(time1).
relax(X):-sound(X),sun(X).
Run Code Online (Sandbox Code Playgroud)

如果我在某些方面错了,请随意纠正我.

  • 我发现这个解释比接受的答案清楚得多,谢谢! (2认同)

Jun*_*uxx 5

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