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

