Using less than on CLIPS program - clips

I am trying to return a message if the user types in a value within certain range. Is this possible on CLIPS? In addition the system should only accept values in increments of 10.
If the user types in a number less or equal to 10 it should say "A"
If the user types in a number greater than 10 and less than 40 it should say "B"
- so it should only accept values 10,20,30,40
This is the code I have so far:
(defrule b-a1
(b-a "a")
=>
(bind ?reply (get-text-from-user "How many points did you achieve?"))
(assert (b-a1 ?reply )))
(defrule b-a2
(b-a1 <= 10)
=>
(assert (conclusion "A")))
(defrule b-a2
(10 < b-a1 < 40)
=>
(assert (conclusion "B")))
Any ideas on how I can get this working?

CLIPS>
(defrule b-a1
(b-a "a")
=>
(printout t "How many points did you achieve? ")
(bind ?reply (read))
(assert (b-a1 ?reply )))
CLIPS>
(defrule b-a2
(b-a1 ?v&:(<= ?v 10))
=>
(assert (conclusion "A")))
CLIPS>
(defrule b-a2
(b-a1 ?v&:(< 10 ?v)&:(< ?v 40))
=>
(assert (conclusion "B")))
CLIPS> (assert (b-a "a"))
<Fact-1>
CLIPS> (run)
How many points did you achieve? 24
CLIPS> (facts)
f-0 (initial-fact)
f-1 (b-a "a")
f-2 (b-a1 24)
f-3 (conclusion "B")
For a total of 4 facts.
CLIPS>

Related

Preventing CLIPS Rule from firing twice

How could I prevent the following rule from firing twice, without retracting the initial facts?
CLIPS>
(defrule cf_calculation
(CF ?cf1)
(CF ?cf2&~?cf1)
=>
(bind ?fCF (+ ?cf1 ?cf2))
(printout t "the final CF is " ?fCF crlf))
CLIPS> (assert (CF 10))
<Fact-1>
CLIPS> (assert (CF 5))
<Fact-2>
CLIPS> (run)
the final CF is 15
the final CF is 15
CLIPS>
Instead of checking for inequality of the two values, check that the first is greater than the second:
CLIPS>
(defrule cf_calculation
(CF ?cf1)
(CF ?cf2&:(> ?cf1 ?cf2))
=>
(bind ?fCF (+ ?cf1 ?cf2))
(printout t "the final CF is " ?fCF crlf))
CLIPS> (assert (CF 10))
<Fact-1>
CLIPS> (assert (CF 5))
<Fact-2>
CLIPS> (run)
the final CF is 15
CLIPS>

Incrementing a global variable within a user answered defrule

I'm trying to increment a defglobal variable (symcount) by 1 if the user defines that they have pain by using the (read) function
(defrule QPain
(initial-fact)
=>
(printout t "Are You In Pain? " crlf)
(bind (ans Answer) (read))
)
(defrule AnsInc
(Answ Answer = "y")
=>
(bind ?*symcount* (+ ?*symcount* 1)))
the increment must only happen of the user presses "y"
otherwise the increment must not happen.
CLIPS> (defglobal ?*symcount* = 0)
CLIPS>
(defrule QPain
=>
(printout t "Are You In Pain? ")
(bind ?answer (read))
(if (eq ?answer y)
then
(bind ?*symcount* (+ ?*symcount* 1))))
CLIPS> (reset)
CLIPS> (run)
Are You In Pain? y
CLIPS> ?*symcount*
1
CLIPS> (reset)
CLIPS> (run)
Are You In Pain? n
CLIPS> ?*symcount*
0
CLIPS>

How to compare a global variable to a string in Clips?

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>

Obtain ID of fact I just asserted

Is there a way for me to get the fact ID of a fact that I just asserted in the RHS of a rule? Something along the lines of
?f <- (assert (new-fact))
CLIPS>
(defrule example
=>
(bind ?f (assert (new-fact)))
(bind ?i (fact-index ?f))
(printout t "The fact index is " ?i crlf))
CLIPS> (reset)
CLIPS> (run)
The fact index is 1
CLIPS> (facts)
f-0 (initial-fact)
f-1 (new-fact)
For a total of 2 facts.
CLIPS>

clips simple rule

does anybody have any idea why this:
(defrule initx
(declare(salience 90))
=>
(assert (blabla 10))
)
(defrule gigel
(declare(salience 89))
=>
(printout t "test" crlf)
)
is not working?
When I delete first rule it works.
Thank you.
What's the behavior that you're seeing? The behavior of the gigel rule is the same regardless of whether the initx rule is present or not.
CLIPS>
(defrule initx
(declare(salience 90))
=>
(assert (blabla 10)))
CLIPS>
(defrule gigel
(declare(salience 89))
=>
(printout t "test" crlf))
CLIPS> (reset)
CLIPS> (run)
test
CLIPS> (facts)
f-0 (initial-fact)
f-1 (blabla 10)
For a total of 2 facts.
CLIPS> (clear)
CLIPS>
(defrule gigel
(declare(salience 89))
=>
(printout t "test" crlf))
CLIPS> (reset)
CLIPS> (run)
test
CLIPS> (facts)
f-0 (initial-fact)
For a total of 1 fact.
CLIPS>

Resources