[rules-users] Help needed - Problems with forall operator

Wolfgang Laun wolfgang.laun at gmail.com
Sat Nov 7 03:55:37 EST 2009


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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/rules-users/attachments/20091107/9bc576d5/attachment.html 


More information about the rules-users mailing list