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))
)
...
)
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>