CLIPS sister, predecesor and age rules - clips

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.

Related

clips how to make rule match forall but one

How could i make a rule that test if all facts from a deftemplate but one matches an specific condition?
Example: with
(deftemplate person (field name)(field hair-color))
having several blonde people, only one is not
get
(printout t "Only " ?name-not-blond " is not blonde" crlf)
CLIPS (6.4 2/9/21)
CLIPS>
(deftemplate person
(slot name)
(slot hair-color))
CLIPS>
(defrule only-one-not-blonde
(person (name ?name-not-blonde)
(hair-color ~blonde))
(not (person (name ~?name-not-blonde)
(hair-color ~blonde)))
=>
(println "Only " ?name-not-blonde " is not blonde."))
CLIPS>
(deffacts initial
(person (name Sue) (hair-color blonde))
(person (name Frank) (hair-color blonde))
(person (name Josh) (hair-color brown)))
CLIPS> (reset)
CLIPS> (facts)
f-1 (person (name Sue) (hair-color blonde))
f-2 (person (name Frank) (hair-color blonde))
f-3 (person (name Josh) (hair-color brown))
For a total of 3 facts.
CLIPS> (agenda)
0 only-one-not-blonde: f-3,*
For a total of 1 activation.
CLIPS> (assert (person (name Anne) (hair-color red)))
<Fact-4>
CLIPS> (agenda)
CLIPS>

CLIPS who is son or daughter, father or mother, grandfather or grandmother

