剪辑如何不重复规则执行?

时间:2018-06-10 19:01:36

标签: clips expert-system

我很难理解为什么这段剪辑代码无法陷入无限循环

(defrule rule0
=>
        (assert (my-fact))
)

(defrule rule1
        ?f <- (my-fact)
=>
        (retract ?f)
)

据我所知,rule0执行断言my-fact然后rule1执行撤消它。为什么现在不再rule0执行? 以下是我的想法:

  • 如果每个规则使用一些基本事实执行,并且使用相同的基础事实避免重新执行此规则,则会为每个规则记忆。
  • 有某种优化器检测到循环并避开它。
  • 剪辑记住插入和删除的事实,并避免重新插入这些事实(高度怀疑它,我几乎可以肯定这不可能)。

注意:我从另一个使用模板而不是事实的小程序中抽象出这段代码。

2 个答案:

答案 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.

但我不建议这样做。