0
votes

I want to build an expert system in which in a case of emergency at a building with some floors (it needs to work for any amount of floors) the elevator should take the people into the ground. The thing is, that the defrule to send the elevator at any floor never makes it in the agenda, so the system just does nothing. The correct action should be to fire the rule and then another rule that takes the people from the floor.

The code for the defrule is this:

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

The facts as they have been initialized from the user in another defrule above are these:

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)

I can't seem to find the solution. Also, I'm using deffacts and not deftemplate as I have seen many people using on the internet.

1

1 Answers

1
votes

You can use the matches command to see which patterns in a rule are matched.

         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> 

In this case, the first pattern is not matched. That's because your pattern expects is_at floor ?x but your fact contains is_at 0 (the symbol floor is missing in your fact). If you correct this issue, the rule will be placed on the agenda.

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>

If you issue a (run) command at this point, the rules will endlessly fire in a loop moving from floor to floor, so that's something you'll need to address next.

If you use deftemplate facts rather than ordered facts, you'll get an error if you misspell slot names, so it's better to use these if you have a fact with multiple attributes.

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>