使用SimPY进行离散事件仿真

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

安装

$ pip install -U simpy

pycharm可以再File | Settings | Project: Simulation | Project Interpreter中添加

主要概念

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

>>> env.process(clock(env, 'slow', 1))

>>> 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

深入原理

通过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中。

稍微复杂一点的例子:

"""

服务站示例

场景介绍:

一个有特定服务提供工作站,客户服务时长不一,工作机器数有限。

Client接受服务步骤:Client到达工作站,若有空闲的机器就立刻接受服务,如果没有,就等待直到其他机器空闲下来。

每个接受过服务的Client都有一个完成满意度(或者为进度)实时统计服务客户数和完成满意进度。

"""

import random

import simpy

# 可接受输入参数

RANDOM_SEED = 0 # 不设置

NUM_MACHINES = 2 # 可以同时处理的机器数(类似工作工位数)

TIME_CONSUMING = 5 # 单任务耗时 (可以设计成随机数)

TIME_INTERVAL = 5 # 来车的间隔时间约5分钟 (可以设计成随机数)

SIM_TIME = 1000 # 仿真总时间

CLIENT_NUMBER = 2 # 初始时已经占用机器数

class WorkStation(object):

"""

一个工作站,拥有特定数量的机器数。 一个客户首先申请服务。在对应服务时间完成后结束并离开工作站

"""

def __init__(self, env, num_machines, washtime):

self.env = env

self.machine = simpy.Resource(env, num_machines)

self.washtime = washtime

self.allClient = 0

self.accomplishClient = 0

def wash(self, car):

"""服务流程"""

yield self.env.timeout(random.randint(2, 10)) # 假设服务时间为随机数(2~10)

self.allClient += 1

per = random.randint(50, 99)

print("%s's 任务完成度:%d%%." % (car, per))

if per > 80:

self.accomplishClient += 1

print("工作站服务客户数:%d,"

"工作站服务达标率:%.2f。" % (self.allClient, float(self.accomplishClient) / float(self.allClient)))

def Client(env, name, cw):

"""

客户到达动作站接受服务,结束后离开

"""

print('%s 到达工作站 at %.2f.' % (name, env.now))

with cw.machine.request() as request:

yield request

print('%s 接受服务 at %.2f.' % (name, env.now))

yield env.process(cw.wash(name))

print('%s 离开服务站 at %.2f.' % (name, env.now))

def setup(env, num_machines, washtime, t_inter, clientNumber):

"""创建一个工作站,几个初始客户,然后持续有客户到达. 每隔t_inter - 2, t_inter + 3分钟(可以自定义)."""

# 创建工作站

workstation = WorkStation(env, num_machines, washtime)

# 创建clientNumber个初始客户

for i in range(clientNumber):

env.process(Client(env, 'Client_%d' % i, workstation))

# 在仿真过程中持续创建客户

while True:

yield env.timeout(random.randint(t_inter - 2, t_inter + 3)) # 3-8分钟

i += 1

env.process(Client(env, 'Client_%d' % i, workstation))

# 初始化并开始仿真任务

print('开始仿真')

# 初始化seed,指定数值的时候方正结果可以复现

random.seed()

# 创建一个环境并开始仿真

env = simpy.Environment()

env.process(setup(env, NUM_MACHINES, TIME_CONSUMING, TIME_INTERVAL, CLIENT_NUMBER))

# 开始执行!

env.run(until=SIM_TIME)

输出:

开始仿真

Client_0 到达工作站 at 0.00.

Client_1 到达工作站 at 0.00.

Client_0 接受服务 at 0.00.

Client_1 接受服务 at 0.00.

Client_2 到达工作站 at 3.00.

Client_0's 任务完成度:54%.

工作站服务客户数:1,工作站服务达标率:0.00。

Client_3 到达工作站 at 7.00.

Client_0 离开服务站 at 7.00.

Client_2 接受服务 at 7.00.

Client_1's 任务完成度:97%.

工作站服务客户数:2,工作站服务达标率:0.50。

.

.

.

Client_179 接受服务 at 986.00.

Client_178 离开服务站 at 986.00.

Client_180 到达工作站 at 989.00.

Client_180 接受服务 at 989.00.

Client_179's 任务完成度:89%.

工作站服务客户数:180,工作站服务达标率:0.36。

Client_179 离开服务站 at 993.00.

Client_181 到达工作站 at 995.00.

Client_181 接受服务 at 995.00.

Client_180's 任务完成度:96%.

工作站服务客户数:181,工作站服务达标率:0.36。

Client_180 离开服务站 at 997.00.

Process finished with exit code 0

