Pitfall of lazy initialization of data

In OPL, external data is always initialized before internal data.

If you are not aware of the lazy initialization of data in OPL, you may be surprised by unexpected results.

OPL is a declarative language. The order of elements as they are written in the source file is less important than with imperative languages. We initialize OPL data elements when they are first used, which may result in an initialization order different from the declaration order in a .mod file. External data (with =... syntax) is always initialized before internal data. Scripting blocks are executed after the external data.

Example

In the following example, the array arrayInitExternally is initialized with three elements in the .dat file, but, because set1 has four elements, the result shows that arrayInitExternally has one more element (initialized by default with zero).

string arrayInitByScript[0..3]; 

execute initializeArray {
  for(var i=0; i<=3; i++) {
    if(i >= 1) arrayInitByScript[i] = "A";
    else arrayInitByScript[i] = "B";
  }
}  
// set1 is later used to index an array initialized externally.
// This external initialization of arrayInitExternally alters the content of set1
// because external initialization is done prior to script execution.
// So instead of having set1={1 2 3}, set1 has an additional element "0" 
// Before the script is executed, arrayInitByScript contains four empty elements ["" "" "" ""]
{int} set1 = union(s in 0..3 : arrayInitByScript[s] != "B") {s};
{int} set2 = union(s in 0..3 : arrayInitByScript[s] != "B") {s};

int arrayInitExternally[set1] = ...; // [0, 0, 0]; //  

execute {
writeln(arrayInitByScript);
writeln(set1);
writeln(set2);
writeln(arrayInitExternally);
}

This produces the output:

["B" "A" "A" "A"]
{0 1 2 3}
{1 2 3}
[0 0 0 0]