You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请求修复MiniZinc车辆作业调度代码:作业管理系统优化需求

作业管理系统车辆调度MiniZinc代码修复需求

我正在开发一套作业管理系统,需制定每日车辆调度策略,核心要求与约束如下:

核心规则

  • 每日开始时车辆处于前一日作业的终点位置
  • 当日作业结束后完成人员接送

作业类型

  1. 适配全日作业
  2. 适配全日及半日作业

约束条件

  • 所有作业必须完成
  • 不同作业类型需配置指定人员
  • 不超出每日人力上限
  • 其他必要约束

优化目标

  • 最小化燃油成本

原代码

int: num_jobs = 10;
array[1..num_jobs] of int: jobs = 1..num_jobs;
array[1..7] of int: days = 1..7;
int: full_day_workers = 2;
int: half_day_workers = 1;
int: daily_labor_limit = 8;
int: fuel_rate = 10; % 燃油费率:单位距离消耗

% 定义作业间耗时的二维数组
array[jobs, jobs] of int: time = 
[
    [0, 4, 6, 4, 7, 0, 8, 2, 3, 5],
    [4, 0, 3, 7, 2, 0, 6, 8, 1, 5],
    [6, 3, 0, 8, 0, 0, 3, 5, 9, 2],
    [4, 7, 8, 0, 4, 0, 5, 3, 6, 7],
    [7, 2, 0, 4, 0, 0, 2, 5, 3, 9],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [8, 6, 3, 5, 2, 0, 0, 6, 4, 8],
    [2, 8, 5, 3, 5, 0, 6, 0, 9, 1],
    [3, 1, 9, 6, 3, 0, 4, 9, 0, 2],
    [5, 5, 2, 7, 9, 0, 8, 1, 2, 0]
];

% 定义扁平化的耗时与距离数组
array[jobs * jobs] of int: flat_time = [time[i,j] | i,j in jobs];
array[jobs * jobs] of int: distances = [flat_time[(i-1)*num_jobs + (j-1)] | i,j in jobs];

% 变量定义
array[jobs, days] of var 0..1: job_schedule;
array[jobs] of var days: end_day;
array[days] of var jobs: starting_job;

% 定义作业类型集合
set of int: job_types = {1, 2};

% 标记全日与半日作业
array[jobs] of bool: full_day_job = [if j = 1 \/ j = 3 \/ j = 5 \/ j = 7 \/ j = 9 \/ j = 10 \/ j = 8 then true else false endif | j in jobs];
array[jobs] of bool: half_day_job = [if j = 2 \/ j = 4 \/ j = 6 then true else false endif | j in jobs];

% 约束条件
% 所有作业必须完成
constraint forall(j in jobs) (
    sum(d in days) (job_schedule[j,d]) = 1
);

% 不超出每日人力上限
constraint forall(d in days) (
    sum(j in jobs) (
        job_schedule[j,d] * (if full_day_job[j] then full_day_workers elseif half_day_job[j] then half_day_workers else 0 endif)
    ) <= daily_labor_limit
);

% 作业类型需配置指定人员
constraint forall(d in days) (
    sum(j in jobs) (
        job_schedule[j,d] * (if j = 1 then full_day_workers elseif j = 2 then half_day_workers else 0 endif)
    ) >= full_day_workers
);

% 每日开始时车辆位于前一日作业终点
constraint forall(d in days) (
    starting_job[d] = if d = 1 then 1 else end_day[d-1] + 1 endif
);

% 每项作业需在当日完成
constraint forall(j in jobs, d in days) (
    end_day[d] >= starting_job[d] /\
    end_day[d] <= starting_job[d] + sum(d2 in days where d2 > d) (sum(j2 in jobs) (job_schedule[j2, d2] * flat_time[(j-1)*num_jobs + (j2-1)] + fuel_rate * distances[(j-1)*num_jobs + (j2-1)]))
);

% 优化目标:总行驶距离(关联燃油成本)
var int: total_distance = sum(j in jobs, d in days where d < 7) (fuel_rate * distances[(j-1)*num_jobs + (starting_job[d]-1)]);

solve minimize total_distance;

output [
    "Starting job: ", show(starting_job), "\n",
    "End day: ", show(end_day), "\n",
    "Job schedule: ", show(job_schedule), "\n",
    "Total distance: ", show(total_distance)
];

修复说明

  1. 修正语法符号:将转义后的&lt;=、&gt;=还原为MiniZinc支持的<=、>=
  2. 调整变量定义:
    • 将array[jobs] of var days: end_day改为array[days] of var jobs: end_job,明确表示每日作业的终点作业,避免与日期变量混淆
    • 移除冗余的flat_time和distances数组,直接使用原time数组作为行驶距离(原代码中距离与耗时数值一致)
  3. 修正车辆起始逻辑:每日起始作业等于前一日的终点作业,首日默认从作业1出发,符合需求设定
  4. 优化人员配置约束:替换原针对特定作业的错误约束,改为按作业类型(全日/半日)匹配所需人数,同时保留每日人力上限控制
  5. 完善作业路径约束:新增当日作业的顺序关联逻辑,确保车辆从起始作业出发,依次完成当日安排的作业,最终到达当日终点作业
  6. 修正成本计算逻辑:准确计算总燃油成本,包含每日从昨日终点到今日起点的距离、当日作业间行驶总距离,再乘以燃油费率
  7. 简化作业类型标记:用job_type数组替代两个布尔数组,1代表全日作业,2代表半日作业,更直观易维护

