Python
 Computer >> コンピューター >  >> プログラミング >> Python

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


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

SimPy(発音は「ブリンピー」に似た響き)は、プロセス指向の離散イベントシミュレーションを実現するためのPythonパッケージです。

インストール

SimPyをインストールする最も簡単な方法は、pipを使うことです。

pip install simpy

実行すると、以下のような出力が表示されます。

Pythonの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)

このプログラムを実行すると、以下のような出力が得られます。

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

この例では、カンファレンス会場の様子を再現しています。参加者は1セッションにつき3つの講演を聴講し、講演はそれぞれ30分、休憩は15分として設定されています。

attendeeプロセスを作成するには、Environmentへの参照(env)、名前(name)、知識量(knowledge)、空腹度(hunger)が必要です。while Trueによる無限ループでセッションが繰り返され、attendee()関数はジェネレータとして動作するため、yield文に到達するたびに制御フローをシミュレーション本体へ返します。

最後に、env.run(until=250)によってシミュレーション時間250までデモを実行しています(3講演 → 休憩 → 3講演 → 休憩 → 1講演という流れで進行します)。

  1. PythonとSeleniumでWhatsAppチャットボットを作る方法

    はじめに この記事では、Pythonを使ってWhatsAppのチャットボットを作成する方法を解説します。TwitterやFacebook向けの一般的なチャットボットとは異なり、WhatsAppは運営ポリシーの関係上、プラットフォーム上で直接ボットを動かすことができません。 しかし、SeleniumというPythonの強力なパッケージを使えば、ブラウザの操作を自動化することでこれを実現できます。Seleniumを利用すれば、ブラウザ経由で「WhatsApp Web」を自由に操作できるのです。 必要なもの 準備が必要なのは、主に以下の3点です。 1. Selenium Seleniumはpip

  2. PythonでのCX_Freezeの使い方:スクリプトを実行ファイル(EXE)に変換する方法

    はじめに 何か面白いものを作りたいという欲求は人間の本能であり、完成したものは誰かに共有したくなるものです。Pythonでもその願いを叶えられます。ただし、作成したPythonスクリプトをそのまま共有するには、相手のマシンにも同じバージョンのPythonと、プログラムで使用しているすべてのモジュールがインストールされている必要があります。 そこで役立つのがCX_Freezeです。このツールを使えば、Pythonがインストールされていない環境でも動作するスタンドアロンの実行ファイル(.exe)を作成できます。 CX_Freezeのインストール まず、コマンドプロンプトで以下のコマンドを実行し、c