Programming Flow Control Features

Introduction

In this chapter we will describe the programming flow control features available in GAMS. The if statement facilitates expressing complex conditional statements (see also chapter Conditional Expressions, Assignments and Equations). In addition, GAMS offers four loop constructs to handle looping requirements: the loop statement, the while statement, the for statement and the repeat statement. At the end of this chapter we will introduce the break, and continue statements, which give additional control over the execution of loop structures, and the abort statement, a statement that may be used to terminate the execution of a program.

Note that this chapter deals with programming flow control features at execution time. In addition, GAMS provides a dollar control option that allows for conditional processing of input files at compile time. For more information, see the detailed description of the option $if. For details on dollar control options in general, see chapter Dollar Control Options.

The If Statement

The if statement is useful to branch conditionally around a group of statements. In some cases this can also be written as a set of dollar conditions, but the if statement may make the GAMS code more readable. An optional else and/or elseif part allows the user to formulate traditional if-then-else constructs.

The If Statement: Syntax

The syntax for an if statement in GAMS is as follows:

if (logical_condition,
    statement; {statement;}
{ elseif logical_condition, 
    statement; {statement;} }
[ else 
    statement; {statement;} ]
);

The keyword if indicates that this is an if statement. The logical condition is followed by one or more statements that are executed if the logical condition is satisfied. For details on the various forms of logical conditions in GAMS, see sections Logical Conditions and Filtering Sets. The if statement may end at this point, without any specifications for cases when the logical condition is FALSE and no action is taken in these cases. However, GAMS also allows further specifications: optional alternative if tests and optional statements for cases when all previous if tests have failed. The keyword elseif introduces an alternative if test with a logical condition and one or more statements. Note that the elseif case is optional and may be repeated multiple times. Note further that the elseif case implies that the logical condition of the if case has not been satisfied. The keyword else introduces the final part of the construct. It is optional and allows specification for cases when the logical condition of the if case (and possibly the elseif case(es)) has not been satisfied.

Attention
Only execution statements are permitted in programming flow control statements. Consequently declaration statements and equation definitions are not allowed inside an if statement.

Examples are given in the next subsection. Note that there is an alternative syntax that is more in line with the syntax of some popular programming languages. For more information, see the detailed description of the dollar control option onEnd.

The If Statement: Examples

Consider the following set of conditional assignment statements that use dollar conditions:

p(i)$(f <= 0) = -1 ;
p(i)$((f > 0) and (f < 1)) = p(i)**2 ;
p(i)$(f >= 1) = p(i)**3 ;
q(j)$(f <= 0) = -1 ;
q(j)$((f > 0) and (f < 1)) = q(j)**2 ;
q(j)$(f >= 1) = q(j)**3 ;

They may be expressed using an if-elseif-else statement:

if (f <= 0,
    p(i) = -1 ;
    q(j) = -1 ;
elseif ((f > 0) and (f < 1)),
    p(i) = p(i)**2 ;
    q(j) = q(j)**2 ;
else
    p(i) = p(i)**3 ;
    q(j) = q(j)**3 ;
) ;

Note that the body of the if statement may contain solve statements. For instance, consider the bit of GAMS code that follows. Note that ml is a GAMS model, z is a free variable, j is a set and x is a variable.

solve ml using lp minimizing z;
if (ml.modelstat = 4,
     display "model ml was infeasible, relax bounds on x and solve again";
     x.up(j) = 2*x.up(j) ;
     solve ml using lp minimizing z ;
else
    if (ml.modelstat <> 1,
        abort "error solving model ml" ;
    );
);

First the model ml is solved. For details on solve statements in GAMS, see section The Solve Statement. Then a post solution analysis is done with the if statement. If the model is infeasible, the upper bound on the variable x is relaxed and the model is solved again. If the original model is not infeasible and it is not optimal either, then the compilation is aborted and the error message above is reported. For more information on GAMS output, see chapter GAMS Output, particularly subsection Model Status for a list of all GAMS model statuses. The display statement is introduced in chapter The Display Statement. For details on the abort command, see abort.

