I just want a function to print on item per line.
I am trying:
(deffunction myprint (?first $?rest)
(if (neq ?rest nil) then
(printout t ?first crlf)
(myprint ?rest)))
What is wrong?
Use the length function to determine if a list is empty (a return value of 0). Comparing a list to the symbol nil will always fail.
You want to print ?first even if ?rest is empty. Otherwise the last element will never be printed.
It is not necessary to use recursion.
CLIPS>
(deffunction myprint ($?rest)
(foreach ?r $?rest
(printout t ?r crlf)))
CLIPS> (myprint a b c)
a
b
c
CLIPS> (myprint (create$ a b) (create$ c d))
a
b
c
d
CLIPS>
Related
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
I need to make complement and difference operations between two sets. I've a example, to do union between two sets, I can reuse this code to make these two other operations.
Thanks
The union example, that I've is:
(deffacts datos-iniciales
(conjunto B C A D E E B C E)
(conjunto E E B F D E))
(defrule inicio
=>
(assert (union)))
(defrule union
?h <- (union $?u)
(conjunto ? $? ?e $?)
(not (union $? ?e $?))
=>
(retract ?h)
(assert (union ?e $?u)))
Specifically, which part of the program should be changed? Thx
Here's how you can compute all three leaving the set-1 and set-2 facts unmodified, ignoring duplicate members, and sorting the results.
CLIPS (6.31 6/12/19)
CLIPS>
(deffacts datos-iniciales
(set-1 B C A D E E B C E)
(set-2 E E B F D E))
CLIPS>
(deffacts universe
(universe A B C D E F G H I J K))
CLIPS>
(deffunction str-sort (?a ?b)
(> (str-compare (sym-cat ?a) (sym-cat ?b)) 0))
CLIPS>
(defrule calcula
=>
(assert (union)
(complement)
(difference)))
CLIPS>
(defrule add-to-union
?union <- (union $?u)
(or (set-1 $? ?v $?)
(set-2 $? ?v $?))
(test (not (member$ ?v ?u)))
=>
(retract ?union)
(assert (union ?u ?v)))
CLIPS>
(defrule add-to-complement
?complement <- (complement $?c)
(universe $?u1 ?v $?u2)
(set-1 $?s)
(test (and (not (member$ ?v ?c))
(not (member$ ?v ?s))))
=>
(retract ?complement)
(assert (complement ?c ?v)))
CLIPS>
(defrule add-to-difference
?difference <- (difference $?d)
(set-1 $? ?v $?)
(set-2 $?set2)
(test (and (not (member$ ?v ?d))
(not (member$ ?v ?set2))))
=>
(retract ?difference)
(assert (difference ?d ?v)))
CLIPS>
(defrule write-union
(declare (salience -10))
(union $?u)
=>
(printout t "The union is " (sort str-sort ?u) crlf))
CLIPS>
(defrule write-complement
(declare (salience -10))
(complement $?c)
=>
(printout t "The complement is " (sort str-sort ?c) crlf))
CLIPS>
(defrule write-difference
(declare (salience -10))
(difference $?d)
=>
(printout t "The difference is " (sort str-sort ?d) crlf))
CLIPS> (reset)
CLIPS> (run)
The union is (A B C D E F)
The complement is (F G H I J K)
The difference is (A C)
CLIPS>
I'd like to compare a variable that holds a symbol to many values, so that if any of them matches the variable, the CE is satisfied. Here is a minimal example:
(defrule compare-students
?x <- (Student (FirstName ?n))
(or (eq ?n John) (eq ?n Beter) (eq ?n Sarah))
=>
(modify ?x (SecondName ?n)))
When I compile the constructs file to c code, I got something like this:
Defining defrule: compare-students +j+j+j
=j=j+j+j
=j=j+j+j
Is this the right way to do that?
Thanks
Preferably use this:
(defrule compare-students
?x <- (Student (FirstName ?n&John | Beter | Sarah)
(SecondName ~?n))
=>
(modify ?x (SecondName ?n)))
Or alternately this:
(defrule compare-students
?x <- (Student (FirstName ?n)
(SecondName ~?n))
(test (or (eq ?n John) (eq ?n Beter) (eq ?n Sarah)))
=>
(modify ?x (SecondName ?n)))
The first uses pattern matching constraints for brevity and the second uses the test conditional element (CE) to indicate that the following syntax is a function call to be evaluated, not a pattern to be matched. In your original rule, you don't use the test CE, so the "or" in that rule is an "or" conditional element. It will attempt to match eq facts rather than make a function call.
I am trying to solve a problem, where I have to fill a 5x5 matrix with letters A, B, C, D, and E. Each letter cannot occur more than once in each row and in each column. With some initial letter positions given.
I created every position as separate facts eg. "M 1 1 X".
I am struggling how to loop a defrule in way to assert a fact with correct letter and check the conditions again.
(defrule solveA5
?a <-(M 5 ?c X)
(not (M ?x ?c A))
=>
(retract ?a)
(assert (M 5 ?c A))
)
Code above for example is only to check presence of A in every position of 5th row, but the problem is that conditions are checked at the beginning only and instead of asserting correct fact and checking again it asserts A in every position.
I've tried using deffunction to loop defrule.
(deffunction solve (?letter)
(loop-for-count (?x 1 5) do
(loop-for-count (?y 1 5) do
(build (str-cat"defrule costam
?a <-(M ?x ?y X)
(not (and(M ?x ?a ?letter) (M ?b ?y ?letter))
=>
(retract ?a)
(assert (M ?x ?y ?letter))")
)
)
)
)
Unfortunately running
(solve A)
returns "FALSE" and doesn't modify any facts.
To handle iteration within rules, you must assert the iteration information as facts to allow the rules to match and modify this information. In the placement, it's not essential to do this in any particular order, so you can just assert information containing the rows, columns, and letters to place and allow the rules fire arbitrarily:
CLIPS>
(deftemplate element
(slot row)
(slot column)
(slot value))
CLIPS>
(deftemplate print
(slot row)
(slot column)
(slot end-of-row))
CLIPS>
(deffacts initial
(rows 1 2 3 4 5)
(columns 1 2 3 4 5)
(letters A B C D E))
CLIPS>
(defrule place
(rows $? ?r1 $?)
(columns $? ?c1 $?)
(letters $? ?l $?)
(not (element (row ?r1) (column ?c1)))
(not (and (element (row ?r2)
(column ?c2)
(value ?l))
(test (or (= ?r1 ?r2) (= ?c1 ?c2)))))
=>
(assert (element (row ?r1) (column ?c1) (value ?l))))
CLIPS>
(defrule print-start
(declare (salience -10))
(rows ?r $?)
(columns ?c $?rest)
=>
(assert (print (row ?r)
(column ?c)
(end-of-row (= (length$ ?rest) 0)))))
CLIPS>
(defrule print-next-column
(declare (salience -10))
?f <- (print (column ?c))
(columns $? ?c ?nc $?rest)
=>
(modify ?f (column ?nc)
(end-of-row (= (length$ ?rest) 0))))
CLIPS>
(defrule print-next-row
(declare (salience -10))
?f <- (print (column ?c) (row ?r))
(columns $?first ?c)
(rows $? ?r ?nr $?)
=>
(if (= (length$ ?first) 0)
then
(bind ?eor TRUE)
(bind ?nc ?c)
else
(bind ?eor FALSE)
(bind ?nc (nth$ 1 ?first)))
(modify ?f (row ?nr)
(column ?nc)
(end-of-row ?eor)))
CLIPS>
(defrule print-placed
(print (row ?r) (column ?c) (end-of-row ?eor))
(element (row ?r) (column ?c) (value ?l))
=>
(if ?eor
then
(printout t ?l crlf)
else
(printout t ?l " ")))
CLIPS>
(defrule print-unplaced
(print (row ?r) (column ?c) (end-of-row ?eor))
(not (element (row ?r) (column ?c)))
=>
(if ?eor
then
(printout t "?" crlf)
else
(printout t "? ")))
CLIPS> (reset)
CLIPS> (run)
E D C B A
? C D A B
? B A D C
? A B C D
A ? ? ? E
CLIPS>
In this example, the print rules iterate over the rows and columns by storing the iteration information in facts. You can see how much more complicated this is than the place rule which assigns the elements in an arbitrary manner.
Whether you assign the values arbitrarily or in a specific order, it's possible to assign values that prevent a solution, so you must implement backtracking in order to guarantee finding the solution if one exists. In this example, the facts store information about the order of the value placements and the values that have been tried:
CLIPS> (clear)
CLIPS>
(deftemplate element
(slot row)
(slot column)
(slot value (default unset))
(multislot values)
(slot placement))
CLIPS>
(deffacts initial
(placement 0)
(rows 1 2 3 4 5)
(columns 1 2 3 4 5)
(letters A B C D E))
CLIPS>
(defrule prime
(placement ?p)
(rows $? ?r $?)
(columns $? ?c $?)
(letters $?l)
(not (element (placement ?p)))
(not (element (row ?r) (column ?c)))
=>
(assert (element (placement ?p) (values ?l) (row ?r) (column ?c))))
CLIPS>
(defrule place-good
?f1 <- (placement ?p)
?f2 <- (element (placement ?p)
(value unset)
(row ?r1)
(column ?c1)
(values ?v $?rest))
(not (and (element (row ?r2)
(column ?c2)
(value ?v))
(test (or (= ?r1 ?r2) (= ?c1 ?c2)))))
=>
(retract ?f1)
(assert (placement (+ ?p 1)))
(modify ?f2 (value ?v) (values ?rest)))
CLIPS>
(defrule place-bad
(placement ?p)
?f2 <- (element (placement ?p)
(value unset)
(row ?r1)
(column ?c1)
(values ?v $?rest))
(element (row ?r2)
(column ?c2)
(value ?v))
(test (or (= ?r1 ?r2) (= ?c1 ?c2)))
=>
(modify ?f2 (values ?rest)))
CLIPS>
(defrule backtrack
?f1 <- (placement ?p)
?f2 <- (element (placement ?p)
(value unset)
(values))
?f3 <- (element (placement =(- ?p 1))
(value ~unset))
=>
(retract ?f1)
(assert (placement (- ?p 1)))
(retract ?f2)
(modify ?f3 (value unset)))
CLIPS>
(defrule print
(declare (salience -10))
(rows $?rows)
(columns $?columns)
=>
(progn$ (?r ?rows)
(progn$ (?c ?columns)
(if (not (do-for-fact ((?f element))
(and (= ?r ?f:row) (= ?c ?f:column))
(printout t ?f:value " ")))
then
(printout t "? ")))
(printout t crlf)))
CLIPS> (reset)
CLIPS> (run)
B C D E A
A B C D E
C A E B D
D E A C B
E D B A C
CLIPS>
The print rules have been simplified into a single rule that iterates over the row and columns in the actions of the rule and uses the fact query functions to retrieve values that have been assigned.
The program also works if you preassign some of the values:
CLIPS> (reset)
CLIPS> (assert (element (row 1) (column 1) (value A)))
<Fact-5>
CLIPS> (assert (element (row 3) (column 3) (value C)))
<Fact-6>
CLIPS> (assert (element (row 5) (column 4) (value E)))
<Fact-7>
CLIPS> (run)
A C E D B
B A D C E
D E C B A
E D B A C
C B A E D
CLIPS>
I know there are several predicate functions that allow to test if a variable is of a certain type.
For example,
(test (integerp ?my_var))
returns TRUE if my_var is of type integer.
Say I have a class A. How do I test if a variable is of type A? That is, I want to test if ?my_var is an instance of A.
I am looking for something like this:
(test (instance_of_A_p ?my_var))
or
(test (is-a (?my_var A))
Use the type function:
CLIPS> (bind ?a 3)
3
CLIPS> (type a)
SYMBOL
CLIPS> (defclass A (is-a USER))
CLIPS> (bind ?a (make-instance a1 of A))
[a1]
CLIPS> (type ?a)
A
CLIPS> (eq (type ?a) A)
TRUE
CLIPS>
So in the LHS of the rule:
(test (eq (type ?a) A))