Variable Order of values in LHS, OR/AND operators - clips

I'm trying to define a rule by this form:
;Plantilla Ficha de paciente
(deftemplate FichaPaciente
(multifield Nombre)
(field Casado)
(field Direccion))
;Plantilla DatosExploración
(deftemplate DatosExploracion
(multifield Nombre)
(multifield Sintomas)
(field GravedadAfeccion))
;Regla para diagnóstico de Eccema
(defrule DiagnosticoEccema
(DatosExploracion
(and
(Nombre $?Nombre)
(or
(Sintomas $? picor $? vesiculas $?)
(Sintomas $? vesiculas $? picor $?)
)
)
)
(FichaPaciente
(Nombre $?Nombre))
=>
(printout t "Posible diagnóstico para el paciente " $?Nombre ": Eccema " crlf)
)
The goal is that it was not important if a DatosExploracion fact has the field Sintomas with values (... picor ... vesicula ...) or (... vesicula ... picor). Vesicula and picor order it's not important.
I'm trying with the "and" and "or" operators, but i receive the error: Invalid slot 'and' not defined in corresponding deftemplate 'DatosExploracion'.
1 - Why CLIPS don't recognize the AND and OR operators like i wanted?
2 - Is there a better or more efficient way of getting that the order of values on field Sintomas it's non important?
Thanks in advance.

Here's one way you can do it:
(defrule DiagnosticoEccema
(DatosExploracion
(Nombre $?Nombre)
(Sintomas $?Sintomas&:(and (member$ picor ?Sintomas)
(member$ vesiculas ?Sintomas))))
(FichaPaciente
(Nombre $?Nombre))
=>
(printout t "Posible diagnóstico para el paciente " $?Nombre ": Eccema " crlf))
And another which uses a helper function to reduce the amount of typing when there are multiple symptoms:
(deffunction all-present (?set1 $?set2)
(foreach ?s ?set2
(if (not (member$ ?s ?set1))
then (return FALSE)))
(return TRUE))
(defrule DiagnosticoEccema
(DatosExploracion
(Nombre $?Nombre)
(Sintomas $?Sintomas&:(all-present ?Sintomas picor vesiculas)))
(FichaPaciente
(Nombre $?Nombre))
=>
(printout t "Posible diagnóstico para el paciente " $?Nombre ": Eccema " crlf))

I've getted the goal on this way
(defrule DiagnosticoEccema
(or (DatosExploracion
(Nombre $?Nombre)
(Sintomas $? picor $? vesiculas $?))
(DatosExploracion
(Nombre $?Nombre)
(Sintomas $? vesiculas $? picor $?))
)
(FichaPaciente
(Nombre $?Nombre))
=>
(printout t "Posible diagnóstico para el paciente " $?Nombre ": Eccema " crlf)
)
But if it was a unordered combination of 3,4 or 5 Values for multifield Sintomas, it would be too tedious. I would like if there is a better way to get this using the connectives | or & in a more efficient way.

Related

hey i have a problem in this clips code can any one please fix it?

