Finalizing sets and dynamic arrays
In Mosel, an array is dynamic if it is indexed by a dynamic set. If an array is used to represent dense data one should avoid defining it as a dynamic array as that uses more memory and is slower than the corresponding static array. As an additional advantage, set finalization allows Mosel to check for `out of range' errors that cannot be detected if the sets are dynamic.
The declaration of an array has one of these two forms
- Explicit dynamic declaration by using the keyword dynamic.
- `Standard' declaration, resulting in a static array (all index sets are known) or an implicitly dynamic array (some or all indexing sets are unknown at the point where the declaration takes place) for which the Mosel compiler will decide on the most suitable representation.
In many optimization models, arrays are declared implicitly dynamic because their contents is initially unknown—but there is no real need to treat them as dynamic structures as they remain unchanged once they have been initialized.
The automatic finalization mechanism of Mosel therefore transforms such implicitly dynamic structures as to handle them more efficiently.
- By default, initializations blocks finalize the sets they initialize and also the index sets of initialized non-dynamic arrays.
- Data of non-dynamic arrays is read before finalization of the index sets in order to create the arrays static.
- Arrays that are not explicitly declared dynamic are only allocated when they are first accessed: this allows these arrays to be static even if their index sets are finalized after the declaration of the arrays.
So, code like the following example
declarations S: set of string A,B: array(S) of real x: array(S) of mpvar end-declarations initializations from "mydata.dat" A end-initializations forall(s in S) create(x(s))
where all arrays are implicitly declared as dynamic arrays (their size is not known at their declaration) but only A that is initialized using a data file really needs to be dynamic, will be treated by Mosel as if you had written the following
declarations S: set of string A: array(S) of real end-declarations initializations from "mydata.dat" A end-initializations finalize(S) declarations B: array(S) of real x: array(S) of mpvar end-declarations
That is, B and x are created as static arrays, making the access to the array entries more efficient.
As a general rule, the following sequence of actions gives better results (in terms of memory consumption and efficiency):
- Declare data arrays and sets that are to be initialized from external sources.
- Perform initializations of data.
- Finalize all related sets.
- Declare any other arrays indexed by these sets (including decision variable arrays).
Note: there are several possibilities to stop Mosel from applying automatic finalization to model objects:
- Declare arrays explicitly as dynamic. (See examples in Sections A transport example and Conditional variable creation and create.)
- Use control parameter autofinal to enable/disable automatic finalization locally:
setparam("autofinal", false) initializations from "datafile.dat" ... end-initializations setparam("autofinal", true)
- Use option noautofinal to disable automatic finalization globally for the whole model:
model "modelname" options noautofinal