使用SimPY进行离散事件仿真

2023-11-02

使用SimPY进行离散事件仿真

SimPY是一个Python下的第三方库,可以方便的进行离散事件的仿真。仿真速度比较快。下面记录一下我的一点心得,不保证完全正确,供参考。

安装

$ pip install -U simpy

##学习资源
-可爱的PYTHON:SimPy 简化了复杂模型-基于Python 2.x
-Pypi库
-主页readthedoc.io
-介绍PPT
-PPT配套Youtube视频

主要概念

  • Environment
  • Process
  • Event
  • Resource

SimPY使用Environment,Process,Event,Resource四大概念来进行离散事件的仿真。

Environment就是整体仿真所在的时间,主要用于提取时间。
Process就是仿真过程中的实体,如:顾客, 设备, 车辆等。 Process本质上也是一个event。源代码里面可以看到是继承Event的一个类。
Event是仿真中触发的事件,可以理解为一个定时器。当定时器到时时,触发事件。
Resource是仿真中的资源,如ATM机,服务器等。

##官方实例

>>> import simpy
>>>
>>> def clock(env, name, tick):
...     while True:
...         print(name, env.now)
...         yield env.timeout(tick)
...
>>> env = simpy.Environment()
>>> env.process(clock(env, 'fast', 0.5))
<Process(clock) object at 0x...>
>>> env.process(clock(env, 'slow', 1))
<Process(clock) object at 0x...>
>>> env.run(until=2)
fast 0
slow 0
fast 0.5
slow 1
fast 1.0
fast 1.5

逻辑很简单,

  1. 创建一个env
  2. 以env为参数创建process, process有名字和参数,process内部使用生成器直接调用了超时事件。
  3. 运行该env

不错吧,很简单就有了一个开始。

##前导知识
简单开始之后需要回顾一下后面会使用到的其他知识。
因为离散事件仿真中会用到大量的随机函数,所以这里回顾一下主要的随机函数。

import random

random.uniform(3,4) # 3到4之间的均匀分布
random.gauss(5,1) # 以5为均值,1为方差的高斯分布。
random.normalvariate(5,1) # 以5为均值,1为方差的高斯分布。
random.randint(4,8) # 从4,5,6,7,8中随机挑出一个整数值。
random.choice([1,4,6,8,0]) # 从1,4,6,8,0中随机挑出一个值。
random.random() # 0-1之间均匀分布的一个实数。

##深入原理
通过SimPY的源代码可以了解到,SimPY使用了一个heapq队列,这个队列中的元素是事件。Environment中对这个 队列进行调度,实际上是将事件压入队列中,environment中还有step方法,就是从队列中取出时间最小的一个事件(也就是时间点上最接近当前时间的下一个事件,使用heapq的heappop方法),然后运行这个事件的callback函数,一般就是Process。 因此仿真实际上是对一系列事件进行压入队列,按时间序弹出队列的过程。这样可以避免使用时间步长进行步进,时间步长步进的缺点就是太慢了。必须一个时间步长一个时间步长的挨个遍历过去,如果时间步长不合理的话,会有大量的计算时间上的浪费。

另外,为了语法上的优美易用,env中使用了Python的反射机制,将常用的几种事件,包括Process, Timeout, Anyof, Allof, Event都绑定为env的一种方法。 这个语法看上去很简单,但实现机制相对有点难以理解(我也只是了解是一种反射),只需要记住类似env.process, env.timeout, env.event, env.all_of, env.any_of的方法调用实际上都是声明了simpy.Process, simpy.Timeout等类的就可以了。详细实现在simpy.core.py中。

##稍复杂的实例
官方教程中的几个例子都比较经典。下面一一介绍

  1. 银行柜台排队问题
"""
银行柜台排队问题

知识点:

- 资源
- 条件事件

场景:
  A counter with a random service time and customers who renege. Based on the
  program bank08.py from TheBank tutorial of SimPy 2. (KGM)
  一个银行柜台,其服务耗时随机分布,客户会因费时长而离开。

"""
import random

import simpy


RANDOM_SEED = 42
NEW_CUSTOMERS = 5  # 总的客户人数
INTERVAL_CUSTOMERS = 10.0  # 新的客户每隔大约10秒钟出现一位
MIN_PATIENCE = 1  # 最低耐心值
MAX_PATIENCE = 3  # 最高耐心值


def source(env, number, interval, counter):
    """本函数随机生成客户"""
    for i in range(number):
        c = customer(env, 'Customer%02d' % i, counter, time_in_bank=12.0)
        env.process(c)
        t = random.expovariate(1.0 / interval)
        yield env.timeout(t)


