JESS vs DROOLS : Backward chaining
Asked Answered
G

2

2

I'm trying to replace Jess with Drools as backward chaining rule engine in our project. I was looking for simple examples about how backward chaining is done with Drools. Interestingly, there's only 1 same example on every site (which I don't get how it's BC but let's forget it for now).

Very trivial example of BC in Jess:

//q is a fact template with a slot named 'n'
//when there's a q with n==8 print something
//I need a q with n==8 to fire a rule so I will insert it myself!

(deftemplate q (slot n))
(do-backward-chaining q)
(defrule printq (q (n 8))   =>  (printout t "n is eight! yeah!" crlf))
(defrule iNeedn8 (need-q (n 8)) => (assert (q (n 8))))
(reset)
(run 1)
//fires printq and prints to console...

Equivalent in Drools:

package com.example;

declare Q
    n : int
end

rule "print q"
when
    Q(n == 8)
then
    System.out.println("n is eight by drools!");
end

//I'M LOST HERE! HELP!

How can I achieve same behaviour with Drools?

Generalize answered 10/6, 2015 at 13:28 Comment(4)
Drools BW chaining isn't the same as Jess' BW chaining, and I think both can't do what Prolog is capable of doing.Smythe
Can't I find which fact is missing (Q(n==8)) for a rule to be fired in Drools? (they differ in functionality, jess is more capable in BWC?)Generalize
I agree with @laune, the two engines implement BWC quite differently and neither, afaik, has the same capabilities of Prolog in this sense. However, the feature is being worked on. It will be documented officially as soon as stable.Baton
@DavideSottara This "documented officially as stable" sounds nice, but the question is: Will it be documented?Smythe
S
1

In Drools, the general idea of BC is to use queries. In addition to your rule "print q" you need:

query noQ( int $num )
    Goal(num==$num) and not Q(num == $num)
end

rule goal when
    Goal( $n: num )
    noQ($n;)
then
    Q q = new Q($n);
    insert( q );
end

rule go when
then
    insert( new Goal( 8 ) );
end

There is no way to instruct Drools to detect the missing fact all by itself; you have to provide the goal and queries to "bridge the gap".

Smythe answered 11/6, 2015 at 6:9 Comment(0)
B
1

Inspired from the Jess feature, there is an experimental, in-development feature that gives you a similar behavior. Here is how a test would look like:

@Test
public void testFindQ8() {
    String droolsSource =
        " package org.drools.abductive.test;                 " +
        "                                                    " +
        " import " + Abducible.class.getName() + ";          " +
        " global java.util.List list;                     \n " +
        "                                                    " +
        " declare Q                                          " +
        "    @Abducible                                      " +
        "    id : int @key                                   " +
        " end                                             \n " +
        "                                                    " +
        " query foo( int $x )                                " +
        "    @Abductive( target=Q.class )                    " +
        "    not Q( $x; )                                    " +
        " end                                             \n " +
        "                                                    " +
        " rule R1                                            " +
        " when                                               " +
        "    $x := foo( 8 ; )                                " +
        " then                                               " +
        "    System.out.println( 'R1 returned ' + $x );      " +
        " end                                             \n " +
        "                                                    " +
        " rule R2                                            " +
        " when                                               " +
        "    $q : Q( 8; )                                    " +
        " then                                               " +
        "    System.out.println( 'We have 8!' );             " +
        " end                                                ";
    /////////////////////////////////////

    KieHelper kieHelper = new KieHelper();
    kieHelper.addContent( droolsSource, ResourceType.DRL ).build().newKieSession().fireAllRules();


}
Baton answered 12/6, 2015 at 5:37 Comment(4)
Thanks , it may be less painful to implement this way. Is there any documentation about @Abductive (how it works), I didn't see any?Generalize
And for @Abducible as well?Smythe
As mentioned, the feature is extremely experimental, so subject to change. Anything documented officially requires the same level of stability of an API. The option of splitting the documentation between "stable" and "experimental" features, to allow for this kind of things, has been discussedBaton
This said, at the moment, "@Abductive" queries will try to insert an instance of the "target" class, if not already present in the WM, for each result tuple. The instance is constructed using the result tuple itself. Other than this, the TMS does not really support abductive reasoning yet. You can follow updates and new capabilities here on the JIRA ticket issues.jboss.org/browse/DROOLS-371 And the unit tests github.com/droolsjbpm/drools/blob/master/drools-compiler/src/…Baton

© 2022 - 2024 — McMap. All rights reserved.