I'm trying to create a diagnosis expert system. I have managed to create the menu and submenu but after inputting my choice(e.g 1). The question that supposed to be asked after the submenu does not appear. Hence not being able to continue. I would like to ask whether is there anything wrong with what I did?
If there is, what is the proper way to do it?
Here's a part of the code for reference:
CLIPS> ;; MainMenu
(defrule Menu
(not (iffoundChoice ?))
=>
(printout t crlf crlf crlf
"Choose one of the problem areas listed below" crlf crlf
" 1.) Brake Pedal System. "crlf crlf
" 2.) Gearbox. "crlf crlf
" 3.) ." crlf crlf
" 4.) END SYSTEM. "crlf crlf crlf
" Enter no. of your choice: ")
(assert (iffoundChoice (read))))
CLIPS> ;; submenu1
(defrule subMenu1
(not (iffoundChoice1 ?))
=>
(printout t crlf crlf crlf
"Choose which topic best relates to your problem? "crlf crlf
" 1.1) Car Pulls One Side When Braking. "crlf crlf
" 1.2) Rear Brake Drag. "crlf crlf
" 1.3) Brake squeal. "crlf crlf
" 4.) END SYSTEM. "crlf crlf crlf
" Enter no. of your choice: ")
(assert (iffoundChoice1 (read))))
CLIPS> ;; Rule 1 based on choice 1
(defrule car_pulls_one_side_when_braking
(iffoundChoice1)
?retractCh1 <- (iffoundChoice1)
(not (ifYesNochoice ?))
=>
(retract ?retractCh1)
(printout t crlf crlf crlf
" Was your tyre uneven? (yes|no) "crlf crlf
" Your answer: ")
(assert (ifYesNochoice (read))))
CLIPS> ;;Rule 2 based on Yes answer in Rule 1
(defrule car_pulls_one_side_when_braking1
(ifYesNochoice yes)
?retractChy <- (ifYesNochoice yes)
(not (ifYesNochoice1 ?))
=>
(retract ?retractChy)
(printout t crlf crlf crlf
" Please check your tyre pressure "crlf crlf
" Is it in good condition? (yes|no) "crlf crlf
" Your answer: "
(assert (ifYesNochoice1 (read)))))
CLIPS> ;;Rule 3 based on Yes answer in Rule 2
(defrule car_pulls_one_side_when_braking2
(ifYesNochoice1 yes)
?retract <- (ifYesNochoice1)
(not (ifYesNochoise2 ?))
=>
(retract ?retract Chy)
(printout t crlf crlf crlf
" Then your car should be no problem. " crlf crlf
" Thanks for using Vehicle Diagnosis Failure System. " crlf crlf))
CLIPS> ;; Rule 4 based on NO answer in Rule 2
(defrule car_pulls_one_side_when_braking3
(ifYesNochoice1 no)
?retract <- (ifYesNochoice1)
(not (ifYesNochoice3 ?))
=>
(retract ?retract Chy)
(printout t crlf crlf crlf
" Please inflate all the tyres according to the tyre plycard. "crlf crlf
" Please check again with your technician if problem is solved. "crlf crlf
" Thanks for using Vehicle Diagnosis Failure System. "crlf crlf))
CLIPS> (reset)
CLIPS> (run)
Change the patterns for iffoundChoice and iffoundChoice1 to include the user selection.
(defrule car_pulls_one_side_when_braking
(iffoundChoice 1) ; <--
?retractCh1 <- (iffoundChoice1 1) ; <--
(not (ifYesNochoice ?))
=>
(retract ?retractCh1)
(printout t crlf crlf crlf
" Was your tyre uneven? (yes|no) "crlf crlf
" Your answer: ")
(assert (ifYesNochoice (read))))
Related
Am writing a project, my code will be in the form as describe below in the code, Is there any need to include salience and how can I use interface? The software will require the user to answer a question in the form of yes or no. I want to know how to do this in the form of checkboxes, where the user will tick the appropriate symptoms of a disease, then the software will be able to predict the kind of disease. thank you . please help
CLIPS> (defrule bacterial-fruit-blotch-of-watermelon
=>
(print "Is the plant showing a symptom of Oily and water-soaked cotyledons? ")
(assert (OWS (read)))
(print "Is the plant showing a symptom of Yellow halo paralleling veins? ")
(assert (YHP (read)))
(print "Is the plant showing a symptom of Small dark and angled lesion on leaves? ")
(assert (SDA (read)))
(print "Is the plant showing a symptom of Dark green blotch on the upper surface of developing fruit? ")
(assert (DGB (read))))
CLIPS> (defrule check
(OWS yes)
(YHP yes)
(SDA yes)
(DGB yes)
=>
(println "The plant is showing a symptom of bacterial fruit blotch of watermelon disease."))
CLIPS> (defrule bacterial-rind-necrosis
=>
(print " Is the plant showing a symptom of corky, dry necrosis? ")
(assert (corky (read)))
(print " Is the plant showing a symptom of misshapen? ")
(assert (misshaping (read)))
(print " Is the plant showing a symptom of dark ,water-soaked depression? ")
(assert (dark (read))))
CLIPS> (defrule check-two
(corky yes)
(misshaping yes)
(dark yes)
=>
(println "The plant is showing a symptom of bacterial rind necrosis of watermelon disease."))
CLIPS> (reset)
CLIPS> (run)
Is the plant showing a symptom of Oily and water-soaked cotyledons? no
Is the plant showing a symptom of Yellow halo paralleling veins? n
Is the plant showing a symptom of Small dark and angled lesion on leaves? no
Is the plant showing a symptom of Dark green blotch on the upper surface of developing fruit? no
Is the plant showing a symptom of corky, dry necrosis? yes
Is the plant showing a symptom of misshapen? yes
Is the plant showing a symptom of dark ,water-soaked depression? yes
The plant is showing a symptom of bacterial rind necrosis of watermelon disease.
CLIPS>
If you want to provide flexibility in how your program interacts with the user, the best thing to do is to separate the code that reasons about symptoms and diseases from the code that interacts with the user. In your current implementation, these are intermingled.
To reimplement your code, first define a deftemplate for representing the symptoms and their associated questions:
(deftemplate symptom
(slot id)
(slot question)
(slot indicative (default yes)))
The indicative slot represents the response to a question that is indicative of a problem. So if the question is "Are the leaves a sickly yellow?", the indicative response would be yes, and if the question is "Are the leaves a healthy green?", the indicative response would be no.
The symptoms from your rules can now be represented as a group of facts:
(deffacts symptoms
(symptom (id ows)
(question "Is the plant showing a symptom of Oily and water-soaked cotyledons?"))
(symptom (id yhp)
(question "Is the plant showing a symptom of Yellow halo paralleling veins?"))
(symptom (id sda)
(question "Is the plant showing a symptom of Small dark and angled lesion on leaves?"))
(symptom (id dgb)
(question "Is the plant showing a symptom of Dark green blotch on the upper surface of developing fruit?"))
(symptom (id corky)
(question "Is the plant showing a symptom of corky, dry necrosis?"))
(symptom (id misshaping)
(question "Is the plant showing a symptom of misshapen?"))
(symptom (id dark)
(question "Is the plant showing a symptom of dark, water-soaked depression?"))
)
The diseases can be similarly represented as a group of facts:
(deftemplate disease
(slot id)
(multislot symptoms))
(deffacts diseases
(disease (id "bacterial fruit blotch")
(symptoms ows yhp sda dgb))
(disease (id "bacterial rind necrosis")
(symptoms corky misshaping dark))
)
The responses to questions and any disease conclusions will also be represented as facts:
(deftemplate answer
(slot id)
(slot value))
(deftemplate conclusion
(slot id))
With the symptoms and diseases represented as data, we can now add a generic rule which determines if every symptom of a disease is present:
(defrule conclude-disease
;; There is a disease
(disease (id ?disease))
;; For every symptom of that disease
(forall (disease (id ?disease)
(symptoms $? ?symptom $?))
(symptom (id ?symptom)
(indicative ?value))
;; There is a response indicative
;; of a problem
(answer (id ?symptom)
(value ?value)))
=>
;; Conclude the plant has the disease
(assert (conclusion (id ?disease))))
Now we can add code to handle interacting with the user. We'll start with your initial approach of using the keyboard to get responses from the user:
(deffunction ask-question (?question $?allowed-values)
(printout t ?question " " ?allowed-values " ")
(bind ?answer (read))
(if (lexemep ?answer)
then (bind ?answer (lowcase ?answer)))
(while (not (member$ ?answer ?allowed-values)) do
(printout t ?question " " ?allowed-values " ")
(bind ?answer (read))
(if (lexemep ?answer)
then (bind ?answer (lowcase ?answer))))
?answer)
(defrule ask-symptom
;; There is a symptom
(symptom (id ?symptom)
(question ?question))
;; For a disease
(disease (id ?disease)
(symptoms $? ?symptom $?))
;; That we have not determined
(not (answer (id ?symptom)))
;; And there is no prior response to a symptom
;; of that disease that is non-indicative.
(not (and (disease (id ?disease)
(symptoms $? ?other-symptom $?))
(symptom (id ?other-symptom)
(indicative ?value))
(answer (id ?other-symptom)
(value ~?value))))
=>
;; Ask the user the symptom question
(bind ?value (ask-question ?question yes no))
;; And assert the response.
(assert (answer (id ?symptom)
(value ?value))))
The ask-symptom rule improves upon the prior approach by not asking about symptoms for diseases that have a non-indicative response for a symptom. So if the response to necrosis is no, the user will not be asked about misshapen or depression.
Finally, some rules can be added to display the conclusions. These rules are given lower salience so that all of the questions are asked before any conclusion is displayed.
(defrule print-conclusion
(declare (salience -10))
(conclusion (id ?disease))
=>
(println "The plant is showing symptoms of " ?disease " watermelon disease."))
(defrule print-no-conclusion
(declare (salience -10))
(not (conclusion))
=>
(println "The plant is not showing all symptoms of a watermelon disease."))
If you want to use an interface rather than interacting through a console, you'd need to replace the code just added for asking questions and displaying conclusions.
CLIPS provides for querying the fact-list. For example, here's how you'd get a list of all the symptom facts from the CLIPS command prompt:
CLIPS> (find-all-facts ((?s symptom)) TRUE)
(<Fact-1> <Fact-2> <Fact-3> <Fact-4> <Fact-5> <Fact-6> <Fact-7>)
CLIPS>
What you can do in your interface is to query CLIPS for all of the symptom facts and then dynamically create the check boxes to display using the slot values in the facts.
When the user is ready for a response, you could have a diagnose button in your interface. When the user clicks that button, you can assert an answer fact with the appropriate values for each check box. After asserting those facts, you can run CLIPS and then use the query functions to retrieve the conclusion facts and then display the results. Alternately, any time a checkbox is changed you can assert the facts and run CLIPS.
If you download CLIPS from SourceForge, there are examples of integrating CLIPS with GUIs for .NET, Java, and iOS.
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.
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>
I have a problem.
I need to delete words from the text and to do printout to file result(Text without deleted words).
Here I'm trying to delete words:
(deffunction text ($?c)
(implode$(create$ ?c ))
(delete$ (?c) 1 3)
(printout t (?c) crlf))
And here example to printout it to file, but how to do it with results of previous function?
CLIPS> (open "on.txt" data "w")
TRUE
CLIPS> (printout data 5)
CLIPS> (close data)
TRUE
CLIPS> (open "on.txt" data "r")
TRUE
CLIPS> (read data)
5
CLIPS> (close data)
I will be happy with whatever information.
I am new to JESS and I know a little of its functionality. I have a program that asks for a students id-number and the program goes and gets the student's subjects.
The thing is by the end of procedure the program asks the user if he/she wants to get another student's subjects.
If the user wants to input another student, It will go back to the first rule that fired but when I tried that, the rule only activated and did not fire.
What could be the problem? I made sure there was (run) of course.
Here's my code.
(defrule check-subject
?a <- (phase check-back)
?stud <- (lookupID (id ?id))
(student-information (id-number ?id)
(course ?course)
(subjects-taken $?taken)
(year ?year)
(semester ?sem))
(prospectus-information (curriculum-name ?course)
(1st-year-1st-sem-subjects $?subjects1))
=>
(printout t "Student took: " (intersection$ $?taken $?subjects1) crlf)
(printout t "Student flunked: " (complement$ $?taken $?subjects1) crlf)
(assert (back-subject (complement$ $?taken $?subjects1)))
(retract ?a ?stud)
(ask))
And I have the function ask
(deffunction ask ()
(printout t "Consult another? (y/n) ")
(if (eq (read) y)
then (assert (phase choose-student))))
And my defrule when phase choose-student is asserted
(defrule student-select
(phase choose-student)
=>
(printout t "Input Student ID: ")
(assert (lookupID (id (read)))))
The rule student-select, activates but never fires. My program stops there.
It's better to write the control part of an application separate from the rules.
(deffunction ask ()
(printout t "Consult another? (y/n) ")
(if (eq (read) y) then
(printout t "Input Student ID: ")
(assert (lookupID (id (read))))
(return TRUE)
else
(return FALSE)))
Use this in a while function:
(while (ask) do (run))
And you won't need the (phase choose-student) any more.