Миницинк, как создать карту или словарную структуру данных

У меня есть простой вопрос относительно синтаксиса Minizinc. Мой входной файл.dzn содержит набор из двух размерных массивов (примерно до 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;

Одна очевидная проблема с этим кодом заключается в том, что мне нужно менять модель каждый раз, когда я меняю ввод. Есть ли лучший способ, как я могу кодировать это в общем виде?

Спасибо!

1 ответ

Решение

В более абстрактном смысле структура карты - это не что иное, как функция, отображающая входные данные определенного типа в массив. Таким образом, карта может быть заменена массивом и функцией. (Разница в том, что вам придется самостоятельно определять функцию)

Прежде чем начать с остальными, я хотел бы отметить, что если ваша модель компилируется в целом быстро, вы можете попробовать использовать тройной массив без функции, rates_index = array3d(0..60, 1..3, 1..501, [ 15, 20, 23, ...., Это будет стоить больше памяти, но сделает модель более гибкой.

Общий способ использования структуры карты - определить функцию 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];
Другие вопросы по тегам