Does not generate anything in the output python code using clipspy - clips

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

Related

Variable Order of values in LHS, OR/AND operators

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.

Test if a fact with a field value of a multifield exists in Clips

I have the following fact templates for a station and a train:
(deftemplate station
(slot name (type SYMBOL))
(slot status (type SYMBOL) (default open)))
(deftemplate train
(slot departs-from (type SYMBOL))
(multislot stops-at (type SYMBOL)))
Both slots departs-from and stops-at reference names of stations.
(deffacts trains-and-stations
(station (name station-a))
(station (name station-b))
(station (name station-c))
(train (departs-from station-a) (stops-at unknown-station))
(train (departs-from station-a) (stops-at station-b station-c))
(train (departs-from station-b) (stops-at station-c station-a)))
I want to make a rule that tests if a station fact used in each train exists:
(defrule check-valid-stations
?train <- (train (departs-from ?from) (stops-at $?stops))
(not (exists (station (name ?from))))
=>
(printout t "Route of " $train " contains an unknown station!" crlf))
The rule above only checks if a departure station is valid, how do I check if both departure station and every stop station exist?
The simplest thing to do is have separate rules that check the departs-from and stops-at stations and fire each time an unknown station is found. If you want a single message to be printed regardless of the number of unknown stations, then add an id slot to each train fact so that you can write more complex patterns that will match just once for each train.
CLIPS (6.31 6/12/19)
CLIPS>
(deftemplate station
(slot name (type SYMBOL))
(slot status (type SYMBOL) (default open)))
CLIPS>
(deftemplate train
(slot id)
(slot departs-from (type SYMBOL))
(multislot stops-at (type SYMBOL)))
CLIPS>
(deffacts trains-and-stations
(station (name station-a))
(station (name station-b))
(station (name station-c))
(train (id 1) (departs-from station-a) (stops-at unknown-station))
(train (id 2) (departs-from station-a) (stops-at station-b station-c))
(train (id 3) (departs-from station-b) (stops-at station-c station-a))
(train (id 4) (departs-from some-station) (stops-at station-c station-a bad-location)))
CLIPS>
(defrule check-valid-stations-departs
?train <- (train (departs-from ?from))
(not (station (name ?from)))
=>
(printout t "Route of " ?train " contains an unknown station: " ?from crlf))
CLIPS>
(defrule check-valid-stations-stops
?train <- (train (stops-at $? ?to $?))
(not (station (name ?to)))
=>
(printout t "Route of " ?train " contains an unknown station: " ?to crlf))
CLIPS>
(defrule check-valid-stations
?train <- (train (id ?id) (departs-from ?from))
(exists (or (not (station (name ?from)))
(and (train (id ?id) (stops-at $? ?to $?))
(not (station (name ?to))))))
=>
(printout t "Route of " ?train " contains an unknown station!" crlf))
CLIPS> (reset)
CLIPS> (run)
Route of <Fact-7> contains an unknown station: some-station
Route of <Fact-7> contains an unknown station!
Route of <Fact-7> contains an unknown station: bad-location
Route of <Fact-4> contains an unknown station!
Route of <Fact-4> contains an unknown station: unknown-station
CLIPS>

Compare one value to another to test if file exists in CLIPS

I'm trying to get user to input a book name, then test if the book exists in the library. If not the program should ask him to enter the book details. But the program sees all input as a new book. Is my comparing the two values wrong or my readline?
Code so far:
(deftemplate book (slot name) (slot author) (slot code))
(deffacts current-lib
(book (name "Alice in Wonderland") (author Lewis-Carroll) (code CAR))
(book (name "The Bourne Supremacy") (author Robert-Ludlum) (code LUD)))
(defrule readnew "inputs potential new book details"
=>
(printout t "Enter the name of the book:")
(bind ?b_name (readline))
(assert (potential ?b_name)))
(defrule add-book "determine if book already exists otherwise add"
?out <- (potential ?newname)
(and (potential ?newname)
(not (book (name ?b_name&?newname) (author $?))))
=>
(printout t "Book is new, please enter the author's name:" crlf)
(bind ?auth (readline))
(printout t "Please enter a three letter code for the book:" crlf)
(bind ?coode (read))
(assert (book (name ?newname) (author ?auth) (code ?coode)))
(retract ?out))
You provided code, but not the steps you took to run it so I'll have to guess at the cause of your problem. The simplest explanation would be that you did not issue a reset command to assert the facts in your current-lib deffacts.
I made a few changes to your code. In your current-lib deffacts, the author names should be strings since you're using readline in your add-book rule to get the names. There is also unnecessary code in the conditions of your add-book rule.
CLIPS (6.31 2/3/18)
CLIPS>
(deftemplate book
(slot name)
(slot author) (slot code))
CLIPS>
(deffacts current-lib
(book (name "Alice in Wonderland") (author "Lewis Carroll") (code CAR))
(book (name "The Bourne Supremacy") (author "Robert Ludlum") (code LUD)))
CLIPS>
(defrule readnew
=>
(printout t "Enter the name of the book:" crlf)
(bind ?b_name (readline))
(assert (potential ?b_name)))
CLIPS>
(defrule add-book
?out <- (potential ?newname)
(not (book (name ?newname)))
=>
(printout t "Book is new, please enter the author's name:" crlf)
(bind ?auth (readline))
(printout t "Please enter a three letter code for the book:" crlf)
(bind ?coode (read))
(assert (book (name ?newname) (author ?auth) (code ?coode)))
(retract ?out))
CLIPS>
Now, if you add a book that doesn't exist you'll be ask for the additional information.
CLIPS> (reset)
CLIPS> (run)
Enter the name of the book:
Ringworld
Book is new, please enter the author's name:
Larry Niven
Please enter a three letter code for the book:
RNG
CLIPS>
If you try to add a book that doesn't exist, the add-book rule won't execute.
CLIPS> (reset)
CLIPS> (run)
Enter the name of the book:
Alice in Wonderland
CLIPS>

CLIPS: reference to ruleName

is there a way to output the name of the fired rule in CLIPS?
Example:
(defrule this-is-my-rule
...
=>
(printout t "this-is-my-rule: and these are the outputs" crlf) ;;#1
)
Instead of writing manually the name of the rule in #1, I'd like to use a psecific command (if any).
Is it possible, please?
Thank
Nicola
There isn't a mechanism for programmatically determining the name of the currently executing rule, but you can use the watch debugging command to print the name of each rule as it is executed:
CLIPS> (defrule rule-1 =>)
CLIPS> (defrule rule-2 =>)
CLIPS> (defrule rule-3 =>)
CLIPS> (watch rules)
CLIPS> (run)
FIRE 1 rule-3: *
FIRE 2 rule-2: *
FIRE 3 rule-1: *
CLIPS>

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