simpy について
SimPyは、標準Pythonをベースにした離散イベントシミュレーションフレームワークを使うためのスキルです。共有リソースを取り合うシステムをモデル化し、待ち行列や資源利用、工程の分析を行えます。リアルタイムシミュレーションと監視機能も備えています。
主な機能
- 01ジェネレーター関数によるプロセスモデル化
- 02共有リソースと待ち行列の管理
- 03イベントスケジューリングとプロセス同期
- 04実時間に同期したシミュレーション
- 05リソース監視、統計、CSV出力
活用シーン
- 01製造ラインと機械スケジューリングの評価
- 02救急患者の流れと人員配置のシミュレーション
- 03ネットワークトラフィックと帯域割り当ての分析
- 04コールセンターなどのサービス容量計画
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ crazymsn/ academic-skills --skill simpyインストール後、Claude Code で/simpyを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/events.mdmonitoring.mdprocess-interaction.mdreal-time.mdresources.mdscripts/basic_simulation_template.pyresource_monitor.py詳細
SimPy - 離散イベントシミュレーション
概要
SimPy は、標準的な Python をベースとしたプロセスベースの離散イベントシミュレーションフレームワークです。エンティティ(顧客、車両、パケットなど)が互いに相互作用し、時間の経過とともに共有リソース(サーバー、機械、帯域幅など)を取り合うようなシステムのモデリングに SimPy を使用します。
主な機能:
- Python のジェネレーター関数を使用したプロセスモデリング
- 共有リソース管理(サーバー、コンテナ、ストア)
- イベント駆動型のスケジューリングと同期
- 壁時計時刻と同期するリアルタイムシミュレーション
- 包括的なモニタリングとデータ収集
このスキルを使用するタイミング
次のような場合に SimPy スキルを使用します:
- 離散イベントシステムのモデリング - イベントが不規則な間隔で発生するシステム
- リソースの競合 - エンティティが限られたリソース(サーバー、機械、人員)を取り合う場合
- 待ち行列分析 - 待ち行列、サービス時間、スループットの検討
- プロセスの最適化 - 製造、物流、またはサービスプロセスの分析
- ネットワークシミュレーション - パケットルーティング、帯域幅割り当て、レイテンシ分析
- キャパシティプランニング - 望ましい性能を得るための最適なリソース量の決定
- システム検証 - 実装前のシステム挙動のテスト
適していない用途:
- 固定の時間刻みを用いる連続シミュレーション(SciPy の ODE ソルバーを検討してください)
- リソースを共有しない独立したプロセス
- 純粋な数理最適化(SciPy の optimize を検討してください)
クイックスタート
基本的なシミュレーションの構造
import simpy
def process(env, name):
"""A simple process that waits and prints."""
print(f'{name} starting at {env.now}')
yield env.timeout(5)
print(f'{name} finishing at {env.now}')
# Create environment
env = simpy.Environment()
# Start processes
env.process(process(env, 'Process 1'))
env.process(process(env, 'Process 2'))
# Run simulation
env.run(until=10)
リソースの使用パターン
import simpy
def customer(env, name, resource):
"""Customer requests resource, uses it, then releases."""
with resource.request() as req:
yield req # Wait for resource
print(f'{name} got resource at {env.now}')
yield env.timeout(3) # Use resource
print(f'{name} released resource at {env.now}')
env = simpy.Environment()
server = simpy.Resource(env, capacity=1)
env.process(customer(env, 'Customer 1', server))
env.process(customer(env, 'Customer 2', server))
env.run()
中核となる概念
1. Environment
シミュレーション環境は、時間を管理し、イベントをスケジュールします。
import simpy
# Standard environment (runs as fast as possible)
env = simpy.Environment(initial_time=0)
# Real-time environment (synchronized with wall-clock)
import simpy.rt
env_rt = simpy.rt.RealtimeEnvironment(factor=1.0)
# Run simulation
env.run(until=100) # Run until time 100
env.run() # Run until no events remain
2. プロセス
プロセスは Python のジェネレーター関数(yield 文を含む関数)を使用して定義します。
def my_process(env, param1, param2):
"""Process that yields events to pause execution."""
print(f'Starting at {env.now}')
# Wait for time to pass
yield env.timeout(5)
print(f'Resumed at {env.now}')
# Wait for another event
yield env.timeout(3)
print(f'Done at {env.now}')
return 'result'
# Start the process
env.process(my_process(env, 'value1', 'value2'))
3. イベント
イベントは、プロセスの同期を行うための基本的な仕組みです。プロセスはイベントを yield し、そのイベントがトリガーされると再開します。
一般的なイベントの種類:
env.timeout(delay)- 時間の経過を待機resource.request()- リソースを要求env.event()- カスタムイベントを作成env.process(func())- イベントとしてのプロセスevent1 & event2- すべてのイベントを待機(AllOf)event1 | event2- いずれかのイベントを待機(AnyOf)
リソース
SimPy は、さまざまなシナリオに対応する複数のリソース型を提供します。詳細は references/resources.md を参照してください。
リソース型の概要
| リソース型 | 用途 |
|---|---|
| Resource | 容量が限られたもの(サーバー、機械) |
| PriorityResource | 優先度に基づくキューイング |
| PreemptiveResource | 高優先度のものが低優先度のものを割り込み可能 |
| Container | バルク材料(燃料、水) |
| Store | Python オブジェクトの保管(FIFO) |
| FilterStore | 条件を指定した選択的な取り出し |
| PriorityStore | 優先度順に並んだアイテム |
クイックリファレンス
import simpy
env = simpy.Environment()
# Basic resource (e.g., servers)
resource = simpy.Resource(env, capacity=2)
# Priority resource
priority_resource = simpy.PriorityResource(env, capacity=1)
# Container (e.g., fuel tank)
fuel_tank = simpy.Container(env, capacity=100, init=50)
# Store (e.g., warehouse)
warehouse = simpy.Store(env, capacity=10)
一般的なシミュレーションパターン
パターン 1: 顧客とサーバーの待ち行列
import simpy
import random
def customer(env, name, server):
arrival = env.now
with server.request() as req:
yield req
wait = env.now - arrival
print(f'{name} waited {wait:.2f}, served at {env.now}')
yield env.timeout(random.uniform(2, 4))
def customer_generator(env, server):
i = 0
while True:
yield env.timeout(random.uniform(1, 3))
i += 1
env.process(customer(env, f'Customer {i}', server))
env = simpy.Environment()
server = simpy.Resource(env, capacity=2)
env.process(customer_generator(env, server))
env.run(until=20)
パターン 2: プロデューサー・コンシューマー
import simpy
def producer(env, store):
item_id = 0
while True:
yield env.timeout(2)
item = f'Item {item_id}'
yield store.put(item)
print(f'Produced {item} at {env.now}')
item_id += 1
def consumer(env, store):
while True:
item = yield store.get()
print(f'Consumed {item} at {env.now}')
yield env.timeout(3)
env = simpy.Environment()
store = simpy.Store(env, capacity=10)
env.process(producer(env, store))
env.process(consumer(env, store))
env.run(until=20)
パターン 3: 並列タスクの実行
import simpy
def task(env, name, duration):
print(f'{name} starting at {env.now}')
yield env.timeout(duration)
print(f'{name} done at {env.now}')
return f'{name} result'
def coordinator(env):
# Start tasks in parallel
task1 = env.process(task(env, 'Task 1', 5))
task2 = env.process(task(env, 'Task 2', 3))
task3 = env.process(task(env, 'Task 3', 4))
# Wait for all to complete
results = yield task1 & task2 & task3
print(f'All done at {env.now}')
env = simpy.Environment()
env.process(coordinator(env))
env.run()
ワークフローガイド
ステップ 1: システムを定義する
次の項目を特定します:
- エンティティ: システム内を移動するものは何か?(顧客、部品、パケット)
- リソース: 制約となるものは何か?(サーバー、機械、帯域幅)
- プロセス: どのような活動があるか?(到着、サービス、退去)
- メトリクス: 何を測定するか?(待ち時間、稼働率、スループット)
ステップ 2: プロセス関数を実装する
プロセスの種類ごとにジェネレーター関数を作成します:
def entity_process(env, name, resources, parameters):
# Arrival logic
arrival_time = env.now
# Request resources
with resource.request() as req:
yield req
# Service logic
service_time = calculate_service_time(parameters)
yield env.timeout(service_time)
# Departure logic
collect_statistics(env.now - arrival_time)
ステップ 3: モニタリングを設定する
モニタリングユーティリティを使用してデータを収集します。包括的な手法については references/monitoring.md を参照してください。
from scripts.resource_monitor import ResourceMonitor
# Create and monitor resource
resource = simpy.Resource(env, capacity=2)
monitor = ResourceMonitor(env, resource, "Server")
# After simulation
monitor.report()
ステップ 4: 実行して分析する
# Run simulation
env.run(until=simulation_time)
# Generate reports
monitor.report()
stats.report()
# Export data for further analysis
monitor.export_csv('results.csv')
高度な機能
プロセス間の相互作用
プロセスは、イベント、プロセスの yield、割り込みを通じて相互作用できます。詳細なパターンについては references/process-interaction.md を参照してください。
主要なメカニズム:
- イベントシグナリング: 調整のための共有イベント
- プロセスの yield: 他のプロセスの完了を待機
- 割り込み: プリエンプションのためにプロセスを強制的に再開
リアルタイムシミュレーション
ハードウェアインザループや対話型アプリケーションのために、シミュレーションを実時間(ウォールクロックタイム)と同期させます。references/real-time.md を参照してください。
import simpy.rt
env = simpy.rt.RealtimeEnvironment(factor=1.0) # 1:1 time mapping
# factor=0.5 means 1 sim unit = 0.5 seconds (2x faster)
包括的なモニタリング
プロセス、リソース、イベントを監視します。以下の手法を含む詳細については references/monitoring.md を参照してください:
- 状態変数の追跡
- リソースのモンキーパッチ
- イベントトレース
- 統計収集
スクリプトとテンプレート
basic_simulation_template.py
以下の機能を備えた、待ち行列シミュレーションを構築するための完全なテンプレートです:
- 設定可能なパラメーター
- 統計収集
- 顧客生成
- リソース使用
- レポート生成
使用方法:
from scripts.basic_simulation_template import SimulationConfig, run_simulation
config = SimulationConfig()
config.num_resources = 2
config.sim_time = 100
stats = run_simulation(config)
stats.report()
resource_monitor.py
再利用可能なモニタリングユーティリティです:
ResourceMonitor- 単一のリソースを追跡MultiResourceMonitor- 複数のリソースを監視ContainerMonitor- コンテナーの量を追跡- 統計の自動計算
- CSV エクスポート機能
使用方法:
from scripts.resource_monitor import ResourceMonitor
monitor = ResourceMonitor(env, resource, "My Resource")
# ... run simulation ...
monitor.report()
monitor.export_csv('data.csv')
リファレンスドキュメント
特定のトピックに関する詳細なガイドです:
references/resources.md- すべてのリソースタイプと例references/events.md- イベントシステムとパターンreferences/process-interaction.md- プロセスの同期references/monitoring.md- データ収集の手法references/real-time.md- リアルタイムシミュレーションのセットアップ
ベストプラクティス
- ジェネレーター関数: プロセス関数では必ず
yieldを使用する - リソースのコンテキストマネージャー: 自動的なクリーンアップのために
with resource.request() as req:を使用する - 再現性: 一貫した結果を得るために
random.seed()を設定する - モニタリング: シミュレーションの終了時だけでなく、全体を通してデータを収集する
- 検証: 単純なケースを解析解と比較する
- ドキュメント: プロセスのロジックとパラメーターの選択にコメントを付ける
- モジュール設計: プロセスのロジック、統計、設定を分離する
よくある落とし穴
- yield の忘れ: プロセスは一時停止するためにイベントを yield する必要がある
- イベントの再利用: イベントは一度しかトリガーできない
- リソースリーク: コンテキストマネージャーを使用するか、確実に解放する
- ブロッキング操作: プロセス内で Python のブロッキング呼び出しを避ける
- 時間単位: 時間単位の解釈を一貫させる
- デッドロック: 少なくとも1つのプロセスが進行できることを保証する
利用例
- 製造: 機械のスケジューリング、生産ライン、在庫管理
- 医療: 救急室のシミュレーション、患者の流れ、スタッフの割り当て
- 通信: ネットワークトラフィック、パケットルーティング、帯域割り当て
- 交通: 交通の流れ、ロジスティクス、車両ルーティング
- サービス業務: コールセンター、小売のレジ、予約スケジューリング
- コンピューターシステム: CPU スケジューリング、メモリ管理、I/O 操作