I have a quite simple program but never use CLIPS.
My task is to show who is who and for whom.
I tried to remake code from my classes but it doesn't work:
(defrule MAIN::son
(or (father ?x ?y)
(mother ?x ?y)
)
(m ?y)
=>
(assert(son ?y ?x))
(printout t ?y " is son to " ?x crlf)
)
(defrule MAIN::daughter
(or (father ?x ?y)
(mother ?x ?y)
)
(f ?y)
=>
(assert(daughter ?y ?x))
(printout t ?y " is daughter to " ?x crlf)
)
(defrule MAIN::grandfather
(or (father ?x ?y)
(mother ?x ?y)
)
(father ?z ?x)
(m ?z)
=>
(assert(grandfather ?z ?y))
(printout t ?z " is grandfather to " ?y crlf)
)
(defrule MAIN::grandmother
(or (father ?x ?y)
(mother ?x ?y)
)
(mother ?z ?x)
(f ?z)
=>
(assert(grandmother ?z ?y))
(printout t ?z " is grandmother to " ?y crlf)
)
(defrule MAIN::grandson
(or (father ?x ?y)
(mother ?x ?y)
)
(or (father ?y ?z)
(mother ?y ?z)
)
(m ?z)
=>
(assert(grandson ?z ?x))
(printout t ?z " is grandson to " ?x crlf)
)
(defrule MAIN::granddaughter
(or (father ?x ?y)
(mother ?x ?y)
)
(or (father ?y ?z)
(mother ?y ?z)
)
(f ?z)
=>
(assert(grandson ?z ?x))
(printout t ?z " is granddaughter to " ?x crlf)
)
(defrule MAIN::brother
(or (father ?x ?y)
(mother ?x ?y)
)
(or (father ?x ?z)
(mother ?x ?z)
)
(notancestor ?y ?z)
(m ?z)
=>
(assert(brother ?z ?y))
(printout t ?z " is brother "to ?x crlf)
)
(defrule MAIN::sister
(or (father ?x ?y)
(mother ?x ?y)
)
(or (father ?x ?z)
(mother ?x ?z)
)
(notancestor ?y ?z)
(f ?z)
=>
(assert(sister ?z ?y))
(printout t ?z " is sister to " ?x crlf)
)
(defrule MAIN::near_ancestor
(or (father ?x ?y)
(mother ?x ?y)
)
(or (father ?x ?z)
(mother ?x ?z)
)
=>
(assert(near_ancestor ?z ?y))
(printout ?z " is near_ancestor to " ?x crlf)
)
(defrule MAIN::ancestor
(ancestor ?x ?y)
(near_ancestor ?y ?z)
=>
(assert(ancestor ?x ?z))
(printout t ?z " is ancestor to " ?x crlf)
)
(defrule MAIN::near_descendant
(or (father ?x ?y)
(mother ?x ?y)
)
(or (father ?x ?z)
(mother ?x ?z)
)
=>
(assert(near_descendant ?y ?z))
(printout t ?x " is near_descendant to" ?z crlf)
)
(defrule MAIN::descendant
(descendant ?x ?y)
(near_descendant ?y ?z)
=>
(assert(descendant ?z ?x))
(printout t ?x " is descendant to " ?z crlf)
)
I'm not sure about entries data:
(deffacts startup
(father Adam Kain)
(father Adam Abel)
(father Adam Set)
(mother Ewa Kain)
(mother Ewa Abel)
(mother Ewa Set)
)
I have such error in CLIPS
CLIPS> (run)
[ROUTER1] Logical name Set was not recognized by any routers
Ewa is near_descendant to Set
[ROUTER1] Logical name Abel was not recognized by any routers
Ewa is near_descendant to Abel
[ROUTER1] Logical name Kain was not recognized by any routers
Ewa is near_descendant to Kain
[ROUTER1] Logical name Set was not recognized by any routers
Ewa is near_descendant to Set
[ROUTER1] Logical name Set was not recognized by any routers
Ewa is near_descendant to Set
[ROUTER1] Logical name Abel was not recognized by any routers
Ewa is near_descendant to Abel
[ROUTER1] Logical name Kain was not recognized by any routers
Ewa is near_descendant to Kain
[ROUTER1] Logical name Abel was not recognized by any routers
Ewa is near_descendant to Abel
[ROUTER1] Logical name Kain was not recognized by any routers
Ewa is near_descendant to Kain
[ROUTER1] Logical name Set was not recognized by any routers
Adam is near_descendant to Set
[ROUTER1] Logical name Abel was not recognized by any routers
Adam is near_descendant to Abel
[ROUTER1] Logical name Kain was not recognized by any routers
Adam is near_descendant to Kain
[ROUTER1] Logical name Set was not recognized by any routers
Adam is near_descendant to Set
[ROUTER1] Logical name Set was not recognized by any routers
Adam is near_descendant to Set
[ROUTER1] Logical name Abel was not recognized by any routers
Adam is near_descendant to Abel
[ROUTER1] Logical name Kain was not recognized by any routers
Adam is near_descendant to Kain
[ROUTER1] Logical name Abel was not recognized by any routers
Adam is near_descendant to Abel
[ROUTER1] Logical name Kain was not recognized by any routers
Adam is near_descendant to Kain
And I've stuck on it.
I will be appreciated for any help
This line in your code
(printout ?z " is near_ancestor to " ?x crlf)
should be this
(printout t ?z " is near_ancestor to " ?x crlf)

CLIPS(templates) - family relations: trouble with handling templates and initial facts while writing rules

