如何编写基于DataFrame的Pulp优化函数?求无循环实现方案
解决Pulp优化问题(无显式for循环实现约束)
首先把时间转换为小时数值便于计算,然后利用Pandas的结构和Pulp的批量约束添加能力,避免显式for循环实现所有约束:
import pulp import pandas as pd # 1. 预处理数据:转换时间为小时数 df = pd.DataFrame({ 'seniority': [3,4,1], 'target': [6,6,6], 'morning_out': ['08:50', '08:20', '08:40'], 'afternoon_in': ['14:30', '15:20', '13:00'] }) def time_to_hours(time_str): h, m = map(int, time_str.split(':')) return h + m/60 # 转换已知时间列为小时数 df['morning_out_h'] = df['morning_out'].apply(time_to_hours) df['afternoon_in_h'] = df['afternoon_in'].apply(time_to_hours) # 2. 创建优化问题与变量 prob = pulp.LpProblem("Shift_Optimization", pulp.LpMinimize) # 约束1要求所有行的morning_in和afternoon_out相同,因此定义全局变量即可 morning_in = pulp.LpVariable("morning_in", lowBound=0, upBound=24) afternoon_out = pulp.LpVariable("afternoon_out", lowBound=0, upBound=24) # 3. 添加约束(无显式for循环) # 约束2:每行工作时长等于target,用列表推导式批量添加 prob += [ (row.morning_out_h - morning_in) + (afternoon_out - row.afternoon_in_h) == row.target for _, row in df.iterrows() ] # 约束3:按seniority定义morning_in的范围,基于唯一seniority值批量添加 seniority_bounds = {1: (7, 8), 3: (6.5, 7.5), 4: (6, 7)} prob += [morning_in >= seniority_bounds[s][0] for s in df.seniority.unique()] prob += [morning_in <= seniority_bounds[s][1] for s in df.seniority.unique()] # 约束4:afternoon_out的时间范围 prob += (afternoon_out >= 16) & (afternoon_out <= 19) # 4. 求解并输出结果 prob.solve() print(f"求解状态: {pulp.LpStatus[prob.status]}") if pulp.LpStatus[prob.status] == 'Optimal': def hours_to_time(hours): h = int(hours) m = int((hours - h)*60) return f"{h}:{m:02d}" print(f"统一morning_in: {hours_to_time(pulp.value(morning_in))}") print(f"统一afternoon_out: {hours_to_time(pulp.value(afternoon_out))}")
关键说明:
- 约束1实现:通过定义全局变量
morning_in和afternoon_out,所有行共用这两个变量,自动满足“所有行值相同”的要求,无需额外约束。 - 约束2实现:用列表推导式替代显式
for循环,批量生成每行的时长等式约束。 - 约束3实现:基于
df.seniority.unique()获取唯一职级,避免遍历所有行,批量添加范围约束。 - 约束4实现:直接添加范围约束,无需循环。
注:你提供的样本数据中,不同行的时长约束会推导出矛盾的afternoon_out - morning_in值,因此实际求解会显示Infeasible(无解),这属于数据逻辑问题,而非代码实现问题。
内容的提问来源于stack exchange,提问作者Mikić Danko
相关产品推荐
相关产品推荐

