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()

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です