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

OR-TOOLS CP-SAT作业车间调度:拆分长任务并避免任务穿插

OR-Tools CP-SAT作业车间调度:拆分任务防穿插问题

我在使用OR-TOOLS CP-SAT实现作业车间调度时遇到了问题:拆分后的任务组会被其他工单的任务穿插。

调度背景

机器采用1、2、3班制运行,周末不工作。部分任务时长超过1个甚至2个班次,因此我将这类任务拆分为准备任务+每个工件对应的单独任务(例如某工单15件操作对应16个任务),要求同一操作拆分出的所有任务必须连续调度,不被其他工单任务打断。

现有代码实现

1. 非工作时间间隔定义

# 不同班制对应的非工作时间间隔:
# 1班制:下午2点-6点 + 周末;2班制:晚10点-早6点 + 周末;3班制:仅周末
i = 0
for machine in machine_data:
    for mach_id, mach in enumerate(machine):
            if mach[1] == 0 and mach[3] == 1:
                if mach[2] == 1:
                    for cal_id, cal in enumerate(cal_data):
                        for shift_id, shift in enumerate(cal):
                            start = int(shift[0])
                            size = int(shift[1]) - int(shift[0])
                            end = int(shift[1])
                            i = i + 1
                            name = str(mach[0]) + '_' + str(mach[2]) + '_' + str(i)  + '_weekend'
                            machine_to_intervals[mach[0]].append(model.NewIntervalVar(start, size, end, name))
                elif mach[2] == 2:
                    for cal_id, cal in enumerate(cal_data):
                        for shift_id, shift in enumerate(cal):
                            start = int(shift[2])
                            size = int(shift[3]) - int(shift[2])
                            end = int(shift[3])
                            i = i + 1
                            name = str(mach[0]) + '_' + str(mach[2]) + '_' + str(i)  + '_weekend'
                            machine_to_intervals[mach[0]].append(model.NewIntervalVar(start, size, end, name))
                elif mach[2] == 3:
                    for cal in cal_data:
                        for shift_id, shift in enumerate(cal):
                            if shift[4] > 0:
                                start = int(shift[4])
                                size = int(shift[5]) - int(shift[4])
                                end = int(shift[5])
                                i = i + 1
                                name = str(mach[0]) + '_' + str(mach[2]) + '_' + str(i)  + '_weekend'
                                machine_to_intervals[mach[0]].append(model.NewIntervalVar(start, size, end, name))

2. 尝试实现拆分任务连续调度的约束

我用OnlyEnforceIf约束要求所有不属于当前操作的任务,要么在拆分后首个任务开始前完成,要么在最后一个任务结束后开始,同时以最小化拆分任务首尾间隔为目标:

split_minimize = []
for i in range(len(splitdf)):
        order = splitdf.iloc[i]['WorkOrder']
        activity = splitdf.iloc[i]['Activity']
        wc = splitdf.iloc[i]['WC_INT']
        order_id = splitdf.iloc[i]['WO_INT']
        # 同一拆分操作的首尾任务行号
        ord_pl_min = splitdf.iloc[i]['MinROW#']
        ord_pl_max = splitdf.iloc[i]['MaxROW#']
        spltMin = all_tasks[order_id, ord_pl_max].end - all_tasks[order_id, ord_pl_min].start
        split_minimize.append(spltMin)
        for job_id, job in enumerate(jobs_data):
            for task_id, task in enumerate(job):
                zName = "z%i_%i_%i" % (i, job_id, task_id)
                z = model.NewBoolVar(zName)
                model.Add(all_tasks[job_id, task_id].end < all_tasks[order_id, ord_pl_min].start).OnlyEnforceIf(z)
                model.Add(all_tasks[job_id, task_id].start > all_tasks[order_id, ord_pl_max].end).OnlyEnforceIf(z.Not())

问题现象

上述方案多数情况下能保证拆分任务连续调度,但偶尔仍会出现其他任务穿插进拆分任务组的情况。我曾尝试用AddCircuit强制任务排序但未成功,想请教如何确保拆分后的任务始终连续,不会被其他任务打断?

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 04:20:08