[rules-users] Help needed - Problems with forall operator
Edson Tirelli
ed.tirelli at gmail.com
Sat Nov 7 09:27:25 EST 2009
Yap, Wolfgang has the picture right. Just 2 clarifications:
* A single pattern forall in Drools is a syntax sugar to a multi-pattern
forall in the following way:
forall( Pattern( <constraints> ) )
=>
forall( $p : Pattern()
Pattern( this == $p, <constraints> )
In other words, drools uses the fact type to define the domain and apply
the constraints to all objects in that domain.
* "not" is the quantifier CE that means "not exists". If you explicitly
write "not( exists ( ) )", the "exists" is redundant, but not eliminated
automatically by Drools yet. So, you are wasting quite a lot of performance,
since that forces drools to create a subnetwork in Rete. For Drools 5.1 and
forward I will automatically eliminate the exists during the logical
transformation step, but up to 5.0.x, you need to do it manually.
Edson
2009/11/7 Wolfgang Laun <wolfgang.laun at gmail.com>
> Here's the explanation why Tom's version does not work. The first pattern
> of a "forall" defines the domain, which is: all CreditReport facts; for each
> object in this domain, the remaining patterns must match; since the FICO
> pattern merely ascertains the existence of a single FICO chained to a parent
> CreditReport with validScoreIndicator false, it fires as soon as there is
> one for each of the existing CreditReports.
>
> Jared's solution has the CreditReport CE in front of the forall, unadorned
> with any quantifier, and the innate behavior of Drools makes sure that the
> hole thing will be tried, once, for any existing CreditReport anyway. Then,
> the forall domain is now FICOs with that CR's id and valid == false - but
> what is the CE? I guess that Drool's behavior is somewhat off the
> definition, using just FICO() - i.e., all existing FICO objects - as the
> domain. (However, I think that Edson changed this recently for 5.1.0.) Thus,
> Jared's rule indeed fires only when all FICOs are linked to the CreditReport
> are false, but it fails to do so as soon as there is at least one other FICO
> with either a different parent, or valid.
>
> Therefore, to be on the safe side with multiple CreditReport facts and
> assorted FICO's being in WM at the same time, I propose this rule:
>
> rule "somerule2"
>
> when
> report: CreditReport( $parentCreditReport_1_Id : myId)
> forall ( $f : FICO( parentId == $parentCreditReport_1_Id )
> FICO( this == $f, validScoreIndicator == false) )
> then
> System.out.println("somerule2 fired on " + $parentCreditReport_1_Id );
> end
>
> Here, the domain is explicitly given as all FICOs of the current CR; and
> for all of them valid must be false.
>
> Still, this solution is not perfect: It would also fire in the absence of
> any FICO for some CR. To fix this, add a guard against there being no FICOs
> for the current CR:
>
>
> report: CreditReport( $parentCreditReport_1_Id : myId)
> exists FICO( parentId == $parentCreditReport_1_Id )
> forall ( $f : FICO( parentId == $parentCreditReport_1_Id )
> FICO( this == $f, validScoreIndicator == false) )
>
> To complete the picture, one might equally well use the negation of forall,
> which would have to be propagated into the predicate (read '|' as "so
> that"):
> forall x in D | P(x) => not existst x in D | not P(x)
>
> Now the condition delimiting the domain and the negated predicate can be
> merged again into one CE:
>
> rule "somerule3"
>
> when
> report: CreditReport( $parentCreditReport_1_Id : myId)
> exists FiCo( parentId == $parentCreditReport_1_Id )
> not ( exists FiCo( parentId == $parentCreditReport_1_Id, validScore ==
> true) )
> then
> System.out.println("somerule3 fired on " + $parentCreditReport_1_Id );
> end
>
> -W
>
>
> On Fri, Nov 6, 2009 at 9:45 PM, Jared Davis <sunray at davisprogramming.com>wrote:
>
>> I think this usage may work for your case.
>>
>> rule "somerule"
>> when
>> report: CreditReport( $parentCreditReport_1_Id : myId)
>> forall (
>> FICO( parentId == $parentCreditReport_1_Id, validScoreIndicator ==
>> false)
>> )
>> then
>> System.out.print("Fired on " + $parentCreditReport_1_Id );
>> end
>>
>>
>>
>> _______________________________________________
>> rules-users mailing list
>> rules-users at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-users
>>
>
>
--
Edson Tirelli
JBoss Drools Core Development
JBoss by Red Hat @ www.jboss.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/rules-users/attachments/20091107/566c650a/attachment.html
More information about the rules-users
mailing list