I have some family tree and want to get granfather from that tree via defrule. Also would be perfect if we can get brother-in-law.
(deftemplate person
(slot name)
(slot gender)
(slot father)
(slot wife))
(deffacts people
(person (name Vasya) (gender male) (wife Liza))
(person (name Liza) (gender female))
(person (name Vladimir) (gender male) (father Vasya))
(person (name Natasha) (gender female) (father Vasya))
(person (name Viktor) (gender male) (father Vasya))
(person (name Misha) (gender male) (wife Natasha))
(person (name Kostya) (gender male) (father Misha) (wife Liza))
(person (name Masha) (gender female) (father Misha)))
(deftemplate mother
(slot namel)
(slot name2))
(deftemplate brother
(slot namel)
(slot name2))
(defrule Brother
(person (name ?x) (gender male) (father ?y&~nil))
(person (name ?z&~?x) (gender male) (father ?y&~nil))
(not (brother (namel ?x) (name2 ?z)))
(not (brother (namel ?z) (name2 ?x)))
=>
(printout t ?x " brother of " ?z crlf)
(assert (brother (namel ?x) (name2 ?z))))
Assuming that you're treating half-brothers as brothers, there are two issues with your existing Brother rule. First, it's requiring that a brother have a male sibling, so Masha and Natasha are not identified as having brothers. Second, half-brothers can also share mothers, not just fathers.
Modify your person deftemplate to include a mother and change the wife slot to a spouse:
(deftemplate person
(slot name)
(slot gender)
(slot mother)
(slot father)
(slot spouse))
Create a new deftemplate for representing relationships between person facts:
(deftemplate relation
(slot p1)
(slot is)
(slot p2))
Modify your deffacts to reflect the updated deftemplate:
(deffacts people
(person (name Vasya) (gender male) (spouse Liza))
(person (name Liza) (gender female))
(person (name Vladimir) (gender male) (father Vasya))
(person (name Natasha) (gender female) (father Vasya))
(person (name Viktor) (gender male) (father Vasya))
(person (name Misha) (gender male) (spouse Natasha))
(person (name Kostya) (gender male) (father Misha) (spouse Liza))
(person (name Masha) (gender female) (father Misha)))
You can then update the brother rule:
(defrule brother
(person (name ?name)
(mother ?mother)
(father ?father))
(or (person (name ?brother&~?name)
(gender male)
(father ?father&~nil))
(person (name ?brother&~?name)
(gender male)
(mother ?mother&~nil)))
=>
(assert (relation (p1 ?brother)
(is brother-of)
(p2 ?name))))
and add new rules for grandfather and brother-in-law:
(defrule grandfather
(person (name ?name)
(mother ?mother)
(father ?father))
(person (name ?mother | ?father)
(father ?grandfather&~nil))
=>
(assert (relation (p1 ?grandfather)
(is grandfather-of)
(p2 ?name))))
(defrule brother-in-law
(person (name ?name)
(spouse ?spouse))
(relation (p1 ?brother-in-law)
(is brother-of)
(p2 ?spouse))
=>
(assert (relation (p1 ?brother-in-law)
(is brother-in-law-of)
(p2 ?name))))
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.
Introduction
I am trying to implement a rule in CLIPS language - the relation that a person is an ancestor of other person.
The constraint is that such rule must be derived only from the following premises:
(male ?x) ("x is a male")
(female ?y) ("y is a female")
(mother-of ?x ?y) ("x is a mother of y")
(father-of ?x ?y) ("x is a father of y")
My attempt
I wrote the following code:
(deftemplate father-of
(slot father)
(slot child)
)
(deftemplate mother-of
(slot mother)
(slot child)
)
(deftemplate male
(slot person)
)
(deftemplate female
(slot person)
)
(deffacts family
(father-of (father John) (child Mark))
(father-of (father John) (child Mary))
(mother-of (mother Alice) (child Mark))
(mother-of (mother Alice) (child Mary))
(male (person John))
(male (person Mark))
(female (person Alice))
(female (person Mary))
)
(defrule ancestor
(or
(mother-of (mother ?x) (child ?w))
(father-of (father ?x) (child ?w))
(and
(mother-of (mother ?x) (child ?y))
(or
(mother-of (mother ?y) (child ?w))
(father-of (father ?y) (child ?w))
)
)
(and
(father-of (father ?x) (child ?y))
(or
(mother-of (mother ?y) (child ?w))
(father-of (father ?y) (child ?w))
)
)
)
=>
(printout t ?x " is an ancestor of " ?w crlf)
(assert (ancestor ?x ?w))
)
The gist of the problem
The above code compiles and returns "true"(in other words, the construced rule is logically correct) and outputs expected results in the case of such list of facts.
However, there is a subtle problem:
This codes works for determining first and second generation of ancestors only.
In other words, it works only in the case if someone is a father/mother of someone or a grandfather/grandmother of someone, but not for checking if someone is a great grandfather/great grandmother or great great grandfather/great great grandmother of someone, etc.
The above code does not handle this issue.
How to overcome this problem?
CLIPS>
(deftemplate father-of
(slot father)
(slot child))
CLIPS>
(deftemplate mother-of
(slot mother)
(slot child))
CLIPS>
(deffacts family
(father-of (father Bob) (child Frank))
(mother-of (mother Linda) (child Frank))
(father-of (father Frank) (child John))
(mother-of (mother Susan) (child John))
(father-of (father John) (child Mark))
(mother-of (mother Alice) (child Mark)))
CLIPS>
(defrule ancestor
(or (mother-of (mother ?x) (child ?w))
(father-of (father ?x) (child ?w))
(and (ancestor ?x ?y)
(ancestor ?y ?w)))
(not (ancestor ?x ?w))
=>
(printout t ?x " is an ancestor of " ?w crlf)
(assert (ancestor ?x ?w)))
CLIPS> (reset)
CLIPS> (run)
Alice is an ancestor of Mark
John is an ancestor of Mark
Susan is an ancestor of John
Susan is an ancestor of Mark
Frank is an ancestor of John
Frank is an ancestor of Mark
Linda is an ancestor of Frank
Linda is an ancestor of Mark
Linda is an ancestor of John
Bob is an ancestor of Frank
Bob is an ancestor of Mark
Bob is an ancestor of John
CLIPS>
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 am trying to make a family tree program where I need to use the AND/OR operation. But somehow I am unable to do it. I am using 6.3 CLIPS WIN. Here is what I am doing.
(deftemplate father-of (slot father) (slot child))
(deftemplate mother-of (slot mother) (slot child))
(deftemplate parent-of (slot parent) (slot child))
(deffacts ........................................
(defrule parent-of ""
(or
(mother-of (mother ?mother) (child ?child))
(father-of (father ?father) (child ?child)))
=>
(and
(assert (parent-of (parent ?mother) (child ?child))
(assert (parent-of (parent ?father) (child ?child))))
I am sorry, these are very basic conditions and operations. However I am unable to do it.
Much appreciate your help.
CLIPS> (deftemplate father-of (slot father) (slot child))
CLIPS> (deftemplate mother-of (slot mother) (slot child))
CLIPS> (deftemplate parent-of (slot parent) (slot child))
CLIPS>
(deffacts example
(mother-of (mother "Jane") (child "Billy"))
(father-of (father "Dave") (child "Billy")))
CLIPS>
(defrule parent-of ""
(or
(mother-of (mother ?parent) (child ?child))
(father-of (father ?parent) (child ?child)))
=>
(assert (parent-of (parent ?parent) (child ?child))))
CLIPS> (reset)
CLIPS> (facts)
f-0 (initial-fact)
f-1 (mother-of (mother "Jane") (child "Billy"))
f-2 (father-of (father "Dave") (child "Billy"))
For a total of 3 facts.
CLIPS> (watch rules)
CLIPS> (run)
FIRE 1 parent-of: f-2
FIRE 2 parent-of: f-1
CLIPS> (facts)
f-0 (initial-fact)
f-1 (mother-of (mother "Jane") (child "Billy"))
f-2 (father-of (father "Dave") (child "Billy"))
f-3 (parent-of (parent "Dave") (child "Billy"))
f-4 (parent-of (parent "Jane") (child "Billy"))
For a total of 5 facts.
CLIPS>
There is no need to use AND in RHS, both asserts will be executed
=>
(assert (parent-of (parent ?mother) (child ?child)))
(assert (parent-of (parent ?father) (child ?child)))