defrule 从未被列入议程|剪辑

defrule never makes it in the agenda | CLIPS

我想建立一个专家系统,在某些楼层的建筑物(它需要为任意数量的楼层工作)发生紧急情况时,电梯应该将人们带到地下。 问题是,在任何楼层发送电梯的 defrule 从未列入议程,因此系统什么都不做。正确的操作应该是触发规则,然后触发另一个规则,让人们离开地板。

defrule 的代码是这样的:

(defrule move_to_floor        "elevator moves to any floor "
      ?i <- (elevator is_at floor ?x has ?y adults and ?z minors)
      (floor ?fl&~?x has ?n adult and ?m minor people)
      (test (> (+ ?n ?m) 0))
      => 
      (retract ?i)
      (assert (elevator is_at floor ?fl has ?y adults and ?z minors))
)

在上面的另一个 defrule 中从用户初始化的事实是:

f-0     (initial-fact)
f-1     (elevator is_at 0 has 0 adults and 0 minors)
f-3     (capacity 4)
f-4     (floors 3)
f-5     (initCanEnter 0) ;At 0 this prevents from entering the init_defrule again
f-6     (floor 3 has 2 adult and 1 minor people)
f-7     (floor 2 has 4 adult and 5 minor people)
f-8     (floor 1 has 1 adult and 2 minor people)

我似乎找不到解决方案。另外,我使用的是 defacts 而不是 deftemplate,因为我在互联网上看到很多人都在使用它。

您可以使用 matches 命令查看匹配规则中的哪些模式。

         CLIPS (6.31 2/3/18)
CLIPS> 
(defrule move_to_floor "elevator moves to any floor "
   ?i <- (elevator is_at floor ?x has ?y adults and ?z minors)
   (floor ?fl&~?x has ?n adult and ?m minor people)
   (test (> (+ ?n ?m) 0))
   => 
   (retract ?i)
   (assert (elevator is_at floor ?fl has ?y adults and ?z minors)))
CLIPS> 
(deffacts initial
   (elevator is_at 0 has 0 adults and 0 minors)
   (capacity 4)
   (floors 3)
   (initCanEnter 0) ;At 0 this prevents from entering the init_defrule again
   (floor 3 has 2 adult and 1 minor people)
   (floor 2 has 4 adult and 5 minor people)
   (floor 1 has 1 adult and 2 minor people))
CLIPS> (reset)
CLIPS> (matches move_to_floor)
Matches for Pattern 1
 None
Matches for Pattern 2
f-5
f-6
f-7
Partial matches for CEs 1 - 2
 None
Activations
 None
(3 0 0)
CLIPS> 

在这种情况下,第一个模式不匹配。那是因为你的模式需要 is_at floor ?x 但你的事实包含 is_at 0 (符号 floor 在你的事实中丢失了)。如果您更正此问题,该规则将被列入议程。

CLIPS>    
(deffacts initial
   (elevator is_at floor 0 has 0 adults and 0 minors)
   (capacity 4)
   (floors 3)
   (initCanEnter 0) ;At 0 this prevents from entering the init_defrule again
   (floor 3 has 2 adult and 1 minor people)
   (floor 2 has 4 adult and 5 minor people)
   (floor 1 has 1 adult and 2 minor people))
CLIPS> (reset)
CLIPS> (agenda)
0      move_to_floor: f-1,f-7
0      move_to_floor: f-1,f-6
0      move_to_floor: f-1,f-5
For a total of 3 activations.
CLIPS>

如果此时发出 (运行) 命令,规则将在楼层间移动的循环中不断触发,因此这是您接下来需要解决的问题。

如果您使用 deftemplate facts 而不是 ordered facts,如果您拼错了插槽名称,则会收到错误消息,因此如果您的 fact 具有多个属性,最好使用这些。

CLIPS> (clear)
CLIPS>   
(deftemplate elevator 
  (slot at_floor (type INTEGER))
  (slot adults (type INTEGER))
  (slot minors (type INTEGER)))
CLIPS>   
(deftemplate floor
   (slot # (type INTEGER))
   (slot adults (type INTEGER))
   (slot minors (type INTEGER)))
CLIPS>    
(deffacts initial
   (elevator (at_floor 0))
   (capacity 4)
   (floors 3)
   (initCanEnter 0) 
   (floor (# 3) (adults 2) (minors 1))
   (floor (# 2) (adults 4) (minors 5))
   (floor (# 1) (adults 1) (minors 2)))
CLIPS>    
 (defrule move_to_floor 
   ?i <- (elevator (at_floor ?x))
   (floor (# ?fl&~?x) (adults ?n) (minors ?m))
   (test (> (+ ?n ?m) 0))
   => 
   (modify ?i (at_floor ?fl)))
CLIPS> (reset)
CLIPS> (facts)
f-0     (initial-fact)
f-1     (elevator (at_floor 0) (adults 0) (minors 0))
f-2     (capacity 4)
f-3     (floors 3)
f-4     (initCanEnter 0)
f-5     (floor (# 3) (adults 2) (minors 1))
f-6     (floor (# 2) (adults 4) (minors 5))
f-7     (floor (# 1) (adults 1) (minors 2))
For a total of 8 facts.
CLIPS> (agenda)
0      move_to_floor: f-1,f-7
0      move_to_floor: f-1,f-6
0      move_to_floor: f-1,f-5
For a total of 3 activations.
CLIPS>