The following GAMS code is illegal since it is not permitted to define equations inside an if statement.

if (s > 0,
    eq.. sum(i,x(i)) =g= 2 ;
);

The following GAMS code is also illegal since declarations inside an if statement are not allowed.

if (s > 0,
   scalar y ; y = 5 ;
);

The Loop Statement

The loop statement facilitates executing a group of statements for each member of a set. Loop statements are particularly useful for cases when parallel assignments are not sufficient. This is the case most often when there is no analytic relationship between the values to be assigned to a parameter. It is, of course, also useful to have a looping statement for general programming.

The Loop Statement: Syntax

The syntax for the loop statement in GAMS is as follows:

loop(index_list[$(logical_condition)],
     statement; {statement;}
) ;

The keyword loop indicates that this is a loop statement. The index_list is the controlling domain of the loop. Note that loops may be controlled by more than one set. In this case parentheses are required around the index list, which is also called the loop set(s). Observe that dynamic sets are allowed as loop sets. The loop set(s) may be restricted by a logical condition. For details on the various forms of logical conditions in GAMS, see sections Logical Conditions and Filtering Sets. For an introduction to dollar conditions in general, see chapter Conditional Expressions, Assignments and Equations. The index list is followed by one or more statements. Except for the final statement, each statement must end with a semicolon ';'. The loop statements are executed for each member of the controlling domain in turn. The order of evaluation is the entry order of the labels. A loop is thus another, more general, type of indexed operation.

Attention
  • Only execution statements are permitted in programming flow control statements. Consequently declaration statements and equation definitions are not allowed inside a loop statement.
  • It is illegal to modify any controlling set inside the body of the loop.

Loop statements in GAMS are often used for iterative calculations, generating reports with put statements and doing scenario based studies with solve statements. Examples are given in the next subsection. Note that there is an alternative syntax that is more in line with the syntax of some popular programming languages. For more information, see the detailed description of the dollar control option onEnd.

The Loop Statement: Examples

Consider a hypothetical case when a growth rate is empirical:

Set        t          / 1985*1990 /
Parameter  pop(t)     / 1985  3456 /
           growth(t)  / 1985  25.3,  1986  27.3,  1987  26.2
                        1988  27.1,  1989  26.6,  1990  26.6 /;

The loop statement is then used to calculate the cumulative sums iteratively:

loop(t, pop(t+1)  = pop(t) + growth(t) ) ;

In this example the driving set is t and we have just one statement in the scope of the loop.

The following small artificial examples illustrate the effects of a dollar condition in a loop statement.

Sets       i       / i1*i3 /
           j       / j1*j5 /
           k(i,j)  / i1.j1, i1.j3, i3.j3, i3.j5 /;
Parameter  c(i)    / i1 3, i2 1 /
           q(i,j)  / i1.j1 1, i1.j2 3, i1.j4 2 / ;
Scalars    x, y, z;
x = 1; y = 3; z = 1;

loop ( (i,j) $ (q(i,j) > 0), x = x + q(i,j));
loop ( i $ (c(i) + c(i)**2), z = z + 1);
loop ( i $ sum(j, abs(q(i,j))), z = z + 1);
loop ( j $ (ord(j) > 1 and ord(j) < card(j)), z = z + 1);
loop ( (i,j) $ k(i,j), y = y + ord(i) + 2*ord(j));

In the first loop statement the controlling domain is the set pair (i,j). It is restricted to those label combinations whose values associated with the parameter q are greater than zero. The logical condition in the second loop statement is \( c(i) + c(i)^2\). This is shorthand for \( c(i) + c(i)^2 \neq 0\). The domain in the third loop statement is restricted to those elements of the set i where the sum over j of the absolute values of the parameter q does not equal zero. Note that this condition is satisfied only for the label "i1". Observe that i and j are both ordered sets. In the fourth loop statement the first and the last element of the set j are excluded. For more on the set operators ord and card, see sections The Ord Operator and The Card Operator respectively. The dollar control in the last loop statement excludes all label combinations that are not members of the set k. For further details on dollar conditions, see chapter Conditional Expressions, Assignments and Equations.

