Adrian Lara
Adrian Lara

Reputation: 23

How to modify local variables in a rule? CLIPS Production System

I am new to CLIPS, I would very much appreciate any idea of my problem. In summary I have a template that graphs a 3x3 with numeric values like sudoku , each value ?v has its row ?f1, column ?c1 and a characteristic called "state" of string type that can be active or inactive.

(deftemplate box
  (slot row)
  (slot column)
  (slot value)
  (slot state
  (allowed-values active inactive)
  (default inactive)))

(deffacts initial-values
  (box (row 1) (column 1) (value 1))
  (box (row 1) (column 2) (value 1))
  (box (row 1) (column 3) (value 1))
  (box (row 2) (column 1) (value 2))
  (box (row 2) (column 2) (value 3))
  (box (row 2) (column 3) (value 1))
  (box (row 3) (column 1) (value 2))
  (box (row 3) (column 2) (value 3))
  (box (row 3) (column 3) (value 56)))

I have written a rule that verifies if there is a value that is not repeated in the same row neither column. If this condition is TRUE I want to change the status to active because by default all values are inactive, I have reviewed the syntax and I have not been able to handle these variables.

 (defrule uniqueness
   (exists (box (row ?f1) (column ?c1) (value ?v)(state inactive))
           (not (and (box (row ?f2) (column ?c2) (value ?v))
                     (test (or (!= ?f1 ?f2) (!= ?c1 ?c2))))))

   =>
   (printout t "There are values that are not repeated" crlf)
   ;;(modify (state active)) ;;this line causes me problems
   )

Upvotes: 0

Views: 508

Answers (1)

Gary Riley
Gary Riley

Reputation: 10757

The exists conditional element is only matched once regardless of the number of matches it contains, so outside the scope of the exists it is not meaningful to refer to facts and variables that were bound within it. You use exists if you want to know generally if at least one fact matches a set of conditions, but you don't use it if you need to perform an action on a specific fact.

To solve your problem, remove the exists and then bind the fact matching the box pattern to a variable so that you can use that variable with the modify command:

(defrule uniqueness
   ?b <- (box (row ?f1) (column ?c1) (value ?v) (state inactive))
   (not (and (box (row ?f2) (column ?c2) (value ?v))
             (test (or (!= ?f1 ?f2) (!= ?c1 ?c2)))))

   =>
   (printout t "There are values that are not repeated" crlf)
   (modify ?b (state active)))

Upvotes: 2

Related Questions