Minizinc:根据数组位置设置枚举选项集,而不是所有数组位置的选项集

Minizinc: set enumerated set of options based on array position, as opposed to set of options for all array positions

我熟悉

等方法
set of int: RANGE = 1..5;
enum OPTS = {A,B,C};
array[RANGE] of var OPTS = result;

但是当我想为 RANGE 中的每个位置指定 OPTS 时呢?看起来像

的东西
[{A,B,C},{A,B},{A,B,C,D},{B,D},{A}]

然后生成 result[n] 以便它选择 n 处的可用选项之一。

我已尝试使用以下模型,但检测到模型不一致。

set of int: RANGE = 1..5;
enum OPTS = {A,B,C,D};
array[RANGE] of set of OPTS: t = [{A,B,C},{A,B},{A,B,C,D},{B,D},{A}];
array[RANGE] of var OPTS: result;
constraint forall(i in RANGE)(
  forall(j in t[i])(
    result[i] = j
  )
);

output [show(result)]

可能的结果是 [B,A,B,D,A] - 最后一个位置 result[5] 只能是 A.

我尝试使用 Minizinc 手册,但我无法破译如何使用规范中的示例,例如 https://www.minizinc.org/doc-2.4.3/en/spec.html#set-operations,这需要我花费无数时间尝试的其他知识(例如如何解释语法)以我的水平寻求解释,因为搜索这些东西似乎真的没有结果。

谢谢!

如果我没理解错的话你可以用set of OPTS构造OPTS的数组,这里叫t(你不能叫它output因为它是保留的单词)。请注意,在您提出问题时,它不是 var 而是常量数组,因此在构造数组时不需要 var 关键字。

set of int: RANGE = 1..5;
enum OPTS = {A,B,C,D};
array[RANGE] of set of OPTS: t = [{A,B,C},{A,B},{A,B,C,D},{B,D},{A}];

更新

这是更新问题的模型。这里的技巧是 t[i] 定义了 result[i] 的有效域,你可以简单地使用 in 来实现。

set of int: RANGE = 1..5;
enum OPTS = {A,B,C,D};
array[RANGE] of set of OPTS: t = [{A,B,C},{A,B},{A,B,C,D},{B,D},{A}];
array[RANGE] of var OPTS: result;

constraint 
  forall(i in RANGE) (
     % ensure that result[i] only takes the values in t[i]
     result[i] in t[i]
  )
;

output [show(result)]

本题共有48种解法,如:

[A, A, A, B, A]
----------
[B, A, A, B, A]
----------
[C, A, A, B, A]
----------
[A, B, A, B, A]
----------
[B, B, A, B, A]
----------
[C, B, A, B, A]
----------
[A, A, B, B, A]
----------
...