Как оптимизировать сопоставление с образцом между различными шаблонными фактами в CLIPS - PullRequest
0 голосов
/ 31 октября 2019

У меня есть правило, похожее на следующее:

(deftemplate person
    (slot name ( type INTEGER))
    (slot surname ( type INTEGER))
)

(defrule surname_cant_be_a_name
    ?p1<-(person (name ?n1))
    ?p2<-(person (surname ?n2&:(= ?n1 ?n2)))
    =>
    (retract ?p2)
)

Функционально это работает. Но я провожу это на огромном наборе фактов, и сложность довольно быстро преодолевается.

Так как правило ищет два объекта-человека, существует сложная ситуация с вложенным циклом, которая замедляет выполнение. Эта настройка проходит через каждую возможную пару человек, и только после пары правило отфильтровывается на основе моей настройки "&: (=? N1? N2))"

Я чувствую, что должен быть более разумный способсделай это. В идеале я хочу, чтобы p1 перебирал все объекты person, но соответствовал только объектам p2, которые соответствуют моему правилу.

Чтобы прояснить свою точку зрения, я ищу что-то вроде следующего, которое позволит избежать двойного зацикливания:

(defrule surname_cant_be_a_name
    ?p1<-(person (name ?n1))
    ?p2<-(person (surname  %%JUST_MATCH_n1%% ))
    =>
    (retract ?p2)
)

Можно ли достичь чего-то подобного? Любая рекомендация по оптимизации этого правила приветствуется.

Спасибо

PS Извините за нелепый пример, но он очень хорошо освещает мою ситуацию.

1 Ответ

2 голосов
/ 31 октября 2019

Если вы сравниваете переменные на равенство, гораздо эффективнее использовать одну и ту же переменную в обоих местах, чем использовать две отдельные переменные и вызывать функцию = или eq длясравнить на равенство. Во всех шаблонах хеш-таблицы используются для быстрого поиска фактов, совместно использующих одни и те же переменные, чего не происходит, когда вы используете вызов функции для сравнения на равенство. Для большого количества фактов это может повысить производительность на порядки:

         CLIPS (6.31 6/12/19)
CLIPS> (clear)
CLIPS> 
(deftemplate person
   (slot name (type INTEGER))
   (slot surname (type INTEGER)))
CLIPS> 
(defrule surname_cant_be_a_name
   ?p1<- (person (name ?n1))
   ?p2<- (person (surname ?n2&:(= ?n1 ?n2)))
   =>
   (retract ?p2))
CLIPS> (timer (loop-for-count (?i 10000) (assert (person (name ?i) (surname (+ ?i 1))))))
12.3485549999987
CLIPS> (clear)
CLIPS> 
(deftemplate person
   (slot name (type INTEGER))
   (slot surname (type INTEGER)))
CLIPS> 
(defrule surname_cant_be_a_name
   ?p1 <- (person (name ?n1))
   ?p2 <- (person (surname ?n1))
   =>
   (retract ?p2))
CLIPS> (timer (loop-for-count (?i 10000) (assert (person (name ?i) (surname (+ ?i 1))))))
0.0177029999995284
CLIPS> (/ 12.3485549999987 0.0177029999995284)
697.540247434201
CLIPS> 
...