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

如何在Pyomo中添加分段线性约束解决任务分配工时优化问题

问题原因

Python内置min函数会在建模阶段立即对输入表达式做布尔比较,但Pyomo的变量表达式在求解前没有实际常量值,无法转换为布尔值,因此触发报错。你需要将分段工时规则转换为混合整数规划可识别的线性约束形式。

解决方案

由于日任务数的取值范围非常有限(最多2个,否则超过日最长8工时限制),直接使用Pyomo内置的Piecewise分段线性组件实现工时映射逻辑是最简单的方案。

修改后完整可运行代码
# 修复后的任务分配代码
from pyomo.environ import *

m = ConcreteModel()
m.TASKS = ('task1', 'task2', 'task3', 'task4')
m.DAYS = (1, 2, 3, 4)

# 变量定义
m.ALLOCATION = Var(m.TASKS, m.DAYS, domain=Binary)
# 单日最多2个任务就达到工时上限,直接限定取值范围减少求解复杂度
m.N_TASKS_PER_DAY = Var(m.DAYS, domain=Integers, bounds=(0, 2))
m.TOTAL_HOURS = Var(m.DAYS, domain=Integers, bounds=(0, 8))

# 优化目标:最小化总工时
m.OBJ = Objective(expr=sum(m.TOTAL_HOURS[day] for day in m.DAYS), sense=minimize)

m.c = ConstraintList()

# 约束1:每个任务仅分配一次
for task in m.TASKS:
    m.c.add(sum(m.ALLOCATION[task, day] for day in m.DAYS) == 1)

# 约束2:每日实际分配任务数计算
for day in m.DAYS:
    m.c.add(sum(m.ALLOCATION[task, day] for task in m.TASKS) == m.N_TASKS_PER_DAY[day])

# 约束3:分段工时映射(替代原直接调用min的错误写法)
# 断点对应每日任务数,f_rule对应任务数匹配的工时
breakpoints = [0, 1, 2]
hour_values = [0, 6, 8]
m.pw_constraint = Piecewise(m.DAYS, m.TOTAL_HOURS, m.N_TASKS_PER_DAY,
                            pw_pts=breakpoints,
                            f_rule=hour_values,
                            pw_constr_type='EQ')

# 约束4:每日工时不超过上限(可省略,分段规则已隐含该限制)
for day in m.DAYS:
    m.c.add(m.TOTAL_HOURS[day] <= 8)

# 求解并输出结果
solver = SolverFactory('glpk')
res = solver.solve(m)
res.write()
print("总工时:", value(m.OBJ))
for day in m.DAYS:
    task_num = value(m.N_TASKS_PER_DAY[day])
    if task_num > 0:
        print(f"第{day}天分配{task_num}个任务,工时{value(m.TOTAL_HOURS[day])}")
运行结果说明

求解后总工时为16小时,符合预期:4个任务分2天执行,每天分配2个任务,单日工时8小时。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 20:24:03