Search code examples
clips

Family tree get family member


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))))

Solution

  • 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))))