Клипы пересмотреть систему

(Прежде всего, извините за мой английский:)) Я пытаюсь создать систему пересмотра для моего проекта (простая классификация натуральных растений), я не хочу вставлять весь свой код, но только важные части, поэтому я постараюсь объяснить, что делает система. Я сделал функцию (которую я называю revise-attribute), когда система находит растения, которые должны соответствовать ответам, данным от пользователя, которые спрашивают пользователя, хочет ли он изменить некоторые атрибуты, если он отвечает "да", он может выбрать какие атрибуты хотят изменить, то система находит факт-адрес атрибутов и отводит их назад, поэтому она начинается с самого начала и должна пересмотреть правила. Например, у меня есть два правила:

(defrule month
        (not(attribute (name month)))
        =>
        (bind ?allow (create$ january february march april mamy june july august september october november december))
        (bind ?answer (ask-question "what month is it?" ?allow))
        (assert (attribute (name month) (value ?answer)))
)

(defrule flowering
    (not (attribute (name flowering)))
    (attribute (name month) (value ?month))
=>
    (assert (attribute (name flowering) (value ?month)))
)

Если в конце пользователь хочет изменить атрибут месяца, последний будет отозван, и правило месяца должно быть переоценено и запущено, потому что атрибута месяца нет, поэтому таким образом он может изменить значение месяц, однако атрибут цветения тоже должен быть изменен, но это не сделано, есть атрибут с именем цветения, который был утвержден. Имея это в виду, я создал модуль, который является "фокусом" после функции ревизии:

(defmodule REVISITING (import MAIN ?ALL) )

(defrule REVISITING::retract-month
    (not (attribute(name month)))
    ?f <- (attribute(name flowering))
=>
    (retract ?f)
)

Таким образом, если месяц отозван, цветение также отозвано. Однако мне интересно, есть ли возможность сделать то же самое в лучшем методе, потому что у меня есть сомнения по поводу следующего правила

(defrule petal-apex-toothed 
    (not (attribute (name petal-apex-toothed )))
    (attribute (name petal-color) (valore blue | unknown))
    (attribute (name habitat) (valore sea | montain | edge_of_the_road |camp | unknow))
    (attributo (name flowering) (valore may | june | july | august))
=>
    (bind ?allow (create$ yes no unknow))
    (bind ?answer (ask-question "The petal's apex is toothed?" ?allow))
    (assert (attribute (name petal-apex-toothed) (value ?answer)))
)

Например, если пользователь хочет изменить атрибут среды обитания, я мог бы создать следующее правило в модуле Пересмотр

(defrule retract-habitat
    (not(attribute(name habitat)))
    ?f <- (attribute (name petal-apex-toothed)))
=>
    (retract ?f)
)

Но если первое значение, введенное пользователем, было mountain, а затем он изменил его с помощью edge_of_road, атрибут petal-apex-toothed также будет отозван и снова запущен, но я думаю, что было бы излишним запрашивать вопрос о petal-apex- зубчатый. Так как я могу улучшить свой код??

PS Надеюсь, мне все ясно, иначе я могу попытаться объяснить себя лучше:)

1 ответ

Решение

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

CLIPS> (clear)
CLIPS> 
(deftemplate attribute
  (slot name)
  (slot value))
CLIPS> 
(deffunction ask-question (?question ?allowed-values)
   (printout t ?question)
   (bind ?answer (read))
   (if (lexemep ?answer) then (bind ?answer (lowcase ?answer)))
   (while (not (member$ ?answer ?allowed-values)) do
      (printout t ?question)
      (bind ?answer (read))
      (if (lexemep ?answer) then (bind ?answer (lowcase ?answer))))
   ?answer)
CLIPS>   
(defrule month
   (not (attribute (name month)))
   =>
   (bind ?allow (create$ january february march april may june july 
                         august september october november december))
   (bind ?answer (ask-question "what month is it? " ?allow))
   (assert (attribute (name month) (value ?answer))))
CLIPS> 
(defrule flowering
   (logical (attribute (name month) (value ?month)))
   (not (attribute (name flowering)))
   =>
   (assert (attribute (name flowering) (value ?month))))
CLIPS> (run)
what month is it? september
CLIPS> (facts)
f-0     (initial-fact)
f-1     (attribute (name month) (value september))
f-2     (attribute (name flowering) (value september))
For a total of 3 facts.
CLIPS> (watch facts)
CLIPS> (retract 1)
<== f-1     (attribute (name month) (value september))
<== f-2     (attribute (name flowering) (value september))
CLIPS> 

Чтобы не задавать повторяющиеся вопросы, подтвердите тот факт, что изначально вопрос задавался для запоминания последнего значения, предоставленного пользователем:

CLIPS> (unwatch all)
CLIPS> (clear)
CLIPS> 
(deftemplate attribute
  (slot name)
  (slot value))
CLIPS>   
(deftemplate prior-response
  (slot attribute)
  (slot value))
CLIPS>   
(deffunction ask-question (?attribute ?question ?allowed-values)
   ;; Use do-for-fact to look for a prior response and if
   ;; found return the value last supplied by the user
   (do-for-fact ((?pr prior-response)) 
                (eq ?pr:attribute ?attribute)
     (return ?pr:value))
   ;; Ask the user the question and repeat
   ;; until a valid response is given
   (printout t ?question)
   (bind ?answer (read))
   (if (lexemep ?answer) then (bind ?answer (lowcase ?answer)))
   (while (not (member$ ?answer ?allowed-values)) do
      (printout t ?question)
      (bind ?answer (read))
      (if (lexemep ?answer) then (bind ?answer (lowcase ?answer))))
   ;; Remember the response
   (assert (prior-response (attribute ?attribute) (value ?answer)))
   ;; Return the answer
   ?answer)
CLIPS>   
(defrule month
   (not (attribute (name month)))
   =>
   (bind ?allow (create$ january february march april may june july 
                         august september october november december))
   (bind ?answer (ask-question month "what month is it? " ?allow))
   (assert (attribute (name month) (value ?answer))))
CLIPS> (run)
what month is it? may
CLIPS> (facts)
f-0     (initial-fact)
f-1     (prior-response (attribute month) (value may))
f-2     (attribute (name month) (value may))
For a total of 3 facts.
CLIPS> (retract 2)
CLIPS> (facts)
f-0     (initial-fact)
f-1     (prior-response (attribute month) (value may))
For a total of 2 facts.
CLIPS> (agenda)
0      month: *
For a total of 1 activation.
CLIPS> (run)
CLIPS> (facts)
f-0     (initial-fact)
f-1     (prior-response (attribute month) (value may))
f-3     (attribute (name month) (value may))
For a total of 3 facts.
CLIPS> 

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

CLIPS> (retract 1 3)
CLIPS> (facts)
f-0     (initial-fact)
For a total of 1 fact.
CLIPS> (run)
what month is it? june
CLIPS> (facts)
f-0     (initial-fact)
f-4     (prior-response (attribute month) (value june))
f-5     (attribute (name month) (value june))
For a total of 3 facts.
CLIPS> 
Другие вопросы по тегам