Why isn't variable x referenced well? - clips

In the following jess / clips code, variable x is not well referenced. Why?
(assert (item 2))
(assert (item 12))
(defrule ex1not
(not (item ?x))
(item ?y & (> ?x 10)) <- HERE I GET "No such variable x"
=>
)

The first pattern matches in the absence of a fact (item ?x), for any value of ?x; it is true when there are no (item) facts at all. The second pattern would then try to compare that ?x to 10. If we were somehow at the second pattern, then since ?x didn't match anything, it has no value, so you can't compare it to anything.
If you edit your question to add what you're actually trying to express, in English, I can edit my answer to show you how.

Related

I need help comparing numbers in defrule with multislot objects in CLIPS

I have the following code
(deftemplate choice-evaluation
(slot x_front)
(slot y_left)
(deftemplate es_result
(slot classp)
(slot classr)
(slot nr) )
(defrule MAIN::one
(x_front ?val)
(bind ?temp 1)
(choice-evaluation(y_left -1) (test (<= ?val ?temp ))(class ?x))
?c<-(choice-evaluation(y_left -1) (test(<= ?val ?temp ))(class ?x))
=>
(assert (es_result (classp 0) (classr ?x) (nr 1)))
(retract ?c))
and I get the error : ERROR:
(defrule MAIN::one
(x_front ?val)
(choice-evaluation (y_left -1) (test
I have tried a lot of things but I will always either get the error above or syntax error for defrules . I do not understand how I can have a comparison in defrules with multislot objects.
I tried creating a rule like the examples here :https://www.csie.ntu.edu.tw/~sylee/courses/clips/advpattern.htm and they do work but it doesnt work for my particular case.
There are several errors in your code which are easier to see if you ident the code:
(defrule MAIN::one
(x_front ?val)
(bind ?temp 1)
(choice-evaluation (y_left -1)
(test (<= ?val ?temp))
(class ?x))
?c <- (choice-evaluation (y_left -1)
(test (<= ?val ?temp))
(class ?x))
=>
(assert (es_result (classp 0) (classr ?x) (nr 1)))
(retract ?c))
You've placed test conditional elements inside choice-evaluation conditional elements so the parser treats the test symbols as slot names and since the choice-evaluation deftemplate has no slot named test you get an error. You'll also get an error for using class as a slot name since this slot is also not defined in the choice-evaluation deftemplate.
Also, (bind ?temp 1) will be treated as a fact pattern, not a function call. If you want to retrieve a value in the conditions of a rule, assert a fact containing that value and assign it to a variable using a pattern like the x_front pattern in your rule. Duplication of the choice-evaluation pattern serves no purpose--Just keep the 2nd one since it binds ?c to the fact-address matching the pattern which is need by the retract command in the actions of the rule.
#Gary Riley thanks for your input it helped a lot!
(choice-evaluation (x_front ?val) (y_left -1) (class ?x))
(test (<= ?val 1 ))
?c <- (choice-evaluation (x_front ?val) (y_left -1) (class ?x))
=>
(assert (es_result (classp 0) (classr ?x) (nr 1)))
(retract ?c))
So turns out this is how it is supposed to be used. Leaving it here in case someone else in the future has a similar problem
credits : I. Xatziligeroudis

Avoid pattern matching (errors) until a slot is set correctly

The LHS of a rule R_blup contains
(test (>= ?s2 2))
that is, it checks if ?s2 is greater or equal to 2. ?s2 corresponds to an instance slot named s2.
Unfortunately, I get the error
Function >= expected argument #1 to be of type integer or float
The problem is that my code executes the (test ... before I can set argument #1, i.e. before I can set s2 to an integer or float value. s2 is supposed to be set to an integer inside a python-call that is triggered by another rule R_blah.
The error is triggered in the middle of another python-call belonging to another rule R_xyz. This python-call modifies an instance via clips_instance.Slots["slot_name"] = some_value.
How is this normally handled? I see three solutions I don't like too much:
Setting a default (integer) value for s2.
Modifying the (test ... to check against nil first.
Adding another check/rule to wait until s2 is not nil any more
Is it maybe possible to try/except/pass the error?
Use the function object-pattern-match-delay to delay pattern matching to create an atomic operation for a series of changes:
CLIPS> (defclass POINT (is-a USER) (slot x) (slot y))
CLIPS>
(defrule check
(object (is-a POINT) (x ?s2))
(test (>= ?s2 2))
=>)
CLIPS> (make-instance [p1] of POINT)
[ARGACCES5] Function >= expected argument #1 to be of type integer or float
[DRIVE1] This error occurred in the join network
Problem resides in associated join
Of pattern #1 in rule check
[p1]
CLIPS> (agenda)
CLIPS>
(object-pattern-match-delay
(make-instance [p2] of POINT)
(make-instance [p3] of POINT)
(send [p2] put-x 3)
(send [p3] put-x 0))
0
CLIPS> (agenda)
0 check: [p2]
For a total of 1 activation.
CLIPS>

CLIPS deftemplate incorrect slot type

I am very puzzled by CLIPS. I have defined in a .clp file a deftemplate and a rule.
(deftemplate basic-ch "Basic characteristics template"
(slot ch-name
(type SYMBOL)
(default ?DERIVE)
)
(slot score
(type INTEGER)
(default 1)
(range 1 5)
)
)
(defrule make-ch
?get-ch <- (get-ch TRUE)
=>
(printout t "Enter ch name" crlf)
(bind ?name (read))
(printout t "Enter ch score" crlf)
(bind ?score (read))
(assert (basic-ch (ch-name ?name) (score ?score)))
(retract ?get-ch)
)
When i (assert (get-ch TRUE)) and (run), it prompts me for the ch name and score. However, if I enter a string for the score, the string score gets asserted by the rule! For example:
Enter ch name
hello
Enter ch score
hello
;(basic-ch (ch-name hello)(score hello)) get asserted?!
How is this possible? I have defined the score to be INTEGER and even provided the range. How can I stop this?
From Section 11, Constraint Attributes, of the Basic Programming Guide:
Two types of constraint checking are supported: static and dynamic.
When static constraint checking is enabled, constraint violations are
checked when function calls and constructs are parsed. This includes
constraint checking between patterns on the LHS of a rule when
variables are used in more than one slot. When dynamic constraint
checking is enabled, newly created data objects (such as deftemplate
facts and instances) have their slot values checked for constraint
violations. Essentially, static constraint checking occurs when a
CLIPS program is loaded and dynamic constraint checking occurs when a
CLIPS program is running. By default, static constraint checking is
enabled and dynamic constraint checking is disabled. The default
behavior can be changed by using the set-static-constraint-checking
and set-dynamic-constraint-checking functions.
If you enable dynamic constraint checking, you'll get an error when you run your program:
CLIPS> (set-dynamic-constraint-checking TRUE)
TRUE
CLIPS> (assert (get-ch TRUE))
<Fact-1>
CLIPS> (run)
Enter ch name
hello
Enter ch score
hello
[CSTRNCHK1] Slot value hello found in fact f-2
does not match the allowed types for slot score.
[PRCCODE4] Execution halted during the actions of defrule make-ch.
CLIPS>
Because it generates an error, dynamic constraint checking is useful for testing, but not for validating user input while a program is executing. If you want to validate use input, define some utility methods:
CLIPS>
(defmethod get-integer ((?query STRING))
(bind ?value FALSE)
(while (not (integerp ?value))
(printout t ?query " ")
(bind ?value (read)))
?value)
CLIPS>
(defmethod get-integer ((?query STRING) (?lower INTEGER) (?upper INTEGER))
(bind ?value FALSE)
(while (or (not (integerp ?value)) (< ?value ?lower) (> ?value ?upper))
(printout t ?query " (" ?lower " - " ?upper ") ")
(bind ?value (read)))
?value)
CLIPS> (get-integer "Pick an integer:")
Pick an integer: hello
Pick an integer: 3
3
CLIPS> (get-integer "Pick an integer" 1 5)
Pick an integer (1 - 5) -1
Pick an integer (1 - 5) hello
Pick an integer (1 - 5) 8
Pick an integer (1 - 5) 4
4
CLIPS>

return two values in clips function

I am writing a project in clips where I have some coordinated entities (squares of a board game). I define their templates like this:
(deftemplate square
(slot x (type INTEGER))
(slot y (type INTEGER))
)
So I want a function that can get a direction argument like right, left, up, down and the ?x, ?y coords and return the coords of the square lying in that direction (bordering the current one).
The problem is that functions can return a single value while I need both x, y.
I have tried
(return ?x ?y)
and
(return (?x ?y))
but they both give syntax errors.
is there a way to achieve that or I need to workaround it?
Thank you for your time.
Use create$ to place multiple values within a multifield value. You can then use nth$ to retrieve individual values:
CLIPS>
(deffunction direction ()
(return (create$ 1 -1)))
CLIPS> (direction)
(1 -1)
CLIPS> (nth$ 1 (direction))
1
CLIPS> (nth$ 2 (direction))
-1
CLIPS>

How can I run the clips with out reset the fact when using CLIPS

Here is my situation:
I want to run the CLIPS periodically and the system can record how many times it runs.
for example: I type in the terminal "run" many times to call the system periodically. then the system can record how many the system runs and show it on the screen. Here is my .clp file
(defglobal ?*lock* = 0)
(deftemplate counter
(slot number))
(deffacts initial_data
(counter (number 0))
)
(defrule set_counter
?f<-(counter (number ?x))
(test (= ?*lock* 0))
=>
(bind ?*lock* 1)
(printout t "plus 1" crlf)
(modify ?f (number (+ ?x 1)))
)
(defrule show_result
?f<-(counter (number ?x))
(test (= ?*lock* 1))
=>
(printout t "the counter value has been changed:" crlf)
(ppfact (fact-index ?f) t)
(bind ?*lock* 0)
)
I use a global value as a lock to control the rules and store the running times in the fact named counter. Now is my problem: Once the system finishes running for the first time. There are no rules in the agenda any more. I want the system can run again with out resetting the facts and the system can process the facts saved form the first running process. How can I refresh the agenda or rematch the rule without reset the facts?
I have find some commands like (refresh rule-name) and (refresh-agenda) but they can not solve my problem. I just type in "(refresh set_counter)" and "(refresh-agenda)" after "(run)". However, no rules are added into agenda.
I don't know if there are solution to my problem or clips can not work like this?
Another question is I try (refresh rule-name) with
(defglobal ?*lock* = 0)
(deftemplate counter
(slot number))
(deftemplate set
(slot number))
(deffacts initial_data
(counter (number 0))
)
(defrule set_counter
(initial-fact)
=>
(bind ?*lock* (+ ?*lock* 1))
(printout t ?*lock* crlf)
)
It works fine. I don't know why it doesn't work in the first example?
really thanks for any advice.
Global variables don't trigger pattern matching so you shouldn't use them in the condition of a rule unless the value is never changed. If you use a fact to represent the lock, the rules will execute for as many cycles as you specify:
(deftemplate lock
(slot value))
(deftemplate counter
(slot number))
(deffacts initial_data
(counter (number 0))
(lock (value 0))
)
(defrule set_counter
?f <- (counter (number ?x))
?l <- (lock (value 0))
=>
(modify ?l (value 1))
(printout t "plus 1" crlf)
(modify ?f (number (+ ?x 1)))
)
(defrule show_result
?f <- (counter (number ?x))
?l <- (lock (value 1))
=>
(printout t "the counter value has been changed:" crlf)
(ppfact (fact-index ?f) t)
(modify ?l (value 0))
)

Resources