I have a simple question regarding the Minizinc's syntax. My input .dzn file contain a set of 2 dimentional arrays (approximately up to 30 arrays), declared as follows:
rates_index_0 = array2d(1..3, 1..501, [ 15, 20, 23, ....
rates_index_12 = array2d(1..3, 1..501, [ 21, 24, 27, ....
...
note: index numbers have gaps in them (e.g., 12 -> 20)
In my model, I need to use one of these arrays depending on the value of the variable. In common programming language I would solve it using a map or a dictionary datastructure. But in Minizinc I am hardcoding this in the following way:
function var int: get_rate(int: index, var int: load, int: dc_size) =
if index == 0 then
rates_index_0[dc_size, load]
else if index == 12 then
rates_index_12[dc_size, load]
else if index == 16 then
rates_index_16[dc_size, load]
else if index == 20 then
rates_index_20[dc_size, load]
else
assert(false, "unknown index", 0)
endif endif endif endif;
The one obvious problem with this code is that I need to change model each time I change input. Is there a better way how I can code this in a generic way?
Thanks!
In an more abstract way a map-structure is nothing more than a function mapping inputs of a certain type to an array. A map can thus be replaced by a array and a function. (The difference being you will have to define the function yourself)
Before I get started with the rest I would like to point out that if your model compiles generally fast, you might want to try a triple array without the function,
rates_index = array3d(0..60, 1..3, 1..501, [ 15, 20, 23, ....
. This will cost more memory, but will make the model more flexible.The general way of using a map-structure would be to define a function
map_index
, that maps your input, in this case integers, to the index of the array, also integers. This means that we can then define a extra level array to point to the right one:rates_index = array3d(0..nr_arrays, 1..3, 1..501, ....
. This means that the content ofget_rates
can then be:rates_index[map_index(index), dc_size, load]
.The function
map_index
itself in its simplest form would contain another version of yourif-then-else
statements:However you can make it dynamic by generating an extra array containing the array number for each index, putting -1 for all arrays that are not available. For your example the mapping would look like this:
array[0..20] of int: mapping = [0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 2, -1, -1, -1, 3];
. Themap_index
function could then dynamically be defined as: