I have a family tree. I need to find a person's brother-in-law using CLIPS.
Family Tree
Rules to find Brother-In-Law
Rule-1 (to find spouse's brother)
(defrule MAIN::fnd_BrthrsNLaw1 ;spouse's brother
(findRelative (person ?pn) (relationship b_i_lw)) ;Brothers-in-Law
(and
(and (and (or (marriage-between (personA ?pn) (personB ?sp))
(marriage-between (personA ?sp) (personB ?pn))
)
(child-of (relationship ?x) (person ?sp) (mother ?m) (father ?f))
)
(child-of (relationship son-of) (person ?pn2) (mother ?m) (father ?f))
)
(not (marriage-between (personA ?pn) (personB ?pn2)))
)
=>
(printout t ?pn "'s brothers-in-Law: (spouse's brother) " ?pn2 crlf)
)
Rule-2 (to find spouse's sister's husband)
(defrule MAIN::fnd_BrthrsNLaw2 ;spouse's sister's husband
(findRelative (person ?pn) (relationship b_i_lw)) ;Brothers-in-Law
(and
(and
(and
(or
(marriage-between (personA ?pn) (personB ?sp))
(marriage-between (personA ?sp) (personB ?pn))
)
(and
(child-of (relationship ?x) (person ?sp) (mother ?a) (father ?b))
(child-of (relationship daughter-of) (person ?p2) (mother ?a) (father ?b))
)
)
(and
(not (eq ?sp ?p2))
(marriage-between (personA ?p2) (personB ?px2))
)
)
=>
(printout t ?pn "'s brothers-in-Law: (spouse's sister's husband) " ?px2 " <sister = " ?p2 " ; spouse = " ?sp " ; spouse's parents: " ?a " , " ?b ">" crlf)
)
Rule-3 (to find sister's husband)
(defrule MAIN::fnd_BrthrsNLaw3 ;sister's husband
(findRelative (person ?p) (relationship b_i_lw)) ;Brothers-in-Law
(and
(and
(child-of (relationship ?y) (person ?p) (mother ?c) (father ?d))
(child-of (relationship daughter-of) (person ?sist) (mother ?c) (father ?d))
)
(and
(not (eq ?p ?sist))
(marriage-between (personA ?sist) (personB ?p2))
)
)
=>
(printout t ?p "'s brothers-in-Law: (sister's husband) " ?p2 <sister = " ?sist " ; " ?p "'s parent = " ?sp " ; spouse's parents: " ?c " , " ?d ">"crlf)
(reset)
)
Templates
(deftemplate MAIN::marriage-between
(slot personA)
(slot personB))
(deftemplate MAIN::child-of
(slot relationship (type SYMBOL) (allowed-symbols son-of daughter-of))
(slot person)
(slot mother)
(slot father))
(deftemplate MAIN::findRelative
(slot relationship (type SYMBOL)
(allowed-symbols g_g_p ;Great-GrandParents
g_ch ;GrandChildren
b_i_lw)) ;Brothers-in-Law
(slot person))
Now for -
1)Diana, brother-in-law ( or b_i_lw) have to be Andrew, Mark and Edward
2)Mark, b_i_lw's are Andrew, Edward and Charles.
3)Charles, b_i_lw' has to be Mark.
But my outputs are not completely correct as some wrong info is also deduced with the correct ones for rules of spouse's brother's sister (rule named "fnd_BrthrsNLaw2") and sister's husband (rule named "fnd_BrthrsNLaw3").
Output for Mark, Diana and Charles are given below:
Output for searching for Diana:
CLIPS> (assert (findRelative (person Diana) (relationship b_i_lw)))
<Fact-20>
CLIPS> (run)
Diana's brothers-in-Law: (spouse's brother) Edward
Diana's brothers-in-Law: (spouse's brother) Andrew
Diana's brothers-in-Law: (spouse's sister's husband) Mark <sister = Anne ; spouse = Charles ; Charles's parents: Elizabeth , Phillip>
Diana's brothers-in-Law: (sister's husband) Charles <sister = Diana ; Diana's parent: Kydd , Spencer>
Output for searching for Mark:
CLIPS> (assert (findRelative (person Mark) (relationship b_i_lw)))
<Fact-20>
CLIPS> (run)
Mark's brothers-in-Law: (spouse's brother) Edward
Mark's brothers-in-Law: (spouse's brother) Andrew
Mark's brothers-in-Law: (spouse's brother) Charles
Mark's brothers-in-Law: (spouse's sister's husband) Mark <sister = Anne ; spouse = Anne ; Anne's parents: Elizabeth , Phillip>
Output for searching for Charles:
CLIPS> (assert (findRelative (person Charles) (relationship b_i_lw)))
<Fact-20>
CLIPS> (run)
Charles's brothers-in-Law: (spouse's sister's husband) Charles <sister = Diana ; spouse = Diana ; Diana's parents: Kydd , Spencer>
Charles's brothers-in-Law: (sister's husband) Mark <sister = Anne ; Anne's parent: Elizabeth , Phillip>
My assumption is use of (not (eq )) in rule-2 and rule-3 is not affecting the 'and' blocks they are inside, though I have tested that (not (eq )) is giving true when and is not equal and false when they are equal, which I intend to get.
You need to use the test CE to evaluate expressions in the conditions of a rule. For example, instead of
(not (eq ?sp ?p2))
use
(test (not (eq ?sp ?p2)))
or
(test (neq ?sp ?p2))
Your existing rules are attempting to match a fact with relation name eq rather than calling the eq function to compare values.
Also, calling the reset command in the fnd_BrthrsNLaw3 rule actions is something you probably don't want to be doing.
Related
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>
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 am trying to write a rule that will match when a certain value is not in a multislot, and then add that value to it.
(deftemplate person
(multislot packing_list
(type SYMBOL)
(default ?DERIVE)))
(defrule apply_adapter
(travel international)
?p <- (person (packing_list $? ~travel_adaptor ))
=>
(modify ?p (packing_list travel_adaptor)))
(println "Added to list" crlf)
)
(deffacts start
(travel international)
(person)
)
Two parts of this I know aren't correct:
?p <- (person (packing_list $? ~travel_adaptor )) does not fire the rule - what is the correct syntax?
(modify ?p (packing_list travel_adaptor))) probably does not do what I want, which is to insert the value, not replace the list.
Any ideas how to fix this?
CLIPS (Cypher Beta 8/21/18)
CLIPS>
(deftemplate person
(multislot packing_list
(type SYMBOL)
(default ?DERIVE)))
CLIPS>
(defrule apply_adapter
(travel international)
?p <- (person (packing_list $?pl))
(test (not (member$ travel_adaptor ?pl)))
=>
(modify ?p (packing_list ?pl travel_adaptor))
(println "Added to list"))
CLIPS>
(deffacts start
(travel international)
(person))
CLIPS> (reset)
CLIPS> (run)
Added to list
CLIPS> (facts)
f-1 (travel international)
f-2 (person (packing_list travel_adaptor))
For a total of 2 facts.
CLIPS>
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))
)
I know that rules in CLIPS are usually given names using defrule. This rule is called rule1:
(deftemplate animal (slot species))
(deffacts animal
(animal (species dog)))
(defrule rule1
(animal (species ?name))
=>
(printout t ?name crlf))
(reset)
(run)
(exit)
;
But I still don't know whether it is necessary for the rules to be named. Is it possible to define a rule without giving it a name, like this?
(deftemplate animal (slot species))
(deffacts animal
(animal (species dog)))
(defrule
(animal (species ?name))
=>
(printout t ?name crlf))
(reset)
(run)
(exit)
;
From section 5 of the Basic Programming Guide:
(defrule <rule-name> [<comment>]
[<declaration>]
<conditional-element>*
=>
<action>*)
The rule name is required.
To dynamically generate a rule name, use the gensym* function which creates a unique symbol:
CLIPS>
(deffunction create-anonymous (?conditions ?actions)
(bind ?str (str-cat "(defrule " (gensym*) " "
?conditions " => " ?actions ")"))
(build ?str))
CLIPS> (deftemplate animal (slot species))
CLIPS>
(create-anonymous "(animal (species ?name))"
"(printout t ?name crlf)")
TRUE
CLIPS> (rules)
gen1
For a total of 1 defrule.
CLIPS> (ppdefrule gen1)
(defrule MAIN::gen1
(animal (species ?name))
=>
(printout t ?name crlf))
CLIPS>