如何强制剪辑忽略规则的特定事实?

How to force clips to ignore a certain fact for a rule?

我有以下deftemplate

(deftemplate potential
     (multislot values (type INTEGER))
)

我想删除这个 deftemplate 的实例,如果它只出现一个整数的话。 例子: 事实 1:潜力 1 2 3 事实 2:潜力 2 3 4 事实 3:潜在 2 3 4 5

我想收回 fact-1 和 fact-3,因为它们唯一包含 1 和 5。

我正在尝试使用如下规则来实现它:

  1 (defrule remove_if_only_option
  2     ?p<-(potential (values $? ?value $?   ))
  3     (not (exists   (potential (values $? ?value $?)  )))
  4     =>
  5     (retract ?p)
  7 )

显然它不起作用,因为第 3 行可以匹配最初的事实。有什么方法可以使这个 运行 规则不考虑其余部分的 ?p 吗?

谢谢。

您的规则中的任何模式都不会受到初始事实存在与否的影响,因为它们都匹配潜在事实。 exists 条件元素在第二个模式中是多余的,所以你的规则等同于

(defrule remove_if_only_option
   ?p <- (potential (values $? ?value $?))
   (not (potential (values $? ?value $?)))
   =>
   (retract ?p))

并且由于条件 x and not x 永远不会为真,因此永远无法满足此规则。

您可以通过比较事实地址来判断两个相同类型的事实是否不同,但是由于您不能在非条件元素中绑定事实地址,因此在这种情况下不能这样做。或者,您可以包含一个插槽,其中包含每个事实的唯一值,可用于判断事实是否不同:

         CLIPS (6.31 6/12/19)
CLIPS> 
(deftemplate potential
   (slot id (default-dynamic (gensym*)))
   (multislot values (type INTEGER)))
CLIPS> 
(defrule remove_if_only_option
   ?p <- (potential (id ?id) (values $? ?value $?))
   (not (potential (id ~?id) (values $? ?value $?)))
   =>
   (retract ?p))
CLIPS> 
(assert (potential (values 1 2 3))
        (potential (values 2 3 4))
        (potential (values 2 3 4 5)))
<Fact-3>
CLIPS> (agenda)
0      remove_if_only_option: f-3,*
0      remove_if_only_option: f-1,*
For a total of 2 activations.
CLIPS> 

最初,这似乎可行,但运行后您会发现存在问题:

CLIPS> (run 1)
CLIPS> (agenda)
0      remove_if_only_option: f-2,*
0      remove_if_only_option: f-1,*
For a total of 2 activations.
CLIPS>

删除 f-3 后,f-2 中的值 4 现在变得唯一,因此此事实现在也将被此规则删除。问题是通用值集隐含地由潜在事实的集合表示,一旦你开始删除它们,你就会改变通用值集。

为此,您至少需要两个步骤,因此至少需要两条规则。一种方法是在一个步骤中标记需要删除的事实,然后在另一个步骤中删除它们:

CLIPS> (clear)
CLIPS> 
(deftemplate potential
   (slot id (default-dynamic (gensym*)))
   (multislot values (type INTEGER))
   (slot delete (default no)))
CLIPS> 
(defrule remove_if_only_option
   (not (done))
   ?p <- (potential (id ?id) (values $? ?value $?) (delete no))
   (not (potential (id ~?id) (values $? ?value $?)))
   =>
   (modify ?p (delete yes)))
CLIPS> 
(defrule remove
   (declare (salience -10))
   ?p <- (potential (delete yes))
   =>
   (assert (done))
   (retract ?p))
CLIPS>    
(assert (potential (values 1 2 3))
        (potential (values 2 3 4))
        (potential (values 2 3 4 5)))
<Fact-3>
CLIPS> (agenda)
0      remove_if_only_option: *,f-3,*
0      remove_if_only_option: *,f-1,*
For a total of 2 activations.
CLIPS> (run 1)
CLIPS> (agenda)
0      remove_if_only_option: *,f-1,*
-10    remove: f-4
For a total of 2 activations.
CLIPS> (facts)
f-0     (initial-fact)
f-1     (potential (id gen4) (values 1 2 3) (delete no))
f-2     (potential (id gen5) (values 2 3 4) (delete no))
f-4     (potential (id gen6) (values 2 3 4 5) (delete yes))
For a total of 4 facts.
CLIPS> (run 1)
CLIPS> (agenda)
-10    remove: f-5
-10    remove: f-4
For a total of 2 activations.
CLIPS> (run)
CLIPS> (facts)
f-0     (initial-fact)
f-2     (potential (id gen5) (values 2 3 4) (delete no))
f-6     (done)
For a total of 3 facts.
CLIPS> 

创建包含唯一值的事实的另一种方法:

CLIPS> (clear)
CLIPS> 
(deftemplate potential
   (slot id (default-dynamic (gensym*)))
   (multislot values (type INTEGER)))
CLIPS> 
(defrule add-to-unique
   (not (done))
   ?c <- (unique $?unique)      
   (potential (id ?id) (values $? ?value $?))
   (not (potential (id ~?id) (values $? ?value $?)))
   (test (not (member$ ?value ?unique)))
   =>
   (retract ?c)
   (assert (unique $?unique ?value)))
CLIPS>  
(defrule remove_if_only_option
   (declare (salience -10))
   (unique $?unique)
   ?p <- (potential (values $? ?value $?))
   (test (member$ ?value ?unique))
   =>
   (assert (done))
   (retract ?p))
CLIPS>   
(assert (potential (values 1 2 3))
        (potential (values 2 3 4))
        (potential (values 2 3 4 5)))
<Fact-3>
CLIPS> (assert (unique))
<Fact-4>
CLIPS> (run)
CLIPS> (facts)
f-0     (initial-fact)
f-2     (potential (id gen26) (values 2 3 4))
f-6     (unique 5 1)
f-7     (done)
For a total of 4 facts.
CLIPS>