<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
  <title></title>
</head>
<body bgcolor="#ffffff" text="#000000">
you can do something like this to drive backward chaining queries.
Notice it inserts a new fact to drive the query down the graph, but
deletes that driver once all it's&nbsp; children have been evaluated. It
uses the -5 salience to ensure it's done after all the children have
been evaluated. So just insert an initial FindAncestor fact call
fireAllRules() and it'll println if it's an ancesor, you could ofcourse
have it insert a result object, or set a value on the originally
inserted FindAncestor.<br>
<br>
rule "query parent"<br>
&nbsp; when<br>
&nbsp;&nbsp;&nbsp; FindAncestor( $name == name, $ancestor : ancestor )<br>
&nbsp;&nbsp;&nbsp; $child : Person(&nbsp; name == $name, $parent : parent )<br>
&nbsp;&nbsp;&nbsp; $parent : Person( this == $parent, this != ancestor)<br>
&nbsp; then<br>
&nbsp;&nbsp;&nbsp; insert( new FindAncestor( $parent, $ancestor ) )<br>
end<br>
&nbsp;<br>
rule "retract query parent driver"<br>
&nbsp; salience - 5<br>
&nbsp; when<br>
&nbsp;&nbsp;&nbsp; $f : FindAncestor( $name == name, $ancestor : ancestor )<br>
&nbsp;&nbsp;&nbsp; $child : Person(&nbsp; name == $name, $parent : parent )<br>
&nbsp;&nbsp;&nbsp; $parent : Person( this == $parent, this != ancestor)<br>
&nbsp; then<br>
&nbsp;&nbsp;&nbsp; retract( $f )<br>
end<br>
&nbsp;<br>
rule "ancestor found"<br>
&nbsp; when<br>
&nbsp;&nbsp;&nbsp; FindAncestor( $name == name, $ancestor : ancestor )<br>
&nbsp;&nbsp;&nbsp; $child : Person(&nbsp; name == $name, $parent : parent )<br>
&nbsp;&nbsp;&nbsp; $parent : Person( this == $parent, this == ancestor)<br>
&nbsp; then<br>
&nbsp;&nbsp;&nbsp;&nbsp; println( "is ancestor" )<br>
end<br>
&nbsp;<br>
rule "retract query ancestor found driver"<br>
&nbsp; salience - 5<br>
&nbsp; when<br>
&nbsp;&nbsp;&nbsp; $f : FindAncestor( $name == name, $ancestor : ancestor )<br>
&nbsp;&nbsp;&nbsp; $child : Person(&nbsp; name == $name, $parent : parent )<br>
&nbsp;&nbsp;&nbsp; $parent : Person( this == $parent, this == ancestor)<br>
&nbsp; then<br>
&nbsp;&nbsp;&nbsp; retract( $f )<br>
end<br>
<br>
Mark<br>
Faron Dutton wrote:
<blockquote
 cite="mid:6a1b25220901210714j2947f440i2dd996d35375586e@mail.gmail.com"
 type="cite">
  <pre wrap="">Thanks. I'll look into this.

On Wed, Jan 21, 2009 at 9:46 AM, Anstis, Michael (M.) <a class="moz-txt-link-rfc2396E" href="mailto:manstis1@ford.com">&lt;manstis1@ford.com&gt;</a> wrote:
  </pre>
  <blockquote type="cite">
    <pre wrap="">I wonder whether a custom accumulate function could be used to move your
logic out of the object model?

Not that accumulate was (probably) meant for this sort of function but the
"init" method could create the empty set and "accumulate" perform your
iteration below?

Just the musing of an idle mind.

________________________________
From: <a class="moz-txt-link-abbreviated" href="mailto:rules-users-bounces@lists.jboss.org">rules-users-bounces@lists.jboss.org</a>
[<a class="moz-txt-link-freetext" href="mailto:rules-users-bounces@lists.jboss.org">mailto:rules-users-bounces@lists.jboss.org</a>] On Behalf Of David Sinclair
Sent: 21 January 2009 14:28
To: Rules Users List
Subject: Re: [rules-users] Reasoning over hierarchies.

You could have something along the lines

class Person {
     Person parent;

     Collection getAncestors() {
           Collection&lt;Person&gt; ancestors = new HashSet&lt;Person&gt;();

            Person currentAncestor = parent;

            while(currentAncestor != null) {
                   ancestors.add(currentAncestor);
                   currentAncestor = currentAncestor.getParent();
            }
     }
}

query isAncestor(String a, String b)
   p: Person(name = a)
   c: Person(name = b, ancestors contains p)
end

that should do it

dave

On Wed, Jan 21, 2009 at 8:54 AM, Faron Dutton <a class="moz-txt-link-rfc2396E" href="mailto:fgdutton@gmail.com">&lt;fgdutton@gmail.com&gt;</a> wrote:
    </pre>
    <blockquote type="cite">
      <pre wrap="">I know this has probably been asked before but I cannot find any mention
of
it. How does one reason over a transitive (recursive) relation in Drools?

-----------------------------------------------------------

The classic example from Prolog:

-- The relation parent(P,C) says that P is a parent of C.
parent(P,C).

-- The predicate ancestor(A,B) implies that A is an ancestor
-- of B if A is a parent of B or A is a parent of C and C
-- is an ancestor of B.
ancestor(A,B) :- parent(A,B).
ancestor(A,B) :- parent(A,C), ancestor(C,B).

-- The query ancestor(bob,frank) asks if bob is an ancestor
-- of frank.
?- ancestor(bob,frank).

-----------------------------------------------------------

In Drools, I can find the parent using

query isParent(String a, String b)
   p: Person(name = a)
   c: Person(name = b, parent = p)
end

likewise, I can find the grandparent using

query isGrandparent(String a, String b)
   g: Person(name = a)
   p: Person(parent = g)
   c: Person(name = b, parent = p)
end

I am unable to formulate the query isAncestor.

_______________________________________________
rules-users mailing list
<a class="moz-txt-link-abbreviated" href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a>
<a class="moz-txt-link-freetext" href="https://lists.jboss.org/mailman/listinfo/rules-users">https://lists.jboss.org/mailman/listinfo/rules-users</a>
      </pre>
    </blockquote>
    <pre wrap="">
_______________________________________________
rules-users mailing list
<a class="moz-txt-link-abbreviated" href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a>
<a class="moz-txt-link-freetext" href="https://lists.jboss.org/mailman/listinfo/rules-users">https://lists.jboss.org/mailman/listinfo/rules-users</a>


    </pre>
  </blockquote>
  <pre wrap=""><!---->_______________________________________________
rules-users mailing list
<a class="moz-txt-link-abbreviated" href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a>
<a class="moz-txt-link-freetext" href="https://lists.jboss.org/mailman/listinfo/rules-users">https://lists.jboss.org/mailman/listinfo/rules-users</a>


  </pre>
</blockquote>
<br>
</body>
</html>