递归调用规则

时间:2016-06-09 14:09:38

标签: recursion 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))

我想要做的是在我可以计算它时修改我的区域的供应温度,即当内部区域被定义为delta-R和露水温度时。 但是对象的修改继续在一个无法进行的递归循环中触发。 请避免这些恼人的循环的最佳做法是什么?

谢谢 尼古拉

1 个答案:

答案 0 :(得分:1)

本规则本身并不循环:

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>

所以这是导致循环的规则之间的相互作用。

有三种常规技术可以防止规则循环。首先,您可以删除符合规则条件的事实/实例之一。例如,流程动作事实:

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

其次,您可以修改事实/实例槽值以防止模式匹配。例如,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))