def customer(env, name, counter, time_in_bank):
    """客户流程函数,客户到来,接受服务或者不耐烦,最后离开."""
    arrive = env.now
    print('%7.4f %s: Here I am' % (arrive, name))

    with counter.request() as req:
        patience = random.uniform(MIN_PATIENCE, MAX_PATIENCE)
        # Wait for the counter or abort at the end of our tether
        results = yield req | env.timeout(patience)

        wait = env.now - arrive

        if req in results:
            # 得到服务
            print('%7.4f %s: Waited %6.3f' % (env.now, name, wait))

            tib = random.expovariate(1.0 / time_in_bank)
            yield env.timeout(tib)
            print('%7.4f %s: Finished' % (env.now, name))

        else:
            # 不耐烦离开
            print('%7.4f %s: RENEGED after %6.3f' % (env.now, name, wait))


# 初始化然后开始模拟
print('Bank renege')
random.seed(RANDOM_SEED)
env = simpy.Environment()

# 开始流程函数并运行
counter = simpy.Resource(env, capacity=1)
env.process(source(env, NEW_CUSTOMERS, INTERVAL_CUSTOMERS, counter))
env.run()
  1. 洗车问题
"""
洗车问题示例.

知识点:

- 等待其它流程
- 资源

场景介绍:
  一个有特定洗车机的洗车房,并且洗车流程会消耗随机长度的时间。
  Car流程为,车到达洗车房,如果有空闲的洗车机,就立刻开始洗车,如果没有,就等待直到
  有洗车机空闲下来。


"""
import random

import simpy


RANDOM_SEED = 42
NUM_MACHINES = 2  # 洗车房中洗车机的数量
WASHTIME = 5      # 使用洗车机洗车所需的时间,分钟
T_INTER = 7       # 来车的间隔时间,约7分钟
SIM_TIME = 20     # 总的模拟时间


class Carwash(object):
    """
    一个洗车房,拥有特定数量的洗车机。 一个车首先申请洗车机。当来车申请到洗车机后
    就可以开始洗车流程,并且在等待指定的洗车时间后完成洗车。

    """
    def __init__(self, env, num_machines, washtime):
        self.env = env
        self.machine = simpy.Resource(env, num_machines)
        self.washtime = washtime

    def wash(self, car):
        """洗车流程。它使用一个car流程并试着清洗它。"""
        yield self.env.timeout(WASHTIME)
        print("Carwash removed %d%% of %s's dirt." %
              (random.randint(50, 99), car))


def car(env, name, cw):
    """车 流程 (每辆车都有一个名字) 每辆车会到达洗车房(``cw``) 并申请洗车机.

    然后开始洗车流程,等待洗车的完成然后离开再不回来...

    """
    print('%s arrives at the carwash at %.2f.' % (name, env.now))
    with cw.machine.request() as request:
        yield request

        print('%s enters the carwash at %.2f.' % (name, env.now))
        yield env.process(cw.wash(name))

        print('%s leaves the carwash at %.2f.' % (name, env.now))


def setup(env, num_machines, washtime, t_inter):
    """创建一个洗车房,几个初始车辆,然后持续创建车辆到达. 每隔``t_inter`` 分钟."""
    # 创建洗车房
    carwash = Carwash(env, num_machines, washtime)

    # 创建4个初始车辆
    for i in range(4):
        env.process(car(env, 'Car %d' % i, carwash))

    # 在仿真过程中持续创建车辆
    while True:
        yield env.timeout(random.randint(t_inter - 2, t_inter + 2))
        i += 1
        env.process(car(env, 'Car %d' % i, carwash))


# 初始化并开始仿真
print('Carwash')
print('Check out http://youtu.be/fXXmeP9TvBg while simulating ... ;-)')
random.seed(RANDOM_SEED)  # This helps reproducing the results

# 创建一个环境并开始仿真
env = simpy.Environment()
env.process(setup(env, NUM_MACHINES, WASHTIME, T_INTER))

# 开始执行!
env.run(until=SIM_TIME)

后续更新新的实例。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用SimPY进行离散事件仿真 的相关文章

