首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Simpy资源容量管理

Simpy资源容量管理
EN

Stack Overflow用户
提问于 2022-04-01 23:40:02
回答 1查看 287关注 0票数 0

我正在为一个非常长的、多重的可再入的制造过程开发一个离散的、甚至模拟器(零件按照一定的顺序通过多个工具,并且经常多次回到同一个工具上)。该程序的总体流程运行良好,并在各种构建计划场景下给出了预期的队列深度、拥塞点等。我尚未找到解决办法的挑战是,一个容量大于1的工具可以一次运行多个部件,但必须同时启动它们(例如,它们可能在一个房间或浴缸中运行,当一个部件正在运行以添加另一个部件时无法打开/访问)。

因此,我正在寻找一种使用工具(比如capacity=4 )来实现工具的方法,以便在运行开始时,如果它的队列中有4个或更多项,它将加载其中的4个项并运行它们,但是如果在时间为零时只有一个部分,那么在运行该部分时,其中一个部分运行和进入队列的任何内容都必须等待运行结束。

我的代码太长,太复杂,无法说明这个问题,但是这个问题被著名的simpy“加油站”示例(下面的代码)描述得很好。我试图摆脱的行为在这段代码中得到了表达。也就是说,加油站的容量= 2,一辆汽车出现并占据了其中一个车位,然后过了一段时间,另一辆车到达并占据了剩余的车位。这对燃气泵很好,但我试图阻止以后的用户一旦启动运行就无法访问。

我可以设想给工具提供一个属性,如self.status,并在工具使用时将状态设置为“繁忙”或其他类似的东西,或者可能以某种方式使用self.res.users,但我不知道是否有更简单的方式让工具以所需的方式运行。

谢谢!

代码语言:javascript
运行
复制
import itertools
import random

import simpy


RANDOM_SEED = 42
GAS_STATION_SIZE = 200     # liters
THRESHOLD = 10             # Threshold for calling the tank truck (in %)
FUEL_TANK_SIZE = 50        # liters
FUEL_TANK_LEVEL = [5, 25]  # Min/max levels of fuel tanks (in liters)
REFUELING_SPEED = 2        # liters / second
TANK_TRUCK_TIME = 300      # Seconds it takes the tank truck to arrive
T_INTER = [30, 300]        # Create a car every [min, max] seconds
SIM_TIME = 1000            # Simulation time in seconds


def car(name, env, gas_station, fuel_pump):
    """A car arrives at the gas station for refueling.

    It requests one of the gas station's fuel pumps and tries to get the
    desired amount of gas from it. If the stations reservoir is
    depleted, the car has to wait for the tank truck to arrive.

    """
    fuel_tank_level = random.randint(*FUEL_TANK_LEVEL)
    print('%s arriving at gas station at %.1f' % (name, env.now))
    with gas_station.request() as req:
        start = env.now
        # Request one of the gas pumps
        yield req

        # Get the required amount of fuel
        liters_required = FUEL_TANK_SIZE - fuel_tank_level
        yield fuel_pump.get(liters_required)

        # The "actual" refueling process takes some time
        yield env.timeout(liters_required / REFUELING_SPEED)

        print('%s finished refueling in %.1f seconds.' % (name,
                                                          env.now - start))


def gas_station_control(env, fuel_pump):
    """Periodically check the level of the *fuel_pump* and call the tank
    truck if the level falls below a threshold."""
    while True:
        if fuel_pump.level / fuel_pump.capacity * 100 < THRESHOLD:
            # We need to call the tank truck now!
            print('Calling tank truck at %d' % env.now)
            # Wait for the tank truck to arrive and refuel the station
            yield env.process(tank_truck(env, fuel_pump))

        yield env.timeout(10)  # Check every 10 seconds


def tank_truck(env, fuel_pump):
    """Arrives at the gas station after a certain delay and refuels it."""
    yield env.timeout(TANK_TRUCK_TIME)
    print('Tank truck arriving at time %d' % env.now)
    amount = fuel_pump.capacity - fuel_pump.level
    print('Tank truck refuelling %.1f liters.' % amount)
    yield fuel_pump.put(amount)


def car_generator(env, gas_station, fuel_pump):
    """Generate new cars that arrive at the gas station."""
    for i in itertools.count():
        yield env.timeout(random.randint(*T_INTER))
        env.process(car('Car %d' % i, env, gas_station, fuel_pump))


# Setup and start the simulation
print('Gas Station refuelling')
random.seed(RANDOM_SEED)

# Create environment and start processes
env = simpy.Environment()
gas_station = simpy.Resource(env, 2)
fuel_pump = simpy.Container(env, GAS_STATION_SIZE, init=GAS_STATION_SIZE)
env.process(gas_station_control(env, fuel_pump))
env.process(car_generator(env, gas_station, fuel_pump))

# Execute!
env.run(until=SIM_TIME)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-02 05:40:32

所以在我看来,每一辆车都有一个水泵,但你真正想要的是一辆泵一次能抓住两辆车。所以你需要一个进行分批处理的过程。这里有一个快速而肮脏的批处理程序。我对输入队列使用了一个存储,当每次我的产额get()得到第一个实体时,我会检查队列中是否有更多的实体可以处理,这样做的真正原因是当队列为空时,我的进程会等待。

代码语言:javascript
运行
复制
"""
    A simple example of a process that process entities in batches

    Programmer: Michael R. Gibbs
"""

import simpy
import random

def batch_process(env, ent_q, next_q, max_cap):
    """
        grabs up to max_cap of entites and processes them
    """

    while True:

        # use a yield to wait when queue is empty 
        ent_1 = yield ent_q.get()

        # grabs up to capacity -1 more
        p_batch = [ent_1] + ent_q.items[:(max_cap - 1)]
        ent_q.items = ent_q.items[(max_cap - 1):]

        print(f'{env.now:.2f} grabbed {len(p_batch)} entites leaving {len(ent_q.items)} left in queue')

        # do the processing
        yield env.timeout(10)

        # send entitles to next stop
        next_q.items = next_q.items + p_batch

def gen_ents(env, q):
    """
        Generate the arrival of entities

        arrival profile starts slow
        has a peek
        then nothing which drains the queue
        and puts the process in a wait mode
        another peek

    """
    for _ in range(10):
        yield env.timeout(random.uniform(1,6))
        q.put(object())
    for _ in range(15):
        yield env.timeout(random.uniform(1,3))
        q.put(object())
    yield env.timeout(50)
    for _ in range(15):
        yield env.timeout(random.uniform(1,3))
        q.put(object())
    for _ in range(10):
        yield env.timeout(random.uniform(1,7))
        q.put(object())


# boot up model
random.seed(100)
env = simpy.Environment()

process_q = simpy.Store(env)
exit_q = simpy.Store(env)

env.process(gen_ents(env, process_q))
env.process(batch_process(env, process_q, exit_q, 4))

env.run(1000)
print(f'Simulation has finish a time {env.now}')
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71713722

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档