Basic formal parameters

Formal parameters play a fundamental role in OPL; they are used in aggregate operators, generic sets, and forall statements.

The simplest formal parameter has the form

p in S

where p is the formal parameter and S is the set from which p takes its values.

The set S can be:

  • an integer range, as in

    
    int n=6;
    int s = sum(i in 1..n) i*i; 
    
  • a string set, as in

    
    {string} Products ={"car","truck"}; 
    float cost[Products] =[12000,10000]; 
    float maxCost = max(p in Products) cost[p]; 
    
  • or a tuple set, as in

    
    {string} Cities = { "Paris", "London", "Berlin" };
    tuple Connection
    {
       string orig;
       string dest;
    }
    {Connection} connections = { <"Paris","Berlin">,<"Paris","London">};
    float cost[connections] = [ 1000, 2000 ];
    float maxCost= max(r in connections) cost[r];
    

If you need to filter the range of the formal parameters using conditions, the formal parameter then takes the form

p in S : filtering condition

and assigns to p all elements of S according to the filter applied.

For instance, in the excerpt


int n=8;
dvar int a[1..n][1..n];
subject to
{
 forall(i in 1..8) 
   forall(j in 1..8: i < j) 
      a[i][j] >= 0;
}

the constraint a[i][j] >= 0 is modeled for all i and j such that 1i < j8.

Note:

OPL does not support aggregates in filter expressions. For example:

  • For an expression such as:

    {int} notFirst = {i | i in 1..10 : card({j | <i,j> in pairs}) == 0};

    the type check displays the error: "Aggregate set is currently not supported for filter expressions."

  • For an expression such as:

    {int} notFirst = {i | i in 1..10 : sum(<i,j>in pairs) i == 0}; 

    the type check displays the error: "Aggregate sum is currently not supported for filter expressions."

Several parameters can often be combined together to produce more compact statements. For instance, the declaration


int s = sum(i,j in 1..n: i < j) i*j; 

is equivalent to


int s = sum(i in 1..n) sum(j in 1..n: i < j) i*j; 

which is less readable.

The declaration


int s = sum(i in 1..n, j in 1..m) i*j; 

is equivalent to


int s = sum(i in 1..n) sum(j in 1..m) i*j; 

These parameters can, of course, be subject to filtering conditions. The excerpt


forall(i,j in 1..n : i < j) 
     a[i][j] >= 0;

is equivalent to


forall(i in 1..n, j in 1..n : i<j) 
     a[i][j] >= 0; 

Here is an even more compact form:


forall(ordered i,j in 1..n) 
     a[i][j] >= 0;

Indeed, in many applications one is interested, given a set S, in stating filters or conditions over all pairs (i, j) of elements of S satisfying i < j in the ordering associated with S. In this excerpt


{T} S = ...;
forall(ordered s, t in S)...;
forall(s in S, t in S: ord(S,s) < ord(S,t)) ... 

the first forall line is equivalent to the second one and illustrates the functionality ordered, often useful in practical applications. T can be one of the types int, float, string, or a tuple type.

Important:

This ordering does not refer to the ordering associated with type T but to the order of the items within the set.