Trying to Optimize Process Using Linear Programming. Getting error about: IndexError: index 1 is out of bounds for axis 0 with size 1

huangapple go评论92阅读模式
英文:

Trying to Optimize Process Using Linear Programming. Getting error about: IndexError: index 1 is out of bounds for axis 0 with size 1

问题

在这行代码中:

  1. prob += lpSum([w[j] * y[j] for j in range(n)])

你遇到了这个错误:

  1. IndexError: index 1 is out of bounds for axis 0 with size 1

这个错误是因为在 w 中的数据是一个一维数组,但你尝试访问索引1,而实际上只有一个元素,索引应为0。你可以尝试将 w 定义为一个标量值而不是一个数组,或者根据你的需求调整代码来解决这个错误。

英文:

I am trying to optimize worker's schedules, based on the following dataframe.

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

First (create dataframe):

  1. import pandas as pd
  2. df = pd.read_clipboard(sep='\\s+')
  3. df = pd.DataFrame(df)

Here is the code that I am testing.

  1. import pandas as pd
  2. import pulp
  3. from pulp import LpMaximize, LpMinimize, LpProblem, LpStatus, lpSum, LpVariable
  4. import numpy as np
  5. df = df.fillna(0).applymap(lambda x: 1 if x == "X" else x)
  6. df.set_index('Time Windows')
  7. a = df.drop(columns=["Workers Required"]).values
  8. a
  9. df.drop(df.tail(1).index,inplace=True)
  10. print(df.shape)
  11. df = df.fillna(0).applymap(lambda x: 1 if x == "X" else x)
  12. print(df.shape)
  13. a = df.to_numpy()
  14. a
  15. # number of shifts
  16. n = a.shape[0]
  17. # number of time windows
  18. T = a.shape[0]
  19. # number of workers required per time window
  20. d = df["Workers Required"].values
  21. # wage rate per shift
  22. #Get last row of dataframe
  23. last_row = df.iloc[-1:,1:]
  24. #Get last row of dataframe as numpy array
  25. w = last_row.to_numpy()
  26. w
  27. # Decision variables
  28. y = LpVariable.dicts("num_workers", list(range(n)), lowBound=0, cat="Integer")
  29. y
  30. # Create problem
  31. prob = LpProblem("scheduling_workers", LpMinimize)
  32. prob += lpSum([w[j] * y[j] for j in range(n)])
  33. for t in range(T):
  34. prob += lpSum([a[t, j] * y[j] for j in range(n)]) >= d[t]
  35. prob.solve()
  36. print("Status:", LpStatus[prob.status])
  37. for shift in range(n):
  38. print(f"The number of workers needed for shift {shift} is {int(y[shift].value())} workers")

When I get to this line:

  1. prob += lpSum([w[j] * y[j] for j in range(n)])

I get this error.

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

The example I am trying to follow is from the link below.

https://towardsdatascience.com/how-to-solve-a-staff-scheduling-problem-with-python-63ae50435ba4

答案1

得分: 1

