Как заставить клипы игнорировать определенный факт для правила? - PullRequest
0 голосов
/ 14 февраля 2020

У меня есть следующий deftemplate

(deftemplate potential
     (multislot values (type INTEGER))
)

, и я хочу удалить экземпляры этого deftemplate, если в нем присутствует только целое число. Пример: факт-1: потенциал 1 2 3 факт-2: потенциал 2 3 4 факт-3: потенциал 2 3 4 5

Я хочу убрать факты-1 и факт-3, потому что они включают 1 и 5 однозначно.

Я пытаюсь добиться этого, используя следующее правило:

  1 (defrule remove_if_only_option
  2     ?p<-(potential (values $? ?value $?   ))
  3     (not (exists   (potential (values $? ?value $?)  )))
  4     =>
  5     (retract ?p)
  7 )

Очевидно, что это не работает, так как строка 3 может соответствовать исходному факту. Есть ли способ сделать этот запуск таким образом, чтобы правило не учитывалось? P для остального?

Спасибо.

1 Ответ

1 голос
/ 14 февраля 2020

Ни один из шаблонов в вашем правиле не будет зависеть от наличия или отсутствия исходного факта, поскольку оба они соответствуют потенциальным фактам. Существующий условный элемент является избыточным во втором шаблоне, поэтому ваше правило эквивалентно

(defrule remove_if_only_option
   ?p <- (potential (values $? ?value $?))
   (not (potential (values $? ?value $?)))
   =>
   (retract ?p))

, и поскольку условие x and not x никогда не выполняется, это правило никогда не будет выполнено.

Вы можете определить, отличаются ли два факта одного и того же типа, сравнивая их адрес факта, но, поскольку вы не можете связать адрес факта в не условном элементе, вы не можете сделать это в этом случае. В качестве альтернативы, вы можете включить слот, содержащий уникальное значение для каждого факта, который можно использовать для определения того, отличаются ли факты:

         CLIPS (6.31 6/12/19)
CLIPS> 
(deftemplate potential
   (slot id (default-dynamic (gensym*)))
   (multislot values (type INTEGER)))
CLIPS> 
(defrule remove_if_only_option
   ?p <- (potential (id ?id) (values $? ?value $?))
   (not (potential (id ~?id) (values $? ?value $?)))
   =>
   (retract ?p))
CLIPS> 
(assert (potential (values 1 2 3))
        (potential (values 2 3 4))
        (potential (values 2 3 4 5)))
<Fact-3>
CLIPS> (agenda)
0      remove_if_only_option: f-3,*
0      remove_if_only_option: f-1,*
For a total of 2 activations.
CLIPS> 

Первоначально это работает, но после запуска вы можете увидеть там Вот проблемы:

CLIPS> (run 1)
CLIPS> (agenda)
0      remove_if_only_option: f-2,*
0      remove_if_only_option: f-1,*
For a total of 2 activations.
CLIPS>

После удаления f-3 значение 4 в f-2 теперь становится уникальным, и поэтому этот факт теперь также будет удален этим правилом. Проблема в том, что общий набор значений неявно представлен набором потенциальных фактов, и как только вы начнете удалять их, вы изменяете общий набор значений.

Для этого вам нужно нужно как минимум два шага и следовательно как минимум два правила. Один из способов сделать это - отметить факты, которые необходимо удалить за один шаг, а затем удалить их за другой:

CLIPS> (clear)
CLIPS> 
(deftemplate potential
   (slot id (default-dynamic (gensym*)))
   (multislot values (type INTEGER))
   (slot delete (default no)))
CLIPS> 
(defrule remove_if_only_option
   (not (done))
   ?p <- (potential (id ?id) (values $? ?value $?) (delete no))
   (not (potential (id ~?id) (values $? ?value $?)))
   =>
   (modify ?p (delete yes)))
CLIPS> 
(defrule remove
   (declare (salience -10))
   ?p <- (potential (delete yes))
   =>
   (assert (done))
   (retract ?p))
CLIPS>    
(assert (potential (values 1 2 3))
        (potential (values 2 3 4))
        (potential (values 2 3 4 5)))
<Fact-3>
CLIPS> (agenda)
0      remove_if_only_option: *,f-3,*
0      remove_if_only_option: *,f-1,*
For a total of 2 activations.
CLIPS> (run 1)
CLIPS> (agenda)
0      remove_if_only_option: *,f-1,*
-10    remove: f-4
For a total of 2 activations.
CLIPS> (facts)
f-0     (initial-fact)
f-1     (potential (id gen4) (values 1 2 3) (delete no))
f-2     (potential (id gen5) (values 2 3 4) (delete no))
f-4     (potential (id gen6) (values 2 3 4 5) (delete yes))
For a total of 4 facts.
CLIPS> (run 1)
CLIPS> (agenda)
-10    remove: f-5
-10    remove: f-4
For a total of 2 activations.
CLIPS> (run)
CLIPS> (facts)
f-0     (initial-fact)
f-2     (potential (id gen5) (values 2 3 4) (delete no))
f-6     (done)
For a total of 3 facts.
CLIPS> 

Другой способ создать факт, содержащий уникальные значения:

CLIPS> (clear)
CLIPS> 
(deftemplate potential
   (slot id (default-dynamic (gensym*)))
   (multislot values (type INTEGER)))
CLIPS> 
(defrule add-to-unique
   (not (done))
   ?c <- (unique $?unique)      
   (potential (id ?id) (values $? ?value $?))
   (not (potential (id ~?id) (values $? ?value $?)))
   (test (not (member$ ?value ?unique)))
   =>
   (retract ?c)
   (assert (unique $?unique ?value)))
CLIPS>  
(defrule remove_if_only_option
   (declare (salience -10))
   (unique $?unique)
   ?p <- (potential (values $? ?value $?))
   (test (member$ ?value ?unique))
   =>
   (assert (done))
   (retract ?p))
CLIPS>   
(assert (potential (values 1 2 3))
        (potential (values 2 3 4))
        (potential (values 2 3 4 5)))
<Fact-3>
CLIPS> (assert (unique))
<Fact-4>
CLIPS> (run)
CLIPS> (facts)
f-0     (initial-fact)
f-2     (potential (id gen26) (values 2 3 4))
f-6     (unique 5 1)
f-7     (done)
For a total of 4 facts.
CLIPS> 
...