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(a)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(a)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(a)lists.jboss.org [mailto:
> rules-users-bounces(a)lists.jboss.org]*De la part de* tim tim
> *Envoyé :* mardi, 7. octobre 2008 16:53
> *À :* rules-users(a)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(a)lists.jboss.org
>
https://lists.jboss.org/mailman/listinfo/rules-users
>
>