PythonのSimPyではじめる離散イベントシミュレーション入門

SimPy(発音は「ブリンピー」に似た響き)は、プロセス指向の離散イベントシミュレーションを実現するためのPythonパッケージです。
インストール
SimPyをインストールする最も簡単な方法は、pipを使うことです。
pip install simpy
実行すると、以下のような出力が表示されます。

本記事の執筆時点における最新バージョンはsimpy-3.0.11で、以降の例はすべてこのバージョンを使用しています。
すでにSimPyがインストールされている場合は、pipの-Uオプションでアップグレードできます。
pip install -U simpy
注意:Python 2.7以上が必要です。また、Linux/Unix/macOS環境では、インストールにroot権限が必要になる場合があります。
インストールが成功したか確認するには、Pythonシェルを開いてsimpyをインポートしてみましょう。
基本概念
SimPyは離散イベントシミュレーション用のライブラリです。メッセージ、車両、顧客といったアクティブな要素は「プロセス」としてモデル化されます。SimPyにおけるアクティブなエンティティであるプロセスの正体は、離散イベントをyieldするPythonジェネレータです。
ここで重要なのは、通常の関数が値をreturnするのに対し、ジェネレータは値をyieldするという違いです。この仕組みにより、イベントを生成しながら、そのイベントがトリガーされるまで処理を待機させることができます。
プロセスがイベントをyieldすると、そのプロセスは一時停止(サスペンド)します。イベントがトリガーされると、SimPyは一時停止していたプロセスを再開させます。複数のプロセスが同じイベントを待っている場合は、yieldした順序どおりに再開されます。
ジェネレータの動作を確認する
def gen(x):
y = yield x + 1
return y
>>> g = gen(1) >>> next(g) 2 >>> next(g) Traceback (most recent call last): File "<pyshell#2>", line 1, in <module> next(g) StopIteration
この例では、最初のyield(x+1の評価)でイテレーションが止まり、次にnext()を呼び出すとStopIteration例外が発生します。これがジェネレータの基本的な挙動です。
Timeoutイベント
Timeout型のイベントは、一定の(シミュレーション上の)時間が経過した後にトリガーされます。Timeoutイベントを使うと、プロセスは指定時間だけ処理を保留したり、スリープしたりできます。Timeoutを含むすべてのイベントは、プロセスが属するEnvironmentオブジェクトの対応するメソッドを呼び出して作成します。
実践例:カンファレンス参加者のシミュレーション
以下は、カンファレンス会場での講演聴講を模したサンプルコードです。1セッションあたり3つの講演(各30分)と15分の休憩を繰り返すモデルとなっています。
# 必要なライブラリをインポート
from random import randint
import simpy
# 設定
TALKS_PER_SESSION = 3 # 1セッションあたりの講演数
TALK_LENGTH = 30 # 講演の長さ(分)
BREAK_LENGTH = 15 # 休憩の長さ(分)
ATTENDEES = 1 # 参加者数
def attendee(env, name, knowledge=0, hunger=0):
talks = 0 # 受講した講演数
breaks = 0 # 取った休憩数
# セッションを繰り返す
while True:
# 講演に参加する
for i in range(TALKS_PER_SESSION):
print('Talk {0} begins at {1}'.format(talks+1, env.now))
knowledge += randint(0, 3) / (1 + hunger) # 知識を獲得
hunger += randint(1, 4) # 空腹度が上がる
talks += 1
yield env.timeout(TALK_LENGTH)
print(f'Talk {talks} ends at {env.now}')
print('Attendee %s finished talks with knowledge %.2f and hunger %.2f' % (name, knowledge, hunger))
# 休憩:ビュッフェへ
food = randint(3, 12)
hunger -= min(food, hunger) # 食事で空腹度を下げる
yield env.timeout(BREAK_LENGTH)
print('Attendee %s finished eating with hunger %.2f' % (name, hunger))
# シミュレーションの実行
env = simpy.Environment()
for i in range(ATTENDEES):
env.process(attendee(env, i))
env.run(until=250)
このプログラムを実行すると、以下のような出力が得られます。

この例では、カンファレンス会場の様子を再現しています。参加者は1セッションにつき3つの講演を聴講し、講演はそれぞれ30分、休憩は15分として設定されています。
attendeeプロセスを作成するには、Environmentへの参照(env)、名前(name)、知識量(knowledge)、空腹度(hunger)が必要です。while Trueによる無限ループでセッションが繰り返され、attendee()関数はジェネレータとして動作するため、yield文に到達するたびに制御フローをシミュレーション本体へ返します。
最後に、env.run(until=250)によってシミュレーション時間250までデモを実行しています(3講演 → 休憩 → 3講演 → 休憩 → 1講演という流れで進行します)。
-
PythonとSeleniumでWhatsAppチャットボットを作る方法
はじめに この記事では、Pythonを使ってWhatsAppのチャットボットを作成する方法を解説します。TwitterやFacebook向けの一般的なチャットボットとは異なり、WhatsAppは運営ポリシーの関係上、プラットフォーム上で直接ボットを動かすことができません。 しかし、SeleniumというPythonの強力なパッケージを使えば、ブラウザの操作を自動化することでこれを実現できます。Seleniumを利用すれば、ブラウザ経由で「WhatsApp Web」を自由に操作できるのです。 必要なもの 準備が必要なのは、主に以下の3点です。 1. Selenium Seleniumはpip
-
PythonでのCX_Freezeの使い方:スクリプトを実行ファイル(EXE)に変換する方法
はじめに 何か面白いものを作りたいという欲求は人間の本能であり、完成したものは誰かに共有したくなるものです。Pythonでもその願いを叶えられます。ただし、作成したPythonスクリプトをそのまま共有するには、相手のマシンにも同じバージョンのPythonと、プログラムで使用しているすべてのモジュールがインストールされている必要があります。 そこで役立つのがCX_Freezeです。このツールを使えば、Pythonがインストールされていない環境でも動作するスタンドアロンの実行ファイル(.exe)を作成できます。 CX_Freezeのインストール まず、コマンドプロンプトで以下のコマンドを実行し、c