Note
The dollar condition may be replaced by an if statement; see the example below.

The next example shows how a model can be solved for each element of a set i with different data using a loop statement. Note that problemdata is a scalar, g(i) and d(i) are parameters, mymodel is a GAMS model and profit is a free variable.

loop (i,
  problemdata = g(i);
  solve mymodel using lp maximizing profit;
  d(i) = profit.l;
);

In the first statement some data in the model is updated in accordance with the \(i^{th}\) element of the parameter g. In the second statement the model is solved. For details on the solve statement, see section The Solve Statement. The objective value for each iteration is saved in the parameter d in the third statement.

A loop is often used to perform iterative calculations. Consider the following example, which finds square roots by Newton's method. This example is purely for illustration - in practice, the function sqrt should be used. Newton's method is based on the assertion that if \(x\) is an approximation to the square root of \(v\), then \((x+v/x)/2\) is a better approximation.

Set       i         "set to drive iterations"                 / i-1*i-100 /;
Parameter value(i)  "used to hold successive approximations";
Scalars   target    "number whose square root is needed"      / 23.456 /
          sqrtval   "final approximation to sqrt(target)"
          curacc    "accuracy of current approximation"
          reltol    "required relative accuracy"              / 1.0e-06 /;

abort$(target <= 0) "argument to newton must be positive";
value("i-1") = target/2  ;
curacc       =  1  ;
loop(i$(curacc > reltol),
       value(i+1) =  0.5*(value(i) + target/value(i));
       sqrtval    =  value(i+1);
       curacc     =  abs (value(i+1)-value(i))/(1+abs(value(i+1)))
) ;
abort$(curacc > reltol) "square root not found"
option decimals=8;
display  "square root found within tolerance",  sqrtval, value;

Note that in this example the dollar condition in the loop does not restrict the driving set i, but it is used to terminate the loop procedure. The scalar curacc is updated in every iteration. As soon as it becomes equal to or smaller than the required relative accuracy reltol the loop stops. As the output below shows, this is the case after seven iterations. The body of the loop statement consists of three statements. The first statement calculates the current approximation and assigns it to the parameter value. The second statement updates the scalar sqrtval, and the third statements computes the accuracy of the current approximation in each iteration. Note that before and after the loop statement we added lines to account for special cases. For details on the abort statement, see section The Abort Statement at the end of this chapter. The output generated by the display statement is given below.

----     19 square root found within tolerance

----     19 PARAMETER SQRTVAL              =   4.84313948 final approximation
                                                          to sqrt(target)

----     19 PARAMETER VALUE         used to hold successive approximations

i-1 11.72800000,    i-2  6.86400000,    i-3  5.14062471,    i-4  4.85174713
i-5  4.84314711,    i-6  4.84313948,    i-7  4.84313948

Note that a statement within the body of a loop may be an if statement (or any other programming flow control statement). Moreover, the logical condition in a loop statement may be expressed with an if statement instead of a dollar condition. The following example serves as illustration. Observe that k is a set and s, t, u and a are parameters.

loop (k,
   if((s(k) < 0 and t(k)),
      u(k) = a(k);
   );
);

Note that if the logical condition is not satisfied the assignment is not made and the parameter u remains unchanged.

Recall that subsets are connected with their supersets by arcs thus building a domain tree where the root node is the universal set. The following example demonstrates how the domain tree may be used in a loop statement.

Set i       / i1*i10 /
    ii(i) 
    j(i)    / i1*i9 / 
    jj(j)   / i1*i8 /   
    jjj(jj) / i1*i7 /;

