FIX UNKNOWN facts keep being asserted implicitly in CLIPS - clips

Fix implicit assert of facts
The deftemplate and defrules
(deftemplate Fuels "Identifying characteristics"
(slot appearance
(type SYMBOL)
(allowed-symbols clear amber brownish-red yellow-tint brown-with-green-tint yellowish-green)
)
(slot smell
(type SYMBOL)
(allowed-symbols strong-odour strong-lingering-odour cooking-oil burnt-popcorn)
)
(slot touch
(type SYMBOL)
(allowed-symbols oily-feel waxy cold slippery)
)
)
(defrule Petrol "Identifying characteristics"
(Fuels (appearance brownish-red|yellow-tint)
(smell strong-odour)
(touch cold)
)
=>
(printout t "It's petrol that is leaking" crlf
"If leak is caused by something other than over filling the tank, do NOT drive the car." crlf
"Fuel leaks are very dangerous and potentially explosive."crlf
"Call a mechanic if you find a fuel leak in your car"crlf
)
)
(defrule Diesel "Identifying characteristics"
(Fuels (appearance brown-with-green-tint|yellowish-green)
(smell strong-lingering-odour)
(touch oily-feel|waxy)
)
=>
(printout t "It's diesel that is leaking" crlf
"If leak is caused by something other than overfilling the tank, do NOT drive the car." crlf
"Fuel leaks are very dangerous and potentially explosive."crlf
"Call a mechanic if you find a fuel leak in your car"crlf
)
)
(defrule Bio-fuel "Identifying characteristics"
(Fuels (appearance clear|amber)
(smell cooking-oil|burnt-popcorn)
(touch slippery)
)
=>
(printout t crlf
"It's bio-fuel that is leaking" crlf
"If leak is caused by something other than overfilling the tank,DO NOT! drive the car." crlf
"Fuel leaks are very dangerous and potentially explosive."crlf
"Call a mechanic if you find a fuel leak in your car."crlf
)
)
When facts command is used this is returned
f-1 (Fuels (appearance brownish-red) (smell strong-odor) (touch oily-feel))
f-2 (Fuels (appearance clear) (smell strong-odor) (touch oily-feel))
f-3 (Fuels (appearance clear) (smell strong-odor) (touch cold))
even though this was asserted :
(Fuels (appearance brownish-red) (smell strong-odour) (touch cold))
Help fix this

There's nothing wrong with this code, but there's also no way that it could produce facts f-2 and f-3 as you've shown in your question.
CLIPS (6.31 6/12/19)
CLIPS>
(deftemplate Fuels "Identifying characteristics"
(slot appearance
(type SYMBOL)
(allowed-symbols clear amber brownish-red yellow-tint brown-with-green-tint yellowish-green)
)
(slot smell
(type SYMBOL)
(allowed-symbols strong-odour strong-lingering-odour cooking-oil burnt-popcorn)
)
(slot touch
(type SYMBOL)
(allowed-symbols oily-feel waxy cold slippery)
)
)
CLIPS>
(defrule Petrol "Identifying characteristics"
(Fuels (appearance brownish-red|yellow-tint)
(smell strong-odour)
(touch cold)
)
=>
(printout t "It's petrol that is leaking" crlf
"If leak is caused by something other than over filling the tank, do NOT drive the car." crlf
"Fuel leaks are very dangerous and potentially explosive."crlf
"Call a mechanic if you find a fuel leak in your car"crlf
)
)
CLIPS>
(defrule Diesel "Identifying characteristics"
(Fuels (appearance brown-with-green-tint|yellowish-green)
(smell strong-lingering-odour)
(touch oily-feel|waxy)
)
=>
(printout t "It's diesel that is leaking" crlf
"If leak is caused by something other than overfilling the tank, do NOT drive the car." crlf
"Fuel leaks are very dangerous and potentially explosive."crlf
"Call a mechanic if you find a fuel leak in your car"crlf
)
)
CLIPS>
(defrule Bio-fuel "Identifying characteristics"
(Fuels (appearance clear|amber)
(smell cooking-oil|burnt-popcorn)
(touch slippery)
)
=>
(printout t crlf
"It's bio-fuel that is leaking" crlf
"If leak is caused by something other than overfilling the tank,DO NOT! drive the car." crlf
"Fuel leaks are very dangerous and potentially explosive."crlf
"Call a mechanic if you find a fuel leak in your car."crlf
)
)
CLIPS> (assert (Fuels (appearance brownish-red) (smell strong-odour) (touch cold)))
<Fact-1>
CLIPS> (agenda)
0 Petrol: f-1
For a total of 1 activation.
CLIPS> (run)
It's petrol that is leaking
If leak is caused by something other than over filling the tank, do NOT drive the car.
Fuel leaks are very dangerous and potentially explosive.
Call a mechanic if you find a fuel leak in your car
CLIPS> (facts)
f-0 (initial-fact)
f-1 (Fuels (appearance brownish-red) (smell strong-odour) (touch cold))
For a total of 2 facts.
CLIPS>

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>

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?

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'm looking on how can i split the facts inserted into a different brackets in CLIPS?

