[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