0
votes

I'm a student, currently learning more and more about Clips and just received an assignment from my prof. It is quite hard I can tell, but still I want to learn how to do it.

I have the following rule:

(defrule R1
?x <- (current on)

(or
(alarm water)
(and (alarm fire) (sprinklers working) )
(alarm explosion) )

=>

(retract ?x)
(assert (current off))
(printout t “Turn off electricity” crlf) )

My task is to modify the rule (and not create other rules), in order to delete the facts that activated the rule. So far I understood that I have to assign the same variable to first and third pattern in the or and retract it in the action part, but what should be done with the and paranthesis? Since I'm still somewhat at the beginning and currently learning the and,or operators I shouldnt use advanced stuff like classes, templates etc.

But any solution is most welcome. Thanks for reading

1

1 Answers

1
votes

The or conditional element works by creating multiple rules, one for each possible combination of conditional elements contained within the or conditional elements of the rule. So this rule:

(defrule example
   (or (a) (b))
   (or (c) (d))
   =>)

is implemented as four separate rules sharing the same name:

(defrule example
   (a)
   (c)
   =>)

(defrule example
   (a)
   (d)
   =>)

(defrule example
   (b)
   (c)
   =>)

(defrule example
   (b)
   (d)
   =>)

So all the or conditional element does is to automate the process of creating permutations of rules that share common patterns. Since all of the generated rules share the same actions, you can't have the actions refer to variables that are only bound in some of the patterns of the different rules.

In the following case, you can retract the alarm fact in the actions of the rule because the variable ?a is bound in every pattern with the or conditional element:

         CLIPS (6.31 6/12/19)
CLIPS> 
(defrule R1
   ?x <- (current on)
   (or ?a <- (alarm water)
       (and ?a <- (alarm fire) 
            (sprinklers working))
       ?a <- (alarm explosion))

   =>
  (retract ?x ?a)
  (assert (current off))
  (printout t "Turn off electricity" crlf))
CLIPS> (assert (current on) (alarm fire) (sprinklers working))
<Fact-3>
CLIPS> (run)
Turn off electricity
CLIPS> (facts)
f-0     (initial-fact)
f-3     (sprinklers working)
f-4     (current off)
For a total of 3 facts.
CLIPS> 

But you couldn't bind the pattern (sprinklers working) to the variable ?s and then try to (retract ?s) in the actions because the variable ?s wouldn't be bound in each of the automatically generated rules.

If you treat the assignment as a puzzle, rather than a lesson in how you'd actually write a rule, you can duplicate some of the patterns and bind them to a different variable so that all of the variables referenced in the actions of the rule are bound to a value in the conditions of the rule:

CLIPS> (clear)
CLIPS> 
(defrule R1
   ?x <- (current on)
   (or (and ?a <- (alarm water)
            ?s <- (alarm water))
       (and ?a <- (alarm fire) 
            ?s <- (sprinklers working))
       (and ?a <- (alarm explosion)
            ?s <- (alarm explosion)))

   =>
  (retract ?x ?a ?s)
  (assert (current off))
  (printout t "Turn off electricity" crlf))
CLIPS> (assert (alarm water))
<Fact-1>
CLIPS> (assert (current on))
<Fact-2>
CLIPS> (run)
Turn off electricity
CLIPS> (facts)
f-0     (initial-fact)
f-3     (current off)
For a total of 2 facts.
CLIPS> (assert (alarm fire) (sprinklers working))
<Fact-5>
CLIPS> (assert (current on))
<Fact-6>
CLIPS> (run)
Turn off electricity
CLIPS> (facts)
f-0     (initial-fact)
f-3     (current off)
For a total of 2 facts.
CLIPS>