CLIPS - 是否可以在 运行 时间内更改规则的显着性?

CLIPS - Is it possible to change salience of rule during Run Time?

我想建立一个专家系统,在某些楼层(底层+三层)的建筑物发生紧急情况时,电梯应该将人带到地下。思路是先从最高层(三楼)救人,再从二楼救人,最后从一楼救人。 我对规则的显着性有疑问(我对每个楼层都有单独的规则)。一开始最突出的是规则 "MoveFloor3" - 将电梯移到三楼(因为我想先从最高楼层救人)。当我从三楼拯救所有人时,我想将此规则中的显着性更改为 0(或某个小于二楼和一楼显着性的数字),因为在那之后我想拯救二楼和一楼的人。 此规则的代码如下,如何修改此代码以在该楼层人数变为0后改变显着性。

(defrule moveFloor3
(declare (salience 50))
?j<-(lastJob ?t&~moveFloor3)
?e<-(elevator ?peopleInElevator)
?f<-(floor3 ?peopleInFloor)
(capacityElevator ?capacityElevator)

=>
(bind ?newPeopleInElevator (+ ?peopleInElevator (min ?peopleInFloor (- ?capacityElevator ?peopleInElevator))))
(bind ?newPeopleInFloor (- ?peopleInFloor (min ?peopleInFloor (- ?capacityElevator ?peopleInElevator))))
(retract ?e ?f ?s ?j)
(assert (elevator ?newPeopleInElevator))
(assert (floor3 ?newPeopleInFloor))
(assert (lastJob moveFloor3))
(printout t "Elevator moved to third floor" crlf)
)

使用全局变量来设置显着性,一旦触发,就可以在规则的 RHS 中更改。另见 Using variables in salience declaration in a rule definition

如果有人遇到同样的问题 - 这是我的解决方案并且有效!

**(defglobal ?*floor3* = 0)**
(defrule moveFloor3
**(declare (salience (+ ?*floor3* 40)))**
?j<-(lastJob ?t&~moveFloor3)
?e<-(elevator ?peopleInElevator)
?f<-(floor3 ?peopleInFloor)
(capacityElevator ?capacityElevator)

=>
(if (eq ?peopleInFloor 0)
    then
    **(bind ?*floor3* -40)**
    else
    (bind ?newPeopleInElevator (+ ?peopleInElevator (min ?peopleInFloor (- ?capacityElevator ?peopleInElevator))))
    (bind ?newPeopleInFloor (- ?peopleInFloor (min ?peopleInFloor (- ?capacityElevator ?peopleInElevator))))
    (retract ?e ?f ?j)
    (assert (elevator ?newPeopleInElevator))
    (assert (floor3 ?newPeopleInFloor))
    (assert (lastJob moveFloor3))
    (printout t "Elevator moved to third floor" crlf)
)
)

这里有一个替代解决方案,它只需要两个规则就可以处理任意数量的楼层,并且不需要使用显着性:

         CLIPS (6.31 6/12/19)
CLIPS> 
(deftemplate floor
   (slot #)
   (slot people))
CLIPS> 
(deftemplate elevator
   (slot capacity)
   (slot occupants))
CLIPS>       
(deffacts initial
   (elevator (capacity 8) 
             (occupants 0))
   (floor (# ground) (people 0))
   (floor (# 1) (people 4))    
   (floor (# 2) (people 8))    
   (floor (# 3) (people 13)))  
CLIPS> 
(defrule pick-up-people
   ;; The elevator is not full
   ?e <- (elevator (capacity ?c)
                   (occupants ?o&~?c))
   ;; There's a floor with people on it
   ?f <- (floor (# ?f1&~ground) (people ?p&~0))
   ;; There's not a higher floor with people
   (not (floor (# ?f2&~ground&:(> ?f2 ?f1)) (people ~0)))
   =>
   ;; The number of people that can enter the elevator is
   ;; the minimum of the remaining occupancy of the elevator
   ;; and the number of people on the floor
   (bind ?added-people (min (- ?c ?o) ?p))
   ;; Print a message 
   (printout t "Elevator moves to floor " ?f1
               " and picks up " ?added-people " "
               (if (= ?added-people 1) then person else people)
               crlf)
   ;; Update  the number of people in the elevator and on the floor
   (modify ?e (occupants (+ ?o ?added-people)))
   (modify ?f (people (- ?p ?added-people))))
CLIPS> 
(defrule drop-off-people
   ;; Determine the number of people on the ground floor
   ?f <- (floor (# ground) (people ?p))
   ;; There must be people in the elevator
   ?e <- (elevator (occupants ?o&~0)
                   (capacity ?c))
   ;; There are no remaining people on any of the floors
   ;; or the elevator is at full occupancy
   (or (not (floor (# ~ground) (people ~0)))
       (test (= ?c ?o)))
   =>
   ;; Print a message
   (printout t "Elevator moves to ground floor and drops off " 
               ?o " " (if (= ?o 1) then person else people) crlf)
   ;; Update the number of people on the ground floor and 
   ;; in the elevator
   (modify ?f (people (+ ?o ?p)))
   (modify ?e (occupants 0)))
CLIPS> (reset)
CLIPS> (run)
Elevator moves to floor 3 and picks up 8 people
Elevator moves to ground floor and drops off 8 people
Elevator moves to floor 3 and picks up 5 people
Elevator moves to floor 2 and picks up 3 people
Elevator moves to ground floor and drops off 8 people
Elevator moves to floor 2 and picks up 5 people
Elevator moves to floor 1 and picks up 3 people
Elevator moves to ground floor and drops off 8 people
Elevator moves to floor 1 and picks up 1 person
Elevator moves to ground floor and drops off 1 person
CLIPS>