0
点赞
收藏
分享

微信扫一扫

Python-simpy的仿真模拟

诗与泡面 2022-03-12 阅读 80

Simpy包的简单使用

Simpy包

基本概念

Simpy-制造仿真:SimPy 是离散事件驱动的仿真库
仿真技术是再现系统动态行为、分析系统配置与参数是否合理、预测瓶颈工序、判断系统性能是否满足规定要求、为制造系统的设计和运行提供决策支持。所有活动部件,例如车辆、顾客,、即便是信息,都可以用 process (进程) 来模拟。这些 process 存放在 environment (环境) 。所有 process 之间,以及与environment 之间的互动,通过 event (事件) 来进行.
process <–>event<–>environment
process 表达为 generators (生成器), 构建event(事件)并通过 yield 语句抛出事件。
当一个进程抛出事件,进程会被暂停,直到事件被激活(triggered)。多个进程可以等待同一个事件。 SimPy 会按照这些进程抛出的事件激活的先后, 来恢复进程。其实中最重要的一类事件是 Timeout, 这类事件允许一段时间后再被激活, 用来表达一个进程休眠或者保持当前的状态持续指定的一段时间。这类事件通过 Environment.timeout来调用。

Environment

模拟环境管理模拟时间以及事件的调度和处理。它还提供了单步执行或执行模拟的方法。正常模拟使用Environment.
Environment常用的方法
simpy.Environment.process - 添加仿真进程
simpy.Environment.event - 创建事件
simpy.Environment.timeout - 提供延时(timeout)事件
simpy.Environment.until - 仿真结束的条件(时间或事件)
simpy.Environment.run - 仿真启动

例子1-汽车启停模拟

import simpy
def car(env):
    while True:
        print('Start parking at %d' % env.now)
        parking_duration=5
        yield env.timeout(parking_duration) # 进程延时 5s,停五秒
        print('Start driving at %d' % env.now)
        trip_duration = 2
        yield env.timeout(trip_duration)  # yield抛出事件,2s,开两秒
# 仿真启动
env = simpy.Environment()   # 实例化环境
env.process(car(env))   # 添加汽车进程
env.run(until=15)   # 设定仿真结束条件, 这里是 15s 后停止

例子2-汽车充电模拟

from random import seed, randint
seed(23)
import  simpy
class EV:
    def __init__(self,env):
        self.env=env
        #两个主进程
        self.drive_proc=env.process(self.drive(env))
        self.bat_ctrl_proc = env.process(self.bat_ctrl(env))
        # 需要抛出的事件
        self.bat_ctrl_reactivate = env.event()
        #需要抛出的事件
        self.bat_ctrl_sleep = env.event()
    def drive(self, env):
        """驾驶进程"""
        while True:
            # 驾驶 20-40 分钟
            print("开始驾驶 时间: ", env.now)
            yield env.timeout(randint(20, 40))
            print("停止驾驶 时间: ", env.now)

            # 停车 1-6 小时
            print("开始停车 时间: ", env.now)
            self.bat_ctrl_reactivate.succeed()  # 激活充电事件
            self.bat_ctrl_reactivate = env.event()
            yield env.timeout(randint(60, 360)) & self.bat_ctrl_sleep  # 停车时间和充电程序同时都满足
            print("结束停车 时间:", env.now)
    def bat_ctrl(self, env):
        """电池充电进程"""
        while True:
            print("充电程序休眠 时间:", env.now)
            yield self.bat_ctrl_reactivate  # 休眠直到充电事件被激活
            print("充电程序激活 时间:", env.now)
            yield env.timeout(randint(30, 90))
            print("充电程序结束 时间:", env.now)
            self.bat_ctrl_sleep.succeed() # 将充电事件 冷却,激活开车进程
            self.bat_ctrl_sleep = env.event()
def main():
    env=simpy.Environment()
    ev=EV(env)
    env.run(until=300)


if __name__=='__main__':
    main()

共享资源

共享资源是另一种建模流程交互的方式。它们形成了一个拥塞点,进程在此排队以便使用它们。
SimPy 定义了三类资源:
Resources :一次可以由有限数量的流程使用的资源(例如,具有有限数量燃料泵的加油站)

import simpy
def car(env, name, bcs, driving_time, charge_duration):
    yield env.timeout(driving_time)
    print('%s arriving at %d' % (name, env.now))
    with bcs.request() as req: #申请资源
         yield req #判断是否可以申请到资源
         #申请到资源就进行后续的操作
         print('%s starting to charge at %s' % (name, env.now))
         yield env.timeout(charge_duration)
         print('%s leaving the bcs at %s' % (name, env.now))
env =simpy.Environment()
bcs=simpy.Resource(env,capacity=2)#定义资源只有两份
for i in range(4):
    #添加进程,定义行驶时间(即定义到达充电桩时间
    env.process(car(env, 'Car %d' % i, bcs, i*2, 5))
env.run(until=25)

Containers :模拟同质、无差别散装的生产和消费的资源。它可能是连续的(如水)或离散的(如苹果)。可以用来模拟一种物品的消耗和补充,但是对于同一种事物Containers是一个标准(例如,同一款汽车的油箱大小,和一筐苹果的数量等)

class GasStation:
     def __init__(self, env):
         #初始化环境中的资源数
         self.fuel_dispensers = simpy.Resource(env, capacity=2)
         #初始化 Container容量和存量
         self.gas_tank = simpy.Container(env, init=100, capacity=1000)
         #在环境中添加进行油量监视的进程
         self.mon_proc = env.process(self.monitor_tank(env))
     def monitor_tank(self, env):
         """
         对油箱的存量进行监控,如果油箱的存量小于最低线,则开启加油线程
         """
         while True:
             if self.gas_tank.level < 100:
                 print(f'Calling tanker at {env.now}')
                 #开启加油线程
                 env.process(tanker(env, self))
             yield env.timeout(15)


def tanker(env, gas_station):
     yield env.timeout(10)  # 模拟加油的船到达加油地点
     print(f'Tanker arriving at {env.now}')
     amount = gas_station.gas_tank.capacity - gas_station.gas_tank.level
     yield gas_station.gas_tank.put(amount)#进行补充油量,作为事件抛出,一直到加油结束,加油线程完成
     
def car(name, env, gas_station):
     print(f'Car {name} arriving at {env.now}')
     with gas_station.fuel_dispensers.request() as req:
         #car 到达,请求加油站的加油坑位
         yield req
         print(f'Car {name} starts refueling at {env.now}')
         #进行加油,改变加油站油箱存量
         yield gas_station.gas_tank.get(40)
         #模拟给车加油
         yield env.timeout(5)
         #离开加油站
         print(f'Car {name} done refueling at {env.now}')


def car_generator(env, gas_station):
     for i in range(4):
         #模拟car进行加油的进程
         env.process(car(i, env, gas_station))
         yield env.timeout(5)

import  simpy
env = simpy.Environment()
gas_station = GasStation(env)
car_gen = env.process(car_generator(env, gas_station))
env.run(35)
举报

相关推荐

0 条评论