I am trying to create a CLIPS program that describes family relations. I am completely lost, I don't even know where to start.
Given the following deftemplates for facts describing a family tree.
(deftemplate father‐of (slot father) (slot child))
(deftemplate mother‐of (slot mother) (slot child))
(deftemplate male (slot person))
(deftemplate female (slot person))
(deftemplate wife‐of (slot wife) (slot husband))
(deftemplate husband‐of (slot husband) (slot wife))
Write rules that infer the following relations. Describe the deftemplates you use to solve
the problem.
a) Uncle, aunt
b) Cousin
c) Grandparent
d) Grandfather, grandmother
e) Sister, bother
Run the expert system for your own family tree.
I have looked up similar examples and tried doing something similar but I am still struggling to understand what I need to do
Here's how you could do it for determining the sister:
CLIPS (6.31 6/12/19)
CLIPS> (deftemplate father-of (slot father) (slot child))
CLIPS> (deftemplate mother-of (slot mother) (slot child))
CLIPS> (deftemplate male (slot person))
CLIPS> (deftemplate female (slot person))
CLIPS>
(deffacts info
(father-of (father Bill) (child Mary))
(mother-of (mother Jane) (child Mary))
(father-of (father Bill) (child John))
(mother-of (mother Jane) (child John))
(male (person Bill))
(male (person John))
(female (person Jane))
(female (person Mary)))
CLIPS>
(defrule sister-of
(or (male (person ?person))
(female (person ?person)))
(female (person ?sister&~?person))
(father-of (father ?father) (child ?person))
(father-of (father ?father) (child ?sister))
(mother-of (mother ?mother) (child ?person))
(mother-of (mother ?mother) (child ?sister))
=>
(printout t ?sister " is the sister of " ?person crlf))
CLIPS> (reset)
CLIPS> (run)
Mary is the sister of John
CLIPS>
Related
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))))
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 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))
)
Suppose I have
(deftemplate a-template (slot A) (slot B))
and from an earlier rule I have A => C. I want to extend the template to
(deftemplate a-template (slot A) (slot B) (slot C))
How do you a write a rule that uses pre-existing rules to populate a fact template.
Thanks in advance
You can't redefine a deftemplate if any facts currently make use of that deftemplate:
CLIPS> (clear)
CLIPS> (deftemplate a-template (slot A) (slot B))
CLIPS> (deftemplate a-template (slot A) (slot B) (slot C))
CLIPS> (assert (a-template))
<Fact-1>
CLIPS> (deftemplate a-template (slot A) (slot B) (slot C) (slot D))
[CSTRCPSR4] Cannot redefine deftemplate a-template while it is in use.
ERROR:
(deftemplate MAIN::a-template
CLIPS>
However, if no such facts exist you can use introspection functions to examine the existing deftemplate in conjunction with the build function to create a new deftemplate:
CLIPS> (clear)
CLIPS>
(deffunction add-slot (?template ?slot)
(bind ?slots (deftemplate-slot-names ?template))
(if (member$ ?slot ?slots)
then
(return))
(bind ?build (str-cat "(deftemplate " ?template))
(progn$ (?s ?slots)
(if (deftemplate-slot-multip ?template ?s)
then
(bind ?build (str-cat ?build " (multislot " ?s ")"))
else
(bind ?build (str-cat ?build " (slot " ?s ")"))))
(bind ?build (str-cat ?build " (slot " ?slot ")"))
(bind ?build (str-cat ?build ")"))
(build ?build))
CLIPS> (deftemplate a-template (slot A) (slot B))
CLIPS> (ppdeftemplate a-template)
(deftemplate MAIN::a-template
(slot A)
(slot B))
CLIPS> (add-slot a-template C)
TRUE
CLIPS> (ppdeftemplate a-template)
(deftemplate MAIN::a-template
(slot A)
(slot B)
(slot C))
CLIPS>
If you wanted to redefine a template with existing facts, you'd need to save the existing facts using the save-facts function, retract all of them, redefine the template, and then reload the saved facts. This could cause rules matching the existing facts to be placed on the agenda if they had already executed.
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)))