I am struggling with the following CLIPS programming problem:
Problem: write a set of rules to define family relations like:
(brother ?x ?y) (i.e. "x is a brother of y")
(sister ?x ?y) (i.e. "x is a sister of y")
(son ?x ?y) (i.e. "x is a son of y")
(daughter ?x ?y) (i.e. "x is a daughter of y")
The constraint in this task is that the rules can be constructed only from the following premises:
(father ?x ?y) (i.e. "x is a father of y")
(mother ?x ?y) (i.e. "x is a mother of y")
(male ?x) (i.e. "x is a male")
(female ?y) (i.e. "y is a female")
The task also assumes that there must be some initial facts provided and that to check the correctness there should be an implementation of displaying information about derived conclusions.
My attempt
I created templates and initial facts as follows:
(deftemplate father-of
(slot father)
(slot child)
)
(deftemplate mother-of
(slot mother)
(slot child)
)
(deftemplate male
(slot person)
)
(deftemplate female
(slot person)
)
(deffacts family
(mother-of(mother Anna) (child Tracy)
(mother-of(mother Anna) (child Cindy)
(female Anna)
(female Tracy)
(female Cindy)
)
My attempt in writing a rule for checking if certain person is a sister of other person was as follows:
(defrule sister-of
(and
(female (person ?x))
(female (person ?y))
(female (person ?z))
(mother-of (mother ?x) (child ?y))
(mother-of (mother ?x) (child ?z))
)
=>
(assert (sister ?y ?z))
(printout t ?y " is a sister of " ?z crlf)
)
Output error
Once I load .clp file I consistenly obtain the following error message of such form:
CLIPS (6.30 3/17/15)
CLIPS> (reset)
CLIPS> (clear)
CLIPS> (load family.clp)
Defining deftemplate: father-of
Defining deftemplate: mother-of
Defining deftemplate: male
Defining deftemplate: female
Defining deffacts: family
[PRNTUTIL2] Syntax Error: Check appropriate syntax for deftemplate pattern.
ERROR:
(deffacts MAIN::family
(mother-of (mother Anna) (child Markus))
(female Anna
FALSE
CLIPS>
My attempts
I checked CLIPS guides regarding basic programming, googled error message, but I did not make any progress.
Help will be greatly appreciated!!! For me it suffices to see how this stuff works in the case of the case of writing a rule (sister ?x ?y) with all the templates and facts provided above.
If you define a deftemplate for a fact, you must include the slot names when specifying the slot values.
(deffacts family
(mother-of(mother Anna) (child Tracy))
(mother-of(mother Anna) (child Cindy))
(female (person Anna))
(female (person Tracy))
(female (person Cindy))
)

Clips Family Expert System

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.

Create rules in CLIPS to move from unknown to known person facts

Assume that you are given a set of 'person' facts that are defined according to the following construct:
(deftemplate person (slot name) (slot sex) (allowed-values male female) (multislot children))
Write rules to do the following:
Create a fact of the form (unknown-person ) for each name that appears in the children multislot of a person fact but not in the name slot of any person fact (it is assumed that no two people have the same name)
For each fact of the form (unknown-person ) ask the user for the sex of the person, retract the fact and assert a new fact of the form (unknown-person ).
For each fact of the form (unknown-person ), retract the fact and create a new person fact for the person (it is assumed that the person has no children).
Your rules should do data validation to ensure that only an allowed value for is supplied by the user
Define the template in CLIPS:
(deftemplate person
(slot name)
(slot sex)
(slot gender (allowed-values male female))
(multislot children))
Start with the unknown-person creation (caveat: this may not be completely correct as it still creates a person without checking to see if they exist).
(defrule childrencataloguer "First layer of unknown person resolution"
(person (children $?ch))
=>
(progn$ (?term ?ch)
(assert (unknown-person ?term))
))
Deal with the caveat above
(defrule removeunknownswithpersonsalready
(person (name ?n))
?up <-(unknown-person ?n)
=>
(retract ?up))
Now, get the gender:
(defrule getgender
?up-nogen <-(unknown-person ?n)
=>
(retract ?up-nogen)
(printout t crlf "Please enter male or female to indicate " ?n "'s gender" crlf )
(assert (unknown-person ?n (read)))
)
There are other ways you can do the gender confirmation, I would have liked to use the deftemplate itself, so that the allowed-values would have fed into the validation. But I don't know how yet.
(assert (gender male))
(assert (gender female))
Now, do validation:
(defrule checkgender
?p <- (unknown-person ?n ?s)
(not (gender ?s))
=>
(retract ?p)
(assert (unknown-person ?n))
)
Finally, graduate from unknown
(defrule graduatefromunknown
(declare (salience -10))
?up <- (unknown-person ?n ?s)
=>
(retract ?up)
(assert (person (name ?n) (sex ?s)))
)

Resources