Функция MiniZinc global_cardinality с перечислениями

Согласно документам

Ключевым поведением перечислимых типов является то, что они автоматически приводятся к целым числам, когда они используются в позиции, ожидающей целое число. Например, это позволяет нам использовать глобальные ограничения, определенные для целых чисел, такие как global_cardinality_low_up

Семейство global_cardinality * бывает двух видов: предикат и функция. В то время как в случае с предикатами, массивы элементов перечисления действительно приводят к целочисленному типу, с функциями такое приведение не работает. Например,

include "global_cardinality_closed.mzn";

enum MyEnum = {A, B, C};
array[1..2] of MyEnum: toCount = [A, C];

array[1..100] of var MyEnum: values;

%1
constraint let {
    array[int] of var int: counts = global_cardinality_closed(values, toCount);
} in counts[1] > counts[2];

%2
constraint global_cardinality_closed(values, toCount, [5, 6]);

компиляция приведенного выше фрагмента кода в MiniZincIDE приводит к:

MiniZinc: type error: no function or predicate with this signature found: `global_cardinality_closed(array[int] of var MyEnum,array[int] of MyEnum)'
Cannot use the following functions or predicates with the same identifier:
predicate global_cardinality_closed(array[$_] of var int: x,array[$_] of int: cover,array[$_] of var int: counts);
    (requires 3 arguments, but 2 given)

В то же время код после %2 компилируется нормально.

Я что-то пропускаю или мне нужно сообщить об ошибке?


person Raman Chodźka    schedule 27.12.2020    source источник


Ответы (1)


Чтобы %1 заработал, вы можете либо

include "global_cardinality_closed_fn.mzn";

или просто

include "globals.mzn";

Функция реализована с использованием предиката:

include "global_cardinality_closed.mzn";

/** @group globals.counting
  Returns an array with number of occurrences of \a cover[\p i] in \a x.

  The elements of \a x must take their values from \a cover.
*/
function array[$Y] of var int: global_cardinality_closed(array[$X] of var int: x,
                                                         array[$Y] of int: cover) :: promise_total =
  let { array[int] of int: cover1d = array1d(cover);
        array[index_set(cover1d)] of var 0..length(x): counts;
        constraint global_cardinality_closed(array1d(x),cover1d,counts); } 
  in arrayXd(cover,counts);
person Axel Kemper    schedule 27.12.2020