I'm working with CLIPS and I'm getting in trouble when trying to add instances in an empty list. I'm using the insert$ function but does not seem to work properly. The concrete code is this:
(loop-for-count (?i 1 (length$ ?listaConvocatoriasAlumno))
(if (neq (nth$ ?i ?listaConvocatoriasAlumno) ?convocatoria)
then
(if (eq (str-compare (send (instance-address * (nth$ ?i ?listaConvocatoriasAlumno)) get-cuadrimestre) ?cuadrimestre) 0)
then
(insert$ ?listaConvocatoriasMismoCuadrimestre (+ (length$ ?listaConvocatoriasMismoCuadrimestre) 1) (nth$ ?i ?listaConvocatoriasAlumno))
)
)
)
?listaConvocatoriasAlumno contains multiples instances of a certain class and I would like to add some of these into another list (?listaConvocatoriasMismoCuadrimestre in this case) which at the beginning of the loop is empty.
Any idea?
Thank you very much in advance!
Just forgot to store the insert return value into the list variable... I'm getting old
Related
I need help to write two rules, that add and remove values from queue. Rule that removes value from queue must use forall structure.
As far as I know, CLIPS does not have arrays, stack, lists or any other type of collections. So I have started with defining template queue with a slot item, that should represent value of a queue, but have not succeeded with the rules. Does anyone have any idea how this can be done?
CLIPS has multifield objects which act as lists.
You can define your queue as a global variable and modify it in your rules as for this example (LIFO queue).
CLIPS> (defglobal ?*queue* = (create$))
; add "foo" to the queue
CLIPS> (bind ?*queue* (insert$ ?*queue* 1 "foo"))
("foo")
; add "bar" to the queue
CLIPS> (bind ?*queue* (insert$ ?*queue* 1 "bar"))
("bar" "foo")
; remove first element from the queue
(bind ?*queue* (delete$ ?*queue* 1 1))
("foo")
I read in this SO answer that
When an instance is created or deleted, all patterns applicable to
that object are updated. However, when a slot is changed, only those
patterns that explicitly match on that slot are affected.
Now I have the following problem:
I have a multislot that receives more and more items over time.
I have a rule R1 that fires if "some_value" is contained in the multislot. When I add "some_value" to the multislot everything works as expected. However, if I add another item, say "another_value" to the multislot, R1 fires again. This is consistent to what I cited above, but it is not what I want. I want R1 to fire only once if "some_value" is contained in the multislot, and I don't want R1 to fire again if another value is added to the multislot.
How can I do that?
I could use many slots instead of a multislot, but this would not work in case I don't know the number of possible values.
If you can't assign the values to different slots--which is how you'd normally handle firing rules on selected changes--then you need to track which changes have been processed. Tracking either the rules or values that have been processed would be the most straightforward way to do this. If each rule processes just one value, then tracking the rules would be better so that you could have multiple rules triggered for the same value change. Here's an example where rules R1 and R2 are restricted to a single change and rule R3 exhibits the behavior you're currently experiencing:
CLIPS> (clear)
CLIPS>
(defclass XAMPL
(is-a USER)
(multislot properties)
(multislot processed))
CLIPS>
(definstances initial
([x1] of XAMPL))
CLIPS>
(defrule add_some_value
(declare (salience -1))
?o <- (object (name [x1])
(properties $?p&:(not (member$ some_value ?p))))
=>
(modify-instance ?o (properties some_value ?p)))
CLIPS>
(defrule add_another_value
(declare (salience -2))
?o <- (object (name [x1])
(properties $?p&:(not (member$ another_value ?p))))
=>
(modify-instance ?o (properties another_value ?p)))
CLIPS>
(defrule R1
?o <- (object (name [x1])
(properties $?properties&:(member$ some_value ?properties))
(processed $?processed&:(not (member$ R1 ?processed))))
=>
(modify-instance ?o (processed ?processed R1))
(printout t "Rule R1 fires" crlf))
CLIPS>
(defrule R2
?o <- (object (name [x1])
(properties $?properties&:(member$ some_value ?properties))
(processed $?processed&:(not (member$ some_value ?processed))))
=>
(modify-instance ?o (processed ?processed some_value))
(printout t "Rule R2 fires" crlf))
CLIPS>
(defrule R3
(object (name [x1])
(properties $?properties&:(member$ some_value ?properties)))
=>
(printout t "Rule R3 fires" crlf))
CLIPS> (reset)
CLIPS> (run)
Rule R2 fires
Rule R1 fires
Rule R3 fires
Rule R3 fires
CLIPS>
(deffunction up ()
?fact <- u
(retract ?fact)
(assert (u green))
)
I'm trying to get something like this to work, a function to alter the states of facts, but with this it gives me an error of like ?fact is not defined. But I have done this in a defrule. Why is this not working?
Functions receive input through their parameters. Rules receive input through their patterns. If you want to pattern match, use a rule:
(defrule up
?fact <- (u)
=>
(retract ?fact)
(assert (u green)))
Alternately if you need to iterate over the existing set of facts for a deftemplate, you can use the fact set query functions (do-for-fact, do-for-all-facts, ...):
(deffunction up ()
(do-for-fact ((?fact u)) TRUE
(retract ?fact))
(assert (u green)))
I have the following deftemplates in CLIPS (6.3):
(deftemplate A ( slot a ) (slot b) )
(deftemplate forSearch (slot property)(slot value))
I need to read the pair (property, value) from input, and then find the fact A whose value in the slot property is value.
If I do something like this:
(defrule r2
(forSearch (property ?c)(value ?d))
(A (?c ?d))
=>
(printout t "debug" crlf)
)
I get the following error:
[PRNTUTIL2] Syntax Error: Check appropriate syntax for deftemplate patterns.
ERROR:
(defrule MAIN::r2
(forSearch (property ?c) (value ?d))
(A (?c
What should I do now?
You have to write to slot name in the pattern matching part of the rule.
The correct sintax is:
(defrule r2
(forSearch (property ?c)(value ?d))
(A (a ?c) (b ?d))
=>
(printout t "debug" crlf)
)
I don't understand what you want to accomplish, and I know it's late, but hope it helps.
I have two stacks, a goal and a stack I'm altering. As I accomplish each step of the goal-stack, I remove a field from it. I know I've finished a particular goal when that stack is now empty. I'm trying to write a rule to test when the variable is empty, but I keep getting an error: [EXPRNPSR1] A function name must be a symbol. Here is my rule.
(defrule done
(declare (salience 30))
?stack <- (curr-stack $?thusfar)
?goal <- (goal-stack ?H)
(test (= ?H ()))
=>
(retract ?stack ?goal))
Any help is appreciated! Thanks!
$?foo is a multi-field variable (0 or more things in it).
?foo is a single field variable (1 thing only).
So, testing ?foo for "emptiness" won't do you much good as far as you've indicated for your stacks.
Does my multi-field variable have at least one thing in it?
(test (> (length $?foo) 0))
Is my multi-field variable empty of things?
(test (= (length $?foo) 0))