evaluating lhs that contains eval() in KIE with PHREAK vs. RETEOO

655 views
Skip to first unread message

Christian Tellu

unread,
Jun 17, 2015, 9:06:23 AM6/17/15
to drools...@googlegroups.com
Hello,

I am trying to identify a different behaviour that my rules have when I switched to PHREAK.

I made a simple test file that is attached.

Essentially I identify the problem until now as having to do with how the LHS of rules is being evaluated, and in particular when these have eval() calls.

It seams that KIE with RETEOO (option on) evaluates the LHS when I insert a fact. Then triggers the RHS of the matched rules when I fireAllRules

But with PHREAK the LHS is not evaluated on insert() but only on fireAllRules

If this is correct, it would be nice if someone can confirm that this is the intended behaviour of the new KIE. Maybe a little more explanation could be useful.

More details why this is an issue for me:
I have two rules R1, R2 that both match on one Fact. But firing one rule R1 the RHS changes the Fact on which the rule fires, using home-made Java code (not the KIE way, like update).

rule R1 salience 10
when $a : MyAsset(variables contains 'V1')"
eval($a.getVarId('100') > 0)
then $a.removeVariable('V1'); end

rule R2
when $a : MyAsset(variables contains 'V2')"
then System.out.println("do something"); end

MyAsset contains both variables V1 and V2.

The RETEOO makes first both these matches (on the insert) and then fires both (on fireAllRules) .

The PHREAK makes (in fireAllRules) the first match and fires the RHS that changes the Fact without the agenda to know about it. Then he tries to fire the second rule, but it did not evaluate yet the eval(), which he does now. But this fails now after the R1 RHS update. This eval() would have succeed if it would have been evaluated at the same time as the Fact match is evaluated.
So this tells me that some optimization in the PHREAK alg matches facts at some point and checks eval() at some later point.

Is this how it is intended ?

Note also that firing the two rules should be in any order, if they have the same salience, and indeed KIE does it, so I could see this behaviour only some of the runs, until I realized and put the salience.

The test and two simple rules above are an oversimplification of the rules I have to port to the new KIE.

I guess my problem with eval() being checked at a different time, would be solved if I used update/modify to tell the agenda that some fact was changed. So probably the assumption that the optimization of PHREAK makes, that update/modify is always used in such situations, is sound. Any comment on these aspects is welcomed.

thank you very much for your time,
have a nice week,
christian
EvalTest.java

Mark Proctor

unread,
Jun 17, 2015, 11:04:01 AM6/17/15
to drools...@googlegroups.com
On 17 Jun 2015, at 14:06, Christian Tellu <christian...@tellu.no> wrote:

Hello,

I am trying to identify a different behaviour that my rules have when I switched to PHREAK.

I made a simple test file that is attached.

Essentially I identify the problem until now as having to do with how the LHS of rules is being evaluated, and in particular when these have eval() calls.

It seams that KIE with RETEOO (option on) evaluates the LHS when I insert a fact. Then triggers the RHS of the matched rules when I fireAllRules

But with PHREAK the LHS is not evaluated on insert() but only on fireAllRules

If this is correct, it would be nice if someone can confirm that this is the intended behaviour of the new KIE. Maybe a little more explanation could be useful.
This is correct. I wrote a blog on this and this is also in the documentation.
"There are two key RETE characteristics that strongly identify any derivative strains, regardless of optimizations. That it is an eager, data oriented algorithm. Where all work is done during the insert, update or delete actions; eagerly producing all partial matches for all rules. PHREAK in contrast is characterised as a lazy, goal oriented algorithm; where partial matching is aggressively delayed.”



More details why this is an issue for me:
I have two rules R1, R2 that both match on one Fact. But firing one rule R1 the RHS changes the Fact on which the rule fires, using home-made Java code (not the KIE way, like update).

rule R1 salience 10
when $a : MyAsset(variables contains 'V1')"
eval($a.getVarId('100') > 0)
then $a.removeVariable('V1'); end

rule R2
when $a : MyAsset(variables contains 'V2')"
then System.out.println("do something"); end

MyAsset contains both variables V1 and V2.

The RETEOO makes first both these matches (on the insert) and then fires both (on fireAllRules) .

The PHREAK makes (in fireAllRules) the first match and fires the RHS that changes the Fact without the agenda to know about it. Then he tries to fire the second rule, but it did not evaluate yet the eval(), which he does now. But this fails now after the R1 RHS update. This eval() would have succeed if it would have been evaluated at the same time as the Fact match is evaluated.
So this tells me that some optimization in the PHREAK alg matches facts at some point and checks eval() at some later point.

Is this how it is intended ?
Not sure why that would be, as R2 is looking for V2, which isn’t yet removed? so even if R1 removes V1, V2 is still there for R2 to match.


Note also that firing the two rules should be in any order, if they have the same salience, and indeed KIE does it, so I could see this behaviour only some of the runs, until I realized and put the salience.

The test and two simple rules above are an oversimplification of the rules I have to port to the new KIE.

I guess my problem with eval() being checked at a different time, would be solved if I used update/modify to tell the agenda that some fact was changed. So probably the assumption that the optimization of PHREAK makes, that update/modify is always used in such situations, is sound. Any comment on these aspects is welcomed.

Something else to be aware of. Rule are now evaluated in the order they appear in a rule fire, when they have equal salience. So rules are ordered by salience and then by file position.

thank you very much for your time,
have a nice week,
christian