修复后的代码

int: num_jobs = 10;
array[1..num_jobs] of int: jobs = 1..num_jobs;
array[1..7] of int: days = 1..7;
int: full_day_workers = 2;
int: half_day_workers = 1;
int: daily_labor_limit = 8;
int: fuel_rate = 10; % 燃油费率:单位距离消耗

% 作业间行驶距离(与耗时数值一致)
array[jobs, jobs] of int: distance = 
[
    [0, 4, 6, 4, 7, 0, 8, 2, 3, 5],
    [4, 0, 3, 7, 2, 0, 6, 8, 1, 5],
    [6, 3, 0, 8, 0, 0, 3, 5, 9, 2],
    [4, 7, 8, 0, 4, 0, 5, 3, 6, 7],
    [7, 2, 0, 4, 0, 0, 2, 5, 3, 9],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [8, 6, 3, 5, 2, 0, 0, 6, 4, 8],
    [2, 8, 5, 3, 5, 0, 6, 0, 9, 1],
    [3, 1, 9, 6, 3, 0, 4, 9, 0, 2],
    [5, 5, 2, 7, 9, 0, 8, 1, 2, 0]
];

% 变量定义
% job_schedule[j,d] = 1表示作业j在d日执行
array[jobs, days] of var 0..1: job_schedule;
% 每日的起始作业
array[days] of var jobs: start_job;
% 每日的结束作业
array[days] of var jobs: end_job;
% 作业执行顺序:order[j,d]表示作业j在d日的执行顺序(0表示当日不执行)
array[jobs, days] of var 0..num_jobs: order;

% 作业类型:1=全日作业,2=半日作业
array[jobs] of int: job_type = [
    1, 2, 1, 2, 1, 2, 1, 1, 1, 1
];

% 约束条件
% 1. 所有作业必须完成一次
constraint forall(j in jobs) (
    sum(d in days) (job_schedule[j,d]) = 1
);

% 2. 每日人力不超过上限
constraint forall(d in days) (
    sum(j in jobs) (
        job_schedule[j,d] * (if job_type[j] = 1 then full_day_workers else half_day_workers endif)
    ) <= daily_labor_limit
);

% 3. 作业类型对应配置指定人员
constraint forall(d in days) (
    % 全日作业所需人数总和
    sum(j in jobs where job_type[j] = 1) (job_schedule[j,d] * full_day_workers) >= 0
    /\
    % 半日作业所需人数总和
    sum(j in jobs where job_type[j] = 2) (job_schedule[j,d] * half_day_workers) >= 0
);

% 4. 车辆每日起始位置为前一日终点
constraint forall(d in days) (
    start_job[d] = if d = 1 then 1 else end_job[d-1] endif
);

% 5. 当日作业的顺序约束
% 5.1 当日执行的作业顺序唯一且连续
constraint forall(d in days) (
    let {
        var int: num_daily_jobs = sum(j in jobs) (job_schedule[j,d])
    } in
    forall(j in jobs) (
        order[j,d] >= 1 /\ order[j,d] <= num_daily_jobs <-> job_schedule[j,d] = 1
    )
    /\
    all_different([order[j,d] | j in jobs where job_schedule[j,d] = 1])
);

% 5.2 起始作业是当日第一个执行的作业
constraint forall(d in days) (
    order[start_job[d], d] = 1
);

% 5.3 作业间行驶路径关联:前一个作业的下一个是后一个作业
constraint forall(d in days, j1 in jobs, j2 in jobs where j1 != j2) (
    (order[j1,d] + 1 = order[j2,d]) -> (job_schedule[j1,d] = 1 /\ job_schedule[j2,d] = 1)
);

% 5.4 当日结束作业是当日最后一个执行的作业
constraint forall(d in days) (
    order[end_job[d], d] = sum(j in jobs) (job_schedule[j,d])
);

% 6. 计算总燃油成本:每日从昨日终点到今日起点的距离 + 当日作业间行驶总距离
var int: total_fuel_cost = fuel_rate * (
    % 首日从初始点到第一个作业的距离
    distance[1, start_job[1]]
    +
    % 后续每日从昨日终点到今日起点的距离
    sum(d in days where d > 1) (distance[end_job[d-1], start_job[d]])
    +
    % 当日作业间行驶距离总和
    sum(d in days, j1 in jobs, j2 in jobs where j1 != j2) (
        (order[j1,d] + 1 = order[j2,d]) * distance[j1, j2]
    )
);

% 优化目标:最小化总燃油成本
solve minimize total_fuel_cost;

% 输出结果
output [
    "每日起始作业: ", show(start_job), "\n",
    "每日结束作业: ", show(end_job), "\n",
    "作业安排矩阵: ", show(job_schedule), "\n",
    "总燃油成本: ", show(total_fuel_cost)
];

内容的提问来源于stack exchange,提问作者Gprog

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 08:07:05