loop(i(jjj), ii(i) = yes;);
display ii;

Observe that the looping set is i(jjj). This means that we loop over those elements of i that are also elements of the set jjj. This construct is permitted since i is in the domain tree on the path from jjj to the universe or universal set. It is allowed to go up the domain tree on one path and go down on another path. Therefore all the elements of jjj are assigned to ii. The outcome of the display statement confirms this:

----     8 SET ii  

i1,    i2,    i3,    i4,    i5,    i6,    i7

The While Statement

The while statement facilitates the repeated execution of one or more statements as long as a logical condition is satisfied.

The While Statement: Syntax

The syntax for the while statement in GAMS is as follows:

while(logical_condition,
      statement; {statement;}
);

The keyword while indicates that this is a while statement. Inside the while statement a logical condition is followed by one or more statements. For details on the various forms of logical conditions in GAMS, see sections Logical Conditions and Filtering Sets. The statements are executed as long as the logical condition is TRUE.

Attention
Only execution statements are permitted in programming flow control statements. Consequently declaration statements and equation definitions are not allowed inside a while statement.

Examples are given in the next subsection. Note that there is an alternative syntax that is more in line with the syntax of some popular programming languages. For more information, see the detailed description of the dollar control option onEnd.

The While Statement: Examples

Consider the following simple example:

Scalar x; x = 1;
while ( round(x,2) < 10,
   x = x + 0.01;
);
display x;

Note that the scalar x is increased in each iteration until it equals 10. Note further, that to ensure an exact result, in numerical comparisons we need a stable check like we have above (round(x,2) < 10), otherwise rounding errors may occur. As soon as x reaches 10, the logical condition is no longer satisfied and therefore there will be no further passes. Hence the final value of x equals 10.

Note that the number of passes in a while statement may be restricted using the command line parameter or option forlim. For details on command line parameters and options, see section Specifying Options Through the Command Line and chapter The Option Statement respectively.

While statements may be used to control the solve statement. For instance, consider the following implementation of a random multi-start method for non-convex optimization.

scalar count   /  1  /;
scalar globmin / inf /;
option bratio = 1 ;
while(count <= 1000,
      x.l(j) = uniform(x.lo(j),x.up(j)) ;
      solve ml using nlp minimizing obj ;
      if (obj.l < globmin,
          globmin = obj.l ;
          bestsol(j) = x.l(j) ;
      ) ;
      count = count+1 ;
) ;

Note that we start from a random starting point by setting the initial level values randomly between the upper and lower bounds. This assumes that the bounds have been previously specified and are not infinity. When the method improves, that is, if the logical condition (obj.l < globmin) is satisfied, the best known solution is stored in the scalar globmin. The level values associated with the best known solution so far are then saved in the parameter bestsol. This procedure is repeated 1000 times. The model [PRIME] is another example where the use of the while statement is illustrated. In this model the set of all prime numbers smaller than 200 is generated.

The following GAMS code is illegal since equation definitions inside a while statement are not permitted.

while(s > 0,
      eq.. sum(i,x(i)) =g= 2 ;
);

The following GAMS code is also illegal since declarations inside a while statement are not allowed.

while(s > 0,
      scalar y ; y = 5 ;
);

The For Statement

The for statement provides a compact way to iterate over a range of values and execute one or more statements each time.

The For Statement: Syntax

The syntax for the for statement in GAMS is as follows:

for (a = start_value to|downto end_value [by incr],
     statement; {statement;}
);

The keyword for indicates that this is a for statement. The scalar a begins with the real number start_value and is changed after each pass of the loop by the increment incr until it reaches the real number end_value. Note that the specification of an increment is optional, the default is 1. If the increment is given, it has to be a positive real number. Note further that to indicates that the scalar a is increased and downto indicates that it is decreased. In each iteration one or more statements are executed.

Attention
Only execution statements are permitted in programming flow control statements. Consequently declaration statements and equation definitions are not allowed inside a for statement.

