Reputation: 149
I'm building a family tree using deftemplates
. I declare initial fact base using deffacts family
by asserting peoples' mothers and fathers. Then I set a bunch of rules to assert siblings, grandparents, cousins, etc. I want to get two names from the user and then based on the facts, it will tell me what their relation to each other is. I am so stumped on this problem please help.
I've been trying to use find-all-facts
, find-fact
but I can't figure out how to use the query syntax properly. Do I need a loop to iterate through every fact?
deftemplates I'm using:
(deftemplate father-of (slot father) (slot child))
(deftemplate mother-of (slot mother) (slot child))
(deftemplate parent-of (slot parent) (slot child))
(deftemplate sister-of (slot sister) (slot sibling))
(deftemplate brother-of (slot brother) (slot sibling))
(deftemplate aunt-of (slot aunt) (slot nephew-or-niece))
(deftemplate uncle-of (slot uncle) (slot nephew-or-niece))
(deftemplate cousin-of (slot cousin-1) (slot cousin-2))
...
Initial fact base snipped:
(deffacts family
;GreatGrandParents
(father-of (father "Henry") (child "Bob"))
(father-of (father "Henry") (child "Susie"))
(father-of (father "Henry") (child "Anton"))
(mother-of (mother "Georgette") (child "Bob"))
...)
What I've been trying:
(defrule get-relationship ""
=>
(printout t crlf "Enter a person in the family: ")
(bind ?p1 (read))
(printout t crlf "Enter another person in the family: ")
(bind ?p2 (read))
(find-all-facts
($a?-of ($a? ?p1) ($b? ?p2)) ;any fact that contains both names entered
((!= 0 (str-compare ?p1 ?p2)) ;given ?p1 and ?p2 are dissimilar
(printout t ?p1 "is a" $a? "of" $b? crlf)) ;display the relationship found
)
Upvotes: 0
Views: 997
Reputation: 10757
Using queries:
CLIPS (6.31 6/12/19)
CLIPS>
(deftemplate of
(slot relation)
(slot p1)
(slot p2))
CLIPS>
(deffacts family
(of (relation father) (p1 "Henry") (p2 "Bob"))
(of (relation father) (p1 "Henry") (p2 "Susie"))
(of (relation father) (p1 "Henry") (p2 "Anton"))
(of (relation mother) (p1 "Georgette") (p2 "Bob")))
CLIPS>
(defrule get-relationship ""
=>
(printout t "Enter a person in the family: ")
(bind ?p1 (readline))
(printout t "Enter another person in the family: ")
(bind ?p2 (readline))
(do-for-all-facts ((?o of))
(and (eq ?p1 ?o:p1)
(eq ?p2 ?o:p2))
(printout t ?p1 " is a " ?o:relation " of " ?p2 crlf)))
CLIPS> (reset)
CLIPS> (run)
Enter a person in the family: Henry
Enter another person in the family: Susie
Henry is a father of Susie
CLIPS>
Using patterns:
CLIPS> (clear)
CLIPS>
(deftemplate of
(slot relation)
(slot p1)
(slot p2))
CLIPS>
(deftemplate find
(slot p1)
(slot p2))
CLIPS>
(deffacts family
(of (relation father) (p1 "Henry") (p2 "Bob"))
(of (relation father) (p1 "Henry") (p2 "Susie"))
(of (relation father) (p1 "Henry") (p2 "Anton"))
(of (relation mother) (p1 "Georgette") (p2 "Bob")))
CLIPS>
(defrule get-find ""
=>
(printout t "Enter a person in the family: ")
(bind ?p1 (readline))
(printout t "Enter another person in the family: ")
(bind ?p2 (readline))
(assert (find (p1 ?p1) (p2 ?p2))))
CLIPS>
(defrule get-relationship
(find (p1 ?p1) (p2 ?p2))
(of (relation ?relation) (p1 ?p1) (p2 ?p2))
=>
(printout t ?p1 " is a " ?relation " of " ?p2 crlf)))
CLIPS>
(defrule done-find ""
(declare (salience -10))
?f <- (find)
=>
(retract ?f))
CLIPS> (reset)
CLIPS> (run)
Enter a person in the family: Georgette
Enter another person in the family: Bob
Georgette is a mother of Bob
CLIPS>
Upvotes: 2