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>
我想建立一个专家系统,在某些楼层(底层+三层)的建筑物发生紧急情况时,电梯应该将人带到地下。思路是先从最高层(三楼)救人,再从二楼救人,最后从一楼救人。 我对规则的显着性有疑问(我对每个楼层都有单独的规则)。一开始最突出的是规则 "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>