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

使用Linear Programming优化员工排班时遇IndexError问题求助

员工排班线性规划优化报错排查与修复

问题背景

使用Python的Pulp库基于给定DataFrame实现员工排班优化时,执行目标函数prob += lpSum([w[j] * y[j] for j in range(n)])触发IndexError: index 1 is out of bounds for axis 0 with size 1错误。

原始数据

Time Windows Shift 1 Shift 2 Shift 3 Shift 4  Workers Required
0    6:00 - 9:00       1       0       0       1              55.0
1   9:00 - 12:00       1       0       0       0              46.0
2  12:00 - 15:00       1       1       0       0              59.0
3  15:00 - 18:00       0       1       0       0              23.0
4  18:00 - 21:00       0       1       1       0              60.0
5  21:00 - 24:00       0       0       1       0              38.0
6   24:00 - 3:00       0       0       1       1              20.0
7    3:00 - 6:00       0       0       0       1              30.0
8      Wage_Rate     135     140     190     188               0.0

错误栈

Traceback (most recent call last):
  Cell In[197], line 1
    prob += lpSum([w[j] * y[j] for j in range(n)])
  Cell In[197], line 1 in <listcomp>
    prob += lpSum([w[j] * y[j] for j in range(n)])
IndexError: index 1 is out of bounds for axis 0 with size 1

错误定位

  • 薪资数组维度与来源错误:代码先执行df.drop(df.tail(1).index,inplace=True)删除了薪资行,后续用last_row = df.iloc[-1:,1:]获取的是最后一个时间段的数据,而非薪资;同时iloc[-1:,1:]返回二维数组,直接用w[j]访问会因维度不匹配报错。
  • 班次与时间窗口数量混淆:原始数据中班次为4个(Shift1-4),但代码用n = a.shape[0]把时间窗口数量(8个)当成班次数量,导致决策变量y的数量错误。

修复步骤

  1. 提前保存薪资数据:在删除最后一行前提取薪资信息,避免丢失。
  2. 修正薪资数组维度:将二维数组展平为一维数组,确保索引访问正常。
  3. 正确定义班次数量:班次数量等于Shift列的数量(4个),而非时间窗口数量。
  4. 修正约束矩阵维度:约束矩阵应为时间窗口数 × 班次数量,保证约束条件索引匹配。

修复后完整代码

import pandas as pd
import pulp
from pulp import LpMinimize, LpProblem, LpStatus, lpSum, LpVariable
import numpy as np

# 读取数据
df = pd.read_clipboard(sep='\\s+')
df = pd.DataFrame(df)

# 提前提取薪资数据(删除最后一行前操作)
wage_row = df.iloc[-1, 1:-1].values  # 提取Shift1-4的薪资,得到一维数组
# 删除薪资行,保留时间窗口数据
df = df.drop(df.tail(1).index)

# 处理数据,确保班次覆盖标记为数值型
df = df.fillna(0).applymap(lambda x: 1 if x == "X" else x)

# 定义关键参数
T = df.shape[0]  # 时间窗口数量:8
n = len(df.columns) - 2  # 班次数量:4(排除Time Windows和Workers Required列)
a = df.drop(columns=["Time Windows", "Workers Required"]).values  # 约束矩阵:8×4
d = df["Workers Required"].values  # 各时间段需求人数

# 决策变量:每个班次的员工数量
y = LpVariable.dicts("num_workers", list(range(n)), lowBound=0, cat="Integer")

# 创建最小化问题
prob = LpProblem("scheduling_workers", LpMinimize)

# 目标函数:总薪资最小化
prob += lpSum([wage_row[j] * y[j] for j in range(n)])

# 约束条件:每个时间段的在岗员工数≥需求人数
for t in range(T):
    prob += lpSum([a[t, j] * y[j] for j in range(n)]) >= d[t]

# 求解问题
prob.solve()

# 输出结果
print("求解状态:", LpStatus[prob.status])
for shift_idx in range(n):
    print(f"班次{shift_idx+1}需要的员工数:{int(y[shift_idx].value())}人")

说明

修复后代码正确区分了时间窗口和班次的维度,薪资数组变为一维数组,索引访问正常;约束矩阵a维度为8×4,对应8个时间窗口和4个班次,约束条件索引匹配无误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 00:05:42