--
You received this message because you are subscribed to the Google Groups "Drools Usage" group.
To unsubscribe from this group and stop receiving emails from it, send an email to drools-usage...@googlegroups.com.
To post to this group, send email to drools...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/drools-usage/c34c6e30-49b5-4eea-91b8-a98f873f8f40%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
<EvalTest.java>

Christian Tellu

unread,
Jun 17, 2015, 11:47:23 AM6/17/15
to drools...@googlegroups.com
Thank you very much Mark.

I must apologise for my sloppiness when simplifying the rules example.
The above two rules should be like:


rule R1 salience 10
when $a : MyAsset(variables contains 'V1')"
then $a.removeVariable('V2'); end


rule R2
when $a : MyAsset(variables contains 'V2')"
eval($a.getVarId('V2') > 0)
then System.out.println("do something"); end

The first rule matches on V1 and disables the second rule by removing V2.
Only in the second rule I would have also an eval(). This will fail because the V2 is not in the Collection of variables and the function needs to work on this.

Note that in the second R2 we can make an _assumption_ that in the eval(), the Collection of variables will contain V2 (because this is what the first part of the match says). Therefore we would not get NullPointerException if we try to get the value of this V2 from the Collection.
But this assumption is broken by the fact that eval() is evaluated later, when the V2 was removed by another rule.

The standard KIE solution that I can see is to add the
   update($a)
whenever I update a fact manually (as I do above).
In this case the first rule would become

rule R1 salience 10
when $a : MyAsset(variables contains 'V1', variables contains 'V2')"
then $a.removeVariable('V2');
update($a); end

But my question about _when is eval() evaluated_ still remains for me ?

(Note in the rule now two checks, so that we avoid infinite look matching the same rule over and over.)

thank you for your answer and time,

have a nice week,
christian

PS: just for completeness, the MyAsset and the getVarId() would be implemented in a very simple way as:

public class MyAsset{
public Map<String, long> storedVariables = new HashMap<String, long>();

public Set<String> getVariables() {
                return storedVariables.keySet();
        }
public long getVarId(String key){
//            if(storedVariables.get(key) == null){return 0;} // without this a NullPointerException appears when evaluating eval()
            return storedVariables.get(key);
        }
}


PPS : thank you for the links to the blog post. I read through it at some point but forgot things, it seams.
And if you answer that eval() is evaluated later, part of the lazy way of PHREAK, then I can understand that this optimization should go hand in hand with the assumption that we should be using standard update/modify constructs. And not do changes manually, without telling the agenda about them (as I did).

Christian Tellu

unread,
Jun 17, 2015, 12:09:47 PM6/17/15
to drools...@googlegroups.com
I would like to add to the above, a strange behaviour of RETEOO.

If I run the above test with RETEOO I get both rules fired.
But the intuition says that the rule R1 with salience higher should fire first, and thus cancel the second rule firing.

The above assumption holds in RETEOO _only_ when using the standard Drools operators of update/modify in RHS.

Mark Proctor

unread,
Jun 17, 2015, 12:22:24 PM6/17/15
to drools...@googlegroups.com
On 17 Jun 2015, at 16:47, Christian Tellu <christian...@tellu.no> wrote:

Thank you very much Mark.

I must apologise for my sloppiness when simplifying the rules example.
The above two rules should be like:

rule R1 salience 10
when $a : MyAsset(variables contains 'V1')"
then $a.removeVariable('V2'); end

rule R2
when $a : MyAsset(variables contains 'V2')"
eval($a.getVarId('V2') > 0)
then System.out.println("do something"); end

The first rule matches on V1 and disables the second rule by removing V2.
Only in the second rule I would have also an eval(). This will fail because the V2 is not in the Collection of variables and the function needs to work on this.

Note that in the second R2 we can make an _assumption_ that in the eval(), the Collection of variables will contain V2 (because this is what the first part of the match says). Therefore we would not get NullPointerException if we try to get the value of this V2 from the Collection.
But this assumption is broken by the fact that eval() is evaluated later, when the V2 was removed by another rule.

The standard KIE solution that I can see is to add the
   update($a)
whenever I update a fact manually (as I do above).
In this case the first rule would become

rule R1 salience 10
when $a : MyAsset(variables contains 'V1', variables contains 'V2')"
then $a.removeVariable('V2');
update($a); end

But my question about _when is eval() evaluated_ still remains for me ?
Why?

as you noted before it’s not done at insert time any more. It’s delayed to fireAllRules and it will evaluate each rule in turn. So it will evaluate and fire R1 and then evaluate and and if true fire R2.

In 6.3 we’ve added propagation type support, that would help you fine tune this:

Note 6.3 is still in beta.

But EAGER or IMMEDIATE would both give you the RETE like behaviour you want. You can see a conversation thread about this here:

Mark

Mark Proctor

unread,
Jun 17, 2015, 12:23:44 PM6/17/15
to drools...@googlegroups.com
On 17 Jun 2015, at 17:09, Christian Tellu <christian...@tellu.no> wrote:

I would like to add to the above, a strange behaviour of RETEOO.

If I run the above test with RETEOO I get both rules fired.
But the intuition says that the rule R1 with salience higher should fire first, and thus cancel the second rule firing.

The above assumption holds in RETEOO _only_ when using the standard Drools operators of update/modify in RHS.
This is expected, otherwise Drools will not know the data is changed and that it needs re-evaluating.
Reply all
Reply to author
Forward
0 new messages