我很难理解为什么这段剪辑代码无法陷入无限循环
(defrule rule0
=>
(assert (my-fact))
)
(defrule rule1
?f <- (my-fact)
=>
(retract ?f)
)
据我所知,rule0
执行断言my-fact
然后rule1
执行撤消它。为什么现在不再rule0
执行?
以下是我的想法:
注意:我从另一个使用模板而不是事实的小程序中抽象出这段代码。
答案 0 :(得分:2)
维基百科对Rete算法的工作原理有一个很好的概述。要理解的关键概念之一是规则不寻求满足它们的数据,而是数据寻找它们满足的规则。 Rete算法假定大多数数据在每个规则触发后保持不变,因此使规则寻找数据将是低效的,因为在每个规则触发之后只有一小部分数据发生变化。而是规则保存已经匹配的状态,并且当对数据进行更改以影响该状态时,它会被更新。
当定义规则rule0时,它被激活,因为它没有条件。当定义规则rule1时,它不会被激活,因为my-fact尚不存在。执行规则rule0时,事实my-fact被断言,然后规则rule1的状态更新并被激活。当执行规则rule1时,我的事实被撤回并且规则rule1的状态被更新,因为它匹配我的事实。规则rule0不受此撤销的影响,因为它没有与my-fact匹配的条件。
答案 1 :(得分:1)
你的第一个解释是与之相关的。规则不会针对同一组事实第二次触发的原则称为折射。使用相同的事实,我不仅意味着相同的值,而且意味着相同的事实地址。
在这里,我们有一个特例。因为rule0没有LHS,所以即使事实基础发生变化,它也不会再次触发。没有LHS意味着没有模式匹配,因此没有进一步激活。
但您可以使用refresh命令再次触发规则。
blablabla(1).png
通常情况下,如果您的事实库中已经存在相同的事实,则无法插入事实(如果它被撤消,您可以再次添加它)。 您可以使用(set-fact-duplication)更改它:
CLIPS> (run)
CLIPS> (refresh rule0)
CLIPS> (agenda)
0 rule0: *
For a total of 1 activation.
但我不建议这样做。