患者スケジューリング問題 PuLP

患者スケジューリング問題

患者スケジューリング問題は、医療機関でのリソース(医師、看護師、診療室など)を最適に割り当てるための問題です。

ここでは、あるクリニックでの医師のスケジューリング問題を考え、それをPuLPを用いて解く例を示します。

まず、以下のような仮定を置きます:

  • クリニックには3人の医師(A、B、C)がいます。
  • 1週間(月曜日から金曜日)のスケジューリングを考えます。
  • 1日に各医師は最大1シフト(午前または午後)しか働けません。
  • 1日に最低2人の医師が必要です。
  • 各医師は1週間に最大4日しか働けません。
  • 各医師は1週間に最低2日は働く必要があります。

この問題を解くためのPythonコードは以下の通りです:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from pulp import *

# 医師と日付のリストを作成
doctors = ['A', 'B', 'C']
days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri']

# 問題を定義
prob = LpProblem("Doctors_Scheduling", LpMinimize)

# 変数を定義(各医師が各日に働くかどうか)
x = LpVariable.dicts("x", (doctors, days), cat='Binary')

# 目的関数を定義(医師の働く日数を最小化)
prob += lpSum(x[doctor][day] for doctor in doctors for day in days)

# 制約を定義
for day in days:
prob += lpSum(x[doctor][day] for doctor in doctors) >= 2 # 1日に最低2人の医師が必要

for doctor in doctors:
prob += lpSum(x[doctor][day] for day in days) <= 4 # 各医師は1週間に最大4日しか働けない
prob += lpSum(x[doctor][day] for day in days) >= 2 # 各医師は1週間に最低2日は働く必要があります

# 問題を解く
prob.solve()

# 結果を表示
for v in prob.variables():
print(v.name, "=", v.varValue)

このコードは、各医師が1週間で働く日数を最小化するスケジュールを作成します。

制約として、各日に最低2人の医師が必要であり、各医師は1週間に最大4日しか働けず、最低でも2日は働く必要があるという条件を設けています。

[実行結果]
x_A_Fri = 1.0
x_A_Mon = 1.0
x_A_Thu = 0.0
x_A_Tue = 1.0
x_A_Wed = 1.0
x_B_Fri = 1.0
x_B_Mon = 1.0
x_B_Thu = 1.0
x_B_Tue = 0.0
x_B_Wed = 0.0
x_C_Fri = 0.0
x_C_Mon = 0.0
x_C_Thu = 1.0
x_C_Tue = 1.0
x_C_Wed = 1.0

グラフ化

結果をグラフ化するためには、matplotlibなどのライブラリを使用します。

以下に、結果をヒートマップとして表示する例を示します:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import matplotlib.pyplot as plt
import numpy as np

# 結果を配列に格納
result = np.zeros((len(doctors), len(days)))
for v in prob.variables():
doctor, day = v.name.split("_")[1:]
result[doctors.index(doctor)][days.index(day)] = v.varValue

# ヒートマップを表示
plt.imshow(result, cmap='hot', interpolation='nearest')
plt.colorbar(label='Shifts')
plt.xticks(np.arange(len(days)), days)
plt.yticks(np.arange(len(doctors)), doctors)
plt.show()

このコードは、各医師が各日に働くかどうかを色で表したヒートマップを作成します。

医師が働く日は明るい色、働かない日は暗い色で表示されます。

[実行結果]