How to address this question will to a large extend depend on the way how this array of variables is used. How is the array accessed / enumerated (always in its entirety, or are you building constraint expressions over certain indices)? How do you decide whether there are 2 or 3 indices (at compile time or data-driven at run time)?
Within a single model it is not possible to declare (globally) an array with 2 different sets of indices, however, multiple declarations (along with their use) could be provided in various different ways, eg through separately compiled portions of code.
- The technically easiest solution probably would be to declare the array with the full set of indices, populating any unused index set with a single default value. This way you avoid having to specify several cases when accessing the array, eg in the definition of constraints.
- Using the concepts of union types and references that have been introduced
in Mosel 6, you can work with some constructs like the following (without any
further detail it is difficult to tell whether this representation is practical for your use case):
model "mytestmodel"
uses 'mmreflect'
parameters
NDIM=2
end-parameters
declarations
! Type declarations
a2d=array(set of string,set of string) of mpvar
a3d=array(set of string,set of string,set of string) of mpvar
! The array of variables
v: any
! Declaration of a subroutine
procedure printsol(a: any)
end-declarations
if NDIM=2 then v:=->(a2d)
forall(j in ['b1','b2','b3']) create(v.a2d('a',j))
elif NDIM=3 then
v:=->(a3d)
forall(j in ['b1','b2','b3']) create(v.a3d('a',j,"c"))
else
writeln("Bad array size")
end-if
writeln("Number of array dimensions=", v.array.nbdim)
printsol(v)
procedure printsol(a: any)
declarations
it: iterator
end-declarations
if a is array of mpvar then
inititer(it,a.array)
while (nextcell(it)) writeln(it.indices, ":", a.array(it).mpvar.sol)
else
writeln("Unexpected data structure")
end-if
end-procedure
end-model
There are various other options (among others, local declarations within
subroutines, using preprocessor markup to select portions of code for
compilation, or working with dynamically loaded Mosel packages), but deciding what
would be a good choice really depends on your specific use case.