Search code examples
clips

CLIPS: OR conditional element that evaluates to TRUE if and only if 2 or more of its internal patterns are TRUE


A normal (or) element evaluates to TRUE if 1 or more of the patterns are matched:

(or
    (object (name name-1))
    (object (name name-2))
    (object (name name-3))
    (object (name name-4))
)

The question is: is there a simple way to create a modified (or) element that evaluates to TRUE if 2 or more of the patterns are matched?

The dumb brute way of doing this would of course be the following, but I'm convinced there's a smoother way.

(or
    (and
        (object (name name-1))
        (object (name name-2))
    )
    (and
        (object (name name-1))
        (object (name name-3))
    )
    (and
        (object (name name-1))
        (object (name name-4))
    )
    (and
        (object (name name-2))
        (object (name name-3))
    )

    ...

)

Solution

  • If you're trying to match more than two objects, then use that same number of patterns and discard extraneous permutations with a call to a utility function:

             CLIPS (6.31 6/12/19)
    CLIPS> (defclass X (is-a USER))
    CLIPS>  
    (definstances Xs
       (name-0 of X)
       (name-1 of X)
       (name-3 of X)
       (name-4 of X)
       (name-5 of X))
    CLIPS>      
    (deffunction in-order (?n1 ?n2)
       (< (str-compare ?n1 ?n2) 0))
    CLIPS>    
    (defrule r1
       (object (name ?name1&[name-1] | [name-2] | [name-3] | [name-4]))
       (object (name ?name2&[name-1] | [name-2] | [name-3] | [name-4]))
       (test (in-order ?name1 ?name2))
       =>)
    CLIPS>    
    (defrule r2
       (exists
          (object (name ?name1&[name-1] | [name-2] | [name-3] | [name-4]))
          (object (name ?name2&[name-1] | [name-2] | [name-3] | [name-4])) 
          (test (in-order ?name1 ?name2)))
       =>)
    CLIPS> (reset)
    CLIPS> (agenda)
    0      r1: [name-1],[name-4]
    0      r1: [name-3],[name-4]
    0      r1: [name-1],[name-3]
    0      r2: *
    For a total of 4 activations.
    CLIPS>