随机推荐

  • 11-TensorFlow 基于ResNet的轴承故障诊断

    1 数据集 数据是来自凯斯西储大学 CWRU 滚动轴承数据中心 官方网站数据下载地址 https csegroups case edu bearingdatacenter pages download data file CWRU滚动轴承数
  • 【Shell牛客刷题系列】SHELL27 nginx日志分析5-统计爬虫抓取404的次数

    该系列是基于牛客Shell题库 针对具体题目进行查漏补缺 学习相应的命令 刷题链接 牛客题霸 Shell篇 该系列文章都放到专栏下 专栏链接为 专栏 Shell 欢迎关注专栏 本文知识预告 本文首先复习了grep awk wc等命令的相关用
  • 计算一个数的二进制表示中有多少个1

    https zhidao baidu com question 1370480689655286419 html 计算机里的数字本来就是用二进制存的 所以计算过程也都是二进制计算 利用一些位运算的特性 可以很容易计算1的个数 有一个很有意思
  • Assets/Vuforia/Scripts/DefaultInitializationErrorHandler.cs(10,7): error CS0246: The type or namespa

    Assets Vuforia Scripts DefaultInitializationErrorHandler cs 10 7 error CS0246 The type or namespace name Vuforia could n
  • android系统如何自适应屏幕大小

    b 1 屏幕相关概念 b 1 1分辨率 是指屏幕上有横竖各有多少个像素 1 2屏幕尺寸 指的是手机实际的物理尺寸 比如常用的2 8英寸 3 2英寸 3 5英寸 3 7英寸 android将屏幕大小分为四个级别 small normal la
  • PCIe的发展过程

    PCIe 在原来的时候 我们的电脑并不像如今这样 有如此统一的接口与总线规范 那时想要给主板做拓展有很大的局限性 因为主板上的接口基本只能对应一个硬件设备 各大厂商之间的规范也各不相同 就是在这样的大环境下 ISA 诞生了 上世纪 80 年
  • VS编写简单的C\C++程序步骤

    VS编写简单的C C 程序步骤 一共分为两个模块 第一个模块新建项目 具体如图 1 选择文件 gt 已安装 gt Visual C gt 空项目 gt 修改项目名 gt 修改项目存储位置 gt 确定 第2个模块 新建源程序文件 具体流程如下
  • ElementUI按需引入各种组件

    ElementUI按需引入各种组件 一 首先按需引入前奏 安装element ui npm i element ui S 安装按需引入必要插件 npm install babel plugin component D 修改 babelrc
  • linux下如何安装python以及一些注意事项

    linux下如何安装python 事先需找到python的下载路径 自己下载下来或者通过wget下载下来 官网包下载路径 https www python org downloads 1 安装python3 6 13 wget https
  • Spring系列之primary可以解决什么问题?

    存在的问题以及解决方案 直接上案例 通过案例来看技术是如何使用的 package com javacode2018 lesson001 demo8 public class NormalBean public interface IServ
  • Python基础知识之4

    Python基础知识之4 函数与库 所谓函数 就是把具有独立功能的代码块组织为一个小模块 在需要的时候可以反复调用 函数分为编译器自带的函数 内建 和用户自己创建的函数 自定义函数 内建函数是编译器开发者已经定义好的函数 用户可以直接使用
  • Sharding-JDBC(六)5.1.0版本,实现按月分表、自动建表、自动刷新节点

    目录 1 Maven 依赖 2 创建表结构 3 yml 配置 4 TimeShardingAlgorithm java 分片算法类 5 ShardingAlgorithmTool java 分片工具类 6 ShardingTablesLoa
  • Home_istoreOS

    1 重置网络 修改lan口 vi etc config network 修改LAN口为 192 168 10 100 修改root密码 原始密码password2 修改为旁路由模式 只需要修改网关为 192 168 10 1 不需要DHCP
  • 解决安装依赖时报错:npm ERR! code ERESOLVE

    系列文章目录 文章目录 系列文章目录 前言 一 错误原因 二 解决方法 三 注意事项 总结 前言 在使用 npm 安装项目依赖时 有时会遇到错误信息 npm ERR code ERESOLVE 该错误通常发生在依赖版本冲突或者依赖解析问题时
  • git解决 error: you need to resolve your current index first

    问题 执行切换代码分支 git checkout featrue 2019 06 24 报错如下 error you need to resolve your current index first 执行git pull代码时报错 Pull
  • styled-components:一本通

    初体验 styled方法 将React组件包装成Styled组件 的三种情况 tagged template literal interpolations 插值表达式 mixin StyledComponent相关特性 extend 继承
  • 计算机系统实验之datalab

    datalab实验是CSAPP中关于整数和浮点数的位运算的实验 对于我们理解位运算和整数 浮点数的位级表示有着很好的帮助 实验目的 修改bits c的C语言代码 使其通过所有在不违反任何编码准则的情况下 在btest中进行测试 进一步熟悉整
  • Java代码中验证IP地址是否可访问【Linux和windows环境下】

    Java代码中验证IP地址是否可访问 Linux和windows环境下 我的需求场景是尝试连接数据源 数据库地址有不同网络环境下的地址 生产 内网 局域网等 所以在连接数据源之前判断一下url中的ip是否可访问 然后决定是否执行下一步操作
  • 解决Qt项目构建或部署时出现的Error while building/deploying project的问题

    解决Qt项目构建或部署时出现的Error while building deploying project的问题 在使用Qt开发项目时 有时会在构建或部署时遇到一些问题 其中最常见的就是Error while building deploy
  • 使用SimPY进行离散事件仿真

    使用SimPY进行离散事件仿真 SimPY是一个Python下的第三方库 可以方便的进行离散事件的仿真 仿真速度比较快 下面记录一下我的一点心得 不保证完全正确 供参考 安装 pip install U simpy 学习资源 可爱的PYTH