How to avoid circular rule activation for non circular problems?

View: New views
5 Messages — Rating Filter:   Alert me  

How to avoid circular rule activation for non circular problems?

by Ralph Ammon :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Some parts of this message have been removed. Learn more about Nabble's security policy.

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?

by Marcus Ilgner :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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?

by Ralph Ammon :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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?

by Ralph Ammon :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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?

by Ralph Ammon :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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
LightInTheBox - Buy quality products at wholesale price