Examples are given in the next subsection. Note that there is an alternative syntax that is more in line with the syntax of some popular programming languages. For more information, see the detailed description of the dollar control option onEnd.

The For Statement: Examples

Consider the following simple example:

Scalar s;
for (s = -3.8 to -0.1 by 1.4,
     display s ;
);

Note that negative real numbers are possible for the start and end values. The resulting listing file will contain the following lines:

----      3 PARAMETER s                    =       -3.800  
----      3 PARAMETER s                    =       -2.400  
----      3 PARAMETER s                    =       -1.000  

Observe that the value of s was increased by 1.4 with each pass of the loop as long as it did not exceed -0.1. In the next example the value of s is decreased:

Scalar s;
for (s = 3 downto -0.1 by 1.4,
     display s ;
);

Note that the number of passes in a for statement may be restricted using the command line parameter or option forlim. For details on command line parameters and options, see section Specifying Options Through the Command Line and chapter The Option Statement respectively.

Like while statements, for statements may be used to control the solve statement. The following example illustrates the use of the for statement by replicating the random search for a global optimum of a non-convex model that we discussed above.

scalar i ;
scalar globmin / inf / ;
option bratio = 1 ;
for (i = 1 to 1000,
     x.l(j) = uniform(x.lo(j),x.up(j)) ;
     solve ml using nlp minimizing obj ;
     if (obj.l < globmin,
         globmin = obj.l ;
         bestsol(j) = x.l(j) ;
     );
);

Note that the logical condition in the while loop (count <= 1000) is replaced by the specification of the range of values for the scalar i. The body of the for loop is identical to the body of the while loop, except for the statement to update the scalar count that we needed in the while loop. This demonstrates the similarities and differences between the two loops.

The following GAMS code is illegal since it is not allowed to define equations inside a for statement.

for (s = 1 to 5,
     eq.. sum(i,x(i)) =g= 2 ;
);

The following GAMS code is also illegal since declarations inside a for statement are not permitted.

for (s = 1 to 5,
     scalar y ; y = 5 ;
);

The Repeat Statement

The repeat statement facilitates the repeated execution of one or more statements. This is done unconditionally at least once and stopped when a logical condition is satisfied.

The Repeat Statement: Syntax

The syntax for the repeat statement in GAMS is as follows:

repeat ( 
    statement; {statement;}
until logical_condition );

The keyword repeat indicates that this is a repeat statement. One or more statements are executed in each iteration. The keyword until introduces the termination criterion: if the logical condition is satisfied, the repeat loop is terminated. For details on the various forms of logical conditions in GAMS, see sections Logical Conditions and Filtering Sets.

Note that the repeat statement is similar to the while statement, but a repeat loop is guaranteed to be executed at least one time since the logical condition is stated after the statements.

Attention
Only execution statements are permitted in programming flow control statements. Consequently declaration statements and equation definitions are not allowed inside a repeat statement.

Examples are given in the next subsection.

The Repeat Statement: Examples

Consider the following simple example:

Scalar a / 1 /;
repeat ( 
    a = a + 1;
    display a;
until a = 5 );

The scalar a is increased in each iteration by 1. If a equals 5, the termination criterion is satisfied and the loop stops. Note that this example works nicely since both, the scalar and the increment, are integer. In case the entity on the right-hand side of the termination condition is not an integer or the increment is not an integer, we recommend a formulation of the check that is more stable to avoid rounding errors. An example for a stable termination condition follows.

Scalar a / 1 /;
repeat (
    a = a + 0.1;
    display a;
until abs(a-5) < 1e-6 );

Observe that in the next example the termination condition is TRUE from the start. In this case the statement in the body of the repeat statement is executed once and then the loop is terminated. Hence the final value of a will be 5.

Scalar a / 4 /;
repeat (
    a = a + 1;
    display a;
until a >= 3 );

