如何在MiniZinc中对'array[int] of var set of int'使用arg_sort?
我在用Chuffed求解器运行MiniZinc模型时遇到类型错误,简化后的出错代码如下:
% Model parameters. int: n_steps; % 调度周期的步数 enum tasks; % 所有任务ID的集合 enum work_centers; % 所有工作中心ID的集合 % task_work_center[t] 表示任务t所需的工作中心 array [tasks] of work_centers: task_work_center; % 模型变量 % task_start[t] 是任务t的开始步数 array [tasks] of var 1..n_steps: task_start ::add_to_output; % 约束 array[work_centers] of var set of 1..n_steps: work_center_tasks = [{task_start[t] | t in tasks where task_work_center[t]==wc} | wc in work_centers]; array[work_centers] of var int: task_permutation; include "arg_sort.mzn"; constraint forall(wc in work_centers)( task_permutation[wc] = arg_sort(work_center_tasks[wc]) %%% 此处报错!!! ); % 目标 solve satisfy;
运行后出现的类型错误:
MiniZinc: type error: no function or predicate with this signature
found: `arg_sort(var set of int)' Cannot use the following functions
or predicates with the same identifier: function array [int] of $$E :
arg_sort(array [$$E] of $$T: x);
(argument 1 expects type array[int] of int, but type var set of int given) function array [int] of var $$E : arg_sort(array [$$E] of
var $$T: x);
(argument 1 expects type array[int] of var int, but type var set of int given) function array [int] of $$E : arg_sort(array [$$E] of
float: x);
(argument 1 expects type array[int] of float, but type var set of int given) function array [int] of var $$E : arg_sort(array [$$E] of
var float: x);
(argument 1 expects type array[int] of var float, but type var set of int given) predicate arg_sort(array [$$E] of var $$T: x,array [int]
of var $$E: p);
(requires 2 arguments, but 1 given) predicate arg_sort(array [$$E] of var float: x,array [int] of var $$E: p);
(requires 2 arguments, but 1 given)
已知条件:预先知道每个工作中心对应的任务数量(各工作中心维度不同),可以不使用集合建模。
核心思路
arg_sort仅支持数组类型输入,不兼容集合类型。因此需要把原有的集合建模替换为数组建模,直接为每个工作中心生成对应任务的开始时间数组,再用arg_sort处理。
修改后的代码示例
% Model parameters. int: n_steps; % 调度周期的步数 enum tasks; % 所有任务ID的集合 enum work_centers; % 所有工作中心ID的集合 % task_work_center[t] 表示任务t所需的工作中心 array [tasks] of work_centers: task_work_center; % 预先定义每个工作中心对应的任务子集(根据实际任务分配填写) % 示例:若work_centers包含wc1、wc2,则定义: % array[work_centers] of set of tasks: wc_tasks = [ % {t | t in tasks where task_work_center[t] == wc1}, % {t | t in tasks where task_work_center[t] == wc2} % ]; array[work_centers] of set of tasks: wc_tasks; % 模型变量 % task_start[t] 是任务t的开始步数 array [tasks] of var 1..n_steps: task_start ::add_to_output; % 为每个工作中心生成任务开始时间的数组(替代原集合) array[work_centers] of array[int] of var int: wc_task_starts = [ [task_start[t] | t in wc_tasks[wc]] | wc in work_centers ]; % 存储每个工作中心的任务排列 array[work_centers] of array[int] of var int: task_permutation; include "arg_sort.mzn"; constraint forall(wc in work_centers)( task_permutation[wc] = arg_sort(wc_task_starts[wc]) ); % 目标 solve satisfy;
关键改动说明
- 定义工作中心任务子集:新增
wc_tasks数组,明确每个工作中心对应的任务集合,作为生成数组的基础。 - 替换集合为数组:用
wc_task_starts数组替代原work_center_tasks集合,直接生成每个工作中心的任务开始时间数组。 - 修正
arg_sort调用:现在arg_sort的输入是数组类型,符合函数参数要求,不会再触发类型错误。
如果偏好使用arg_sort的谓词版本(双参数形式),可将约束调整为:
constraint forall(wc in work_centers)( arg_sort(wc_task_starts[wc], task_permutation[wc]) );
内容的提问来源于stack exchange,提问作者Emilie Picard-Cantin

