Как дополнительно проверить значения фактов только для выбранных фактов? - PullRequest
0 голосов
/ 04 июля 2019

У меня есть следующий шаблон:

(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 фактах.
  2. Проверьте, все ли пары полей: значение в drule также одинаковы в других соответствующих заявках.(только если поле найдено в заявке) ответил
  3. Проверьте, все ли пары полей: значений одинаковы в каждой выбранной паре.(Только если поле найдено).

Например,

(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 Ответ

1 голос
/ 04 июля 2019

Я не уверен, что это именно то, что вам нужно для удовлетворения критерия № 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), либо добавив дополнительный шаблон для извлечения их из конкретный факт претензии.

Поскольку у вас есть некоторая сложная логика, вам может быть проще отладить ваш код, если вы разделите логику между несколькими правилами:

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