如何仅为选定事实进一步检查事实值?

时间:2019-07-04 09:29:00

标签: clips expert-system

我有以下模板:

(deftemplate drule
         (slot name1)
         (slot id)
         (multislot field1)
             (multislot value1)
         (slot name2)
         (multislot field2)
         (multislot value2))

(deftemplate claim
         (slot name)
         (multislot field)
         (multislot value))

我有以下规则:

(defrule drule
  (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 $?))))
  (forall
   (claim
    (field $?f5 ?field5 $?)(value $?v5&:(= (length$ ?f5)(length$ ?v5)) ?value5 $?))
   (not
    (claim (field $?f6 ?field5 $?)(value $?v6&:(= (length$ ?f6)(length$ ?v6)) ~?value5 $?))))
=>
(assert (success)))

以上规则执行以下操作:

  1. 检查是否在drule个事实中找到了claim中的所有field:value对。
  2. 检查drule中的所有field:value对在其他匹配声明中是否也相同。 (仅当找到字段时 索赔中)answered
  3. 检查每个选定对中的所有field:values对是否相同。 (仅当找到字段时)。

例如,

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

上面应该成功,而下面应该失败。因为EmpName不匹配。

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

但是当有以下断言时,我的规则就会失败

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

即使有一个具有相同EmpName字段的声明,我也要触发规则。我的规则会检查所有索赔,如果有 是任意字段:值不匹配,则不会触发。

编辑:是否可以将字段EmpName或其他字段(如Company检索到RHS?例如,对于上述最后一组事实,我可以将RHS设为(assert (User ?name successfully entered))。我只想要在总体上匹配的索赔(CLIPS会给我一个错误)。

谢谢。

1 个答案:

答案 0 :(得分:1)

由于我不完全理解您的解释,因此我不确定这是否正是您要满足标准3的要求,但是对于您给出的示例来说,它是正确的。

public Info [] merge(Info [] localArray, Info [] globalArray) {

    List<Info> resultList = new ArrayList();
    for(Info infoGlobal : globalArray) {
        Info infoLocal = findInfo(infoGlobal.getId(), localArray);
        if( infoLocal != null )
            infoGlobal.setFavor(infoLocal.isFavor());
        resultList.add(infoGlobal);
    }

    return resultList.toArray();
}

private Info findInfo(int id, Info [] infoArray) {

    for(Info info : infoArray)
        if(info.getId == id)
            return info ;

   return null ;
}

对于要在RHS上使用的值,可以通过将它们添加到drule模式(如name1和name2在此处所做的那样)或添加其他模式以从所有条件元素之外检索它们,方法是具体的索赔事实。

由于您具有一些复杂的逻辑,因此,如果您将逻辑划分为多个规则,则可能会更容易调试代码:

(defrule drule
   (drule (id ?id)
          (name1 ?name1)
          (name2 ?name2))
   (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 $?))))
   (forall
      (claim (name ?name3&?name1|?name2)
             (field $?f5 ?field5 $?)
             (value $?v5&:(= (length$ ?f5)(length$ ?v5)) ?value5 $?))
      (exists
         (claim (name ~?name3&?name1|?name2)
                (field $?f6 ?field5 $?)
                (value $?v6&:(= (length$ ?f6)(length$ ?v6)) ?value5 $?))))
   =>
   (assert (success)))