2016-09-16 4 views
0

(Tout d'abord, désolé pour mon anglais :)) J'essaie de créer un système de révision pour mon projet (une simple classification des plantes naturelles), je ne veux pas coller tout mon code , mais seulement les parties importantes, donc je vais essayer d'expliquer ce que le système fait. J'ai fait une fonction (que j'appelle réviser-attribut), quand le système trouve les plantes qui doivent correspondre aux réponses données par l'utilisateur, qui demandent à l'utilisateur s'il veut modifier certains attributs, s'il répond "oui" il peut choisir quels attributs veulent changer, alors le système trouve le fait et la fin des attributs et les rétracte, donc il commence dès le début et devrait réévaluer les règles. Par exemple, j'ai ces deux règles:Clips réviser le système

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

Si, à la fin, l'utilisateur souhaite modifier l'attribut mois, ce dernier sera rétractés et le mois de règle devrait être réévalué et tiré parce qu'il n » est pas t aucun attribut de mois, ainsi de cette manière il peut changer la valeur du mois, cependant l'attribut de floraison devrait être changé aussi, mais ceci n'est pas fait il y a un attribut avec le nom floraison qui a été affirmé. Dans cet esprit, j'ai créé un module qui est « focus » après la fonction revoir:

(defmodule REVISITING (import MAIN ?ALL)) 

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

Donc, si le mois est rétracté, la floraison est escamoté aussi. Cependant, je me demande s'il y a une possibilité de faire la même chose dans une meilleure méthode parce que j'ai un doute pour la règle suivante

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

Par exemple, si l'utilisateur souhaite modifier l'attribut de l'habitat que je pourrais créer la règle suivante dans le module Revisiter

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

mais si la première valeur entrée par l'utilisateur était la montagne, puis il a changé avec edge_of_road sera rétracté l'attribut pétale-sommet dents trop et re-tiré, mais je chose il pourrait être redondant de demander la question à propos de pétale-apex-denté. Alors, comment puis-je améliorer mon code?

P.S. J'espère avoir été clair, sinon je peux essayer d'expliquer mysef mieux :)

Répondre

0

Utilisez l'élément conditionnel logique dans les conditions d'une règle pour rendre les assertions des actions d'une règle dépendant logiquement de l'existence d'un groupe de motifs :

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> 

pour éviter les questions suivantes sont évitées à nouveau, affirmer un fait lorsque la question est à l'origine demandé de se rappeler la dernière valeur fournie par l'utilisateur:

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> 

lorsque l'utilisateur veut changer la valeur de la à hommage, vous aurez besoin de se rétracter à la fois l'attribut et le fait de réponse précédente associée:

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>