Initializing arrays
Describes the various ways in which you can initialize arrays.
You can initialize arrays:
Externally
Arrays can be initialized by external data, in which case the declaration has the form:
int a[1..2] [1..3] = ...;
and the actual initialization is given in
a data source, which is a separate .dat file
in IBM ILOG OPL.
By listing values
This is how arrays are initialized in most of the examples presented so far. Multidimensional arrays in OPL are, in fact, arrays of arrays and must be initialized accordingly. For example, the declaration:
/* .mod file */ int a[1..2][1..3] = ...; /* .dat file */ a = [ [10, 20, 30], [40, 50, 60] ];initializes a two-dimensional array by giving initializations for the one-dimensional arrays of its first dimension. It is easy to see how to generalize this initialization to any number of dimensions.
By specifying pairs
An array can also be initialized by specifying pairs (index, value), as in the declaration:
/* .mod file */ int a[Days] = ...; /* .dat file */ a = #[ “Monday”: 1, ”Tuesday”: 2, ”Wednesday”: 3, ”Thursday”: 4, ”Friday”: 5, ”Saturday”: 6, ”Sunday”: 7 ]#;Note:When the initialization is specified by (index, value) pairs, the delimiters
#[and]#must be used instead of[and].The ordering of the pairs can be arbitrary.
These two forms of initialization can be combined arbitrarily, as in:
/* .mod file */ int a[1..2][1..3] = ...; /* .dat file */ a = #[ 2: [40, 50, 60], 1: [10, 20, 30] ]#;
Internally
You can initialize arrays internally (that is, in the .mod file) using the same syntax as in .dat files. Here, the array items may be expressions
that are evaluated during initialization. The syntax for pairs #[, ]# is not available
for internal initialization.
In preprocessing instructions
Arrays can also be initialized in the preprocessing instructions, as in:
range R = 1..8;
int a[R];
execute {
for(var i in R) {
a[i] = i + 1;
}}
which initializes the array in such a way
that a[1] = 2, a[2] = 3, and so on. See Preprocessing of data.
As generic arrays
OPL also supports generic arrays, that is, arrays whose items are initialized by an expression. These generic arrays may significantly simplify the modeling of an application. The declaration:
int a[i in 1..10] = i+1;
declares an array of 10 elements such that
the value of a[i] is i+1.
Generic arrays can of course be multidimensional, as in:
int m[i in 0..10][j in 0..10] = 10*i + j;
which initializes element m[i][j] to 10*i + j. Generic arrays are useful in performing
some simple transformations. For instance, generic arrays can be used
to transpose matrices in a simple way, as in:
int m[Dim1][Dim2] = ...;
int t[j in Dim2][i in Dim1] = m[i][j];
More generally speaking, generic arrays can be used to permute the indices of arrays in simple ways.
As generic indexed arrays
To have more flexibility when initializing arrays in a generic way, OPL enables you to control the index value in addition to the item value, as described earlier in As generic arrays. To illustrate the syntax, the same examples can be expressed as follows:
int a[1..10] = [ i-1 : i | i in 2..11 ];
int m[0..10][0..10] = [ i : [ j : 10*i+j ] | i,j in 0..10 ];
This syntax is close to the syntax used for
initializing arrays in .dat files by means
of indices, delimited by #[ and ] #, as explained above in Specifying
pairs. Using this syntax is an efficient means of initializing
arrays used to index data.
The oilDB.mod example
contains an execute block that performs
initialization. Instead of:
GasType gas[Gasolines];
execute {
for(var g in gasData) {
gas[g.name] = g
}
}
the same can be expressed with the syntax for generic indexed arrays as:
GasType gas[Gasolines] = [ g.name : g | g in gasData ];
Likewise, this syntax, from transp4.mod
float Cost[Routes];
execute INITIALIZE {
for( var t in TableRoutes ) {
Cost[Routes.get(t.p,Connections.get(t.o,t.d))] = t.cost;
}
}
is equivalent to
float Cost[Routes] = [ <t.p,<t.o,t.d>>:t.cost | t in TableRoutes ];
It is recommended to use generic arrays or generic indexed arrays whenever possible, since they make the model more explicit and readable.
If an index is met more than once, no warning is issued and the latest value set for this index is the one kept.
For example:
int n=5; {int} s= {1,3,4,2,5}; sorted {int} s2=asSet(1..n);; reversed {int} s3=asSet(1..n);; int x[1..n]=[maxl(n-i,i): i | i in s]; int x2[1..n]=[maxl(n-i,i): i | i in s2]; int x3[1..n]=[maxl(n-i,i): i | i in s3]; execute { writeln(x); writeln(x2); writeln(x3); }gives out
[0 0 2 4 5] [0 0 3 4 5] [0 0 2 1 5]