鉴于以下事实和谓词:
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将不会尝试值time2和time3第一个条款.
更多关于切割:
Prolog从左到右评估谓词的子句.它将值绑定到最左边子句中的变量.如果该条款是true,它将移动到下一个.如果是的话false,prolog也会尝试其他值.
如果任何值都不能满足任何条款false,那么它将是整个谓词(因为条款由AND连接).
整个事物作为树的深度优先遍历,其中子句是节点,边缘表示其变量的不同值.如果遍历找到一个子句false,它将返回其前一个子句并尝试不同的值.
这是削减.如果!在两个子句之间放置一个cut(),则意味着如果切割后的子句变为false,则只有在评估后的评估运行时,尝试新值才会继续.这意味着在切割之前使用的变量的值被锁定,并且当评估越过切割时它们不能被改变.
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:
反对就像我在4.中所说的那样!运营商取得成功.
sound(time3).
sound(time1).
sun(time1).
relax(X):-sound(X),sun(X).
Run Code Online (Sandbox Code Playgroud)
如果我在某些方面错了,请随意纠正我.
| 归档时间: |
|
| 查看次数: |
22034 次 |
| 最近记录: |