[rules-users] insertLogical and modifyRetract (drools-solver)

tim tim timbaermannextra at googlemail.com
Tue Oct 7 15:18:18 EDT 2008


ups, i created a nice endless loop with my proposed solution. :-)

the correct (still ugly) solution is:

rule "fact1 should be smaller then 1"
    when
        $f : UserFact($fact1 : fact1 >= 1)
           not IntConstraintOccurence(
                              ruleId == "fact1 should be smaller then 1",
                              constraintType ==
ConstraintType.NEGATIVE_SOFT,
                             causes contains $f,
                             weight != $fact1)  // the weight has to be
different, else the rule should not fire

    then
          // use the value of fact1 to determine the error
          insertLogical(new IntConstraintOccurence("fact1 should be smaller
then 1", $fact1, $f ));
end

rule "fact1 should be smaller then 1, old constraint exists"
    when
        $f : UserFact($fact1 : fact1 >= 1);

        // see if there is already a fact in the
        $oldConstraint : IntConstraintOccurence(
                              ruleId == "fact1 should be smaller then 1",
                              constraintType ==
ConstraintType.NEGATIVE_SOFT,
                             causes contains $f,
                             weight != $fact1)  // the weight has to be
different, else the rule should not fire
then
           retract($oldConstraint); // manually retract the obsolete fact
          // use the value of fact1 to determine the error
          insertLogical(new IntConstraintOccurence("fact1 should be smaller
then 1",ConstraintType.NEGATIVE_SOFT,  $fact1, $f ));
end





On Tue, Oct 7, 2008 at 6:59 PM, tim tim <timbaermannextra at googlemail.com>wrote:

> thanks, you are right, that is kind of a solution. but not really what i am
> looking for.
> i am using drools-solver, and the "CreatedFact" is an
> IntConstraintOccurrence, which i do not want to change.
>
> maybe i should make the example more specific for my problem.
>
> i have a rule, used for the solver:
>
> rule "fact1 should be smaller then 1"
>     when
>         $f : UserFact(fact1 >= 1);
>     then
>           // use the value of fact1 to determine the error
>           insertLogical(new IntConstraintOccurence("fact1 should be smaller
> then 1", $f.getFact1(), $f ));
> end
>
>
> i have a Move that decrements fact1, so that after the move the error
> should be 1 smaller.
> but the move is almost never triggered, because the old constraintOccurence
> is not retracted from memory and the new one added anyway,
> hence the error is nearly double after the move, as now two
> constraintOccurences represent the same error.
>
>
> what i could think of is something like this:
>
> one rule for the first test:
>
> rule "fact1 should be smaller then 1"
>     when
>         $f : UserFact(fact1 >= 1)
>            not IntConstraintOccurence(
>                               ruleId == "fact1 should be smaller then 1",
>                               constraintType ==
> ConstraintType.NEGATIVE_SOFT,
>                              causes contains $f)
>     then
>           // use the value of fact1 to determine the error
>           insertLogical(new IntConstraintOccurence("fact1 should be smaller
> then 1", $f.getFact1(), $f ));
> end
>
> and a second rule, when the first rule has already fired before:
>
> rule "fact1 should be smaller then 1, old constraint exists"
>     when
>         $f : UserFact(fact1 >= 1);
>
>         // see if there is already a fact in the
>         $oldConstraint : IntConstraintOccurence(
>                               ruleId == "fact1 should be smaller then 1",
>                               constraintType ==
> ConstraintType.NEGATIVE_SOFT,
>                              causes contains $f)
> then
>            retract($oldConstraint); // manually retract the obsolete fact
>           // use the value of fact1 to determine the error
>           insertLogical(new IntConstraintOccurence("fact1 should be smaller
> then 1",ConstraintType.NEGATIVE_SOFT,  $f.getFact1(), $f ));
> end
>
> this solution seems very verbose for such a common task. and again, i do
> not understand, why an obsolete fact is not
> retracted automatically?
>
> best, tim
>
> On Tue, Oct 7, 2008 at 5:57 PM, Gras, Patrick <Patrick.Gras at generali.ch>wrote:
>
>>  Hello,
>>
>> If you can change the code for CreatedFact and let it have a reference to
>> UserFact and change the rule to:
>>
>> rule "fact = 1"
>>     when
>>         $f : UserFact(fact1 == 1);
>>     then
>>           insertLogical(new CreatedFact($f));
>> end
>> you will also have to overide equals and hashcode for CreatedFact so that
>> several CreatedFacts referencing the same UserFact are considered equal...
>>
>> But with this solution CreatedFact will always be up to date with the
>> value of UserFact even without firing the rules and maybe it's not what you
>> want...
>>
>> -Patrick
>>
>> -----Message d'origine-----
>> *De :* rules-users-bounces at lists.jboss.org [mailto:
>> rules-users-bounces at lists.jboss.org]*De la part de* tim tim
>> *Envoyé :* mardi, 7. octobre 2008 16:53
>> *À :* rules-users at lists.jboss.org
>> *Objet :* [rules-users] insertLogical and modifyRetract
>>
>> Hello,
>>
>> I am a bit confused about how insertLogical() supposed to work in drools
>> 5.
>>
>> when i have a rule such as:
>>
>> rule "fact = 1"
>>     when
>>         $f : UserFact(fact1 == 1);
>>     then
>>           insertLogical(new CreatedFact($f.getFact2()));
>> end
>>
>> now i change $f in such a way, that the rule will fire again.
>> via
>>
>> // build first version
>> UserFact f = new UserFact();
>> f.setFact1(1);
>> f.setFact2(1);
>>
>> memory.insert(f);
>> memory.fireAllRules(); // <- Rule fires once
>>
>> // now i change the memory and fire the rules again
>>
>> memory.modifyRetract(f) ;
>> f.setFact2(100); // <- changing $f, but leaving fact1 as it is.
>> memory.modifyInsert(f);
>>
>> memory.fireAllRules();  // <- Rule fires again
>>
>> now the rule should fire again, which it does.
>> but i end up with two CreatedFact instances in the workingMemory..
>> one with the old OtherFact value 1, and one with the new value, 100
>>
>> but i want only the second instance. the one created first is not valid
>> any more.
>> i could write an extra rule for retracting the first CreatedFact-fact, but
>> then i would have
>> a very tight coupling of the two rules.
>>
>> is there a better way?
>> it seems odd to me, that a consequence of a rule stays in memory, when
>> there is
>> a more current version of the rule evocation with the _same_ facts in the
>> precondition
>> and a different consequence.
>>
>> thanks in advance, tim
>>
>>
>> _______________________________________________
>> rules-users mailing list
>> rules-users at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-users
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/rules-users/attachments/20081007/27085687/attachment.html 


More information about the rules-users mailing list