你的问题主要是因为对 Pandas 的误用。正确使用切片,它将正常工作:

  1. from io import StringIO
  2. import pandas as pd
  3. import pulp
  4. with StringIO(
  5. '''Time Windows,Shift 1,Shift 2,Shift 3,Shift 4,Workers Required
  6. 6:00 - 9:00, 1, 0, 0, 1, 55.0
  7. 9:00 - 12:00, 1, 0, 0, 0, 46.0
  8. 12:00 - 15:00, 1, 1, 0, 0, 59.0
  9. 15:00 - 18:00, 0, 1, 0, 0, 23.0
  10. 18:00 - 21:00, 0, 1, 1, 0, 60.0
  11. 21:00 - 24:00, 0, 0, 1, 0, 38.0
  12. 24:00 - 3:00, 0, 0, 1, 1, 20.0
  13. 3:00 - 6:00, 0, 0, 0, 1, 30.0
  14. Wage_Rate, 135, 140, 190, 188, 0.0''') as f:
  15. df = pd.read_csv(f, skipinitialspace=True, index_col='Time Windows')
  16. is_shift = df.columns.str.startswith('Shift')
  17. is_wage = df.index == 'Wage_Rate'
  18. shifts = df.loc[~is_wage, is_shift]
  19. wage_rate = df.loc[is_wage, is_shift].squeeze()
  20. workers_req = df.loc[~is_wage, 'Workers Required']
  21. workers_per_shift = pulp.LpVariable.dicts(name='workers_per', indices=shifts.columns, lowBound=0, cat=pulp.LpInteger)
  22. prob = pulp.LpProblem(name='scheduling_workers', sense=pulp.LpMinimize)
  23. prob.objective = pulp.lpDot(wage_rate, workers_per_shift.values())
  24. for (time, shift), worker_req in zip(shifts.iterrows(), workers_req):
  25. prob.addConstraint(name=f'workers_min_{time}', constraint=pulp.lpDot(shift, workers_per_shift.values()) >= worker_req)
  26. print(prob)
  27. prob.solve()
  28. for k, v in workers_per_shift.items():
  29. print(f'{k} has {v.value():.0f} workers')
  1. scheduling_workers:
  2. MINIMIZE
  3. 135*workers_per_Shift_1 + 140*workers_per_Shift_2 + 190*workers_per_Shift_3 + 188*workers_per_Shift_4 + 0
  4. SUBJECT TO
  5. workers_min_6:00___9:00: workers_per_Shift_1 + workers_per_Shift_4 >= 55
  6. workers_min_9:00___12:00: workers_per_Shift_1 >= 46
  7. workers_min_12:00___15:00: workers_per_Shift_1 + workers_per_Shift_2 >= 59
  8. workers_min_15:00___18:00: workers_per_Shift_2 >= 23
  9. workers_min_18:00___21:00: workers_per_Shift_2 + workers_per_Shift_3 >= 60
  10. workers_min_21:00___24:00: workers_per_Shift_3 >= 38
  11. workers_min_24:00___3:00: workers_per_Shift_3 + workers_per_Shift_4 >= 20
  12. workers_min_3:00___6:00: workers_per_Shift_4 >= 30
  13. VARIABLES
  14. 0 <= workers_per_Shift_1 Integer
  15. 0 <= workers_per_Shift_2 Integer
  16. 0 <= workers_per_Shift_3 Integer
  17. 0 <= workers_per_Shift_4 Integer
  18. 欢迎使用 CBC MILP 求解器
  19. 版本:2.10.3
  20. 构建日期:20191215
  21. 命令行 - C:\Users\gtoom\src\stackexchange\.venv\lib\site-packages\pulp\solverdir\cbc\win\cbc.exe C:\Users\gtoom\AppData\Local\Temp759563a6c3439b8221b857b9f617af-pulp.mps timeMode elapsed branch printingOptions all solution C:\Users\gtoom\AppData\Local\Temp759563a6c3439b8221b857b9f617af-pulp.sol (默认策略 1)
  22. 2 NAME MODEL
  23. 3 ROWS
  24. 13 COLUMNS
  25. 38 RHS
  26. 47 BOUNDS
  27. 52 ENDATA
  28. 问题 MODEL 共有 8 行,4 列,12 个元素
  29. Coin0008I 0 个错误读取模型
  30. timeMode 选项从 CPU 更改为经过的时间
  31. 连续目标值为 22290 - 0.00
  32. Cgl0004I 处理后的模型有 0 行,0 列(0 个整数(其中 0 个是二进制))和 0 个元素
  33. Cbc3007W 没有整数变量 - 无事可做
  34. 根节点处的切割将目标从 22290 更改为 -1.79769e+308
  35. 探测尝试了 0 次,并在添加切割回合后创建了 0 个切割,其中 0 个活跃(0.000 秒)
  36. Gomory 尝试了 0 次,并在添加切割回合后创建了 0 个切割,其中 0 个活跃(0.000 秒)
  37. 尝试了 0 次的背包问题,并创建了 0 个切割,其中 0 个在添加切割回合后是活跃的(0.000 秒)
  38. 尝试了 0 次的团问题,并创建了 0 个切割,其中 0 个在添加切割回合后是活跃的(0.000 秒)
  39. 尝试了 0 次的混合整数舍入问题,并创建了 0 个切割,其中 0 个在添加切割回合后是活跃的(0.000 秒)
  40. FlowCover 尝试了 0 次,并创建了 0
  41. <details>
  42. <summary>英文:</summary>
  43. Your problems mostly come from misuse of Pandas. Use sane slicing, and it works fine:
  44. ```python
  45. from io import StringIO
  46. import pandas as pd
  47. import pulp
  48. with StringIO(
  49. &#39;&#39;&#39;Time Windows,Shift 1,Shift 2,Shift 3,Shift 4,Workers Required
  50. 6:00 - 9:00, 1, 0, 0, 1, 55.0
  51. 9:00 - 12:00, 1, 0, 0, 0, 46.0
  52. 12:00 - 15:00, 1, 1, 0, 0, 59.0
  53. 15:00 - 18:00, 0, 1, 0, 0, 23.0
  54. 18:00 - 21:00, 0, 1, 1, 0, 60.0
  55. 21:00 - 24:00, 0, 0, 1, 0, 38.0
  56. 24:00 - 3:00, 0, 0, 1, 1, 20.0
  57. 3:00 - 6:00, 0, 0, 0, 1, 30.0
  58. Wage_Rate, 135, 140, 190, 188, 0.0&#39;&#39;&#39;) as f:
  59. df = pd.read_csv(f, skipinitialspace=True, index_col=&#39;Time Windows&#39;)
  60. is_shift = df.columns.str.startswith(&#39;Shift&#39;)
  61. is_wage = df.index == &#39;Wage_Rate&#39;
  62. shifts = df.loc[~is_wage, is_shift]
  63. wage_rate = df.loc[is_wage, is_shift].squeeze()
  64. workers_req = df.loc[~is_wage, &#39;Workers Required&#39;]
  65. workers_per_shift = pulp.LpVariable.dicts(name=&#39;workers_per&#39;, indices=shifts.columns, lowBound=0, cat=pulp.LpInteger)
  66. prob = pulp.LpProblem(name=&#39;scheduling_workers&#39;, sense=pulp.LpMinimize)
  67. prob.objective = pulp.lpDot(wage_rate, workers_per_shift.values())
  68. for (time, shift), worker_req in zip(shifts.iterrows(), workers_req):
  69. prob.addConstraint(name=f&#39;workers_min_{time}&#39;, constraint=pulp.lpDot(shift, workers_per_shift.values()) &gt;= worker_req)
  70. print(prob)
  71. prob.solve()
  72. for k, v in workers_per_shift.items():
  73. print(f&#39;{k} has {v.value():.0f} workers&#39;)
  1. scheduling_workers:
  2. MINIMIZE
  3. 135*workers_per_Shift_1 + 140*workers_per_Shift_2 + 190*workers_per_Shift_3 + 188*workers_per_Shift_4 + 0
  4. SUBJECT TO
  5. workers_min_6:00___9:00: workers_per_Shift_1 + workers_per_Shift_4 &gt;= 55
  6. workers_min_9:00___12:00: workers_per_Shift_1 &gt;= 46
  7. workers_min_12:00___15:00: workers_per_Shift_1 + workers_per_Shift_2 &gt;= 59
  8. workers_min_15:00___18:00: workers_per_Shift_2 &gt;= 23
  9. workers_min_18:00___21:00: workers_per_Shift_2 + workers_per_Shift_3 &gt;= 60
  10. workers_min_21:00___24:00: workers_per_Shift_3 &gt;= 38
  11. workers_min_24:00___3:00: workers_per_Shift_3 + workers_per_Shift_4 &gt;= 20
  12. workers_min_3:00___6:00: workers_per_Shift_4 &gt;= 30
  13. VARIABLES
  14. 0 &lt;= workers_per_Shift_1 Integer
  15. 0 &lt;= workers_per_Shift_2 Integer
  16. 0 &lt;= workers_per_Shift_3 Integer
  17. 0 &lt;= workers_per_Shift_4 Integer
  18. Welcome to the CBC MILP Solver
  19. Version: 2.10.3
  20. Build Date: Dec 15 2019
  21. command line - C:\Users\gtoom\src\stackexchange\.venv\lib\site-packages\pulp\solverdir\cbc\win\cbc.exe C:\Users\gtoom\AppData\Local\Temp759563a6c3439b8221b857b9f617af-pulp.mps timeMode elapsed branch printingOptions all solution C:\Users\gtoom\AppData\Local\Temp759563a6c3439b8221b857b9f617af-pulp.sol (default strategy 1)
  22. At line 2 NAME MODEL
  23. At line 3 ROWS
  24. At line 13 COLUMNS
  25. At line 38 RHS
  26. At line 47 BOUNDS
  27. At line 52 ENDATA
  28. Problem MODEL has 8 rows, 4 columns and 12 elements
  29. Coin0008I MODEL read with 0 errors
  30. Option for timeMode changed from cpu to elapsed
  31. Continuous objective value is 22290 - 0.00 seconds
  32. Cgl0004I processed model has 0 rows, 0 columns (0 integer (0 of which binary)) and 0 elements
  33. Cbc3007W No integer variables - nothing to do
  34. Cuts at root node changed objective from 22290 to -1.79769e+308
  35. Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
  36. Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
  37. Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
  38. Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
  39. MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
  40. FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
  41. TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
  42. ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
  43. Result - Optimal solution found
  44. Objective value: 22290.00000000
  45. Enumerated nodes: 0
  46. Total iterations: 0
  47. Time (CPU seconds): 0.00
  48. Time (Wallclock seconds): 0.00
  49. Option for printingOptions changed from normal to all
  50. Total time (CPU seconds): 0.01 (Wallclock seconds): 0.01
  51. Shift 1 has 46 workers
  52. Shift 2 has 23 workers
  53. Shift 3 has 38 workers
  54. Shift 4 has 30 workers

huangapple
  • 本文由 发表于 2023年4月4日 07:54:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/75924536.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定