So here's my CLIPS code
CLIPS> (deftemplate animal
(slot name)
(slot favourite-food)
(slot habitat)
(slot main-prey)
(multislot predators)
(slot distinctive-features))
CLIPS> (deffacts animal
(animal (name Sumatran-Elephant)
(favourite-food grass)
(habitat "Rainforest and tropical woodland")
(main-prey "grass, fruit, roots")
(predators Human Tiger)
(distinctive-features "Long trunk and large feet"))
(animal (name Monkey)
(favourite-food fruit)
(habitat "Tropical forests, grasslands and mountainous plains")
(main-prey "Fruit, Seeds, Insects")
(predators Birds Snakes Wildcats)
(distinctive-features "Long, agile tail and loud vocal calls"))
(animal (name Magpie)
(favourite-food fruit)
(habitat "Open woodland, grasslands and savannas")
(main-prey "Fruit, Nuts, Seeds, Insects")
(predators Foxes Cats Coyote)
(distinctive-features "Black and white markings and long wedge-shaped tail")))
CLIPS> (deftemplate find-predators(slot predators))
CLIPS> (defrule find-predators
(find-predators(predators ?predator_name))
(animal(name ?name)
(predators $?other1 ?predator_name $?other2))
=> (printout t ?predator_name " is the predator of " ?name crlf
"Other predators are " ?other1 ?other2 crlf))
CLIPS> (reset)
CLIPS> (assert(find-predators(predators Human)))
<Fact-4>
CLIPS> (run)
Human is the predator of Sumatran-Elephant
Other predators are ()(Tiger)
CLIPS> (assert(find-predators(predators Coyote)))
<Fact-5>
CLIPS> (run)
Coyote is the predator of Magpie
Other predators are (Foxes Cats)()
But the answer should be like this
Coyote is the predator of Magpie
Other predators are (Foxes) (Cats)
How do I split the facts for the multi slots above?
Need helps if anyone know the best default that can be replaced from the above code
Combine the multifield values in the variables $?other and $?other2 into a single multifield value and then use the implode$ function to convert that value into a string with spaces between the predator names.
(defrule find-predators
(find-predators (predators ?predator_name))
(animal (name ?name)
(predators $?other1 ?predator_name $?other2))
=>
(printout t ?predator_name " is the predator of " ?name crlf
"Other predators are " (implode$ (create$ ?other1 ?other2)) crlf))

CLIPS/clipspy Rule Order

So I'm trying to self-learn CLIPS and clipspy for a class assignment and I'm a bit stuck. The code below compiles and runs just fine but the output is a bit strange. I am trying to expand on examples I found in the manual.
import clips
import logging
env = clips.Environment()
logging.basicConfig(level=10, format='%(message)s')
router = clips.LoggingRouter()
router.add_to_environment(env)
env.build("""
(defrule whodunit
(shoot ?hunter ?who)
=>
(printout t ?hunter " shot " ?who crlf)
)""")
env.build("""
(defrule animalGame
(animal ?ani)
(shoot $? ?ani)
=>
(assert (game ?ani))
)""")
env.build("""
(defrule gameAnimal
(game ?ani)
=>
(assert (animal ?ani))
)""")
env.build("""
(defrule isIllegal
(shoot ?a ?b)
(not(game ?b))
=>
(assert (criminal ?a))
)""")
env.assert_string("(animal duck)")
env.assert_string("(animal dog)")
env.assert_string("(shoot Brian duck)")
env.assert_string("(shoot Bob rhino)")
env.assert_string("(game deer)")
env.run()
for fact in env.facts():
print(fact)
This outputs:
(initial-fact)
(animal duck)
(animal dog)
(shoot Brian duck)
(shoot Bob rhino)
(game deer)
(animal deer)
(criminal Bob)
(criminal Brian)
(game duck)
It seems that Brian is labeled a criminal for shooting an animal that is not game despite the animal he is shooting being declared game in the next step. Is there anyway to re-evaluate rules to fix this contradiction?
I figured it out. The answer is salience. I also realized there's some logical flaws/inconsistencies declaring all animals hunted as game and charging shooting animals that are not game as criminal. Anyways:
env.build("""
(defrule animalGame
(declare (salience 100))
(animal ?ani)
(shoot $? ?ani)
=>
(assert (game ?ani))
)""")

How to make CLIPS program work?

