skyrimpacman
skyrimpacman

Reputation: 31

How to stop rule repeating activation on facts that have already been modified?

I have a rule I have made in CLIPS that deletes two values from a multislot field. Even though it does this, the rule repeats itself on the same facts that have now deleted the two values and this goes on infinitely.

Below are my fact templates and the rule

(deftemplate ar-node
    (slot group
        (type SYMBOL)
        (allowed-symbols grp1 grp2 grp3 grp4) )
    (slot name
        (type SYMBOL)
        (allowed-symbols oc nps ef sef yn))
    (slot direction
        (type SYMBOL)
        (allowed-symbols + -))
    (slot element
        (type INTEGER)
        (range 1 3))
    (slot trip
        (type INTEGER)
        (range 1 4))
    (multislot allowed-values
        (type SYMBOL)
        (allowed-symbols D R L A C S nil)
        (default D))
    (slot value
        (type SYMBOL)
        (allowed-symbols D R L A C S nil)
        (default D)))
(defrule 22_061 
    (ar-node (group ?group)
             (name ?name)
             (direction ?direction)
             (element ?element)
             (trip ?trip)
             (value ?value&R))
    
    =>
    (do-for-all-facts ((?fact ar-node)) (and (eq ?fact:group ?group)
                                             (eq ?fact:name ?name)
                                             (eq ?fact:direction ?direction)
                                             (eq ?fact:element 1)
                                             (> ?fact:trip 1))
    (modify ?fact (allowed-values (delete-member$ ?fact:allowed-values C S))))
)

Here is also some example facts that will cause the rule to execute (the rule would only delete the C and S from the second fact here)

(ar-node (group grp1) (name cool) (direction +) (element 1) (trip 1) (allowed-values L D R A C S) (value R))
(ar-node (group grp1) (name cool) (direction +) (element 1) (trip 2) (allowed-values L D R A C S) (value L))

I have tried using more parameters to only delete values if the values are present such as (eq $member ?fact:allowed-values C S) in the RHS (and) statement or even to the LHS of the rule. However these either doesn't work or the rule won't execute at all.

I think the solution will be some way to check that the fact has C or S in the multifield on the LHS but I don't know how I could search all the facts before hand like I do on the RHS. Also I would prefer not to have to edit the fact template too though if its necessary to store something that.

Any advice or suggestions are welcome and I am new to CLIPS so sorry if this may be trivial but I'm super stumped even after using a bunch of functions from the documentation.

Upvotes: 0

Views: 219

Answers (1)

Gary Riley
Gary Riley

Reputation: 10757

You can modify the query in the RHS to check for the presence of C or S:

(defrule 22_061 
    (ar-node (group ?group)
             (name ?name)
             (direction ?direction)
             (value R))
    
    =>
    (do-for-all-facts ((?fact ar-node)) (and (eq ?fact:group ?group)
                                             (eq ?fact:name ?name)
                                             (eq ?fact:direction ?direction)
                                             (eq ?fact:element 1)
                                             (> ?fact:trip 1)
                                             (or (member$ C ?fact:allowed-values)
                                                 (member$ S ?fact:allowed-values)))
    (modify ?fact (allowed-values (delete-member$ ?fact:allowed-values C S))))
)

Or you can use pattern matching in the LHS and allow the rule to fire multiple times to modify all the facts:

(defrule 22_061 
    (ar-node (group ?group)
             (name ?name)
             (direction ?direction)
             (value R))
    ?fact <- (ar-node (group ?group)
                      (name ?name)
                      (direction ?direction)
                      (element 1)
                      (trip ?trip&:(> ?trip 1))
                      (allowed-values $?b C | S $?e))
    =>
    (modify ?fact (allowed-values (delete-member$ (create$ ?b ?e) C S))))

Upvotes: 1

Related Questions