Can I implement a if else in LHS of rule for the f

2019-08-20 02:18发布

问题:

I have facts such as

(claim (name Employee) (field 'EmpName' 'Company') (value 'Bob' 'ABC'))
(claim (name Event) (field 'EventName' 'Company') (value 'Conference' 'ABC'))
(drule (id gen1)(name1 'Employee') (field1 'EmpName' 'Company') (value1 'Bob' 'ABC') (name2 'Event')
    (field2 'EventName') (value2 'Conference'))

I have tried a rule such as following. But it does not work as intended.

(defrule drule-rule
    (drule 
        (id ?id))
    (forall
        (drule 
                (id ?id)
                        (name1 ?name1)
                (field1 $?f11 ?field1 $?)
                (value1 $?v11&:(= (length$ ?f11) (length$ ?v11)) ?value1 $?))
                    (name2 ?name2)
                (field2 $?f22 ?field2 $?)
                (value2 $?v22&:(= (length$ ?f22) (length$ ?v22)) ?value2 $?))
        (claim 
            (name ?name1)
                (field $?f1 ?field1 $?)
                (value $?v1&:(= (length$ ?f1) (length$ ?v1)) ?value1 $?))
                (claim (name ?name2)
                (field $?f2 ?field2 $?)
                (value $?v2&:(= (length$ ?f2) (length$ ?v2)) ?value2 $?)))
         (forall
                 (claim 
            (field $?f3 ?field3 $?)
                    (value $?v4&:(= (length$ ?f3) (length$ ?v3)) ?value3 $?))
                 (claim 
            (field $?f4 ?field4 $?)
                    (value $?v4&:(= (length$ ?f4) (length$ ?v4)) ?value3 $?)))

 =>
        (assert (Action allowed)))

I want the above rule to check each field in matched claim in the first forall with other matched claims. If same field name is found, then check the value of that field in other claims.

For the above facts, the assertion should work. While for the below, the assertion should fail because Company field does not match other claim.

(claim (name Employee) (field 'EmpName' 'Company') (value 'Bob' 'xyz'))
(claim (name Event) (field 'EventName' 'Company') (value 'Conference' 'ABC'))
(drule (id gen1)(name1 'Employee') (field1 'EmpName' 'Company') (value1 'Bob' 'ABC') (name2 'Event')
    (field2 'EventName') (value2 'Conference'))

Is this possible with a single rule? Or any other alternatives?

Thank you.

回答1:

In addition to converting the second forall conditional element to two separate not conditional elements, there were a few issues with your data (inconsistent use of single quotations around names and placing the inconsistent company 'xyz' in the 'Employee' claim that is already checked by the drule fact rather than the 'Event' claim where it is not).

         CLIPS (6.31 4/1/19)
CLIPS> 
(deftemplate drule
   (slot id)
   (slot name1)
   (multislot field1)
   (multislot value1)
   (slot name2)
   (multislot field2)
   (multislot value2))
CLIPS>    
(deftemplate claim
   (slot name)
   (multislot field)
   (multislot value))
CLIPS>     
(defrule drule-rule
   (drule (id ?id))
   (forall
      (drule (id ?id)
             (name1 ?name1)
             (field1 $?f11 ?field1 $?)
             (value1 $?v11&:(= (length$ ?f11) (length$ ?v11)) ?value1 $?)
             (name2 ?name2)
             (field2 $?f22 ?field2 $?)
             (value2 $?v22&:(= (length$ ?f22) (length$ ?v22)) ?value2 $?))
      (claim (name ?name1)
             (field $?f1 ?field1 $?)
             (value $?v1&:(= (length$ ?f1) (length$ ?v1)) ?value1 $?))
      (claim (name ?name2)
             (field $?f2 ?field2 $?)
             (value $?v2&:(= (length$ ?f2) (length$ ?v2)) ?value2 $?))
      (not (claim (field $?f3 ?field1 $?)
                  (value $?v3&:(= (length$ ?f3) (length$ ?v3)) ~?value1 $?)))
      (not (claim (field $?f4 ?field2 $?)
                  (value $?v4&:(= (length$ ?f4) (length$ ?v4)) ~?value2 $?))))


   =>
   (assert (Action allowed)))
CLIPS>    
(assert
   (claim (name 'Employee') 
          (field 'EmpName' 'Company')
          (value 'Bob' 'ABC'))
   (claim (name 'Event')
          (field 'EventName' 'Company')
          (value 'Conference' 'ABC'))
   (drule (id gen1)
          (name1 'Employee')
          (field1 'EmpName' 'Company')
          (value1 'Bob' 'ABC')
          (name2 'Event')
          (field2 'EventName')
          (value2 'Conference')))
<Fact-3>
CLIPS> (agenda)
0      drule-rule: f-3,*
For a total of 1 activation.
CLIPS> (reset)
CLIPS>           
(assert
   (claim (name 'Employee')
          (field 'EmpName' 'Company')
          (value 'Bob' 'ABC'))
   (claim (name 'Event')
          (field 'EventName' 'Company')
          (value 'Conference' 'xyz'))
   (drule (id gen1)
          (name1 'Employee')
          (field1 'EmpName' 'Company')
          (value1 'Bob' 'ABC')
          (name2 'Event')
          (field2 'EventName')
          (value2 'Conference')))
<Fact-3>
CLIPS> (agenda)
CLIPS>