I'm trying to change the code of the expert system (The Engine Diagnosis Expert System) Add disordered patterns - . Clip does not produce errors, but the questions are not loaded. What am I doing wrong?
(deftemplate your_car "This is template for describing condition car"
(slot working-state (default undefined))
(slot rotation-state (default undefined))
(slot spark-state (default undefined))
(slot charge-state (default undefined))
(slot symptom (default undefined))
(slot repair(default undefined))
)
(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
)
;-----------------------------------------------------------------------------------
(deffunction yes-or-no-p (?question)
(bind ?response (ask-question ?question yes no у n))
(if (or (eq ?response yes) (eq ?response y))
then
TRUE
else
FALSE)
)
;-----------------------------------------------------------------------------------
(defrule determine-engine-state ""
;(your_car (working-state undefined))
;(your_car (repair undefined))
?f1 <- (your_car (working-state undefined)(repair undefined))
=>
(if (yes-or-no-p "Does the engine start (yes/no)? ")
then
(if (yes-or-no-p "Does the engine run normally (yes/no)? ")
then
(modify ?f1 (working-state "engine normal"))
else
(modify ?f1 (working-state "engine unsatisfactory")))
else
(modify ?f1 (working-state "engine does-not-start"))))
;...
;-----------------------------------------------------------------------------------
(defrule no-repairs ""
(declare (salience -10))
;(your_car (repair undefined))
?f1 <- (your_car (repair undefined))
=>
(modify ?f1 (repair "Take your car to a mechanic."))
)
(defrule print-repair ""
(declare (salience 10))
;(your_car (repair ?item))
?f1 <- (your_car (repair ?item))
=>
(printout t crlf crlf)
(printout t "Suggested Repair:")
(printout t crlf crlf)
(format t " %s%n%n%n" ?item)
)
;-----------------------------------------------------------------------------------
(defrule system-banner ""
(declare (salience 10))
=>
(printout t crlf crlf)
(printout t "****************************************" crlf)
(printout t "* The Engine Diagnosis Expert System *" crlf)
(printout t "****************************************" crlf)
(printout t crlf crlf)
)
A deftemplate defines the structure of a fact, but it does not create them. Add a deffacts to your program after the deftemplate definition.
(deffacts start
(your_car))
When a (reset) command is issued, this will assert the facts contained in any deffacts constructs.
CLIPS> (clear)
CLIPS>
(deftemplate your_car "This is template for describing condition car"
(slot working-state (default undefined))
(slot rotation-state (default undefined))
(slot spark-state (default undefined))
(slot charge-state (default undefined))
(slot symptom (default undefined))
(slot repair(default undefined))
)
CLIPS>
(deffacts start
(your_car))
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>
(deffunction yes-or-no-p (?question)
(bind ?response (ask-question ?question yes no у n))
(if (or (eq ?response yes) (eq ?response y))
then
TRUE
else
FALSE)
)
CLIPS>
(defrule determine-engine-state ""
?f1 <- (your_car (working-state undefined)(repair undefined))
=>
(if (yes-or-no-p "Does the engine start (yes/no)? ")
then
(if (yes-or-no-p "Does the engine run normally (yes/no)? ")
then
(modify ?f1 (working-state "engine normal"))
else
(modify ?f1 (working-state "engine unsatisfactory")))
else
(modify ?f1 (working-state "engine does-not-start"))))
CLIPS>
(defrule no-repairs ""
(declare (salience -10))
?f1 <- (your_car (repair undefined))
=>
(modify ?f1 (repair "Take your car to a mechanic."))
)
CLIPS>
(defrule print-repair ""
(declare (salience 10))
?f1 <- (your_car (repair ?item))
=>
(printout t crlf crlf)
(printout t "Suggested Repair:")
(printout t crlf crlf)
(format t " %s%n%n%n" ?item)
)
CLIPS>
(defrule system-banner ""
(declare (salience 10))
=>
(printout t crlf crlf)
(printout t "****************************************" crlf)
(printout t "* The Engine Diagnosis Expert System *" crlf)
(printout t "****************************************" crlf)
(printout t crlf crlf)
)
CLIPS> (reset)
CLIPS> (run)
Suggested Repair:
undefined
****************************************
* The Engine Diagnosis Expert System *
****************************************
Does the engine start (yes/no)? yes
Does the engine run normally (yes/no)? yes
Suggested Repair:
undefined
Suggested Repair:
Take your car to a mechanic.
CLIPS>
Related
I am trying to retract a deftemplate fact but when I do this CLIPS keeps saying I have to first declare the deffunction yet it is the appropriate deftemplate.What seems to be the problem?
I have attached the related code:
I get this error:
[EXPRNPSR3] Missing function declaration for Agriculture.
What seems to be the problem?
(deftemplate Agriculture
(slot weed
(type SYMBOL)
(allowed-symbols B G))
(slot crop
(type SYMBOL)
(allowed-symbols C S))
(slot organic-matter
(type INTEGER)
(allowed-values 1 2 3)))
(defrule Sencor-1
(and (Agriculture(weed B))
(Agriculture(crop C|S))
(Agriculture(organic-matter 1)))
=>
(printout t "Do not use Sencor!!"crlf))
(defrule Sencor-2
(and (Agriculture(weed B))
(Agriculture(crop C|S))
(Agriculture(organic-matter 2|3)))
=>
(printout t " " crlf "Use 3/4 pt/ac of Sencor" crlf ))
(defrule Lasso-1
(and (Agriculture(weed B|G))
(Agriculture(crop C|S))
(Agriculture(organic-matter 1)))
=>
(printout t crlf"Use 2 pt/ac of Lasso" crlf))
(defrule Lasso-2
(and (Agriculture(weed B|G))
(Agriculture(crop C|S))
(Agriculture(organic-matter 2)))
=>
(printout t crlf "Use 1 pt/ac of Lasso" crlf))
(defrule Lasso-3
(and (Agriculture(weed B|G))
(Agriculture(crop C|S))
(Agriculture(organic-matter 3)))
=>
(printout t crlf "Use 0.5 pt/ac of Lasso" crlf))
(defrule Bicep-1
(and (Agriculture(weed B|G))
(Agriculture(crop C))
(Agriculture(organic-matter 1)))
=>
(printout t crlf "Use 1.5 pt/ac of Bicep" crlf))
(defrule Bicep-2
(and (Agriculture(weed B|G))
(Agriculture(crop C))
(Agriculture(organic-matter 2)))
=>
(printout t crlf"Use 2.5 pt/ac of Bicep" crlf))
(defrule Bicep-3
(and (Agriculture(weed B|G))
(Agriculture(crop C))
(Agriculture(organic-matter 3)))
=>
(printout t crlf "Use 3 pt/ac of Bicep" crlf))
(defrule input
(initial-fact)
=>
(printout t crlf "What is the crop? (C:corn,S:soybean)")
(bind ?a (read))
(assert(Agriculture(crop ?a))) ;gets input from user
(printout t crlf "What is the weed problem? (B:broadleaf, G:grass)")
(bind ?b (read))
(assert(Agriculture(weed ?b)))
(printout t crlf "What is the % of organic matter content? (1:<2%,2:2-4%,3:>4%)")
(bind ?c (read))
(assert(Agriculture(organic-matter ?c)))
?d <- (Agriculture(crop ?a) (weed ?b) (organic-matter ?c))
(printout t ""crlf crlf "RECOMMENDATIONS:"crlf)
(retract ?d))
In the RHS of the input rule you state:
?d <- (Agriculture(crop ?a) (weed ?b) (organic-matter ?c))
This is interpreted as "Run function Agriculture and bind its results into ?d".
What you probably are trying to do is:
(bind ?d (assert (Agriculture (crop ?a) (weed ?b) (organic-matter ?c))))
In my expert system user must check Developer and Price after he'll see notebook which is suitable for this parameters.
For example with this parameters (on screenshot) I must have result: Model: Noteebok1
But I don't see anything. Where is a problem or bug?
CLP File Code:
(defglobal ?*s* = 0)
(deftemplate Notebook
(slot pModel)
(slot pDeveloper)
(slot pPrice))
;*******************************************************************
(deffunction QuestionOf(?TextQuestion $?variations)
(printout t ?TextQuestion)
(bind ?Answer (read))
(if (lexemep ?Answer)
then (bind ?Answer (lowcase ?Answer)))
(while (not (member ?Answer ?variations)) do
(printout t ?TextQuestion)
(bind ?Answer (read))
(if (lexemep ?Answer)
then (bind ?Answer (lowcase ?Answer))))
?Answer)
;********************************************************************'
(defrule banner
(declare (salience 10))
=>(load-facts D:\fact.txt)
(printout t crlf crlf)
(printout t "Expert system. Nout search")
(printout t crlf crlf))
;******************************************************************'
(defrule QuestionDeveloper
(not (Developer ?))
=>(bind ?asssert(QuestionOf "Check Developer (a-HP,b-Samsung,c-Apple,d-IDontKnow)" a b c d))
(if (eq ?asssert a)then (assert (Developer HP)))
(if (eq ?asssert b)then (assert (Developer Samsung)))
(if (eq ?asssert c)then (assert (Developer Apple)))
(if (eq ?asssert d)then (assert (Developer IDontKnow))))
;******************************************************************'
(defrule QuestionPrice
(not (Price ?))
=>(bind ?asssert(QuestionOf "Price?(a-300,b-400,c-500,d-IDontKnow)" a b c d))
(if (eq ?asssert a)then (assert (Price 300)))
(if (eq ?asssert b)then (assert (Price 400)))
(if (eq ?asssert c)then (assert (Price 500)))
(if (eq ?asssert d)then (assert (Price IDontKnow))))
;******************************************************************'
(defrule Vyvod
(or (Developer ?xDeveloper)(Developer IDontKnow))
(or (Price ?xPrice)(Price IDontKnow))
(Notebook(pModel ?Model)(pDeveloper ?xDeveloper)(pPrice ?xPrice))
=>(bind ?*s*(+ ?*s* 1))
(printout t crlf " " ?*s* ". Model : " ?Model crlf))
;******************************************************************'
Fact.txt:
(Notebook(pModel Notebook1)(pDeveloper HP)(pPrice 500))
(Notebook(pModel Notebook2)(pDeveloper Samsung)(pPrice 400))
(Notebook(pModel Notebook3)(pDeveloper Apple)(pPrice 500))
The facts from the file fact.txt are not being loaded. Check that the file is at the specified path and that you have read access.
In my system the user inputs a Y or N to answer simple questions. I call this rule after every question to increment a counter. There are some general problems with my code but i can't see where
(defrule QPain
(initial-fact)
=>
(printout t "Are You In Pain? " crlf)
(bind ?*Answer* (read))
)
(defrule IncSym
(test(=(str-compare (?*Answer*) "y")0))
=>
(bind ?*symcount* (+ ?*symcount* 1))
)
Thanks
The syntactic errors can be corrected as follows:
CLIPS> (clear)
CLIPS> (defglobal ?*Answer* = nil)
CLIPS> (defglobal ?*symcount* = 0)
CLIPS>
(defrule QPain
=>
(printout t "Are you in pain? ")
(bind ?*Answer* (read)))
CLIPS>
(defrule IncSym
(test (eq ?*Answer* y))
=>
(bind ?*symcount* (+ ?*symcount* 1)))
CLIPS> (reset)
CLIPS> (run)
Are you in pain? y
CLIPS> (show-defglobals)
?*Answer* = y
?*symcount* = 0
CLIPS>
This won't produce the behavior you're expecting, however, since ?*symcount* will not be incremented. The behavior of global variables and why you should not be using them in the manner you're attempting has been discussed previously:
How exactly (refresh) works in the clips?
CLIPS: forcing a rule to re-evaluate the value of a global variable?
Number equality test fails in CLIPS pattern matching?
CLIPS constant compiler directive
How can I run the clips with out reset the fact when using CLIPS
Instead of using global variables to track responses and symptoms, you should use facts or instances. Here's one approach:
CLIPS> (clear)
CLIPS>
(deftemplate symptom
(slot id)
(slot response))
CLIPS>
(deftemplate symptom-list
(multislot values))
CLIPS>
(deffacts initial
(symptom-list))
CLIPS>
(defrule QPain
=>
(printout t "Are you in pain? ")
(assert (symptom (id in-pain) (response (read)))))
CLIPS>
(defrule IncSym
(symptom (id ?id) (response y))
?f <- (symptom-list (values $?list))
(test (not (member$ ?id ?list)))
=>
(modify ?f (values ?list ?id)))
CLIPS>
(defrule symptoms-found
(declare (salience -10))
(symptom-list (values $?list))
=>
(printout t "Symptom count: " (length$ ?list) crlf))
CLIPS> (reset)
CLIPS> (run)
Are you in pain? y
Symptom count: 1
CLIPS> (reset)
CLIPS> (run)
Are you in pain? n
Symptom count: 0
CLIPS>
And another:
CLIPS> (clear)
CLIPS>
(deftemplate symptom
(slot id)
(slot response))
CLIPS>
(defrule QPain
=>
(printout t "Are you in pain? ")
(assert (symptom (id in-pain) (response (read)))))
CLIPS>
(defrule symptoms-found
(declare (salience -10))
=>
(bind ?count (find-all-facts ((?f symptom)) (eq ?f:response y)))
(printout t "Symptom count: " (length$ ?count) crlf))
CLIPS> (reset)
CLIPS> (run)
Are you in pain? y
Symptom count: 1
CLIPS> (reset)
CLIPS> (run)
Are you in pain? n
Symptom count: 0
CLIPS>
; template person
(deftemplate person
(slot name (type STRING))
(slot gender (type SYMBOL)(allowed-symbols m f)); male, female
(slot birthyear (type INTEGER))
(slot birthPlace(type STRING))
(slot Fname (type STRING))
(slot Mname (type STRING))
(multislot siblingsName (type STRING))
(slot spouse (type STRING))
(slot height (type INTEGER))
(slot weight (type INTEGER))
(slot hairColor (type STRING))
(slot eyeColor (type STRING))
(multislot oddHabits (type STRING))
)
; menu
(defrule menu
(declare (salience 9000))
(initial-fact)
=>
(printout t crlf
"Menu : " crlf
" 1- Infer family relations " crlf
" 2- Add additional members " crlf
" 3- Modify properties of already existing members " crlf
" 4- List properties of a specific individual by name or reference. " crlf
" 5- Find for all individuals matching a certain property. " crlf
" 6- Find all individuals matching two properties. " crlf
" 7- Display family relations (same like 1) along with their height comparison." crlf
" 8- exit the program" crlf
"Choose 1 - 8 -> "
)
(assert (task type =(read)))
)
; exit
(defrule Exit
(task type 8)
=>
(exit)
)
(defrule AddMember
(task type 2)
=>
(printout t "Enter Name" crlf)
(bind ?name (read))
(printout t "Enter gender" crlf)
(bind ?G (read))
(printout t "Enter birth year" crlf)
(bind ?BY(read))
(printout t "Enter birth place" crlf)
(bind ?BP(read))
(printout t "Enter Father name " crlf)
(bind ?FN (read))
(printout t "Enter Mother name" crlf)
(bind ?MN(read))
(printout t "Enter siblings" crlf)
(bind ?SI(readline))
(printout t "Enter spouse" crlf)
(bind ?SP (read))
(printout t "Enter height" crlf)
(bind ?H (read))
(assert
(person
(name ?name)(gender ?G)(birthyear ?BY)(birthPlace ?BP)(Fname ?FN)(Mname ?MN)(siblingsName ?SI )(spouse ?SP) (height ?H))
)
)
(defrule Modify
(task type 3)
=>
(printout t " (a) to modify gender" crlf)
(printout t " (b) to modify Birth Year" crlf)
(printout t " (c) to modify Birth Place" crlf)
(printout t " (d) to modify Father Name" crlf)
(printout t " (e) to modify Mother Name" crlf)
(printout t " (f) to modify Spouse" crlf)
(printout t " (g) to modify height" crlf)
(printout t " (h) to modify weight" crlf)
(assert (task type =(read)))
)
(defrule ModifyGender
(task type a)
=>
(printout t "Enter the name of person that you want to modify" crlf)
(bind ?n (read))
(printout t " Enter new value" crlf)
(bind ?V (read))
?num <- (person (name ?n))
(printout t " num is " ?num " " crlf)
(modify ?num (gender ?V))
)
When loading the file of my project an error shows up:
[EXPRNPSR3] Missing function declaration for person.
Error:
(defrule MAIN::ModifyGender
(task type a)
=>
(printout t "Enter the name of person that you want to modify" crlf)
(bind ?n (read))
(printout t " Enter new value" crlf)
(bind ?V (read))
?num
<-
Can anyone help me?
Patterns matching facts are only allowed in the condition portion of a rule, not in the actions of the rule. You can either use multiple rules to determine which person to change and to apply the change:
(defrule ModifyGender-ask
?f <- (task type a)
=>
(retract ?f)
(printout t "Enter the name of person that you want to modify" crlf)
(bind ?n (read))
(printout t " Enter new value" crlf)
(bind ?V (read))
(assert (modify-gender ?n ?V)))
(defrule ModifyGender-apply
?f <- (modify-gender ?n ?v)
?num <- (person (name ?n))
=>
(retract ?f)
(modify ?num (gender ?v)))
(defrule ModifyGender-don't-apply
?f <- (modify-gender ?n ?v)
(not (person (name ?n)))
=>
(retract ?f))
Or you can use the fact-set query functions to locate and change the person from the actions of the rule:
(defrule ModifyGender
?f <- (task type a)
=>
(retract ?f)
(printout t "Enter the name of person that you want to modify" crlf)
(bind ?n (read))
(printout t " Enter new value" crlf)
(bind ?V (read))
(if (any-factp ((?p person)) (eq ?p:name ?n))
then
(do-for-fact ((?p person)) (eq ?p:name ?n)
(modify ?p (gender ?V)))
else
(printout t "Person " ?n " does not exist." crlf)))
Morning, Excuse the silly question but I am busy building a expert system much like the "21 Questions" game that uses questions asked to the user in order to determine the right dog for them. The expert system is coded in CLIPS / .CPS language and one of the requirements I am looking to include is that when the user is asked a yes/no question they are required to input "y" or "n".
In all the resources we have been taught we have only been tough number validation and not a specific character validation and I cannot find any resources that do this either.
This is an example of the number validation I did in order to ensure they input a valid number on one of my questions
(defrule test-integer
(number-in ?number&:(integerp ?number))
=>
(printout t ?number "is valid"
(defrule test-non-int
?number-address <- (number-in ?number&:(not (integerp ?number)))
=>
(printout t ?number " not valid int" crlf)
(retract ?number-address))
This is how you'd do it using rules:
CLIPS>
(defrule test-response
(response-in ?response&y|n)
=>
(printout t ?response " is valid" crlf))
CLIPS>
(defrule test-non-response
?response-address <- (response-in ?response&~y&~n)
=>
(printout t ?response " not valid response" crlf)
(retract ?response-address))
CLIPS> (assert (response-in xyz))
<Fact-1>
CLIPS> (run)
xyz not valid response
CLIPS> (assert (response-in n))
<Fact-2>
CLIPS> (run)
n is valid
CLIPS>
I'd suggest using a function that only accepts correct responses:
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> (ask-question "Continue? " y n yes no)
Continue? k
Continue? l
Continue? ye
Continue? YeS
yes
CLIPS>
What i figured out was to link the answer from the one defrule to that of another defrule first to check if the answer was valid and then again if that answer was valid to link it to the correct defrule then that will proceed with the next question.
Code is from my own Expert System:
(defrule Small-CoatType-Full
(Small-Coat f)
(person (name ?name))
=>
(open "result.txt" result "a")
(printout result ?name " Likes Smaller, Fury Dogs" crlf)
(close result)
(printout t "Would you like a low energetic(l) or high energetic(h) breed?" crlf)
(assert (Small-Energy-Level(lowcase(read)))))
(defrule Small-Energy-Level-Wrong
(Small-Energy-Level ?var &~l&~h)
=>
(printout t crlf "Plesae Only Choose (l) or (h)")
(assert (Small-Energy-Level (lowcase(read)))))`