I just realized that I changed my mind on implementation mid-post and misled you a bit. You do *not* need a special implementation of Map since you are never reasoning over it; the accumulate rule consequence decomposes the map results into DfsSearchResult facts. So replace any references to DfsSearchResults above with Map.
Sorry for any confusion. Mike On Mar 13, 2012 10:12 PM, "Mike Melton" <mike.mel...@gmail.com> wrote: > Sorry - I didn't have the time earlier to fully parse the more complex > rule. The problem you're having is that the engine reevaluates the > conditions on each working memory change, and since, as you noticed, the > list has changed, the rule fires again. The no-loop attribute prevents a > rule from reactivating itself "with the current set of facts". You do not > have the same set of facts, and so no-loop is not applicable in your case. > > It looks to me like you want to insert the results of the Dfs.search() > operation as a fact or list of facts, and then include a pattern in your > condition that prevents the rule from firing if these results exist in > working memory. You would then have another rule or set of rules that > process the results, retracting them as they go. Once all the results from > one firing of the accumulate rule have been processed and retracted, then > the accumulate rule would be free to fire again on the next set of data. > > (An aside: since Dfs.search() returns a Map, you'll probably want to > create your own implementation since a rule with a pattern on Map() would > evaluate true for any map that happens to be in working memory. However, a > rule that's looking for DfsSearchResults would only match in your > particular case. Another (perhaps better) option is to use traits to have > your Map "don" a trait that your other rules can then reason on. Traits are > still an experiment feature but I've played with them and they are very > cool.) > > Before I ramble too much further, here is a very pseudocoded version of > what I'm talking about. I'm going to assume that Dfs.search() returns > something called DfsSearchResults; whether that type is an implementation > of Map or a trait is semi-irrelevant. > > We're also going to assume a new type called DfsSearchResult: > > declare DfsSearchResult > assignment : PlanifEventAssignment > employee : EmployeeValue > end > > So your accumulate rule would be: > > rule "close-shift" > when > not DfsSearchResult( ) // Keeps this rule from activating again until > all results of the previous firing are processed > $shift : Shift( ) > $assignments : ... // this condition stays the same > $availables : ... // this condition stays the same too > $results : DfsSearchResults( size > 0 ) from Dfs.search( $assignments, > $availables ) > then > for ( DfsSearchResult dsr : $results ) { // the magic of pseudocode is > it doesn't compile and we don't care! > PlanifEventAssignment assignment = ... > EmployeeValue employee = ... > insert( new DfsSearchResult( assignment, employee ) ); > } > end > > And now you'll have a processing rule: > > rule "update-assignment" > when > $dsr : DfsSearchResult( $a : assignment, $e : employee ) > then > modify($a) { setClose(true); setEmployee($e); } > retract($dsr); > end > > > I think that will get you as least in the right direction. I hope this > helps. > > Mike > > P.S. Now that I think about it, I'd like to amend the guideline I wrote in > my last email: "No looping in the consequence unless it is to decompose a > collection of data into simple facts that are much easier to reason over... > or if I have another really good reason." > > > 2012/3/13 Patrik Dufresne <ikus...@gmail.com> > >> Hi Mike, >> >> I see your point, it's very valid for the snippet rule, but can't be >> apply to the real one since I need to run a function using eval(). >> >> Patrik Dufresne >> >> >> >> On Tue, Mar 13, 2012 at 4:45 PM, Mike Melton <mike.mel...@gmail.com>wrote: >> >>> Let the rule engine do what it does best. You are fighting against the >>> optimizations of the engine by trying to control the flow. You can rewrite >>> your rule as >>> >>> rule "my-rule" >>> when >>> $entity : Entity( closed == false ) >>> then >>> modify($entity) { setClosed(true); } >>> end >>> >>> The rule will fire (once) for each Entity which matches the condition. I >>> haven't taken the time to apply the same exercise to your more complex >>> rule, but a general rule you should abide by is "No looping in the >>> consequence unless I have a really good reason." >>> >>> Mike >>> >>> >>> 2012/3/13 Patrik Dufresne <ikus...@gmail.com> >>> >>>> Hi, >>>> >>>> I have some trouble to figure out how to stop / start the propagation >>>> of updates within a Then block. >>>> Here is a snippet to represent the problem I have. >>>> >>>> rule "my-rule" >>>> when >>>> $objects : List() >>>> from accumulate( $entity : Entity(closed==false), >>>> collectList($entity) ) >>>> then >>>> for(Object obj : $objects) { >>>> ((Entity) obj).setClosed(true); >>>> update(obj); >>>> } >>>> end >>>> >>>> When this rule's consequence is called first, the first enity in the >>>> list is 'update', but then update if propagated to immediately causing the >>>> rule to be evaluated with all the entities minus the updated one. So I'm >>>> wondering if there is a transaction like operation allowing me to update >>>> all the entities in the list and then fire the rules. >>>> >>>> According to the documentation no-loop should have help me for this. >>>> >>>> Here is the original rules >>>> rule "close-shift" >>>> salience -1 >>>> when >>>> $shift : Shift( ) >>>> $assignments : List( size > 0 ) >>>> from accumulate ( >>>> $assignment : PlanifEventAssignment( >>>> close == false, >>>> shift == $shift ), >>>> collectList($assignment) ) >>>> $availables : List( size >= $assignments.size ) >>>> from accumulate ( ( and >>>> ShiftAssignment( >>>> shift == $shift, >>>> $employee : employee) >>>> $available : EmployeeAvailable ( >>>> employee == $employee, >>>> assignment.shift == $shift) ), >>>> collectList($available) ) >>>> eval( Dfs.search($assignments, $availables) != null ) >>>> then >>>> // Recalculate the result. >>>> Map table = Dfs.search($assignments, $availables); >>>> for(Object entry : table.entrySet()) { >>>> PlanifEventAssignment assignment = >>>> (PlanifEventAssignment)((Entry)entry).getKey(); >>>> EmployeeValue employee = (EmployeeValue)((Entry)entry).getValue(); >>>> assignment.setClose(true); >>>> assignment.setEmployee(employee); >>>> update(assignment); >>>> } >>>> end >>>> >>>> >>>> Patrik Dufresne >>>> >>>> _______________________________________________ >>>> 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