離散事象システムとは
本クレートの紹介の前に、離散事象システム(Discrete Event System)について簡単に説明します。
離散事象システムとは、時間の経過に伴って離散的なタイミングでイベントが発火し、それを順次処理していくシステムのことです。
一般的に、待ち行列理論やペトリネットを用いてモデリングされます。
今回開発したのは、このような離散事象システムのシミュレーションを支援するためのクレートです。
des-sim クレートのご紹介
離散事象システムのシミュレーションをより手軽に実装できるようにするため、des-sim というクレートを作成しました。
日本語のREADMEはこちらからご確認いただけます。
SimPyとの違い(イベント駆動型シミュレーター)
Pythonの有名なシミュレーションパッケージである SimPy は「プロセス型シミュレーター」ですが、des-sim は古典的な「イベント駆動型シミュレーター」を採用しています。
-
プロセス型 (SimPyなど): ジェネレータ (
yield) を活用し、「処理A → N秒待機 → 状態を確認して処理Bを行い、成功イベントを発火」のように、一つのイベント処理内で時間経過を表現しながら直感的に記述できます。 -
イベント駆動型 (
des-sim): 時間を進めた際、その時刻にスケジュールされたイベントがあれば処理を実行します。「処理Aを実行 → 処理BのイベントをN秒後にスケジュールする」というように、一つのイベント内で次のイベントをスケジュールし、N秒後に処理Bのイベントが発火する仕組みです。
書き味は異なりますが、プロセス型もイベント駆動型もシミュレーターとして実現できることは同じです。
des-sim の特徴と構成
des-sim クレートは、主に3つのモジュールから構成されています。
1. modeling モジュール
シミュレーション対象をモデリングするための機能を提供します。ユーザーが主に操作するのはこのモジュールです。
-
event/model: この2つだけで最低限のシミュレーションのモデリングが可能です。 -
source: 定期的にイベントをスケジュールするのに利用します。 -
hook: 実行時のログや状態を収集するフックになります。 -
sampler: 次のイベント時刻を確率的に決定できるようにランダムにサンプリングする方法を提供します。
これらは、シミュレーション開始前に execution モジュールの Engine に登録するだけで利用できるようになってます。なお、eventやsourceはシミュレーション中にも登録可能です。
2. execution モジュール
シミュレーションの実行環境を提供します。
Engine と、それを駆動する Runner トレイトから構成されており、独自の Runner を実装してシミュレーションを行うことも可能です。
標準で以下の Runner を提供しています。
-
StandardRunner: 処理がない時間をスキップするかどうかを選択できる標準的なランナーです。 -
RealtimeRunner: シミュレーションを現実の時間の進行に合わせて実行します。 -
AsyncRunner: イベント処理を非同期に行うことができます。
なお、StandardRunner と RealtimeRunner は、Model、Source、Hook を決定論的(実行するたびに結果が変わらない)に実装することで、シミュレーション結果を完全に再現できるよう設計されています。
3. context モジュール
実行環境に対する操作(イベントのスケジュールなど)を行うためのコンテキストを提供します。
context モジュール は、modeling モジュール内のメソッド引数として渡されるため、ユーザーは受け取ったコンテキストのメソッドを呼び出すだけで簡単に操作できます。
サンプルコード
GitHubリポジトリの examples ディレクトリ に、いくつかのサンプルを用意しています。
まずは挙動が一番わかりやすい StandardRunner用のサンプル をぜひご覧ください。
苦労した点
各種Runnerの実装の他にイベント駆動のままエージェントベース風(サンプル)に書くことができるようにするのに苦戦しました。その産物としてagent モジュールを用意する形になりましたが、依然として複雑なままです。将来より書きやすくなるといいなーとは思っています。
おわりに
個人的には使いやすいクレートに仕上がったと感じていますが、実際に使っていただくことでさらなる改善点が見つかるはずです。
ぜひ一度お試しいただき、ご感想やIssueなどをお寄せいただければ幸いです!