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

Python PuLP排班优化算法目标函数定义问题求助

解决PuLP排班优化中按权重分配员工的目标函数问题

现有目标函数的核心问题

  1. 优化方向完全错误:你将问题定义为pulp.LpMinimize,但第一个目标函数是计算「权重×班次变量」的和。权重越高的班次,在最小化逻辑下会被系统优先减少分配人数,这和你「高权重班次多配置员工」的需求完全相反。比如你设置夜班权重0.5,系统会尽量少排夜班员工,导致结果不符合预期。
  2. 偏差计算逻辑无效:第二个尝试的偏差函数直接累加(变量-权重),正负偏差会相互抵消,根本无法真正最小化实际班次人数与目标权重的差异,同样也没纠正优化方向的问题。

正确的目标函数实现

思路1:最大化加权班次总工时(直接匹配需求)

要让高权重班次的员工数尽可能多,只需将问题改为最大化加权和即可——权重越高的班次,被分配的员工数自然越多。

修改后的目标函数:

def create_objective_function(variables, days, employees):
    var_Sabah, var_Aksam, var_Gece, _ = variables
    obj_shift_weights = pulp.LpAffineExpression()

    # 权重数值越高,对应班次应分配越多员工
    weight_morning = 0.3
    weight_evening = 0.2
    weight_night = 0.5

    for i in range(days):
        for j in range(employees):
            obj_shift_weights += var_Sabah[i][j] * weight_morning
            obj_shift_weights += var_Aksam[i][j] * weight_evening
            obj_shift_weights += var_Gece[i][j] * weight_night

    return obj_shift_weights

同时,在创建问题时必须改为最大化模式:

problem = pulp.LpProblem("Shift", pulp.LpMaximize)  # 替换原来的LpMinimize

思路2:最小化实际班次占比与目标权重的偏差(精准控制比例)

如果需要各班次的总工时占比严格贴近设定权重,可以通过最小化实际值与目标值的偏差实现。由于PuLP是线性规划工具,处理绝对值偏差需要引入辅助变量:

def create_objective_function(problem, variables, days, employees, week):
    var_Sabah, var_Aksam, var_Gece, _ = variables
    
    # 权重总和建议设为1,方便计算占比
    weight_morning = 0.3
    weight_evening = 0.2
    weight_night = 0.5
    
    # 计算总需分配的工作工时(每个员工每周工作5天)
    total_work_hours = employees * 5 * week
    # 各班次的目标工时数
    target_morning = total_work_hours * weight_morning
    target_evening = total_work_hours * weight_evening
    target_night = total_work_hours * weight_night
    
    # 计算实际各班次的总工时
    actual_morning = pulp.lpSum(var_Sabah[i][j] for i in range(days) for j in range(employees))
    actual_evening = pulp.lpSum(var_Aksam[i][j] for i in range(days) for j in range(employees))
    actual_night = pulp.lpSum(var_Gece[i][j] for i in range(days) for j in range(employees))
    
    # 引入偏差变量(处理绝对值偏差的线性化)
    dev_morning_pos = pulp.LpVariable("dev_morning_pos", lowBound=0)
    dev_morning_neg = pulp.LpVariable("dev_morning_neg", lowBound=0)
    dev_evening_pos = pulp.LpVariable("dev_evening_pos", lowBound=0)
    dev_evening_neg = pulp.LpVariable("dev_evening_neg", lowBound=0)
    dev_night_pos = pulp.LpVariable("dev_night_pos", lowBound=0)
    dev_night_neg = pulp.LpVariable("dev_night_neg", lowBound=0)
    
    # 添加偏差约束
    problem += actual_morning - target_morning == dev_morning_pos - dev_morning_neg
    problem += actual_evening - target_evening == dev_evening_pos - dev_evening_neg
    problem += actual_night - target_night == dev_night_pos - dev_night_neg
    
    # 目标:最小化总偏差
    return pulp.lpSum([dev_morning_pos, dev_morning_neg, dev_evening_pos, dev_evening_neg, dev_night_pos, dev_night_neg])

调用时需要把problem作为参数传入目标函数。

额外代码修正点

你的约束函数中存在变量初始化错误,比如c = None后直接执行c += ...会抛出TypeError,所有约束中的变量都需要初始化为pulp.LpAffineExpression():

# 错误写法
c = None
c += var_Sabah[i][j] + var_Aksam[i][j] + var_Gece[i][j] + var_Tatil[i][j]

# 正确写法
c = pulp.LpAffineExpression()
c += var_Sabah[i][j] + var_Aksam[i][j] + var_Gece[i][j] + var_Tatil[i][j]

所有约束函数中的类似初始化都需要修正,否则程序无法正常运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 02:14:50