2016-09-16 2 views
0

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

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

Если, в конце концов, пользователь хочет изменить атрибут месяца, этот последний будет втянут и правило месяц должен быть пересмотрен и обжигает, потому что ISN» t no month, поэтому таким образом он может изменить значение месяца, однако атрибут цветения также должен быть изменен, но это не сделано, есть атрибут с именем colorering, который был подтвержден. Имея это в виду, я создал модуль, который является «фокус» после Пересмотреть-функции:

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

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

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

ответ

0

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

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>