CLIPS 在 RHS 中用 OR 条件断言事实

CLIPS asserting facts with OR condition in RHS

在 CLIPS 中有没有办法处理像这样的规则:

(defrule temperature
    (IT-IS-COLD-INSIDE TRUE)
    =>
    (assert 
        (IT-IS-COLD-OUTSIDE TRUE)
    )
    (or
        (assert (WINDOW-IS-OPEN TRUE))
        (assert (DOOR-IS-OPEN TRUE))
    )
)

我很好奇的是,例如,另一个规则触发,假设该规则的结果是 DOOR-IS-OPEN 被断言为 FALSE,那么 CLIPS 是否可以得出结论,这意味着 WINDOW-IS-OPEN 必须为真(当然如果 IT-IS-COLD-INSIDE 已经为真)?

或者我应该用另一种方式写它:

(defrule temperature 
    (or
        (WINDOW-IS-OPEN TRUE)
        (DOOR-IS-OPEN TRUE)
    )
    (IT-IS-COLD-OUTSIDE TRUE)
    =>
    (assert (IT-IS-COLD-INSIDE TRUE))    
)

这个问题的问题是它在我的用例中并不总是正确的(尽管第一个例子总是涵盖真相)。比方说,也许里面有很强的暖气。我也可以将其添加到图片中,但这并不总是可能的。我正在尝试开发一个可以处理部分定义的数据的系统。

当我 运行 我的原始示例时,它断言第一个事实 (WINDOW-IS-OPEN TRUE) 但从不断言第二个。

语法可能有误,但我猜你已经知道我要实现的目标了。

首先定义两个deftemplates:一个代表已知的属性值,另一个代表可推断的属性值。可推导属性值的分组将使用 link 槽分组在一起。

         CLIPS (6.31 6/12/19)
CLIPS> 
(deftemplate av
   (slot attribute)
   (slot value))
CLIPS> 
(deftemplate dav
   (slot attribute)
   (slot value)
   (slot link))
CLIPS>    
(deffacts initial
   (av (attribute it-is-cold-inside)
       (value TRUE)))
CLIPS> 

然后可以使用以下代码实现您的温度规则。

CLIPS> 
(defrule temperature
   (av (attribute it-is-cold-inside)
       (value TRUE))
   =>
   (assert (av (attribute it-is-cold-outside)
               (value TRUE))
           (dav (attribute window-is-open)
                (value TRUE)
                (link temperature))
           (dav (attribute door-is-open)
                (value TRUE)
                (link temperature))))      
CLIPS> 

接下来创建用于管理可推导属性值的规则。 remove-dav 规则将在已知的 av 事实与其冲突时删除任何 dav 事实。 one-remaining-dav 规则会将 dav 事实转换为 av 事实,当它是特定 link 的最后剩余 dav 事实时。

CLIPS> 
(defrule remove-dav
   (declare (salience 10))
   ?dav <- (dav (attribute ?a)
                (value ?v))
   (av (attribute ?a)
       (value ~?v))
   =>
   (retract ?dav))
CLIPS>    
(defrule one-remaining-dav
   ?dav <- (dav (attribute ?a)
                (value ?v)
                (link ?l))
   (not (and (dav (attribute ?a2)
                  (value ?v2)
                  (link ?l))
             (test (or (neq ?a ?a2) 
                       (neq ?v ?v2)))))
   =>
   (retract ?dav)
   (assert (av (attribute ?a)
               (value ?v))))
CLIPS>

因此当温度规则最初创建可扣除属性值时:

CLIPS> (reset)
CLIPS> (watch rules)
CLIPS> (watch facts)
CLIPS> (run)
FIRE    1 temperature: f-1
==> f-2     (av (attribute it-is-cold-outside) (value TRUE))
==> f-3     (dav (attribute window-is-open) (value TRUE) (link temperature))
==> f-4     (dav (attribute door-is-open) (value TRUE) (link temperature))
CLIPS> 

后期有新信息补充时可以适当扣除:

CLIPS> (assert (av (attribute door-is-open) (value FALSE)))
==> f-5     (av (attribute door-is-open) (value FALSE))
<Fact-5>
CLIPS> (run)
FIRE    1 remove-dav: f-4,f-5
<== f-4     (dav (attribute door-is-open) (value TRUE) (link temperature))
FIRE    2 one-remaining-dav: f-3,*
<== f-3     (dav (attribute window-is-open) (value TRUE) (link temperature))
==> f-6     (av (attribute window-is-open) (value TRUE))
CLIPS>

谢谢加里!我想这就是我要找的。 我稍微修改了代码以使其更易于理解:

(defrule temperature
   (av (attribute it-is-cold-inside)
       (value TRUE))
   =>
   (assert (av (attribute it-is-cold-outside)
               (value TRUE))
           (dav (attribute window-is-open)
                (value MAYBE)
                (link temperature))
           (dav (attribute door-is-open)
                (value MAYBE)
                (link temperature)))) 
(defrule one-remaining-dav
   ?dav <- (dav (attribute ?a)
                (value ?v)
                (link ?l))
   (not (and (dav (attribute ?a2)
                  (value ?v2)
                  (link ?l))
             (test (or (neq ?a ?a2) 
                       (neq ?v ?v2)))))
   =>
   (retract ?dav)
   (assert (av (attribute ?a)
               (value TRUE))))