Search code examples
matchingclipsexpert-system

CLIPS: Match multislot if all values match different other facts


Is there any possibility to match each multislot in CLIPS to different other facts? I have a short example rule:

(stn-action (id ?id) (name lock-position) (state pending)
            (cond-actions) (opts ?r ?action ?to))
(stn-action (id ?other-id) (name lock-position) (state running|finished)
            (opts ?r ?action ?other-to&:~(eq ?other-to ?to)))

cond-actions is a multifield and I want each value to match against a fact that matches the second line. Obviously I need to match with member$, but I don't know how to match each member against a different fact in my fact-base. Is there any possibility to do this? A short set of complete facts that match would look like this:

(stn-action (id 3) (name lock-position) (state pending) (duration 0)
            (cond-actions 1 2) (opts R-1 PICK-CC C-CS2-I) (active-robot R-1) (sync-id 1000003))
(stn-action (id 2) (name lock-position) (state running) (duration 0)
            (cond-actions 1) (opts R-1 GET-PROD C-CS2-O) (active-robot R-1) (sync-id 1000002))
(stn-action (id 1) (name lock-position) (state finished) (duration 0)
            (cond-actions) (opts R-1 GET-PROD C-BS-O) (active-robot R-1) (sync-id 1000001))

My old solution was to remove id's from all fields upon action completion, but due to a different issue I cannot do this anymore


Solution

  • Use the forall conditional element:

    CLIPS> 
    (deftemplate stn-action
       (slot id)
       (slot name)
       (slot state)
       (slot duration)
       (multislot cond-actions)
       (multislot opts)
       (slot active-robot)
       (slot sync-id))
    CLIPS>    
    (deffacts initial
       ;; id 3 will not match because PICK-CC doesn't match GET-PROD
       (stn-action (id 3) (name lock-position) (state pending) (duration 0)
                   (cond-actions 1 2) (opts R-1 PICK-CC C-CS2-I) 
                   (active-robot R-1) (sync-id 1000003))
       (stn-action (id 2) (name lock-position) (state running) (duration 0)
                   (cond-actions 1) (opts R-1 GET-PROD C-CS2-O) 
                   (active-robot R-1) (sync-id 1000002))
       (stn-action (id 1) (name lock-position) (state finished) (duration 0)
                   (cond-actions) (opts R-1 GET-PROD C-BS-O) 
                   (active-robot R-1) (sync-id 1000001))
       ;; id 6 will match
       (stn-action (id 6) (name lock-position) (state pending) (duration 0)
                   (cond-actions 5 4) (opts R-1 PICK-CC C-CS2-I) 
                   (active-robot R-1) (sync-id 1000003))
       (stn-action (id 5) (name lock-position) (state running) (duration 0)
                   (cond-actions 4) (opts R-1 PICK-CC C-CS2-O) 
                   (active-robot R-1) (sync-id 1000002))
       (stn-action (id 4) (name lock-position) (state finished) (duration 0)
                   (cond-actions) (opts R-1 PICK-CC C-BS-O) 
                   (active-robot R-1) (sync-id 1000001)))
    CLIPS> 
    
    (defrule match
       (stn-action (id ?id) 
                   (name lock-position) 
                   (state pending)
                   (opts ?r ?action ?to))
       (forall (stn-action (id ?id) 
                           (cond-actions $? ?other-id $?))
               (stn-action (id ?other-id) 
                           (name lock-position) 
                           (state running | finished)
                           (opts ?r ?action ?other-to&~?to)))
       =>
       (printout t "id " ?id " has all cond-actions satisfied" crlf))
    CLIPS> (reset)
    CLIPS> (run)
    id 6 has all cond-actions satisfied
    CLIPS>