这次文章是关于如何用 SimPy 来解决两个仿真需求:

如何随时中断恢复 Process (进程)

如何动态设置 Resource (资源)的数量

相应地这两个需求满足的场景是:

仿真过程中, 某一工序被中断, 中断可以依据一个预先设定的时间或者是不确定时间

仿真过程中, 人力资源也是依据时间变化, 模拟现实中工人的排班安排

回顾资源和进程的概念

Resource 和 Process 是 SimPy 对人力资源和进程进行抽象的构造. Resource 好比一个队列, 其长度就是提前设置好的资源数, 不同的工序就按照时间先后和赋予的优先级进入队列. Process 从构造上来说就是一个生成器, 我们可以通过 send 方法传入 Exception 对 Process 进行打断.

比如某个工序需要占用一个工人, 耗时 30 min 来完成一个进程, 当前所有可以调用的工人数是 10, 代码形式如下:

import simpy

import random

WORKERNUM = 10 # 工人数

PROCESS_TIME = 30 * 60 # 工序耗时, 使用秒作为单位

MEAN_ = 4 * 60 # 平均物件生成时间

def process(env, workers, store):

"""工序"""

while True:

with workers.request() as req:

yield req

item = yield store.get()

print(f"{env.now} - {item} - start")

yield env.timeout(PROCESS_TIME)

print(f"{env.now} - {item} - done")

def put_item(env, store):

"""每隔一段时间生成一个物品"""

for i in range(100):

item = f"{i}_item"

store.put(item)

yield env.timeout(random.expovariate(1 / MEAN_))

env = simpy.Environment()

workers = simpy.Resource(env, 10)

store = simpy.Store(env)

env.process(process(env, workers, store))

env.process(put_item(env, store))

env.run()

Process 进程的动态调整

存在以下两种情景:

进程随时中断以及恢复

按照时间表对进程进行启动或者终止

要区分一件事情, 中断的时候是让当前进程完成后再中断, 还是立即中断. 具体场景可以想象为一个工人被调离当前岗位, 他应该是先完成手头上的工序, 或者他需要停下手头的工作离开工位.

如果是必须实现进程的随时中断, 只能通过 process.interrupt() 中断 process, 即第一种场景; 假若中断是按照时间表进行, 就可以通过第二种场景, 构建多个不同时间开启的进程来进行模拟.

进程中断的实现

from simpy import interrupt, Environment

env = Environment()

def interrupter(env, victim_proc):

yield env.timeout(1)

victim_proc.interrupt('Spam')

def victim(env):

try:

yield env.timeout(10)

except Interrupt as interrupt:

cause = interrupt.cause

多段进程模拟按时间安排的开关

import simpy

PROCESS_TIME = 3

def put_item(env, store):

for i in range(20):

yield env.timeout(0.5)

store.put(f"{i}_item")

def process(i, env, store, start, end):

yield env.timeout(start)

while True:

item = yield store.get()

# 判断 item 到达时间是否超出本进程关闭时间

if env.now > end:

print(f"{env.now} - process {i} - end")

store.put(item)

env.exit()

else:

print(f"{env.now} - {item} - start")

yield env.timeout(PROCESS_TIME)

print(f"{env.now} - {item} - end")

env = simpy.Environment()

store = simpy.Store(env)

env.process(put_item(env, store))

for i, (start, end) in enumerate([(20, 30), (40, 50), (60, 90)]):

env.process(process(i, env, store, start, end))

env.run()

Resource 资源的动态调整

资源人数按指定的排版表调配

由于Resource 在实例化后, 就没办法修改了. 为了满足在仿真过程中对资源进行修改, 使用了一个反向的思路. 首先所有资源使用 PriorityResource 实例, 预先设置一个可以调节的最大资源数, 当需要调节资源数的时候, 使用一个优先级为 -1 的 request 去占用资源, 而正常的进程默认优先级是 0.

通过这样的操作会使得, 我们调节资源的占用进程优先级更高, 正常进程可以调用的资源数会变成

:

可以调用资源 = 最大资源 - 占用资源

import simpy

PROCESS_TIME = 2

def put_item(env, store):

for i in range(20):

yield env.timeout(0.5)

store.put(f"{i}_item")

def process(env, store, resource):

while True:

item = yield store.get()

with resource.request() as req:

yield req

yield env.timeout(PROCESS_TIME)

def set_resource(env, resource, start_time, end_time):

"""占用资源,模拟资源减少的情况,

end_time 会出现 np.inf 无穷大,

simpy 只会用作为排序,可以放在timeout事件里。

"""

duration = end_time - start_time

yield env.timeout(start_time)

with resource.request(priority=-1) as req:

yield req

yield env.timeout(duration)

env = simpy.Environment()

store = simpy.Store(env)

res = simpy.PriorityResource(env, 10)

res_time_table = [(10, 20, 5), (20, 30, 6)]

env.process(put_item(env, store))

env.process(process(env, store, res))

for start, end, target_num in res_time_table:

place_holder = 10 - target_num

for _ in range(place_holder):

env.process(set_resource(env, res, start, end))

env.run()

python 仿真_Python SimPy 仿真系列 (2)相关推荐

  1. python的仿真效果好吗_Python SimPy 仿真系列 (1)

    本系列文章旨在介绍 SimPy 在工业仿真中的应用. 在物流行业/工厂制造业/餐饮服务业存在大量急需优化的场景, 例如:如何最优化快递分拣人员的排班表以满足双十一突发的快递件量 如何估算餐厅在用餐高峰 ...

  2. python 仿真模拟_Python SimPy 仿真系列 (1)

    本系列文章旨在介绍 SimPy 在工业仿真中的应用. 在物流行业/工厂制造业/餐饮服务业存在大量急需优化的场景, 例如: 如何最优化快递分拣人员的排班表以满足双十一突发的快递件量 如何估算餐厅在用餐高 ...

  3. python 图表_Python入门学习系列——使用Python调用Web API实现图表统计

    使用Python调用Web API实现图表统计 Web API:Web应用编程接口,用于URL请求特定信息的程序交互,请求的数据大多以非常易于处理的格式返回,比如JSON或CSV等. 本文将使用Pyt ...

  4. python四分位数_Python解释数学系列——分位数Quantile

    1. 分位数计算案例与Python代码 案例1 Ex1: Given a data = [6, 47, 49, 15, 42, 41, 7, 39, 43, 40, 36],求Q1, Q2, Q3, ...

  5. python剪刀石头布_Python Tkinter教程系列01:剪刀石头布游戏

    编写剪刀石头布游戏 让我们使用Python 3和Tkinter开发相同的游戏.我们可以将游戏命名为Rock-Paper-Scissors-Lizard-Spock. 规则和玩法Rock crushes ...

  6. python转置_python数据分析类库系列Numpy之 数组转置和轴对换

    转置是重塑的一种特殊形式,它返回的是源数据的视图(不会进行任何复制操作).数组不仅有transpose方法,还有一个特殊的T属性 arr = np.arange(15).reshape((3, 5)) ...

  7. “离散元数值模拟仿真技术与应用”系列专题培训的通知

    各有关单位: 随着我国经济的发展,岩土工程涉及的要求从材料.理论到施工工艺都提出了全方位的系统升级.在岩土工程分析设计中,3DEC和PFC软件快速建模也一直是岩土工作者所关注的问题.3DEC是非连续岩 ...

  8. python timestamp转string_Python仿真区块链【含源码】

    在区块链或数字货币领域,Python并不是主流的开发语言.但是如果 你的目的是研究区块链技术的原理,或者需要在自己的笔记本上仿真一个 区块链网络并进行一些研究性的实验,比如完成自己的毕业设计项目 或科 ...

  9. Python批量运行Gprmax仿真并快速提取雷达波走时和振幅

    Python批量运行Gprmax仿真并快速提取雷达波走时和振幅 使用gprmax仿真模拟时,通常在cmd窗口写命令,运行结果保存的文件夹不能任意选择,这样很不方便.尤其是在做钻孔电磁波仿真时,需要大量 ...

最新文章

  1. 从LSTM到GRU基于门控的循环神经网络总结
  2. mac下Clion与QT引入FFmpeg库
  3. dns-prefetch—DNS预解析技术
  4. wordpress插件-WP Rocket 3.9.3缓存加速插件免授权版
  5. python安装轮子_python
  6. 二叉树2 - 数据结构和算法44
  7. 单选按钮必填会有红色选中提示吗_视频切割怎么弄?视频剪辑软件可以切割视频吗?...
  8. JS实现静默发送邮件功能(选择填报提交后发送、数据查询后发送参考前者)
  9. overleaf换模板
  10. vivox50支持鸿蒙,vivo X50系列极致轻薄的机身下,还有哪些功能和亮点?
  11. 联想 Newifi mini Y1 Padavan固件设置5Ghz桥接
  12. [技巧]深入了解强大的 ES6 「 ... 」 运算符
  13. 网站站长统计代码说明与配置
  14. c++图像处理之对比度拉伸变换
  15. Linux系统查看服务器版本方法
  16. 2019年1月2日申请美国F1学生签证记录
  17. 问答学习系统 - 针式PKM V8.20新增功能
  18. ANSYS电磁仿真软件
  19. MYSQL主流版本简述
  20. 覃氏的由来(据历史学家考证)

热门文章

  1. #再一次用construct2做游戏
  2. go本地调用image-syncer
  3. 【代码】python paramiko模块代码示例:远程执行命令及上传和下载
  4. gradle镜像配置:使用阿里云仓库服务的代理仓库地址代替jcenter()、mavenCentral()及google()
  5. 阿里DataV可视化大屏介绍
  6. K8S 基本架构与常用术语
  7. Python Django 参数解包及代码示例
  8. Python3身份运算符(比较对象是否相同)
  9. 设置nginx开机启动
  10. solr中的ik分词器的原理是什么