this is a clips expert system code to make a diagnosis for a disease so i am trying to find out whats the problem in that code and i really dont know what to do
[CSTRCPSR1]
[CSTRCPSR2]
error
defrule diagnosis
(symptom ?s)
(disease (symptoms ?s) (name ?d))
=>
(printout t "The patient may have " ?d "." crlf))
(defrule ask-symptoms
(not (symptom ?))
=>
(bind ?symptom (read))
(assert (symptom ?symptom)))
(defrule ask-symptoms
(not (symptom ?))
=>
(printout t "What are the patient's symptoms?" crlf)
(bind ?symptom (read))
(assert (symptom ?symptom)))
(defrule ask-symptoms-2
(symptom ?s)
(not (symptom ?))
=>
(printout t "Any other symptom? " crlf)
(bind ?symptom (read))
(assert (symptom ?symptom)))
(defclass disease
(is-a USER)
(role concrete)
(multislot symptoms)
(slot name))
(definstances diseases
(disease (symptoms fever headache) (name "influenza"))
(disease (symptoms fever sorethroat) (name "strep throat"))
(disease (symptoms cough shortness-of-breath) (name "pneumonia"))
(disease (symptoms stomachache nausea) (name "food poisoning")))
i tried everything to fix it but i really dont know where is the problem
The diagnosis defrule is missing an opening parenthesis.
The diagnosis defrule references the disease defclass before the
class is defined.
Classes automatically have a name slot defined.
You have two ask-symptoms rules.
The conditions of the ask-symptoms-2 rule will never be satisfied.
Any fact matching the first pattern will cause the following pattern
to fail.
If you want to read multiple symptoms, use the readline function
along with the explode$ function.
In the diagnosis rule, you need to use the object keyword to match
an instance of a defclass.
In the diagnosis rule, the disease pattern can only be matched by
diseases with exactly one symptom.
For example:
CLIPS (6.4 2/9/21)
CLIPS>
(defclass disease
(is-a USER)
(role concrete)
(multislot symptoms)
(slot text))
CLIPS>
(defrule diagnosis
(object (is-a disease) (name ?name) (text ?d))
(exists
(symptoms $? ?s $?)
(object (is-a disease) (name ?name) (symptoms $? ?s $?)))
=>
(printout t "The patient may have " ?d "." crlf))
CLIPS>
(defrule ask-symptoms
=>
(printout t "What are the patient's symptoms? ")
(bind ?symptoms (readline))
(assert (symptoms (explode$ ?symptoms))))
CLIPS>
(definstances diseases
(influenza of disease (symptoms fever headache) (text "influenza"))
(strep-throat of disease (symptoms fever sorethroat) (text "strep throat"))
(pneumonia of disease (symptoms cough shortness-of-breath) (text "pneumonia"))
(food-poisoning of disease (symptoms stomachache nausea) (text "food poisoning")))
CLIPS> (reset)
CLIPS> (run)
What are the patient's symptoms? cough nausea
The patient may have pneumonia.
The patient may have food poisoning.
CLIPS>

Does not generate anything in the output python code using clipspy

I am creating an expert system using clipspy, when I run the code in Python it throws nothing in the output and I have not been able to find the reason.
Python code:
import clips
DEFTEMPLATE_STRING = """
(deftemplate dormitorio
(slot Presencia (type STRING))
(slot Iluminación (type STRING)))
"""
env = clips.Environment()
env.build(DEFTEMPLATE_STRING)
env.load('test.CLP')
Dormitorio = env.find_template('dormitorio')
fact_Dormitorio = Dormitorio.assert_fact(Presencia = 'Si',
Iluminación = 'Apagada')
env.reset()
env.run()
Clips file:
(defrule dormitorio
(Presencia Si)
(Iluminación Apagada)
=>
(printout t "Encender la iluminación del dormitorio." crlf)
(modify 1 (Iluminación Encendida))
)
What is expected is to output the print and modify the variable (Iluminación)?
You used dormitorio as the rule name when it needs to come after the rule name and an opening parenthesis for a fact pattern.
Don't use an integer constant with the modify command in the actions of the rule. Bind the fact matching the pattern to a variable and use that with the modify command.
(defrule r1
?d <- (dormitorio
(Presencia Si)
(Iluminación Apagada))
=>
(printout t "Encender la iluminación del dormitorio." crlf)
(modify ?d (Iluminación Encendida)))

Rules Don't Execute

