【问题标题】:CLIPS asserting facts with OR condition in RHSCLIPS 在 RHS 中用 OR 条件断言事实
【发布时间】:2019-10-03 17:44:25
【问题描述】:

在 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),但从不断言第二个事实。

语法可能是错误的,但我想你知道我想要实现的目标。

【问题讨论】:

    标签: conditional-statements clips


    【解决方案1】:

    首先定义两个deftemplates:一个用于表示已知的属性值,另一个用于表示可推断的属性值。可演绎属性值的分组将使用链接槽组合在一起。

             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> 
    

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

    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>
    

    【讨论】:

      【解决方案2】:

      谢谢加里!我想这就是我一直在寻找的。 我稍微修改了代码以便更容易理解:

      (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))))
      

      【讨论】:

      • 如果您只是推断某事为真,这将起作用,但在这种情况下,您可以通过从第一个模式中删除 (value ?v) 并更改第二个模式来简化 one-remaining-dav模式到 (not (dav (attribute ~?a) (link ?l)))。如果您的属性 window-state 和 door-state 的值为 open/close 或 outside-temperature 的值为cold/comfortable/hot,这也将不起作用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-21
      • 2016-04-11
      • 1970-01-01
      • 1970-01-01
      • 2019-10-30
      • 1970-01-01
      相关资源
      最近更新 更多