首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在simpy中更改模拟过程中的资源数

在simpy中更改模拟过程中的资源数
EN

Stack Overflow用户
提问于 2022-05-30 20:06:09
回答 1查看 161关注 0票数 2

我目前正在研究一种模型,该模型模拟了在simpy中整个操作一天的交付过程。运送是由骑手进行的,他们一次只交付一个包裹。包裹需要在特定的时间窗口内交付。此外,该系统整天都在处理不断波动的需求。因此,我想调整现行制度的雇员人数,以配合每小时不断波动的需求。我把骑手建模成一种有一定能力的资源。在模拟运行过程中是否有可能调整资源的容量,或者是否有其他方法可以用我的系统对骑手进行建模?

我已经在simpy文档、示例或其他帖子中寻找了可能的解决方案。然而,我还没有成功。因此,对于任何建议或可能的解决方案,我将非常感激!提前谢谢你。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-05-31 01:45:02

使用存储而不是资源。资源有固定数量的资源。商店的工作方式有点像带有可选最大容量的列表的队列。若要减少存储中的数量,只需停止将对象放回存储区。

举个例子,我用一个类包装了一个商店来管理骑手的数量。

代码语言:javascript
复制
"""
    Simple demo of a pool of riders delivering packages where the 
    number of riders can change over time

    Idel riders are keep in a store that is wrapped in a class
    to manage the number of riders

    Programmer Michael R. Gibbs
"""

import simpy
import random

class Rider():
    """
        quick class to track the riders that deliver packanges
    """

    # tranks the next id to be assiend to a rider
    next_id = 1

    def __init__(self):

        self.id = Rider.next_id
        Rider.next_id += 1

class Pack():
    """
        quick class to track the packanges
    """

    # tranks the next id to be assiend to a pack
    next_id = 1

    def __init__(self):

        self.id = Pack.next_id
        Pack.next_id += 1

class RiderPool():
    """
        Pool of riders where the number of riders can be changed
    """

    def __init__(self, env, start_riders=10):

        self.env = env

        # tracks the number of ridres we need
        self.target_cnt = start_riders

        # tracks the number of riders we have
        self.curr_cnt = start_riders

        # the store idel riders
        self.riders = simpy.Store(env)

        # stores do not start with objects like resource pools do.
        # need to add riders yourself as part of set up
        self.riders.items = [Rider() for _ in range(start_riders)]
 

    def add_rider(self):
        """
            Add a rider to the pool
        """

        self.target_cnt += 1


        if self.curr_cnt < self.target_cnt:
            # need to add a rider to the pool to get to the target
            rider = Rider()
            self.riders.put(rider)
            self.curr_cnt += 1
            print(f'{env.now:0.2f} rider {rider.id} added')

        else:
            # already have enough riders,
            # must have tried to reduce the rider pool while all riders were busy
            # In effect we are cancelling a previous remove rider call
            print(f'{env.now:0.2f} keeping rider scheduled to be removed instead of adding')

    def remove_rider(self):
        """
            Remove a ridder from the pool

            If all the riders are busy, the actual removal of a rider
            will happen when a that rider finishes it current task and is
            tried to be put/returned back into the pool
        """

        self.target_cnt -= 1

        if self.curr_cnt > self.target_cnt:
            if len(self.riders.items) > 0:
                # we have a idel rider that we can remove now

                rider = yield self.riders.get()
                self.curr_cnt -= 1
                print(f'{env.now:0.2f} rider {rider.id} removed from store')

            else:
                # wait for a rider th be put back to the pool
                pass
        

    def get(self):
        """
            Get a rider from the pool

            returns a get request that can be yield to, not a rider
        """

        rider_req = self.riders.get()

        return rider_req

    def put(self, rider):
        """
            put a rider pack into the pool
        """

        if self.curr_cnt <= self.target_cnt:
            # still need the rider
            self.riders.put(rider)
        else:
            # have tool many riders, do not add back to pool
            self.curr_cnt -= 1
            print(f'{env.now:0.2f} rider {rider.id} removed on return to pool')

def gen_packs(env, riders):
    """
        generates the arrival of packages to be delivered by riders
    """

    while True:

        yield env.timeout(random.randint(1,4))
        pack = Pack()

        env.process(ship_pack(env, pack, riders))

def ship_pack(env, pack, riders):
    """
        The process of a rider delivering a packages
    """

    print(f'{env.now:0.2f} pack {pack.id} getting rider')

    rider = yield riders.get()

    print(f'{env.now:0.2f} pack {pack.id} has rider {rider.id}')

    # trip time
    yield env.timeout(random.randint(5,22))

    riders.put(rider)

    print(f'{env.now:0.2f} pack {pack.id} delivered')

def rider_sched(env, riders):
    """
        Changes the number of riders in rider pool over time
    """


    yield env.timeout(30)
    # time to remove a few riders

    print(f'{env.now:0.2f} -- reducing riders')
    print(f'{env.now:0.2f} -- request queue len {len(riders.riders.get_queue)}')
    print(f'{env.now:0.2f} -- rider store len {len(riders.riders.items)}')

    for _ in range(5):
        env.process(riders.remove_rider())

    yield env.timeout(60)
    # time to add back some riders

    print(f'{env.now:0.2f} -- adding riders ')
    for _ in range(2):
        riders.add_rider()


# run the model
env = simpy.Environment()
riders = RiderPool(env, 10)

env.process(gen_packs(env, riders))
env.process(rider_sched(env, riders))

env.run(100)

print(f'{env.now:0.2f} -- end rider count {riders.target_cnt}')
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72439540

复制
相关文章

相似问题

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