|
View:
New views
5 Messages
—
Rating Filter:
Alert me
|
|
|
How to avoid circular rule activation for non circular problems?I’d like to get some hints to improve the rules
of my simple planning system. My simple planning system is derived from the
HelloWorld Drools Project. The job of my planning system is to calculate startTime
and endTime as function of duration and predecessors for each task. Each task
has the fields long duration; Set<Task>
predesessors; long startTime; long endTime; For each task the rule (endTime = startTime +
duration) should hold. If a task has no predecessors, then its startTime should
be 0. If a task has predecessors, then is should start at the latest endTime of
all predecessors. These are my DRL-rules: rule "Calc EndTime" no-loop true when $t : Task() then $t.setEndTime(
$t.getStartTime() + $t.getDuration() ); System.out.println(
"Drools: Set " + $t.getName() + ".EndTime to " +
$t.getEndTime() ); update( $t ); end rule "Calc StartTime without
predecessors" lock-on-active true when $t : Task(predecessorCount ==
0) then $t.setStartTime( 0
); System.out.println(
"Drools: " + $t.toString() + " can start immediately" ); update( $t ); end rule "Calc StartTime with
predecessors" when $t : Task(predecessorCount > 0,
$predecessors : predecessors ) # Checking EndTime > 0 for all
predecessors means that all EndTimes are # initialy calculated. This is not
what we realy want. Actually we'd like # to recalculate the successors
EndTime, when ever it is needed. forall ( $succTask
: Task( this == $t ) $predTask
: Task( this memberOf $predecessors, endTime > 0 ) ) $endTime : Number() from accumulate(
$p : Task() from $predecessors,
max($p.getEndTime()) ) then $t.setStartTime(
$endTime.longValue() ); System.out.println(
"Drools: " + $t.toString() + " has new StartTime" ); # !!!! If we did an
update($t); here, we would get an infinite recursion. end My TestClass creates three tasks: task0, task1 and
task2. Each task has an initial duration and (task0, task1) are predecessors of
task2. It is important that this example has no circular dependencies;
otherwise the rules, mentioned above, couldn’t be applied. After fireAllRuels() the endTime of task2 is
calculated wrong, so obviously the rule "Calc EndTime" should be
activated. Is the rule-attribute (no-loop = true) not the right solution to
avoid circularity here? Then the duration of task0 is updated outside of the
rule engine. After a second fireAllRuels() the endTime of task0 is recalculated,
but task2 is not recalculated at all. How can I tell the rule engine, that a
task depends on its predecessors? I'd appreciate any input that could help me making
this example work and if it works very efficient on a big number of tasks
it’s brilliant. If anybody is interested in my TestClass, to run this
example with some logging, please tell me. Ralph Ammon _______________________________________________ rules-users mailing list rules-users@... https://lists.jboss.org/mailman/listinfo/rules-users |
|
|
Re: How to avoid circular rule activation for non circular problems?On Thu, Jul 24, 2008 at 3:28 PM, Ralph Ammon <ralph.ammon@...> wrote:
> I'd like to get some hints to improve the rules of my simple planning > system. > > > > My simple planning system is derived from the HelloWorld Drools Project. The > job of my planning system is to calculate startTime and endTime as function > of duration and predecessors for each task. Each task has the fields > > long duration; > > Set<Task> predesessors; > > long startTime; > > long endTime; > > For each task the rule (endTime = startTime + duration) should hold. If a > task has no predecessors, then its startTime should be 0. If a task has > predecessors, then is should start at the latest endTime of all > predecessors. > Maybe something like this would work? rule "Calc EndTime" no-loop true when $t : Task(endTime != (startTime+duration)) then $t.setEndTime( $t.getStartTime() + $t.getDuration() ); System.out.println( "Drools: Set " + $t.getName() + ".EndTime to " + $t.getEndTime() ); update( $t ); end Afaik, this will also enable Drools to only check this rule if one of the attributes used in the LHS is changed. So if you change any other field of your object at some point, this rule will not be evaluated again. Please note that I haven't checked the syntax but I think that it should work like this. Best regards Marcus _______________________________________________ rules-users mailing list rules-users@... https://lists.jboss.org/mailman/listinfo/rules-users |
|
|
AW: How to avoid circular rule activation for noncircular problems?Thank you Marcus,
with your constraint I got rid of the "no-loop true" and the endTime is recalculated when needed. So my first problem is really solved! So I tried a similar constraint for the rule "Calc StartTime with redecessors" rule "Calc StartTime with predecessors" when $t : Task(predecessorCount > 0, $predecessors : predecessors ) forall ( $succTask : Task( this == $t ) $predTask : Task( this memberOf $predecessors, endTime > 0 ) ) $endTime : Number() from accumulate( $p : Task() from $predecessors, max($p.getEndTime()) ) # new constraint Task(this == $t, eval($t.getStartTime() != $endTime.longValue())) then $t.setStartTime( $endTime.longValue() ); System.out.println( "Drools: " + $t.toString() + " has new StartTime" ); # new update update( $t ); end The improvement is that I can do an update in the RHS without infinite recursion. But the rule is still wrong, because it doesn't fire when the maximum of predecessors endTimes changes. Best regards Ralph _______________________________________________ rules-users mailing list rules-users@... https://lists.jboss.org/mailman/listinfo/rules-users |
|
|
AW: How to avoid circular rule activation fornoncircular problems?Sorry for the line breaks. Here I post my changes in a (hopefully) more readable format:
rule "Calc StartTime with predecessors" when $t : Task(predecessorCount > 0, $predecessors : predecessors ) forall( $succTask : Task( this == $t ) $predTask : Task( this memberOf $predecessors, endTime > 0 ) ) $endTime : Number() from accumulate ( $p : Task() from $predecessors, max($p.getEndTime()) ) # new constraint Task( this == $t, eval($t.getStartTime() != $endTime.longValue()) ) then $t.setStartTime( $endTime.longValue() ); System.out.println( "Drools: " + $t.toString() + " has new StartTime" ); # new update update( $t ); end Best regards Ralph _______________________________________________ rules-users mailing list rules-users@... https://lists.jboss.org/mailman/listinfo/rules-users |
|
|
AW: How to avoid circular rule activationfornoncircular problems?Thank you,
my problem is solved, the following rules work for all my test cases: rule "Calc EndTime" when $t : Task( endTime != ( startTime + duration) ) then $t.setEndTime( $t.getStartTime() + $t.getDuration() ); System.out.println( "Drools: Set " + $t.getName() + ".EndTime to " + $t.getEndTime() ); update( $t ); end rule "Calc StartTime without predecessors" when $t : Task( predecessorCount == 0, startTime > 0 ) then $t.setStartTime( 0 ); System.out.println( "Drools: " + $t.toString() + " can start immediately" ); update( $t ); end rule "Calc StartTime with predecessors" when $t : Task( predecessorCount > 0, $oldStart : startTime, $predecessors : predecessors ) $predTask : Task( this memberOf $predecessors, endTime > $oldStart ) then $t.setStartTime( $predTask.getEndTime() ); System.out.println( "Drools: " + $t.toString() + " has new StartTime" ); update( $t ); end rule "Reset StartTime with predecessors" when $t : Task( predecessorCount > 0, $oldStart : startTime, $predecessors : predecessors ) forall( $predTask : Task( this memberOf $predecessors ) Task( this == $predTask, endTime < $oldStart) ) then $t.setStartTime( 0 ); System.out.println( "Drools: " + $t.toString() + " reset StartTime" ); update( $t ); end Best regards Ralph _______________________________________________ rules-users mailing list rules-users@... https://lists.jboss.org/mailman/listinfo/rules-users |
| Free Forum Powered by Nabble | Forum Help |