Flow of Control

In a calc section, model statements are normally executed sequentially.  Flow of control statements can be used to alter the execution order of statements.  In effect, this gives you a programming, or scripting, capability within the LINGO environment.

@IFC and @ELSE

These statements provide you with conditional IF/THEN/ELSE branching capabilities.  The syntax is as follows:

@IFC( <conditional-exp>:

  statement_1[; …; statement_n;]

[@ELSE

  statement_1[; …; statement_n;]]

);

with the @ELSE block of statements being optional in case a pure if statement is desired.

Note:Be aware of the use of the letter ‘C’ in @IFC.  This is to distinguish the flow of control if statement (@IFC) from the arithmetic if (@IF).

To illustrate, the following sample code uses if/else blocks as part of a binary search for a key value in an array:

@IFC( KEY #EQ# X( inew):

  loc = inew;

@else

  @ifC( key #lt# x( inew):

     ie = inew;

  @else

     ib = inew;

  );

);

@FOR

You’ve encountered the @FOR set looping statement previously as a way to generate constraints in the model section. @FOR is also allowed in the calc section to perform looping.  The main difference is that @FOR does not generate constraints when used in the calc section.  Instead, it immediately executes any assignment statements contained within its scope.  The following example shows a @FOR loop extracted from a portfolio model.  The loop is used to solve the portfolio model for a number of different levels of desired return.  For each level of return, the model minimizes variance, and the variance is stored for later use.

@FOR( POINTS( I):

  ! Compute new return level;

  RET_LIM = RET_MIN + (I-1)*INTERVAL;

  ! Re-solve the model;

  @SOLVE();

  ! Store the return value;

  YRET( I) = RET_LIM;

  ! Store the variance too;

  XSTD( I) = VARIANCE^0.5;

);

@WHILE

The @WHILE statement is used for looping over a group of statements until some termination criterion is met.  The syntax is as follows:

@WHILE( <conditional-exp>: statement_1[; …; statement_n;]);

As long as the conditional expression is true, the @WHILE function will keep looping over its block of statements.

As an example, the following code uses an @WHILE loop to search for a key value in an array as part of a binary search procedure:

@while( key #ne# x( loc):

  inew = @floor( ( ie + ib) / 2);

  @ifc ( key #eq# x( inew):

     loc = inew;

  @else

     @ifC( key #lt# x( inew):

        ie = inew - 1;

     @else

        ib = inew + 1;

     );

  );

);

In this case, the loop executes until the current value selected from the array, X(LOC), is equal to the key value, KEY.

@BREAK

The @BREAK statement is used to break out of the current loop.  Execution resumes at the first statement immediately following the end of the current loop.  The @BREAK statement is valid only within @FOR and @WHILE loops in calc sections and does not take any arguments.  As an example, we extend the @WHILE loop in the binary search example above to include an @BREAK statement that will be executed when the key value can’t be found:

@while( key #ne# x( loc):

  !exit loop if key can’t be found;

  @ifc( ie – IB #LE# 1:

     @PAUSE( 'Unable to find key!!!');

     @break;

  );

  inew = @floor( ( ie + ib) / 2);

  @ifc ( key #eq# x( inew):

     loc = inew;

  @else

     @ifC( key #lt# x( inew):

        ie = inew - 1;

     @else

        ib = inew + 1;

     );

  );

);

@STOP( [‘MESSAGE’])

The @STOP statement terminates execution of the current model.  The @STOP statement is valid only within calc sections and takes on optional text argument.  When an @STOP is executed, LINGO will display error message 258:

[Error Code:  258]

Model execution halted.  STOP statement encountered.

If a text argument is included in the @STOP, then it will also be displayed as part of this error message.

As an example, we extend the @WHILE loop in the binary search example above to include an @STOP statement that will be executed when the key value can’t be found:

@while( key #ne# x( loc):

  !exit if key can’t be found;

  @ifc( ie –IB #LE# 1:

     @STOP( 'Unable to find key!!!');

  );

  inew = @floor( ( ie + ib) / 2);

  @ifc ( key #eq# x( inew):

     loc = inew;

  @else

     @ifC( key #lt# x( inew):

        ie = inew;

     @else

        ib = inew;

     );

  );

);