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.
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 am with the following CLIPS programming problem:
New family relationship knowledge base. Please apply the following specification:
use deftemplate to define the person
a person’s attributes are: name, age, sex, children,
each attribute should be defined as a slot except children, that are multi slot
in sex slot use the (allowed-symbols female male)
add data type to each slot
use deffacts to add people from diagram
define rules:
—mother,
—father,
—sister,
—predecessor
—old — giving the difference in age between predecessor and offspring
This is the code I made:
(deftemplate person
(slot name (type SYMBOL))
(slot age (type INTEGER))
(slot sex (type SYMBOL) (allowed-symbols female male))
(multislot children (type SYMBOL))
)
(deffacts init
(person (name Fernando) (age 55) (sex male) (children Jesus Celia))
(person (name Maria) (age 50) (sex female) (children Jesus Celia))
(person (name Jesus) (age 25) (sex male))
(person (name Celia) (age 20) (sex female))
(person (name Antonio) (age 70) (sex male) (children Fernando Ana))
(person (name Ana) (age 38) (sex female))
(person (name Calra) (age 68) (sex female) (children Fernando Ana))
)
(defrule mother
(person (name ?name) (sex female) (children $?before ?child $?after))
=>
(assert (mother ?name ?child))
(printout t ?name " is mother of " $?child crlf))
(defrule father
(person (name ?name) (sex male) (children $?before ?child $?after))
=>
(assert (father ?name ?child))
(printout t ?name " is father of " $?child crlf))
(defrule sister
(children ?z ?x)
(children ?z ?y)
(female ?x)
(not (test (eq ?x ?y)))
=>
(assert sister ?x ?y))
(printout t ?x "is a sister to " ?y crlf))
(defrule predecessor
(or
(children ?x ?y)
(and (children ?x ?z)(predecessor ?z ?y))
)
=>
(assert (predecessor ?x ?y)
(printout t ?x "is a predecessor to " ?y crlf))
(defrule old
?fact_no <- (person (name ?n) (age ?a1 ?a2))
(test (<= ?a1 ?a2))
=>
(assert (result (- ?a1 ?a2)))
(printout t "There are " ?result " years" crlf))
The mother and father relationship is working but not the rest. It gives me the following ERRORS:
CLIPS> Loading Selection...
[CSTRCPSR4] Cannot redefine deftemplate person while it is in use.
ERROR:
(deftemplate MAIN::person
[CSTRCPSR1] WARNING: Redefining deffacts: init
[CSTRCPSR1] WARNING: Redefining defrule: mother +j+j
Defining defrule: father +j+j
[CSTRCPSR1] WARNING: Redefining defrule: sister
[PRNTUTIL2] Syntax Error: Check appropriate syntax for RHS patterns.
ERROR:
(defrule MAIN::sister
(children ?z ?x)
(children ?z ?y)
(female ?x)
(not (test (eq ?x ?y)))
=>
(assert sister
Defining defrule: predecessor
[EXPRNPSR3] Missing function declaration for defrule.
ERROR:
(defrule MAIN::predecessor
(or (children ?x ?y)
(and (children ?x ?z)
(predecessor ?z ?y)))
=>
(assert (predecessor ?x ?y)
(printout t ?x "is a predecessor to " ?y crlf))
(defrule
Thank you so much in advance
If you already have code loaded, issue a clear command before you try to load the same code a second time. That will remove the [CSTRCPSR4] error message.
You have missing parentheses in the sister and predecessor rules. Correcting these will allow the rules to load without errors.
(defrule sister
(children ?z ?x)
(children ?z ?y)
(female ?x)
(not (test (eq ?x ?y)))
=>
(assert (sister ?x ?y))
(printout t ?x "is a sister to " ?y crlf))
(defrule predecessor
(or
(children ?x ?y)
(and (children ?x ?z)(predecessor ?z ?y))
)
=>
(assert (predecessor ?x ?y))
(printout t ?x "is a predecessor to " ?y crlf))
These rules will still not execute with your existing code because they require children and female facts and none of your rules assert these facts.
It's not clear what you're trying to do with your old rule, but since you're trying to match two values in the age slot this rule will generate errors because that slot can only contain one value.
I'm trying to implement a basic expert system in the Clips programming language. I have a knowledge base of children with their respective parents. I want to set up a rule so that if two children have the same parents then it asserts the fact that they are siblings.
(deftemplate person "family tree"
(slot name)
(slot father)
(slot mother))
(assert
(person
(name "William")
(father "John")
(mother "Megan")))
(assert
(person (name "David")
(father "John")
(mother "Megan")))
(defrule sibling
(person
(name ?name1)
(father ?x)
(mother ?x))
(person
(name ?name2)
(father ?y)
(mother ?y)))
and when I define the rule I get a syntax error:
Syntax Error: Check appropriate syntax for defrule.
The correct syntax for your rule is:
(defrule sibling
(person (name ?name1) (father ?x) (mother ?x))
(person (name ?name2) (father ?y) (mother ?y))
=>
...)
Within a rule, a template is referred as:
(template_name (slot_name value) (slot_name value))
A rule is divided in two sides: the LHS (Left-Hand Side) where you define the conditions satisfying such rule and the RHS (Right-Hand Side) where you define the consequent actions.
In CLIPS, the => operator separates the two sides.
Example:
(defrule animal-is-a-duck
(animal ?name)
(quacks)
(two legs)
(lay eggs)
=>
(assert (animal ?name is a duck)))
You can read more about CLIPS syntax in the basic programming guide.
Your rule should be something like this:
(defrule sibling
(person
(name ?name1)
(father ?x)
(mother ?y))
(person
(name ?name2)
(father ?x)
(mother ?y))
(test (neq ?name1 ?name2))
=>
(assert (siblings ?name1 ?name2)))
The original rule could be satisfied only if the father and the mother were the same person in each fact being matched.
This rule permits duplicates:
f-3 (siblings "David" "William")
f-4 (siblings "William" "David")
so you can either catch that in another rule or you can write a more complex rule (or another rule) also matching against currently generated matched siblings facts.
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))
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>