I am new to CLIPS and I thought of looking over existing solved problems for a start and try to figure it backwards. There is the following problem found in Giarratano-Riley: Expert Systems and Programming 3rd edition and it states the following:
Fires are classified according to the principal burning material.
Translate the following information to rules for determining fire
class.
Type A fires involve ordinary combustibles such as paper, wood, and cloth.
Type B fires involve flammable and combustible liquids (such as
oil and gas), greases, and similar materials.
Type C fires involve energized electrical equipment.
Type D fires involve combustible metals such as magnesium, sodium, and potassium.
The type of extinguisher that should be used on a fire depends on the fire class.
Translate the following information to rules.
Class A fires should be extinguished with heat-absorbing or
combustion-retarding extinguishers such as water or water-based
liquids and dry chemicals.
Class B fires should be extinguisher by mexcluding air, inhibiting the release of
combustible vapors, or interrupting the combustion chain reaction. Extinguishers
include dry chemicals, carbon dioxide, foam, and bromotrifluoromethane.
Class C fires should be extinguished with a non conducting agent to prevent
short circuits. If possible the power should be cut. Extinguishers
include dry chemicals, carbon dioxide, and bromotrifluoromethane.
Class D fires should be extinguished with smothering and heat- absorbing chemicals > that do not react with the burning metals. Such chemicals include trimethoxyboroxine
and screened graphitized coke.
Describe the facts used in the rules. The input to the program should be made by asserting the type of burning material as a fact. The output should indicate which extinguishers may be used and other actions that should be taken, such as cutting off the power. Show that your program works for one material form each of the fire classes.
And then it is solved by Berkely and the code is the following. My question is, how do I call these rules and make the program work? I loaded the buffer, reset, run and it only loads the rules into the command-line.
; Define templates used in rules
(deftemplate fire (slot burning-material))
(deftemplate extinguisher-system (multislot function) (multislot extinguisher))
(deftemplate response (multislot actions))
(deftemplate fire-class (slot class))
; Define rules for determining fire classes
(defrule class-A-fire
(fire (burning-material paper | wood | cloth | other-ordinary-combustibles)) =>
(assert (fire-class (class A))))
(defrule class-B-fire
(fire (burning-material oil | gas | greases | other-flammable-combustible-liquids)) =>
(assert (fire-class (class B))))
(defrule class-C-fire
(fire (burning-material energized-electrical-equipment)) =>
(assert (fire-class (class C))))
(defrule class-D-fire
(fire (burning-material magnesium | sodium | potassium | other-combustible-metals)) =>
(assert (fire-class (class D))))
; Define rules for determining the type of extinguisher that should be used on a fire
(defrule class-A-emergency
(fire-class (class A))
=>
(assert (response (actions activate-extinguisher-A)))
(assert (extinguisher-system (function heat-absorbing combustion-retarding) (extinguisher water water-based-liquids dry-chemicals))))
(defrule class-B-emergency
(fire-class (class B))
=>
(assert (response (actions activate-extinguisher-B)))
(assert (extinguisher-system (function excluding-air inhibiting-release-of-combustible-vapors interrupting-combustion-chain-reaction) (extinguisher dry-chemicals carbon-dioxide foam bromotrifluoromethane))))
(defrule class-C-emergency
(fire-class (class C))
=>
(assert (response (actions activate-extinguisher-C power-cut)))
(assert (extinguisher-system (function nonconducting-agent) (extinguisher dry-chemicals carbon-dioxide bromotrifluoromethoane))))
(defrule class-D-emergency
(fire-class (class D))
=>
(assert (response (actions activate-extinguisher-D)))
(assert (extinguisher-system (function smothering-heatabsorbing-chemicals) (extinguisher trimethoxyboroxine screened-graphitized-coke))))
I guess you made it until here:
CLIPS> Loading Selection...
Defining deftemplate: fire
Defining deftemplate: extinguisher-system
Defining deftemplate: response
Defining deftemplate: fire-class
Defining defrule: class-A-fire +j+j
Defining defrule: class-B-fire +j+j
Defining defrule: class-C-fire +j+j
Defining defrule: class-D-fire +j+j
Defining defrule: class-A-emergency +j+j
Defining defrule: class-B-emergency +j+j
Defining defrule: class-C-emergency +j+j
Defining defrule: class-D-emergency +j+j
CLIPS> (reset)
Now you need to load the problem data. For example, for a wood fire:
CLIPS> (assert (fire (burning-material wood)))
<Fact-1>
CLIPS> (facts)
f-0 (initial-fact)
f-1 (fire (burning-material wood))
And the, run the rules engine
CLIPS> (run)
CLIPS> (facts)
f-0 (initial-fact)
f-1 (fire (burning-material wood))
f-2 (fire-class (class A))
f-3 (response (actions activate-extinguisher-A))
f-4 (extinguisher-system (function heat-absorbing combustion-retarding) (extinguisher water water-based-liquids dry-chemicals))
And clean it to check the next problem
CLIPS> (reset)
CLIPS> (assert (fire (burning-material gas)))
<Fact-1>
CLIPS> (run)
...

Resources