In the absence of an accumulate in current drools 3 version, I tried to create a set of rules to have some sort of running sum (or any other accumulation function), but it needs as much as 3 helper objects per object qualified for accumulation.

Anybody any ideas on reducing number of helper objects and retracts/asserts? via xor-groups or no-loops?

one helper (price == -3) especially prevents looping of accumulate if sum is modified by de-accumulate if some other object no longer qualifies. Is it possible to have some sort of "no-loop" groups, where RHS changes in working memory will not only not trigger activation of the current rule but all rules in a group?

Integration test listed below.

I misused Cheese as helper object, didn't want to create a new class: type="sum" holds accumulated sum, type="limit reached" is used as flag indicating sum boundary crossings, (type=s, price elem { -1, -2, -3}) state accumulation status of qualified object s (Strings in this case); where s.length() will be accumulated

Is it possible to have some sort of "retraction hook/listener" on asserted objects by letting them implement a special interface? This implementation assumes that if an object does not longer qualify (e.g. is retracted), it will nevertheless be available (via helper, price == -1) for de-accumulation when the rules are fired again.

Juergen


----------------------------------------------------------
/*
    public void testLogicalAssertionsRunningSum() throws Exception {
        PackageBuilder builder = new PackageBuilder();
builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "test_LogicalAssertionsRunningSum.drl" ) ) );
        Package pkg = builder.getPackage();

        RuleBase ruleBase = getRuleBase();
        ruleBase.addPackage( pkg );
        WorkingMemory workingMemory = ruleBase.newWorkingMemory();

//workingMemory.addEventListener(new org.drools.event.DebugAgendaEventListener()); //workingMemory.addEventListener(new org.drools.event.DebugWorkingMemoryEventListener());

        List list;

        Cheese c = new Cheese("sum", 0);

        FactHandle h = workingMemory.assertObject(c);
        FactHandle h1 = workingMemory.assertObject("1");
        workingMemory.fireAllRules();
        assertEquals(1, c.getPrice());
                System.err.println("sum in code=" + c);
        FactHandle h2 = workingMemory.assertObject("123");
        workingMemory.fireAllRules();
        assertEquals(4, c.getPrice());
                System.err.println("sum in code=" + c);
        FactHandle h3 = workingMemory.assertObject("12");
        workingMemory.fireAllRules();
        assertEquals(6, c.getPrice());
                System.err.println("sum in code=" + c);
        workingMemory.retractObject( h1 );
        workingMemory.fireAllRules();
        assertEquals(5, c.getPrice());
                System.err.println("sum in code=" + c);
        workingMemory.retractObject( h2 );
        workingMemory.fireAllRules();
        assertEquals(2, c.getPrice());
                System.err.println("sum in code=" + c);
        workingMemory.retractObject( h3 );
        workingMemory.fireAllRules();
        assertEquals(0, c.getPrice());
                System.err.println("sum in code=" + c);
    }
*/
package org.drools.test;

import java.lang.String;
import org.drools.Cheese;

rule "object qualifies for accumulation"
    when
        s : String()
        eval(s != "sum" && s != "limit reached")
    then
        Cheese c = new Cheese(s, -1);
                assert(c);
                assertLogical(new Cheese(c.getType(), -2));
end

rule "accumulate"
        when
                sum : Cheese(type == "sum")
                Cheese(s : type, price == -1)
                Cheese(type == s, price == -2)
                not Cheese(type == s, price == -3)
        then
                //apply accumulate function
                sum.setPrice(sum.getPrice() + s.length());
                
                modify(sum);
                assert(new Cheese(s, -3));
                System.err.println("+sum=" + sum);
end

rule "de-accumulate"
        when
                sum : Cheese(type == "sum")
                c : Cheese(s : type, price == -1)
                a : Cheese(type == s, price == -3)
                not Cheese(type == s, price == -2)
        then
                //apply inverse function
                sum.setPrice(sum.getPrice() - s.length());
                
                modify(sum);
                retract(c);
                retract(a);
                System.err.println("-sum=" + sum);
end

rule "do-something-when-limit-reached"
        when
                Cheese(type == "sum", price > 3)
                not Cheese(type == "limit reached")
        then
                assert(new Cheese("limit reached", -1));
                System.err.println("limit reached");
end

rule "do-something-when-limit-below"
        when
                Cheese(type == "sum", price <= 3)
                c : Cheese(type == "limit reached")
        then
                retract(c);
                System.err.println("limit below");
end

Reply via email to