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-boun...@lists.jboss.org 
[mailto:rules-users-boun...@lists.jboss.org] On Behalf Of Mark Proctor
Sent: Tuesday, April 24, 2012 9:12 PM
To: rules-users@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-boun...@lists.jboss.org 
> [mailto:rules-users-boun...@lists.jboss.org] On Behalf Of Welsh, Armand
> Sent: Monday, April 23, 2012 3:22 PM
> To: rules-users@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-boun...@lists.jboss.org 
> [mailto:rules-users-boun...@lists.jboss.org] On Behalf Of Christopher Dolan
> Sent: Monday, April 23, 2012 1:01 PM
> To: rules-users@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@lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users
>
> _______________________________________________
> rules-users mailing list
> rules-users@lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users
>
> _______________________________________________
> rules-users mailing list
> rules-users@lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users

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

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

Reply via email to