Note that the number of passes in a while statement may be restricted using the command line parameter or option forlim. For details on command line parameters and options, see section Specifying Options Through the Command Line and chapter The Option Statement respectively.

Here is a little more complex example. A repeat statement is used to narrow the interval where a quadratic function passes through zero. Note that, as is often the case, one of the statements in the repeat loop is another programming flow control statement, in this case an if statement.

Scalar max             "current upper boundary of interval"   /10/
       min             "current lower boundary of interval"   /-10/
       root            "value where function equals zero"
       function_value1 "function value at min"
       function_value2 "function value at max"
       tolerance       "tolerance for root"                   /0.00000001/
       signswitch      "indicates that sign switch was found" /0/
       inc             "increment to try to find sign switch" ;

function_value1 = 6 - 5*min + sqr(min);
inc             = (max - min)/37;
root            = min;

repeat (
   root = root + inc;
   function_value2 = 6 - 5*root + sqr(root);

   if((    sign(function_value1) <> sign(function_value2)
       and abs(function_value1) > 0
       and abs(function_value2) > tolerance ),
      max = root;
      signswitch = 1;
   else
      if(abs(function_value2) > tolerance,
         function_value1 = function_value2;
         min = root;
      );
   );
until (signswitch > 0) or (root > max) );
display min, max, function_value1, function_value2;

The result of the display statement shows that the value of min is 1.892 and the value of max is 2.432, the interval was narrowed to 0.54, which is just a little less than the value of inc. As expected, function_value1 and function_value2 differ in sign, confirming that the root of the quadratic function is indeed in the interval.

The Break Statement

The break statement gives additional control over the execution of loop structures, namely the loop statement, the while statement, the for statement and the repeat statement. It allows to break the execution of a loop structure prematurely.

The Break Statement: Syntax

The syntax for the break statement is as follows:

break [n];

The keyword break indicates that this is a break statement. It terminates the n inner most control structures. n is optional and if it is omitted, it is set to 1.

Most often break statements are used in the context of if statements or with dollar conditions. For details on the various forms of logical conditions in GAMS, see sections Logical Conditions and Filtering Sets.

The Break Statement: Examples

This is a simple, artificial example using the break statement to exit a loop statement:

Set    i   / i1*i10 /;
Scalar cnt / 0 /;

loop(i,
  break$sameas('i6',i);
  cnt = cnt+1;
);

display cnt;

The break statement in combination with the dollar condition terminates the execution of the loop body in the 6th iteration. This can be seen looking at the value of cnt after the loop, which will be 5.

Here is a little more complex example which uses the optional argument n to terminate more than one loop structure at once:

Set    i   / i1*i10 /;
Scalar x, y,
       cnt / 0 /;

for(x = 1 to 10,
  y = 0;
  while(y < 10,
    y = y+1;
    loop(i,
      break$sameas('i6',i) 2;
      cnt = cnt+1;
    );
  );
);
display cnt;

In this example, cnt will be 50 at the end. As in the previous example, it is increased 5 times in the inner most loop, before the break statement is executed. This time break is called with the argument 2, which causes the two inner most control structures (namely the loop and the while) to be terminated. The outer most control structure (the for) is not influenced, so that its body gets executed 10 times, which results in a total of 50 increments for the scalar cnt.

Note, if break would be called with the argument 3 instead of 2, also the for loop would be terminated, so that cnt would be 5 at the end. If break would be called with 1 (or without additional argument) instead of 2, only the inner most loop would be terminated so that cnt would be 500 at the end.

The Continue Statement

The continue statement gives additional control over the execution of loop structures, namely the loop statement, the while statement, the for statement and the repeat statement. It allows to jump to the end of the inner most loop structure without executing the remaining statements in the body.

The Continue Statement: Syntax

The syntax for the continue statement is as follows:

continue;

The keyword continue indicates that this is a continue statement. It jumps to the end of the inner most control structure.

