问题描述
我熟悉这样的方法
set of int: RANGE = 1..5;
enum OPTS = {A,B,C};
array[RANGE] of var OPTS = result;
但是当我想为 OPTS
中的每个位置指定 RANGE
时怎么办?看起来像的东西
[{A,C},{A,B},C,D},{B,{A}]
然后生成 result[n]
以便它选择 n
处的可用选项之一。
我已尝试使用以下模型,但检测到模型不一致。
set of int: RANGE = 1..5;
enum OPTS = {A,D};
array[RANGE] of set of OPTS: t = [{A,{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,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,C},{A,B},D},{B,{A}];
更新
这是更新问题的模型。这里的技巧是 t[i]
定义了 result[i]
的有效域,您可以简单地使用 in
来实现这一点。
set of int: RANGE = 1..5;
enum OPTS = {A,{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]
----------
[C,A]
----------
[A,A]
----------
...