I have an expert system to figure out the corresponding animal. I have inserted all of the facts, however when I try to (run) the Expert System no question is asked, when the first question should be displayed as 'Is the animal big?' Does anyone have any idea please.
Many thanks in advance
(deffacts startup (animal mouse) (animal squirrel) (animal hamster) (animal giraffe) (animal elephant) (animal hippo)
(animal rhino) (animal big) (neck-long giraffe) (nose-long elephant) (swim-alot hippo) (animal-squeak mouse) (tail-bushy squirrel))
=>
(defrule is-animal-big
(not (animal-big ?))
=> (printout t "Is the animal big (yes or no)?")
(assert (animal-big (read))))
(defrule yes-big-check-neck
(animal-big yes)
(not (neck-long ?))
=>
(printout t "Is the animals neck long (yes or no)?")
(assert (neck-long (read))
)
(defrule neck-long-yes
(neck-long yes)
=>
(printout t "your animal is a giraffe" crlf)
(bind ?animal giraffe)
(assert (animal-is ? animal))
)
;;;========================================
(defrule neck-long-no-check-nose
(neck-long no)
(not (nose-long ?))
=>
(printout t "Is the animals nose long (yes or no)?")
(assert (nose-long (read))
)
(defrule nose-long-yes
(nose-long yes)
=>
(printout t "your animal is an elephant" crlf)
(bind ?animal elephant)
(assert (animal-is ? animal))
)
;;;=======================================
(defrule nose-long-no-check-swim
(nose-long no)
(not (swim-alot ?))
=>
(printout t "Does the animal swim a lot (yes or no)?")
(assert swim-alot (read((
)
(defrule swim-alot-yes
(swim-alot yes)
=>
(printout t "your animal is a hippo" crlf)
(bind ?animal hippo)
(assert (animal-is ? animal))
)
;;;=====================================
(defrule swim-alot-no
(swim-alot no)
=>
(printout t "your animal is a rhino" crlf)
(bind ?animal rhino)
(assert (animal-is ? animal))
)
;;;======================================
(defrule no-big-check-squeak
(animal-big no)
(not (animal-squeak ?))
=>
(printout t "Does the animal squeak (yes or no)?")
(assert animal-squeak (read))
)
(defrule animal-squeak-yes
(animal-squeak yes)
=>
(printout t "your animal is a mouse" crlf)
(bind ?animal mouse)
(assert (animal-is ? animal))
)
;;;=======================================
(defrule squeak-no-check-tail
(animal-squeak no)
(not (tail-bushy ?))
=>
(printout t "Is the animals tail bushy (yes or no)?")
(assert tail-bushy (read))
)
(defrule tail-bushy-yes
(tail-bushy yes)
=>
(printout t "your animal is a squirrel" crlf)
(bind ?animal squirrel)
(assert (animal-is ? animal))
)
;;;=======================================
(defrule tail-bushy-no
(tail-bushy no)
=>
(printout t "your animal is a hamster" crlf)
(bind ?animal hamster)
(assert (animal is ? animal)))
;;;==============================
;;;******************************
Your code is riddled with syntax errors, but the startup deffacts and is-animal-big defrule compile without errors. You're probably not issuing a (reset) command to assert the facts within your deffacts before issuing a (run) command.

Checking a object property in LHS

I need to check the existence of a value for an o'bject's property in a LHS.
(defrule check-property
?room <- (object (is-a ROOM))
(integerp (send ?room get-property)) ; #1
=>
(printout ?*debug-print* "Room " ?room " has property" crlf))
But it seems to me that #1 is not valuated in LHS. Instead if I put it in RHS, it returns TRUE.
Where am I wrong?
Thx,
Nic
Use the test conditional element to evaluate an expression in the LHS of a rule:
(defrule check-property
?room <- (object (is-a ROOM))
(test (integerp (send ?room get-property)))
=>
(printout ?*debug-print* "Room " ?room " has property" crlf))
It's better to explicitly retrieve the slot value by matching it rather than using the slot accessor as this will cause the condition to be reevaluated whenever the slot value changes:
(defrule check-property
?room <- (object (is-a ROOM)
(property ?property))
(test (integerp ?property))
=>
(printout ?*debug-print* "Room " ?room " has property" crlf))

can i retrieve fact's value after searching for it? Clips

I know how to search to check whether fact slot exists, I need to know how to obtain the value of other slots in that fact
(deftemplate details
(slot name(type STRING))(slot occ (type STRING))......)
and
(deffacts details
(details (occ "student")(name "mike"))
(details (occ "professor")(name "john"))
.......
)
(defrule search
(userinfo(occ?occ))
(details(occ?occ) )
=>
?????????????????????????
)
Just bind them in the conditions of the rule:
(defrule search
(userinfo (occ ?occ))
(details (occ ?occ) (name ?name))
=>
(printout t "Name is " ?name crlf))

Resources