在带有数组集的 minizinc 中使用 forall(不连续)
Using forall in minizinc with an array set (not contiguous)
我正在尝试使用 forall 实例来添加约束,但我遇到了这个错误,我不确定我应该怎么做。
(array slice must be contiguous)
in call 'forall'
in array comprehension expression
with i = {10,24}
in binary '<=' operator expression
in call 'slice_1d'
我正在处理一个调度问题,我需要应用一个限制来确定一组任务(由 suc 确定)只能在特定任务(由 1..nTasks 确定)已经完成后开始.
模型如下
include "globals.mzn";
int: n_res;
array [1..n_res] of int: res_cap;
int: n_tasks;
array [1..n_tasks] of int: duration;
array [1..n_res, 1..n_tasks] of int: res_req;
array [1..n_tasks] of set of int: suc;
int: t_max = sum(i in 1..n_tasks)(duration[i]);
array [1..n_tasks] of var 0..t_max: start;
array [1..n_tasks] of var 0..t_max: end;
var 0..t_max: makespan;
% constraint that I can't implement. this constraint should make every task[i] to start after a set of tasks{i} are finished. The set is defined by the array suc.
constraint forall (i in suc)(end[i] <= start[i]);
constraint cumulative(start, duration, row(res_req, 1), res_cap[1]);
constraint cumulative(start, duration, row(res_req, 2), res_cap[2]);
constraint cumulative(start, duration, row(res_req, 3), res_cap[3]);
constraint cumulative(start, duration, row(res_req, 4), res_cap[4]);
constraint forall(i in 1..n_tasks)(end[i] = start[i]+duration[i]);
constraint makespan = max(i in 1..n_tasks)(end[i]);
solve minimize makespan;
数组 suc 和 1..nTasks 的行数相同。
我有一个一维数组,其中包含可以在任务 [i] 结束后开始的特定任务集。
在一个较小的实例中,例如:
成功 = [{5, 15}, {17, 23, 28}, {10, 12}, {8}]
我需要实现的是:
end[i] | i in 1..nTasks <= start[i] | i in suc
对于我发布的特定集合,可以像这样手动完成:
end[1] <= start[5]
end[1] <= start[15]
end[2] <= start[17]
end[2] <= start[23]
end[2] <= start[28]
end[3] <= start[10]
end[3] <= start[12]
end[4] <= start[8]
我刚开始使用 minizinc,有些东西告诉我我遗漏了一些可能很简单的东西,但是,已经有一段时间了,我无法实现它。
我如何编写可以执行此操作的 forall 实例?
罪魁祸首是这个约束(如错误所示):
constraint forall (i in suc)(end[i] <= start[i]);
您尝试使用 suc
作为循环的生成器。问题是您需要为该约束做两件事:当前任务的开始应该在该任务的后续任务之前。使用您的方法这是不可能的,因为 i
将具有诸如 { 10, 24 }
之类的值,但是当前任务没有值(参考)(即 start[i]
的值)。
这里有一个解决方法:用i in n_res
循环遍历所有任务(i
是第i个任务),然后循环遍历suc[i]
得到每个任务的后续任务。
constraint forall (i in 1..n_res) (
forall(s in suc[i]) (
end[i] <= start[s]
)
);
另一种可能更简单的方法是将两个 forall
循环合并为一个循环:
constraint forall (i in 1..n_res, s in suc[i]) (
end[i] <= start[s]
);
当我 运行 模型时,它生成了这个解决方案:
% obj = 51
start = array1d(1..30, [7, 21, 4, 31, 6, 41, 34, 3, 35, 39, 21, 28, 47, 0, 38, 48, 44, 35, 28, 7, 10, 34, 11, 47, 41, 3, 11, 3, 22, 17]);
end = array1d(1..30, [17, 25, 5, 34, 11, 51, 35, 7, 41, 47, 28, 35, 51, 3, 48, 51, 48, 38, 35, 12, 11, 44, 19, 48, 47, 7, 18, 9, 31, 21]);
makespan = 51;
----------
% obj = 51
==========
我正在尝试使用 forall 实例来添加约束,但我遇到了这个错误,我不确定我应该怎么做。
(array slice must be contiguous) in call 'forall' in array comprehension expression with i = {10,24} in binary '<=' operator expression in call 'slice_1d'
我正在处理一个调度问题,我需要应用一个限制来确定一组任务(由 suc 确定)只能在特定任务(由 1..nTasks 确定)已经完成后开始.
模型如下
include "globals.mzn";
int: n_res;
array [1..n_res] of int: res_cap;
int: n_tasks;
array [1..n_tasks] of int: duration;
array [1..n_res, 1..n_tasks] of int: res_req;
array [1..n_tasks] of set of int: suc;
int: t_max = sum(i in 1..n_tasks)(duration[i]);
array [1..n_tasks] of var 0..t_max: start;
array [1..n_tasks] of var 0..t_max: end;
var 0..t_max: makespan;
% constraint that I can't implement. this constraint should make every task[i] to start after a set of tasks{i} are finished. The set is defined by the array suc.
constraint forall (i in suc)(end[i] <= start[i]);
constraint cumulative(start, duration, row(res_req, 1), res_cap[1]);
constraint cumulative(start, duration, row(res_req, 2), res_cap[2]);
constraint cumulative(start, duration, row(res_req, 3), res_cap[3]);
constraint cumulative(start, duration, row(res_req, 4), res_cap[4]);
constraint forall(i in 1..n_tasks)(end[i] = start[i]+duration[i]);
constraint makespan = max(i in 1..n_tasks)(end[i]);
solve minimize makespan;
数组 suc 和 1..nTasks 的行数相同。
我有一个一维数组,其中包含可以在任务 [i] 结束后开始的特定任务集。
在一个较小的实例中,例如: 成功 = [{5, 15}, {17, 23, 28}, {10, 12}, {8}]
我需要实现的是:
end[i] | i in 1..nTasks <= start[i] | i in suc
对于我发布的特定集合,可以像这样手动完成:
end[1] <= start[5]
end[1] <= start[15]
end[2] <= start[17]
end[2] <= start[23]
end[2] <= start[28]
end[3] <= start[10]
end[3] <= start[12]
end[4] <= start[8]
我刚开始使用 minizinc,有些东西告诉我我遗漏了一些可能很简单的东西,但是,已经有一段时间了,我无法实现它。
我如何编写可以执行此操作的 forall 实例?
罪魁祸首是这个约束(如错误所示):
constraint forall (i in suc)(end[i] <= start[i]);
您尝试使用 suc
作为循环的生成器。问题是您需要为该约束做两件事:当前任务的开始应该在该任务的后续任务之前。使用您的方法这是不可能的,因为 i
将具有诸如 { 10, 24 }
之类的值,但是当前任务没有值(参考)(即 start[i]
的值)。
这里有一个解决方法:用i in n_res
循环遍历所有任务(i
是第i个任务),然后循环遍历suc[i]
得到每个任务的后续任务。
constraint forall (i in 1..n_res) (
forall(s in suc[i]) (
end[i] <= start[s]
)
);
另一种可能更简单的方法是将两个 forall
循环合并为一个循环:
constraint forall (i in 1..n_res, s in suc[i]) (
end[i] <= start[s]
);
当我 运行 模型时,它生成了这个解决方案:
% obj = 51
start = array1d(1..30, [7, 21, 4, 31, 6, 41, 34, 3, 35, 39, 21, 28, 47, 0, 38, 48, 44, 35, 28, 7, 10, 34, 11, 47, 41, 3, 11, 3, 22, 17]);
end = array1d(1..30, [17, 25, 5, 34, 11, 51, 35, 7, 41, 47, 28, 35, 51, 3, 48, 51, 48, 38, 35, 12, 11, 44, 19, 48, 47, 7, 18, 9, 31, 21]);
makespan = 51;
----------
% obj = 51
==========