I'm new in Clips. I'd like to know if it is a way to read an array (chain of numeric or characters with an index, sorry if it's the wrong name) on LHS. I have rules to ask for a value (s,cs,cn,n) then it assert the value to next asking rule, to finally read all the values in an answering rule to get a diagnostic, but in my small example I have 4 questions and 4 options for each one so mixing all the answers would give me 64 rules, and I have so at least 30 questions in my program so I think that would be too much rules (I'm doing my first Expert System an maybe this is normal). In any case I think I could get the values from questions into an array an read it in answering rules, but my questions are:
*How can I bind the values from my function into an array?
*Is it possible to verify that array in LHS?
*Do you have any other idea to verify the answer-rules? Hope you can help me.
(deffunction funcionPregunta (?pregunta $?valoresAceptados) ;;ask-question function
(printout t ?pregunta)
(bind ?respuesta (read))
(if (lexemep ?respuesta)
then (bind ?respuesta (lowcase ?respuesta)))
(while (not (member$ ?respuesta ?valoresAceptados)) do
(printout t ?pregunta)
(bind ?respuesta (read))
(if (lexemep ?respuesta)
then (bind ?respuesta (lowcase ?respuesta))))
?respuesta)
;;===============================================================
;; QUESTION RULES
;;===============================================================
(defrule pregunta1T5 "AGORAFOBIA"
(not (diagnostico ?))
=>
(assert (Pregunta2T5
(funcionPregunta "1.Siente miedo o ansiedad marcada. (always/frecuently/rare/never)? "
s cs cn n))))
(defrule Pregunta2T5 "AGORAPUBLICO"
(not (diagnostico ?))
(Pregunta2T5 ?Pregunta2T5)
=>
(assert (Pregunta3T5
(funcionPregunta "2.Siente miedo en una multitud. (always/frecuently/rare/never)? "
s cs cn n)))
)
(defrule Pregunta3T5 "AGORAMIEDO"
(not (diagnostico ?))
(Pregunta3T5 ?Pregunta3T5)
=>
(assert (Pregunta4T5
(funcionPregunta "3.Miedo de estar en una situacion. (always/frecuently/rare/never)? "
s cs cn n)))
)
(defrule Pregunta4T5 "AGORAANSIEDAD"
... ;; similar rules
;;===============================================================
;; ANSWERS RULES
;;===============================================================
(defrule Respuesta1T6 "RESULTADO 1 TAS"
(not (diagnostico ?))
(Pregunta2T6 s)(Pregunta3T6 s)(Pregunta4T6 s)(Pregunta5T6 s)
=>
(assert (diagnostico "TRASTORNO DE ANSIEDAD SOCIAL"))
)
(defrule Respuesta2T6 "RESULTADO 2 TAS"
(not (diagnostico ?))
(Pregunta2T6 cs)(Pregunta3T6 s)(Pregunta4T6 s)(Pregunta5T6 s)
=>
(assert (diagnostico "TRASTORNO DE ANSIEDAD SOCIAL"))
)
In the case of the two answer rules you've already got, the simplest way to reduce the number of rules is just to combine them:
(defrule Respuesta1T6-2T6
(not (diagnostico ?))
(Pregunta2T6 s | cs) ; s or cs is allowed
(Pregunta3T6 s)
(Pregunta4T6 s)
(Pregunta5T6 s)
=>
(assert (diagnostico "TRASTORNO DE ANSIEDAD SOCIAL")))
If you're creating lots of rules that differ only in the constants matched in the patterns, you should consider representing the rules as a combination of facts containing these constants and generic rules to process that data. For example, you could rewrite your question rules like this:
(deftemplate Pregunta ; question
(slot identidad) ; ID
(slot texto) ; text
(multislot respuestas) ; responses
(slot precursora ; precursor
(default ninguna))) ; none
(deftemplate Responder ; answer
(slot identidad) ; ID
(slot valor)) ; value
(deffacts Preguntas
(Pregunta (identidad AGORAFOBIA)
(texto "1. Siente miedo o ansiedad marcada. (always/frecuently/rare/never)? ")
(respuestas s cs cn n))
(Pregunta (identidad AGORAPUBLICO)
(texto "2. Siente miedo en una multitud. (always/frecuently/rare/never)? ")
(respuestas s cs cn n)
(precursora AGORAFOBIA))
(Pregunta (identidad AGORAMIEDO)
(texto "3. Miedo de estar en una situacion. (always/frecuently/rare/never)? ")
(respuestas s cs cn n)
(precursora AGORAPUBLICO)))
(defrule pedir-pregunta ; ask question
(not (diagnostico ?))
(Pregunta (identidad ?id)
(texto ?t)
(respuestas $?r)
(precursora ?p))
(or (test (eq ?p ninguna))
(Responder (identidad ?p)))
=>
(assert (Responder (identidad ?id)
(valor (funcionPregunta ?t ?r)))))
And your diagnosis rules like this:
(deftemplate Trastorno ; disorder
(slot nombre) ; name
(multislot sintomas)) ; symptoms
(deftemplate Sintoma
(slot identidad) ; ID
(slot responder) ; answer
(multislot valors)) ; values
(deffacts Trastornos
(Trastorno (nombre "TRASTORNO DE ANSIEDAD SOCIAL")
(sintomas AGORAFOBIA-cs-s AGORAPUBLICO-s AGORAMIEDO-s)))
(deffacts Sintomas
(Sintoma (identidad AGORAFOBIA-cs-s)
(responder AGORAFOBIA)
(valors cs s))
(Sintoma (identidad AGORAPUBLICO-s)
(responder AGORAPUBLICO)
(valors s))
(Sintoma (identidad AGORAMIEDO-s)
(responder AGORAMIEDO)
(valors s)))
(defrule Respuesta
(not (diagnostico ?))
(Trastorno (nombre ?n)) ; There is a disorder.
(forall (Trastorno (nombre ?n) ; For every symptom
(sintomas $? ?s $?)) ; of the disorder,
(Sintoma (identidad ?s) ; there is a list
(responder ?r) ; of possible values
(valors $?sv)) ; for that symptom
(Responder (identidad ?r) ; matched by a response.
(valor ?v&:(member$ ?v ?sv))))
=>
(assert (diagnostico ?n)))