首先定义两个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>