[rules-users] Best practice for 0..1 relations

Christopher Dolan christopher.dolan at avid.com
Wed Apr 25 14:39:14 EDT 2012


Aha, that makes sense! I didn't realize you could bind a variable from two different branches of an "or". Following that pattern, my strawman rule becomes this:

    rule "household income"
        when
            $p1 : Person()
            ((not Relation(person1 == $p1, type == "spouse") and $p2income : int from 0) or
             Relation(person1 == $p1, type == "spouse", $p2income: person2.getIncome()))
        then
            insertLogical(new Income($p1.getIncome() + $p2income));
    end

Thanks! That's a good compromise of readability and maintainability.
Chris

-----Original Message-----
From: rules-users-bounces at lists.jboss.org [mailto:rules-users-bounces at lists.jboss.org] On Behalf Of Mark Proctor
Sent: Tuesday, April 24, 2012 9:12 PM
To: rules-users at lists.jboss.org
Subject: Re: [rules-users] Best practice for 0..1 relations

On 23/04/2012 21:31, Christopher Dolan wrote:
> Sorry, I wasn't clear... In the example, it's the spouse that's the optional fact. I want the rule to fire whether or not a spouse exists, but the RHS computes the income differently if a spouse exists or not. If a spouse is added/removed, I want the rule to re-fire and the income should be changed.
Take a look at my Pong game and the "Create Ball" rule
https://github.com/droolsjbpm/drools/blob/master/drools-examples/src/main/resources/org/drools/games/pong/init.drl

I create a ball with different dx directions depend on different states, 
all from within one rule:

rule "Create Ball" when
      not Ball()
      ( PointWin(player.id == PlayerId.PlayerOne ) and dx : Number() from 2 ) or
      ( PointWin(player.id == PlayerId.PlayerTwo ) and dx : Number() from -2 ) or
      ( not PointWin( ) and dx : Number() from -2 )
then
     ball = new Ball( (pconf.tableWidth/2)-(pconf.ballWidth/2),
                      (pconf.tableHeight/2)-(pconf.ballWidth/2),
                       pconf.ballWidth);
     ball.speed = pconf.ballStartingSpeed;
     ball.dx = dx;
     insert( ball );
end


>
> Chris
>
> -----Original Message-----
> From: rules-users-bounces at lists.jboss.org [mailto:rules-users-bounces at lists.jboss.org] On Behalf Of Welsh, Armand
> Sent: Monday, April 23, 2012 3:22 PM
> To: rules-users at lists.jboss.org
> Subject: Re: [rules-users] Best practice for 0..1 relations
>
> So, I assume the fact that is not needed in the LHS is Income.
>
> By inserting Income into Working Memory, you are subjecting it to rete evaluation against the current knowledge tree.  I consider the cost of each operation.  Insert is very costly, and insertLogical even more costly.
>
> I don't know anything about how your data model is built, but based on this very simple example, I would think you would be better off with a Global like this:
>
> Global Income income
>
> Style 1: one rule for each scenario
>      rule "household income, single"
>          when
>              $p1 : Person()
>              not Relation(person1 == $p1, type == "spouse")
>          then
>              income = new Income($p1.getIncome());
>      end
>      rule "household income, married"
>          when
>              $p1 : Person()
>              Relation(person1 == $p1, type == "spouse", $p2: person2)
>          then
>              income = new Income($p1.getIncome() + $p2.getIncome());
>      end
>
> Style 2: a single rule with a collection
>      rule "household income "
>          when
>              $p1 : Person()
>              $rels : List() from collect(Relation($p1 == person1, type == "spouse"))
>          then
>              income = new Income($p1.getIncome() + ($rels.size() == 0 ? 0 : $rels.get(0).getPerson2().getIncome());
>      end
>
> Then in code, you can get the Global value to determine what it got set to, if you need outside of the Drools processing.  All thread safety factors must be considered in a multi-threaded environment.  Global are not objects know to rete, and therefore, use of them is very fast in the LHS.  And the RHS is never aware of changes to Globals (drools assumes them to be static values, that do not change) so care must be taken if using them in the RHS of rules, which I would advise against doing except for special cases where you know a change in the global variable won't be a problem (such as this simple scenario where the global is not used in the RHS at all).
>
> -----Original Message-----
> From: rules-users-bounces at lists.jboss.org [mailto:rules-users-bounces at lists.jboss.org] On Behalf Of Christopher Dolan
> Sent: Monday, April 23, 2012 1:01 PM
> To: rules-users at lists.jboss.org
> Subject: [rules-users] Best practice for 0..1 relations
>
> What's the best way to encode a fact that's needed in the RHS but is not important in the LHS?
>
> Consider a contrived example of computing total household income for single or married persons. I can think of two ways to encode this rule, but I don't like either of them:
>
> Style 1: one rule for each scenario
>      rule "household income, single"
>          when
>              $p1 : Person()
>              not Relation(person1 == $p1, type == "spouse")
>          then
>              insertLogical(new Income($p1.getIncome()));
>      end
>      rule "household income, married"
>          when
>              $p1 : Person()
>              Relation(person1 == $p1, type == "spouse", $p2: person2)
>          then
>              insertLogical(new Income($p1.getIncome() + $p2.getIncome()));
>      end
>
> Style 2: a single rule with a collection
>      rule "household income "
>          when
>              $p1 : Person()
>              $rels : List() from collect(Relation($p1 == person1, type == "spouse"))
>          then
>              insertLogical(new Income($p1.getIncome() + ($rels.size() == 0 ? 0 : $rels.get(0).getPerson2().getIncome()));
>      end
>
>
> (please ignore the bug that the income may get inserted twice because people are spouses of each other)
>
>
> Style 1 is more verbose, but more straightforward: it's how I think of the problem intuitively. Style 2 is much more compact, and is more maintainable if I need to add more predicates or a more complicated RHS. But the idea of needing a List when I know there will be exactly 0 or 1 related facts just seems wrong.
>
> I've searched for some LHS syntax that assigns a variable without participating in boolean evaluation, but I've failed to find anything.
>
> Chris
>
>
> _______________________________________________
> rules-users mailing list
> rules-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users
>
> _______________________________________________
> rules-users mailing list
> rules-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users
>
> _______________________________________________
> rules-users mailing list
> rules-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users

_______________________________________________
rules-users mailing list
rules-users at lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users



More information about the rules-users mailing list