Although most folks won't complain, my only comment here is that the logic is 
all contained in the action side (RHS) of the rule in the form of if-then-else 
statements (basic Java) followed by more if-then-else (more basic Java) 
statements.  This is basically procedural code put into a rulebase in a 
procedural manner.  This begs the question, "Is a rulebase actually needed for 
this problem?"  Not the way is has been solved here.  

I kind of like Wolfgang's original solution on 5 Jan which would be more of a 
rulebase approach and would make maintenance at a later date much easier.  Yes, 
it has more rules (which is the object of a rulebase), BUT the logic is 
properly defined on the LHS where it belongs and each rule is independently 
incremental as it should be.  Also, using the rulebase approach would allow 
expansion of the basic problem into more complex problems later on.
 

SDG
jco


On Jan 7, 2011, at 8:15 AM, Derek Adams wrote:

> Thanks for the help guys.  Here is what I ended up with.  This works, but I'm 
> sure it's not the most efficient way to solve the problem.
> 
> (defrule setCalculatedCostGCI20k5k
>     (HrBenefitJoin (hrBenefitConfigId "00001-0000000076")(benefitJoinId 
> ?bjid)(calculatedCost ?cost)(OBJECT ?obj)(coveredPersonId 
> ?cPer)(payingPersonId ?pPer)(relationshipId ?rel))
>     (Person (personId ?cPer)(dob ?dob)(OBJECT ?objP))
> =>
>     (printout t "age = " (call ?objP calcAgeAsOf(call 
> com.arahant.utils.DateUtils now )) " for " ?bjid " " crlf)
> 
>     (if (eq ?rel nil) then
>         (if (< (call ?objP calcAgeAsOf(call com.arahant.utils.DateUtils now 
> )) 30) then
>             (call ?obj overrideAgeCost 11.55)
>          else (if (< (call ?objP calcAgeAsOf(call com.arahant.utils.DateUtils 
> now )) 40) then
>                 (call ?obj overrideAgeCost 18.95)
>               else (if (< (call ?objP calcAgeAsOf(call 
> com.arahant.utils.DateUtils now )) 50) then
>                     (call ?obj overrideAgeCost 38.35)
>                     else (if (< (call ?objP calcAgeAsOf(call 
> com.arahant.utils.DateUtils now )) 60) then
>                         (call ?obj overrideAgeCost 65.95)
>                           else (if (< (call ?objP calcAgeAsOf(call 
> com.arahant.utils.DateUtils now )) 70) then
>                                     (call ?obj overrideAgeCost 104.35)
>                                 else
>                                     (printout t "age greater than 69 ... " 
> (call ?objP calcAgeAsOf(call com.arahant.utils.DateUtils now )) " for " ?bjid 
> " " crlf))))))
>      else (if (neq ?rel nil) then
>                 (if (< (call ?objP calcAgeAsOf(call 
> com.arahant.utils.DateUtils now )) 30) then
>                     (call ?obj overrideAgeCost 4.20)
>                  else (if (< (call ?objP calcAgeAsOf(call 
> com.arahant.utils.DateUtils now )) 40) then
>                         (call ?obj overrideAgeCost 6.05)
>                       else (if (< (call ?objP calcAgeAsOf(call 
> com.arahant.utils.DateUtils now )) 50) then
>                             (call ?obj overrideAgeCost 10.90)
>                             else (if (< (call ?objP calcAgeAsOf(call 
> com.arahant.utils.DateUtils now )) 60) then
>                                 (call ?obj overrideAgeCost 17.80)
>                                   else (if (< (call ?objP calcAgeAsOf(call 
> com.arahant.utils.DateUtils now )) 70) then
>                                             (call ?obj overrideAgeCost 27.40)
>                                         else
>                                             (printout t "age greater than 69 
> ... " (call ?objP calcAgeAsOf(call com.arahant.utils.DateUtils now )) " for " 
> ?bjid " " crlf))))))))
>     (printout t "setCalculatedCostGCI function fired for " ?bjid ". 
> overrideAgeCost =  " (call ?obj overrideAgeCost) crlf)
> ;    (printout t "setCalculatedCostGCI function fired for " ?bjid " " crlf)
> 
> )
> 
> On Thu, Jan 6, 2011 at 10:32 AM, Wolfgang Laun <wolfgang.l...@gmail.com> 
> wrote:
> This additional information does not require a fundamentally different 
> approach.
> 
> Using the same set of facts CostEmployee/CostSpouse, we can now use
> two rules, one calculating the cost for the employee, and the other
> one for the spouse.
> 
> (defrule calc-self
>  ?hbj <- (HrBenefitJoin (hrBenefitConfigId "00001-0000000073")
>                 (calculatedCost 0)
>                 {relationshipId  == nil}
>                 (payingPersonId  ?pPer)
>                 (coveredPersonId ?cPer) )
>  (Person        (personId        ?cPer) (dob ?dob) )
>  (CostEmployee  (lo ?lo&:(<= ?lo (yrs ?dob)))
>                 (hi ?hi&:(>= ?hi (yrs ?dob)))(cost ?cost))
> =>
>  (printout t "Cost for " ?cPer " paid by himself: " ?cost crlf )
> )
> 
> (defrule calc-other
>  ?hbj <- (HrBenefitJoin (hrBenefitConfigId "00001-0000000073")
>                 (calculatedCost 0)
>                 {relationshipId  != nil}
>                 (payingPersonId  ?pPer)
>                 (coveredPersonId ?cPer) )
>  (Person        (personId        ?cPer) (dob ?dob) )
>  (CostSpouse    (lo ?lo&:(<= ?lo (yrs ?dob)))
>                 (hi ?hi&:(>= ?hi (yrs ?dob)))(cost ?cost))
> =>
>  (printout t "Cost for " ?cPer " paid by " ?pPer ": " ?cost crlf )
> )
> 
> The date calculation is abstracted into a
>   (deffunction yrs (?dob) ... (return ?yrs) )
> 
> Implementing this in Jess or in Java is a simple programming exercise,
> but it presumably it depends on some technical/legal issues, e.g., it
> may not be possible to use "today" as a basis for calculating the
> difference in years from the person's dob.
> 
> Since there's no information what to do with the resulting cost, it's
> just printed to standard output, but updating slot calculatedCost in
> HrBenefitJoin is straightforward.
> 
> Cheers
> Wolfgang
> 
> 
> On 05/01/2011, Derek Adams <dad...@arahant.com> wrote:
> > the facts that I am working with are:
> >
> > (HrBenefitJoin (hrBenefitConfigId "00001-0000000073")(benefitJoinId
> > ?bjid)(calculatedCost ?cost)(OBJECT ?obj)(coveredPersonId
> > ?cPer)(payingPersonId ?pPer)(relationshipId ?rel))
> > (Person (personId ?cPer)(dob ?dob)(OBJECT ?objP))
> >
> > ?rel is what identifies the "covered person" as spouse or employee.  If ?rel
> > is nil, it's employee, else it's spouse.
> >
> > So ?objP is my covered person (either spouse or employee).
> >
> > On Wed, Jan 5, 2011 at 3:36 PM, Wolfgang Laun
> > <wolfgang.l...@gmail.com>wrote:
> >
> >> With this kind of problem, there are (at least) two approaches. Given that
> >> Employee and Spouse are represented as facts:
> >>    (deftemplate Spouse   (slot name)(slot age))
> >>    (deftemplate Employee (slot name)(slot age)(slot spouse))
> >>
> >>    (deffacts test-facts
> >>       (Employee (name "John Smith")(age 35)(spouse "Jane Smith"))
> >>       (Spouse   (name "Jane Smith")(age 28))
> >>       (Employee (name "Honey Rider")(age 39)(spouse "James Rider"))
> >>       (Spouse   (name "James Rider")(age 45))
> >>    )
> >>
> >> (1) You can write one rule for each possible combination of age brackets.
> >>
> >> (defrule compute_1_1
> >>     (Employee (name ?name){age >= 18 && age <= 29}(spouse ?spouse))
> >>     (Spouse   {name == ?spouse}{age >= 18 && age <= 29})
> >> =>
> >>     (printout t "cost " ?name " " (+  11.55 6.65) crlf)
> >> )
> >> ... more boring code ...
> >> (defrule compute_3_3
> >>     (Employee (name ?name){age >= 40 && age <= 49}(spouse ?spouse))
> >>     (Spouse   {name == ?spouse}{age >= 40 && age <= 49})
> >> =>
> >>     (printout t "cost " ?name " " (+  38.35 20.05) crlf)
> >> )
> >>
> >> (2) You can represent the tables for the costs as facts:
> >>    (deftemplate CostEmployee (slot lo)(slot hi)(slot cost))
> >>    (deftemplate CostSpouse   (slot lo)(slot hi)(slot cost))
> >>
> >>    (deffacts costs
> >>        (CostEmployee (lo 18)(hi 29)(cost 11.55))
> >>        (CostEmployee (lo 30)(hi 39)(cost 18.95))
> >>        (CostEmployee (lo 40)(hi 49)(cost 38.35))
> >>        (CostSpouse   (lo 18)(hi 29)(cost  6.65))
> >>        (CostSpouse   (lo 30)(hi 39)(cost 10.35))
> >>        (CostSpouse   (lo 40)(hi 49)(cost 20.05))
> >>    )
> >>
> >> and use a single rule:
> >>
> >>    (defrule compute
> >>        (Employee (name ?name)(age ?ageE)(spouse ?spouse))
> >>        (Spouse   {name == ?spouse}(age ?ageS))
> >>        (CostEmployee {lo <= ?ageE}{hi >= ?ageE}(cost ?costE))
> >>        (CostSpouse   {lo <= ?ageS}{hi >= ?ageS}(cost ?costS))
> >>    =>
> >>        (printout t "cost " ?name " " (+  ?costE ?costS) crlf)
> >>    )
> >>
> >> HTH
> >> Wolfgang
> >>
> >>
> >>
> >>
> >>
> >> On 5 January 2011 22:30, Wolfgang Laun <wolfgang.l...@gmail.com> wrote:
> >>
> >>> Sent on behalf of Derek Adams:
> >>>
> >>>
> >>> Hey Jess Users!  This is my first post, so I apologize for anything
> >>> "noob"
> >>> that I say/do...
> >>>
> >>> I'm very new to Jess.  I understand the basics but applying my knowledge
> >>> for the first time is proving more difficult than I anticipated.  Here is
> >>> the problem:
> >>>
> >>> I need to set up a rule in Jess that calculates the cost of a benefit
> >>> based on age and enrollees.
> >>> *
> >>> Example:
> >>> The Benefit Configuration is "Employee $10k / Spouse $5k"
> >>> The enrollees are the employee (John Smith age 30) and spouse (Jane Smith
> >>> and 28).
> >>> The costs are calculated as follows:
> >>>
> >>> Age               Employee            Spouse
> >>> 18-29            11.55                    6.65
> >>> 30-39            18.95                   10.35
> >>> 40-49            38.35                   20.05*
> >>>
> >>> *So John's cost is 18.95 and Jane's cost is 6.65 for a total of 25.60*.
> >>>
> >>> Any advice would be greatly appreciated!
> >>>
> >>> Thanks,
> >>>
> >>> Derek Adams
> >>>
> >>
> >>
> >
> >
> > --
> > *Derek Adams*
> > Lead Developer
> > Arahant LLC
> > Work: 615-376-5500 ext. 314
> > Cell: 270-543-0920
> >
> 
> 
> --------------------------------------------------------------------
> To unsubscribe, send the words 'unsubscribe jess-users y...@address.com'
> in the BODY of a message to majord...@sandia.gov, NOT to the list
> (use your own address!) List problems? Notify owner-jess-us...@sandia.gov.
> --------------------------------------------------------------------
> 
> 
> 
> 
> -- 
> Derek Adams
> Lead Developer 
> Arahant LLC
> Work: 615-376-5500 ext. 314
> Cell: 270-543-0920

Reply via email to