python语言例子_【Python】SimPy的使用示例-Go语言中文社区相关推荐

  1. python最短路径例子_[python]dijkstra 算法的 加权的最短路径 案例

    这个还有很多概念有点明确 from collections import defaultdict # defaultdict, 找不到的key的value 就设定为 0,https://blog.cs ...

  2. python语言例子_第一个Python实例

    1. 第一个Python实例 Python随着时代的进步,变得越来越受欢迎,当然也有它受人喜欢的道理.下面我们首先通过对比来了解一下. 不知道大家有没有学过C或C++,在C语言中输出一个简单的'Hel ...

  3. 初识python教学反思_[python第一课]初识python

    print("1.第一章:初识python\npython历史:\n1.python是用c语言写的\n2.python是可以调用c语言库函数\n3.Python1.0是1994年1月\n4. ...

  4. python 病毒 基因_#Python#提取基因对应的蛋白质名

    提取基因对应的蛋白质官方名 最开始,是需要将基因跟其编码的蛋白质对应起来,找遍了各种数据库都没发现有相关的注释文件,Uniprot作为处理蛋白质的大佬,结果里都有,肯定有办法能够满足需求. 搜索TP5 ...

  5. python keyboard模块_[python] PyMouse、PyKeyboard用python操作鼠标和键盘

    1.PyUserInput 简介 PyUserInput是一个使用python的跨平台的操作鼠标和键盘的模块,非常方便使用.支持的平台及依赖如下: Linux - Xlib Mac - Quartz, ...

  6. python语言例子_机器学习案例分析(基于Python语言)

    领取成功 您已领取成功! 您可以进入Android/iOS/Kindle平台的多看阅读客户端,刷新个人中心的已购列表,即可下载图书,享受精品阅读时光啦! - | 回复不要太快哦~ 回复内容不能为空哦 ...

  7. python索引例子_谈谈python中的索引

    最近以python为工具,取代VBA处理工作中Excel遇到的小问题,我觉得其优点:一是语言更清爽友善,因为VBA的语言一来IDE难用,语法风格不大气优雅(我个人的见解):二是,我一直怀疑Excel对 ...

  8. 什么是python编程例子_案例详解:优化Python编程的4个妙招

    全文共3510字,预计学习时长7分钟 作为数据科学家,敲出最优的Python代码非常非常重要.别无他法,杂乱低效的代码笔记本会消耗你的时间,也会浪费大量项目资金.经验丰富的数据科学家和专业人士都很清楚 ...

  9. python加法例子_第二讲 做加法的例子

    # Django Step by Step (二) ## 1 引言 随着学习,我们的例子也开始复杂了,下一步我想实现一个简单的 web 加法器.界面会是这样: ![](https://img.kanc ...

最新文章

  1. 02移动端布局基础之流式布局项目实战(京东移动端首页)
  2. 土豆上的小霉菌引发百万人死亡和逃难,却造就全球7千万后裔
  3. 静态库与动态库(一):概述
  4. java jep_Java 10 – JEP 286:局部变量类型推断
  5. DBCP连接池配置常用参数说明
  6. SpringBoot2 整合 AXIS2 服务端和客户端
  7. 001Linux课程内容
  8. 苹果启动“突围”计划 建立自营金融服务
  9. OMG,学它!mac怎么安装java插件
  10. RestFul 风格规范
  11. 高速野蛮生长的单片机嵌入式行业,各个岗位的需求也随之增大
  12. EXPLAIN查看SQL执行计划
  13. Snipaste2.7.3下载安装与使用(超实用的截图利器)
  14. 学习RAID磁盘阵列
  15. HUAWEI Mate40Pro解除账号忘记密码ID强制刷机鸿蒙系统激活锁能解开吗
  16. git-secrets安装教程
  17. 计算机系学霸情书,大学生“学霸情书”火了,各专业表达浪漫!网友:教科书级别!...
  18. 设备树基本语法及属性分析
  19. 教你如何进入有密码的 XP 系统
  20. APS高级计划排程系统,工厂各部门实施前后有哪些区别?

热门文章

  1. Redis学习一Redis的介绍与安装部署
  2. Nexus搭建Maven服务器
  3. kendo grid输入框验证方法
  4. EJB3与EJB2的差别
  5. Kubernetes原理浅析
  6. mybatis mysql5.7_spring boot整合ES+mysql5.7+mybatis+iview个人博客系统
  7. php 文件指定位置添加内容,C++_VC++在TXT文件指定位置追加内容的方法,本文实例讲述了VC++操作文本文 - phpStudy...
  8. C语言 BMP24位变单色,怎么将24位色BMP图片改为单色或16色?(2)
  9. pytorch保存模型时报错***object has no attribute 'state_dict'
  10. 使用Hadoop自带的例子wordcount实现词频统计