我对Minizinc的语法有一个简单的问题。我的输入.dzn文件包含一组2维数组(大约最多30个数组),声明如下:
rates_index_0 = array2d(1..3, 1..501, [ 15, 20, 23, ....
rates_index_12 = array2d(1..3, 1..501, [ 21, 24, 27, ....
...
注意:索引号中有间隙(例如,12 - > 20)
在我的模型中,我需要根据变量的值使用其中一个数组。在通用编程语言中,我将使用地图或字典数据结构来解决它。但是在Minizinc中,我用以下方式对其进行了硬编码:
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;
这段代码的一个明显问题是每次更改输入时我都需要更改模型。有没有更好的方法可以用通用方式对其进行编码?
谢谢!
答案 0 :(得分:4)
以更抽象的方式,地图结构只不过是将某种类型的输入映射到数组的函数。因此,映射可以由数组和函数替换。 (不同之处在于你必须自己定义这个功能)
在开始使用其他内容之前,我想指出,如果您的模型编译速度通常很快,您可能需要尝试不使用函数rates_index = array3d(0..60, 1..3, 1..501, [ 15, 20, 23, ....
的三元数组。这会花费更多内存,但会使模型更加灵活。
使用map-structure的一般方法是定义一个函数map_index
,它将输入(在本例中为整数)映射到数组的索引,也是整数。这意味着我们可以定义一个额外的级别数组以指向正确的数组:rates_index = array3d(0..nr_arrays, 1..3, 1..501, ....
。这意味着get_rates
的内容可以是:rates_index[map_index(index), dc_size, load]
。
最简单形式的函数map_index
本身将包含if-then-else
语句的另一个版本:
function int: map_index(int: index) =
if index == 0 then
0
else if index == 12 then
1
else if index == 16 then
2
else if index == 20 then
3
else
assert(false, "unknown index", 0)
endif endif endif endif;
但是,您可以通过生成包含每个索引的数组编号的额外数组来使其动态化,为所有不可用的数组添加-1。对于您的示例,映射将如下所示: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];
。然后可以动态地将map_index
函数定义为:
function int: map_index(int: index) =
mapping[index];