I am new to clips, I found that my retract not really delete the facts.
(defrule test
(select ?select~indoor&~outdoor)
=>
(retract ?select)
)
After the clips run this code, I try to check by using (facts),but I still found that the facts select is still there
You need to bind a variable to the fact matching the pattern. You can't retract the fact by binding a variable to a value inside the fact.
CLIPS (6.31 2/3/18)
CLIPS>
(defrule test
?f <- (select ...)
=>
(retract ?f))
CLIPS> (assert (select ...))
<Fact-1>
CLIPS> (facts)
f-0 (initial-fact)
f-1 (select ...)
For a total of 2 facts.
CLIPS> (run)
CLIPS> (facts)
f-0 (initial-fact)
For a total of 1 fact.
CLIPS>
Related
I originally attempted using the modify function but it doesn't do anything and just prints false, I don't know what I am doing wrong.
I used
(modify ?tv (v ?x))
it didn't work.
I then used
(retract ?tv)
(assert (v ?x))
instead, which worked.
But I don't want to type that out every time I want to modify a fact, so I made a deffunction to do it for me, but
(deffunction modfact(?index ?factname ?factvalue)
(retract ?index)
(assert (?factname ?factvalue))
)
in this it gives a syntax error of:
[PRNTUTIL2] Syntax Error: Check appropriate syntax for first field of a RHS pattern.
ERROR:
(deffunction MAIN::modfact
(?index ?factname ?factvalue)
(retract ?index)
(assert (?factname
Which seems to me that its saying that I can't actually make this function because I can't assert a fact with the value of the variable. How can I get this to work?
Modify only works with facts that have an associated deftemplate defined with slots:
CLIPS>
(deftemplate task
(slot id)
(slot completed))
CLIPS> (watch facts)
CLIPS> (assert (task (id x) (completed no)))
==> f-1 (task (id x) (completed no))
<Fact-1>
CLIPS>
(defrule modit
?f <- (task (completed ~yes))
=>
(modify ?f (completed yes)))
CLIPS> (run)
<== f-1 (task (id x) (completed no))
==> f-2 (task (id x) (completed yes))
CLIPS>
When using the assert command, the first field of the fact must be a symbol. If you must get around this restriction you can use the str-assert function.
CLIPS>
(deffunction modfact (?index ?factname ?factvalue)
(retract ?index)
(str-assert (str-cat "(" ?factname " " ?factvalue ")")))
CLIPS> (assert (v 3))
==> f-3 (v 3)
<Fact-3>
CLIPS> (modfact 3 v 4)
<== f-3 (v 3)
==> f-4 (v 4)
<Fact-4>
CLIPS>
Is it possible to cause CLIPS to re-evaluate the value of a global variable in a defrule? I have this:
(defrule encourage "Do we have a GPA higher than 3.7?"
(test (> (gpa) 3.7))
=>
(printout t "Keep up the excellent work!" crlf))
gpa is function that calculates and returns a number based on two global variables (grade points and number of credits). I read somewhere that changes to global variables do not invoke pattern matching. How do I go about forcing this? I want to print that string every time I do (run) as long as the GPA is higher than 3.7.
Don't attempt to use global variables or function calls in this manner. First, global variables are specifically designed to not trigger pattern matching. Second, it would take a bit of magic for CLIPS to know when a function call needs to be reevaluated as there are any number of changes which could cause a function to return a different value, not just changes to globals. If you want a particular piece of information to trigger pattern matching, then stick it in a fact or instance. It will make your code easier to understand if you parameterize the function calls and bind the values to be used as arguments in the conditions of the rule.
CLIPS> (clear)
CLIPS>
(deffunction gpa (?grade-points ?number-of-credits)
(/ ?grade-points ?number-of-credits))
CLIPS>
(defrule encourage "Do we have a GPA higher than 3.7?"
(grade-points ?gp)
(number-of-credits ?noc)
(test (> (gpa ?gp ?noc) 3.7))
=>
(printout t "Keep up the excellent work!" crlf))
CLIPS> (assert (grade-points 35) (number-of-credits 10))
<Fact-2>
CLIPS> (agenda)
CLIPS> (facts)
f-0 (initial-fact)
f-1 (grade-points 35)
f-2 (number-of-credits 10)
For a total of 3 facts.
CLIPS> (retract 1)
CLIPS> (assert (grade-points 38))
<Fact-3>
CLIPS> (agenda)
0 encourage: f-3,f-2
For a total of 1 activation.
CLIPS>
Alternately, you can use the fact query functions to iterate over a group of facts to dynamically compute the gpa based on facts rather than globals. Each time you modify one of these facts (add or remove), you can also assert a fact indicating the gpa needs to be rechecked to trigger the encourage rule.
CLIPS> (clear)
CLIPS>
(deftemplate grade
(slot class)
(slot grade-points)
(slot credits))
CLIPS>
(deffunction gpa ()
(bind ?grade-points 0)
(bind ?credits 0)
(do-for-all-facts ((?g grade)) TRUE
(bind ?grade-points (+ ?grade-points ?g:grade-points))
(bind ?credits (+ ?credits ?g:credits)))
(if (= ?credits 0)
then 0
else (/ ?grade-points ?credits)))
CLIPS>
(defrule encourage
?f <- (check-gpa)
=>
(retract ?f)
(if (> (gpa) 3.7)
then
(printout t "Keep up the excellent work!" crlf)))
CLIPS> (gpa)
0
CLIPS> (assert (check-gpa))
<Fact-1>
CLIPS> (run)
CLIPS> (assert (grade (class Algebra) (grade-points 12) (credits 3)))
<Fact-2>
CLIPS> (gpa)
4.0
CLIPS> (assert (check-gpa))
<Fact-3>
CLIPS> (run)
Keep up the excellent work!
CLIPS> (assert (grade (class History) (grade-points 6) (credits 2)))
<Fact-4>
CLIPS> (gpa)
3.6
CLIPS> (assert (check-gpa))
<Fact-5>
CLIPS> (run)
CLIPS> (assert (grade (class Science) (grade-points 12) (credits 3)))
<Fact-6>
CLIPS> (gpa)
3.75
CLIPS> (assert (check-gpa))
<Fact-7>
CLIPS> (run)
Keep up the excellent work!
CLIPS>
i am writing an expert system on cheese.
when reset all the facts about various cheese is loaded into the system and by asking question such as texture smell etc this will retract certain facts from the system.
My Question how do you keep track of the amount of rules in the system. I created a count but i was wondering if there was a way to see the amount of facts currently in the system when running a rule.
Any help would be appriciated
You can make a call to get-defrule-list or get-fact-list to determine the number of rules/facts present in the system:
CLIPS> (assert (a) (b) (c) (d))
<Fact-4>
CLIPS> (defrule x =>)
CLIPS> (defrule y =>)
CLIPS> (defrule z =>)
CLIPS> (length$ (get-defrule-list *))
3
CLIPS> (length$ (get-fact-list *))
5
CLIPS> (facts)
f-0 (initial-fact)
f-1 (a)
f-2 (b)
f-3 (c)
f-4 (d)
For a total of 5 facts.
CLIPS> (rules)
x
y
z
For a total of 3 defrules.
CLIPS>
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>
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>