递归调用规则

Recursive call to a rule

我的这条规则触发了数千条其他相同的规则:

(defrule calculate-temperature
    ?zone <- (object (is-a ZONE) (id ?id-zone) (dew-temperature ?dew-temperature) (delta-R ?delta-R))
    (process-action (is cooling))        
    =>
    (bind ?supply-temperature (+ ?delta-R ?dew-temperature))
    (modify-instance ?zone (supply-temperature ?supply-temperature))        
    (printout ?*debug-print* "supply-temperature:", ?supply-temperature crlf))

我想做的是在我可以计算时修改我的区域的供应温度,即当内部区域定义了 delta-R 和露点温度时。 但是对象的修改在递归永无止境的循环中不断触发。 请问,避免这些烦人的循环的最佳做法是什么?

谢谢 尼古拉

这条规则本身不会循环:

CLIPS> (clear)
CLIPS> 
(defclass ZONE
   (is-a USER)
   (slot id)
   (slot dew-temperature)
   (slot supply-temperature)
   (slot delta-R))
CLIPS> 
(definstances start-instances
   (z1 of ZONE (id 1) (dew-temperature 100) (delta-R 10)))
CLIPS>    
(deftemplate process-action 
   (slot is))
CLIPS> 
(deffacts start-facts
   (process-action (is cooling)))
CLIPS> (defglobal ?*debug-print* = nil)
CLIPS> 
(defrule calculate-temperature
   ?zone <- (object (is-a ZONE) 
                    (id ?id-zone)
                    (dew-temperature ?dew-temperature)
                    (delta-R ?delta-R))
   (process-action (is cooling))        
   =>
   (bind ?supply-temperature (+ ?delta-R ?dew-temperature))
   (modify-instance ?zone (supply-temperature ?supply-temperature))        
   (printout ?*debug-print* "supply-temperature:", ?supply-temperature crlf))
CLIPS> (watch slots)
CLIPS> (reset)
::= local slot id in instance z1 <- 1
::= local slot dew-temperature in instance z1 <- 100
::= local slot delta-R in instance z1 <- 10
::= local slot supply-temperature in instance z1 <- nil
CLIPS> (run)   
::= local slot supply-temperature in instance z1 <- 110
CLIPS>

所以是您的规则之间的交互导致了循环。

可通过三种通用技术来防止规则循环。首先,您可以删除符合规则条件的 facts/instances 之一。例如,过程-动作事实:

(defrule calculate-temperature
   ?zone <- (object (is-a ZONE) 
                    (id ?id-zone)
                    (dew-temperature ?dew-temperature)
                    (delta-R ?delta-R))
   ?p <- (process-action (is cooling))        
   =>
   (retract ?p)
   (bind ?supply-temperature (+ ?delta-R ?dew-temperature))
   (modify-instance ?zone (supply-temperature ?supply-temperature))        
   (printout ?*debug-print* "supply-temperature:", ?supply-temperature crlf))

其次,您可以修改 fact/instance 槽值以防止模式匹配。例如,delta-R:

(defrule calculate-temperature
   ?zone <- (object (is-a ZONE) 
                    (id ?id-zone)
                    (dew-temperature ?dew-temperature)
                    (delta-R ?delta-R&~0))
   (process-action (is cooling))        
   =>
   (bind ?supply-temperature (+ ?delta-R ?dew-temperature))
   (modify-instance ?zone (supply-temperature ?supply-temperature) (delta-R 0))        
   (printout ?*debug-print* "supply-temperature:", ?supply-temperature crlf))

第三(这仅适用于对象模式匹配),规则仅由对规则条件中明确匹配的插槽的更改触发。所以如果你想改变 delta-R 来触发规则,而不是改变露点温度,你可以这样写规则:

(defrule calculate-temperature
   ?zone <- (object (is-a ZONE) 
                    (id ?id-zone)
                    (delta-R ?delta-R))
   (process-action (is cooling))        
   =>
   (bind ?supply-temperature (+ ?delta-R (send ?zone get-dew-temperature)))
   (modify-instance ?zone (supply-temperature ?supply-temperature))        
   (printout ?*debug-print* "supply-temperature:", ?supply-temperature crlf))