0
votes

Let's say I have some facts (I do not know how many there are) like this: lamp x is off. With a defrule I proggressively turn all lamps on so every fact will be: lamp x is on. How do I check every lamp that is on. I know that if there were three lamps I could write:

(defrule checkAllLamps
    (lamp 1 is on)
    (lamp 2 is on)
    (lamp 3 is on)
    =>
    (printout t "All lamps are on now")
)

But for x lamps? Thank you!

2

2 Answers

2
votes

You can use fact-set query functions for that (chapter 12.9.12 of the Basic Programming Guide).

(deftemplate lamp 
  (slot id (type INTEGER)) 
  (slot state (type SYMBOL)))

(defrule all-lamps-are-on 
  (lamp (state on)) 
  (test (>= (length$ (find-all-facts ((?l lamp)) (eq ?l:state on))) 3)) 
  => 
  (printout t "All lamps are on" crlf))     
1
votes

Here's how you can check whether all of the lamps are on. The checkAllLamps rule treats the case where there are no lamps at all as all lamps being on, whereas the checkAllLampsAtLeastOne rule requires that there is at least one lamp that is on.

         CLIPS (6.31 2/3/18)
CLIPS> 
(defrule checkAllLamps
   (not (lamp ? is off))
   =>
   (printout t "All lamps are on now" crlf))
CLIPS> 
(defrule checkAllLampsAtLeastOne
   (exists (lamp ? is on))
   (not (lamp ? is off))
   =>
   (printout t "All lamps are on now" crlf))
CLIPS> (agenda)
0      checkAllLamps: *
For a total of 1 activation.
CLIPS> (assert (lamp 1 is on))
<Fact-1>
CLIPS> (agenda)
0      checkAllLampsAtLeastOne: *,*
0      checkAllLamps: *
For a total of 2 activations.
CLIPS> (assert (lamp 2 is off))
<Fact-2>
CLIPS> (agenda)
CLIPS> (retract 2)
CLIPS> (assert (lamp 2 is on))
<Fact-3>
CLIPS> (agenda)
0      checkAllLampsAtLeastOne: *,*
0      checkAllLamps: *
For a total of 2 activations.
CLIPS>