来自另一个阵列的 Minizinc 约束
Minizinc constraints from another array
我正在尝试使用 minizinc 进行我的第一个约束编程。我正在尝试创建一个时间表,其中包含 n
个时段和 n
个人,每个时段分配不同的人。我正在使用 array of var int
来模拟时间表,使用 alldifferent()
来确保每个时段都有不同的人。
一个单独的 array
大小 n
,names
包含他们的名字,如下所示:
% Pseudo enum
set of int: NameIndex = 1..2;
int: Forename = 1;
int: Surname = 2;
int: n = 4; % Number of slots and people
set of int: slots = 1..n;
array[slots, NameIndex] of string: names = [| "John", "Doe"
| "Ann", "Jones"
| "Fred", "Doe"
| "Barry", "Doe" |];
% The schedule
array[slots] of var slots: schedule;
% Every person is scheduled:
include "alldifferent.mzn";
constraint alldifferent(schedule);
% How to constrain by a value from names, say alphabetic order by forename.
% Want to compare each value in schedule to the next one.
%constraint forall (i in 1..n-1) (names[schedule[i],Forename] < names[schedule[i+1],Forename]);
solve satisfy;
output [show(i) ++ ": " ++ show(names[schedule[i], Forename]) ++ " " ++ show(names[schedule[i], Surname]) ++ "\n"
| i in slots]
% should be:
% | i in schedule]
如何通过名称中的值来约束调度?在我上面的(损坏的)示例中,当取消注释 forall
约束时,我得到(使用 Minizinc IDE):
in call 'forall'
in array comprehension expression
with i = 1
in binary '<' operator expression
in array access
cannot find matching declaration
我跟着错误直到不明白找不到哪个声明。当我从 schdule 值索引到数组时,输出块 show()
s 来自名称的值非常愉快。
我错过了什么?有没有更好的方法来模拟名称?我希望将名称扩展到其他 'attributes' 人并创建其他限制。我确定模型和我的 forall 约束都非常幼稚!
问题是 MiniZinc 对字符串的支持不多;并且特定于您的示例:不支持比较字符串(“<”)。
也就是说,有一些计划支持 var 字符串(即使用字符串作为决策变量),但我不知道它何时发布的确切状态。
这是一个非常简单的修复,但它需要一些预处理:
1) 创建一个包含每个名称的(排序)索引的新数组:
array[slots] of int: names_ix = [4, % John Doe
1, % Ann Jones
3, % Fred Doe
2, % Barry Doe
];
2) 更改排序约束以使用这个新数组
constraint
forall (i in 1..n-1) (
names_ix[schedule[i]] <= names_ix[schedule[i+1]]
);
[有一个更复杂的变体,要求您将名称中的每个字符转换为整数(在 "var int" 的矩阵中),然后要求单词 - 作为整数集合 - 是有序的。请注意,这往往很混乱,例如处理不同长度的字符串等]
我正在尝试使用 minizinc 进行我的第一个约束编程。我正在尝试创建一个时间表,其中包含 n
个时段和 n
个人,每个时段分配不同的人。我正在使用 array of var int
来模拟时间表,使用 alldifferent()
来确保每个时段都有不同的人。
一个单独的 array
大小 n
,names
包含他们的名字,如下所示:
% Pseudo enum
set of int: NameIndex = 1..2;
int: Forename = 1;
int: Surname = 2;
int: n = 4; % Number of slots and people
set of int: slots = 1..n;
array[slots, NameIndex] of string: names = [| "John", "Doe"
| "Ann", "Jones"
| "Fred", "Doe"
| "Barry", "Doe" |];
% The schedule
array[slots] of var slots: schedule;
% Every person is scheduled:
include "alldifferent.mzn";
constraint alldifferent(schedule);
% How to constrain by a value from names, say alphabetic order by forename.
% Want to compare each value in schedule to the next one.
%constraint forall (i in 1..n-1) (names[schedule[i],Forename] < names[schedule[i+1],Forename]);
solve satisfy;
output [show(i) ++ ": " ++ show(names[schedule[i], Forename]) ++ " " ++ show(names[schedule[i], Surname]) ++ "\n"
| i in slots]
% should be:
% | i in schedule]
如何通过名称中的值来约束调度?在我上面的(损坏的)示例中,当取消注释 forall
约束时,我得到(使用 Minizinc IDE):
in call 'forall'
in array comprehension expression
with i = 1
in binary '<' operator expression
in array access
cannot find matching declaration
我跟着错误直到不明白找不到哪个声明。当我从 schdule 值索引到数组时,输出块 show()
s 来自名称的值非常愉快。
我错过了什么?有没有更好的方法来模拟名称?我希望将名称扩展到其他 'attributes' 人并创建其他限制。我确定模型和我的 forall 约束都非常幼稚!
问题是 MiniZinc 对字符串的支持不多;并且特定于您的示例:不支持比较字符串(“<”)。
也就是说,有一些计划支持 var 字符串(即使用字符串作为决策变量),但我不知道它何时发布的确切状态。
这是一个非常简单的修复,但它需要一些预处理:
1) 创建一个包含每个名称的(排序)索引的新数组:
array[slots] of int: names_ix = [4, % John Doe
1, % Ann Jones
3, % Fred Doe
2, % Barry Doe
];
2) 更改排序约束以使用这个新数组
constraint
forall (i in 1..n-1) (
names_ix[schedule[i]] <= names_ix[schedule[i+1]]
);
[有一个更复杂的变体,要求您将名称中的每个字符转换为整数(在 "var int" 的矩阵中),然后要求单词 - 作为整数集合 - 是有序的。请注意,这往往很混乱,例如处理不同长度的字符串等]