teratail header banner
teratail header banner
質問するログイン新規登録

質問編集履歴

1

質問内容

2020/12/22 06:18

投稿

K.takita
K.takita

スコア14

title CHANGED
@@ -1,1 +1,1 @@
1
- False場合の削除について
1
+ プログラムエラーについて
body CHANGED
@@ -1,11 +1,12 @@
1
1
  ### 前提・実現したいこと
2
+ すみません。先ほど投稿した、「Falseの場合削除する」についての質問内容ですが、聞きたかったことと異なっていたため、内容を変えさせていただきます。
2
3
  以下の作成したプログラムについての質問です。
3
- このプログラムでは各メンバーの希望出勤時刻と、シフトの同時刻を比較し、希望出勤時刻が0, シフトの同時刻が1のときFalse、それ以外のものをTrueで返すプログラムを表しています。
4
4
  ### 該当のソースコード
5
5
 
6
6
  ```python
7
7
  import numpy as np
8
8
  import pandas as pd
9
+ from pulp import LpBinary, LpMinimize, LpProblem, LpVariable, lpSum, value
9
10
 
10
11
  #アルバイトの集合
11
12
  n_member = 5
@@ -25,6 +26,7 @@
25
26
  shiftnumber = pd.Series(f"shift{sn+1}" for sn in range(n_shiftnumber))
26
27
 
27
28
 
29
+
28
30
  #シフトの一覧(直書き)
29
31
  shift = pd.DataFrame([[0, 0, 0, 0, 0, 0, 0, 0, 0],
30
32
  [1, 1, 1, 1, 1, 1, 1, 1, 1],
@@ -33,7 +35,33 @@
33
35
  [0, 0, 0, 0, 0, 0, 1, 1, 1],
34
36
  [1, 1, 1, 0, 0, 0, 1, 1, 1]], index=shiftnumber, columns=time)
35
37
 
38
+ #0:出勤不可のシフトパターン, 1:出勤可能のシフトパターン
39
+ shiftdaycount = [int(sum(x) > 0) for x in shift.values]
36
40
 
41
+
42
+
43
+
44
+ #各シフトの労働時間(直書き)
45
+ wtime = pd.DataFrame([[0, 0, 0, 0, 0, 0, 0],
46
+ [9, 9, 9, 9, 9, 9, 9],
47
+ [3, 3, 3, 3, 3, 3, 3],
48
+ [3, 3, 3, 3, 3, 3, 3],
49
+ [3, 3, 3, 3, 3, 3, 3],
50
+ [6, 6, 6, 6, 6, 6, 6]], index=shiftnumber, columns=day)
51
+
52
+ #必要人数
53
+ need = pd.DataFrame([[2, 2, 2, 2, 2, 2, 2, 2, 2]], index=day, columns=time)
54
+
55
+ #希望出勤日
56
+ kibou = pd.DataFrame([[1, 1, 1, 1, 1, 1, 1],
57
+ [1, 1, 1, 1, 1, 1, 1],
58
+ [1, 1, 1, 1, 1, 1, 1],
59
+ [1, 1, 1, 1, 1, 1, 1],
60
+ [0, 0, 0, 0, 0, 0, 0]], index=member, columns=day)
61
+
62
+
63
+
64
+
37
65
  #時間を考慮したデータ
38
66
  #Day1
39
67
  kiboutime1 = pd.DataFrame([[0, 0, 0, 1, 1, 1, 0, 0, 0],
@@ -41,15 +69,105 @@
41
69
  [1, 1, 1, 0, 0, 0, 1, 1, 1],
42
70
  [1, 1, 1, 0, 0, 0, 1, 1, 1],
43
71
  [0, 0, 0, 0, 0, 0, 0, 0, 0]], index=kibou.iloc[:,0], columns=time)
72
+
44
73
 
74
+
75
+ #for t in range(time.size):
76
+ # for s in range(n_shiftnumber):
45
- #希望出勤時刻が0, シフトの同時刻が1のときFalse、その他をTrueで返す
77
+ # for m in range(member.size):
78
+ # shift.iloc[s,t] <= kiboutime1.iloc[m,t]
79
+
80
+
81
+
82
+
83
+
84
+ #各メンバーの時給
85
+ jikyu = pd.DataFrame([[900, 900, 900, 900, 900, 900, 900],
86
+ [900, 900, 900, 900, 900, 900, 900],
87
+ [900, 900, 900, 900, 900, 900, 900],
88
+ [900, 900, 900, 900, 900, 900, 900],
89
+ [900, 900, 900, 900, 900, 900, 900]], index=member, columns=day)
90
+
91
+ #1日の人件費
92
+ jinkenhi = pd.DataFrame([[16200],
93
+ [16200],
94
+ [16200],
95
+ [16200],
96
+ [16200],
97
+ [16200],
98
+ [16200]], index=day)
99
+
100
+
101
+
102
+ #モデルの作成
103
+ prob = LpProblem(sense=LpMinimize)
104
+
105
+ #変数
106
+ X = LpVariable.dicts('X', ([m for m in range(member.size)], [d for d in range(day.size)], [s for s in range(n_shiftnumber)]), 0, 1, 'Integer')
107
+
108
+
109
+ #目的関数
110
+ prob += kibou.values.sum() - lpSum(shiftdaycount[s] * X[m][d][s] for s in range(n_shiftnumber) for d in range(day.size) for m in range(member.size))
111
+
112
+ #制約条件
113
+ #(制約1)
114
+ for m in range(member.size):
115
+ #希望出勤日数
116
+ ks = kibou.iloc[m].sum()
117
+ #実際に働いた日数
118
+ actual = lpSum(shiftdaycount[s] * X[m][d][s] for s in range(n_shiftnumber) for d in range(day.size))
119
+ #(制約1)実際に働いた日数が希望出勤日数を超えない制約
120
+ prob += actual <= ks
121
+
122
+
123
+
124
+ #(制約2)必要最低人数を満たす制約
125
+ for d in range(day.size):
126
+ for t in range(time.size):
127
+ prob += lpSum(shift.values[s][t] * X[m][d][s] for s in range(n_shiftnumber) for m in range(member.size) ) >= need.iloc[d, t]
128
+
129
+ #(制約4)各メンバーが1日に取りうるシフトは必ず1つ
130
+ for m in range(member.size):
131
+ for d in range(day.size):
132
+ prob += lpSum(X[m][d][s] for s in range(n_shiftnumber)) == 1
133
+
134
+ #(制約5)人件費を超えない
135
+ for d in range(day.size):
136
+ prob += lpSum(jikyu.iloc[m, d] * wtime.iloc[s, d] * X[m][d][s] for m in range(member.size) for s in range(n_shiftnumber) ) <= jinkenhi.iloc[d]
137
+
138
+ #(制約6)6日以上の連続勤務を禁止する
139
+ for m in range(member.size):
140
+ prob += lpSum(shiftdaycount[s] * X[m][d][s] for s in range(n_shiftnumber) for d in range(day.size)) <= 6
141
+
142
+ #(制約7)
46
143
  for t in range(time.size):
47
144
  for s in range(n_shiftnumber):
48
145
  for m in range(member.size):
49
- shift.iloc[s,t] <= kiboutime1.iloc[m,t]
146
+ prob += shift.iloc[s,t] <= kiboutime1.iloc[m,t]
147
+
148
+
149
+ prob.solve()
150
+
151
+
152
+ scheduling = pd.DataFrame(index=member, columns=day)
153
+ for m in range(member.size):
154
+ for d in range(day.size):
155
+ for s in range(n_shiftnumber):
156
+ if X[m][d][s].value() == 1:
157
+ scheduling.iloc[m, d] = shiftnumber[s]
50
158
 
51
159
 
160
+ scheduling.to_csv("scheduling.csv")
161
+
52
162
  ```
53
-
163
+ (制約7)のところで、各メンバーの希望出勤時間とシフトパターンの同時刻部分を比較しています。シフトの時刻は、同時刻の希望出勤時間以下となる制約(希望出勤時間が0の時、シフトの同時刻は0をとり、その他の場合は0または1をとる)を表しています。
54
- この結果のFalseを削除したいのですが、どのようにすればよいのでしょうか
164
+ 手書きはありますが、やりたことイメージは以下の通り
165
+ ![イメージ説明](498ca2e8dd3dbd4948d5407225f7c06b.jpeg)
166
+ しかし以下のようなエラーメッセージが出てきてしまいます。
167
+ ### 発生してるエラーメッセージ
168
+ ```python
169
+ TypeError: Can only add LpConstraintVar, LpConstraint, LpAffineExpression or True objects
170
+ ```
171
+ (制約7)より前のものは、正しく動いていることが確認できているため、(制約7)の部分でエラーが起きていると思うのですが、どのように直したらいいか、または、別のやり方があるのかわからない状態です。
172
+ 一方的な質問ですがご教授いただきたいです。
55
- ご教授いただけると幸いです。よろしくお願いします。
173
+ よろしくお願いいたします。