Most often continue statements are used in the context of if statements or with dollar conditions. For details on the various forms of logical conditions in GAMS, see sections Logical Conditions and Filtering Sets.

The Continue Statement: Examples

This is a simple, artificial example using the continue statement to skip parts of a loop body:

Set    i   / i1*i10 /;
Scalar cnt / 0 /;

loop(i,
  continue$(mod(ord(i),2)=0);
  cnt=cnt+1
);

display cnt;

In that example, every 2nd iteration of the loop statement is skipped. Therefore, cnt will be 5 at the end of the loop.

The Abort Statement

The abort statement is used to terminate the execution of a program. Most often the abort statement is used in the context of conditionals. Examples are given below. Also it may be used to display a text or an identifier in the listing file similar to the display statement but mostly to present the reason for the termination of the execution.

Note that the abort statement is to be distinguished from the dollar control option $abort which may be used to terminate the compilation of a program.

The Abort Statement: Syntax

The syntax for the abort statement is as follows:

abort [ ident | quoted text {, ident | quoted text} ];

The keyword abort indicates that this is an abort statement, all other elements of the statement are optional. Ident denotes an identifier. If the identifier is a set or a parameter, only the name of the set or parameter itself is specified, without any domains. If the identifier is a variable, an equation or a model, it must be followed by a suffix, since only attributes of variables, equations and models can be displayed. For more on variable and equation attributes including full lists, see sections Variable Attributes and Equation Attributes respectively. For details on model attributes, see section Model Attributes. Recall that sets also have attributes, they may also be displayed using the suffix notation. For details on set attributes, see section Set Attributes. As usual, quoted text must be surrounded by single or double quotes. The identifiers and the text may be mixed and matched in any order, and the whole statement may be continued over several lines.

An abort statement causes the termination of the execution with an execution error and the information in the statement will be displayed.

There is also a variant with the extension .noError that terminates the execution and displays the information, but does not cause an execution error. The syntax is as follows:

abort.noError [ ident | quoted text {, ident | quoted text} ];

Most often abort statements are used in the context of if statements or with dollar conditions. The syntax is as follows:

if (logical_condition, abort [ ident | quoted text {, ident | quoted text} ]; );

or

abort$logical_condition [ ident | quoted text {, ident | quoted text} ];

For details on the various forms of logical conditions in GAMS, see sections Logical Conditions and Filtering Sets.

The Abort Statement: Examples

Consider the following artificial example:

Set       i    / i1*i5 /;
Parameter p(i) / i1 1, i2 2, i3 3, i4 5, i5 8 /;
loop(i, 
   if (p(i) > 3, abort "Parameter larger than 3", p);
   p(i) = p(i) + 2;
);

Note that the abort statement is part of an if statement which is part of a loop statement. The execution of this program will be terminated with the following display and error message:

----      4 Parameter larger than 3

----      4 PARAMETER p  

i1 3.000,    i2 4.000,    i3 5.000,    i4 5.000,    i5 8.000

**** Exec Error at line 4: Execution halted: abort 'Parameter larger than 3'

Observe that the values of p('1'), p('2') and p('3') were updated, but the values of p('4') and p('5') are equal to the initialization values since the program was terminated before they could be updated.

If the extension .noError is used in the example above, the following lines will appear in the listing file:

----      4 Parameter larger than 3

----      4 PARAMETER p  

i1 3.000,    i2 4.000,    i3 5.000,    i4 5.000,    i5 8.000

****
**** Execution halted from line 4: abort.noError 'Parameter larger than 3'
****

Note that the execution of the program is aborted as before, but there is no execution error in this case.

Instead of an if statement we may use a dollar condition in the loop:

Set       i    / i1*i5 /;
Parameter p(i) / i1 1, i2 2, i3 3, i4 5, i5 8 /;
loop(i, 
   abort$(p(i) > 3) "Parameter larger than 3", p;
   p(i) = p(i) + 2;
);

Observe that this alternative formulation has the same outcome as above.