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

How to further check fact values for only selected facts?

我有以下模板:

(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 中的所有 fields:value 对是否在 claim 个事实中找到。
  2. 检查 drule 中的所有 field:value 对是否在其他 匹配的 声明中也相同。 (仅当找到字段时 在索赔中)
  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 字段。我的规则检查所有声明,如果有 是任何 field:value 不匹配然后它不会触发。

编辑:有没有办法将 EmpName 字段或 Company 之类的其他字段检索到 RHS?例如,对于上面的最后一组事实,我可以将 RHS 设置为 (assert (User ?name successfully entered))。我只想要在 forall 中匹配的声明(CLIPS 给我一个错误)。

谢谢。

我不确定这是否正是您想要满足标准 #3 的原因,因为我不完全理解您的解释,但它适用于您给出的示例。

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

对于要在 RHS 上使用的值,您可以通过将它们添加到 drule 模式(就像这里对 name1 和 name2 所做的那样)或通过添加额外的模式来检索它们,从而在 forall 条件元素之外检索它们他们来自特定的索赔事实。

由于您有一些复杂的逻辑,如果您在多个规则之间拆分逻辑,您可能会发现更容易调试代码:

(defrule check-1
   (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 $?))
   (not (and (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 $?))))
   =>
   (assert (mismatch ?id)))

(defrule check-2
   (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 $?))
   (or (claim (field $?f3 ?field1 $?)
               (value $?v3&:(= (length$ ?f3)(length$ ?v3)) ~?value1 $?))
       (claim (field $?f4 ?field2 $?)
              (value $?v4&:(= (length$ ?f4)(length$ ?v4)) ~?value2 $?)))
   =>
   (assert (mismatch ?id)))

(defrule check-3
   (drule (id ?id)
          (name1 ?name1)
          (name2 ?name2))
   (exists (claim (name ?name3&?name1|?name2)
                  (field $?f3 ?field3 $?)
                  (value $?v3&:(= (length$ ?f3) (length$ ?v3)) ?value3 $?))
           (not (claim (name ~?name3&?name1|?name2)
                       (field $?f4 ?field3 $?)
                       (value $?v4&:(= (length$ ?f4)(length$ ?v4)) ?value3 $?))))
   =>
   (assert (mismatch ?id)))

(defrule drule
   (declare (salience -10))
   (drule (id ?id))
   (not (mismatch ?id))
   =>
   (assert (success)))