fs71gh
fs71gh

Reputation: 63

Cant make 'not' and 'eq' work together

I have a family tree. I need to find a person's brother-in-law using CLIPS.

Family Tree

http://oi61.tinypic.com/viik4y.jpg

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.

Upvotes: 0

Views: 183

Answers (1)

Gary Riley
Gary Riley

Reputation: 10757

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.

Upvotes: 2

Related Questions