simpyを使ってみる
最近ずっとpython のシミュレーションを勉強していたが,そこでsimpyという面白いライブラリを知った.
simulation pythonの略でsimpyと呼ばれるらしい.
試しに使ってみた.博物館内での来館者の動きをシミュレーションし、各展示物の混雑状況を示す.
コードは下記.
import simpy
import random
import matplotlib.pyplot as plt
# シミュレーションパラメータ
NUM_VISITORS = 100 # 来館者数
ARRIVAL_INTERVAL = 5 # 来館者の到着間隔(分)
EXHIBITS = ['A', 'B', 'C', 'D'] # 展示のリスト
STAY_TIME = { # 各展示での滞在時間(分)の平均
'A': 10,
'B': 15,
'C': 20,
'D': 5
}
SIM_TIME = 480 # シミュレーション時間(分)= 8時間
# 展示ごとのキャパシティ(同時に滞在できる人数)
EXHIBIT_CAPACITY = {
'A': 30,
'B': 20,
'C': 25,
'D': 15
}
# データ収集用の辞書
exhibit_occupancy = {exhibit: [] for exhibit in EXHIBITS}
time_points = []
def visitor(env, name, exhibit_resources):
"""来館者の行動を定義するプロセス"""
# 博物館に到着
# print(f"{env.now}: {name} が博物館に到着しました。")
# 展示を順番に訪問
for exhibit in EXHIBITS:
with exhibit_resources[exhibit].request() as request:
yield request
# 展示を見始める
# print(f"{env.now}: {name} が展示{exhibit}を見始めました。")
stay_duration = random.expovariate(1.0 / STAY_TIME[exhibit])
yield env.timeout(stay_duration)
# 展示を見終わる
# print(f"{env.now}: {name} が展示{exhibit}を見終わりました。")
# 博物館を退館
# print(f"{env.now}: {name} が博物館を退館しました。")
def setup_museum(env, exhibit_resources):
"""博物館のリソースと来館者の生成を設定"""
for i in range(NUM_VISITORS):
yield env.timeout(random.expovariate(1.0 / ARRIVAL_INTERVAL))
env.process(visitor(env, f"Visitor {i+1}", exhibit_resources))
def monitor(env, exhibit_resources):
"""各展示物の現在の滞在人数を記録するプロセス"""
while True:
current_time = env.now
time_points.append(current_time)
for exhibit in EXHIBITS:
occupancy = len(exhibit_resources[exhibit].users)
exhibit_occupancy[exhibit].append(occupancy)
yield env.timeout(1) # 1分ごとに記録
# シミュレーション環境の設定
env = simpy.Environment()
# 各展示のリソース(キャパシティ付き)
exhibit_resources = {exhibit: simpy.Resource(env, capacity=cap)
for exhibit, cap in EXHIBIT_CAPACITY.items()}
env.process(setup_museum(env, exhibit_resources))
env.process(monitor(env, exhibit_resources))
# シミュレーションの実行
env.run(until=SIM_TIME)
# 可視化の設定
fig, ax = plt.subplots(figsize=(10, 6))
for exhibit in EXHIBITS:
ax.plot(time_points, exhibit_occupancy[exhibit], label=f'Exhibit {exhibit}')
ax.set_xlabel('Time (minutes)')
ax.set_ylabel('Number of Visitors')
ax.set_title('Visitor Occupancy Over Time per Exhibit')
ax.legend()
ax.grid(True)
plt.show()