【问题标题】:Simpy resource unavialbalitySimpy 资源不可用
【发布时间】:2021-11-18 07:03:11
【问题描述】:

我试图在 simpy 中使资源在一段时间内不可用。问题在于超时,我发现资源仍然处于活动状态并在它应该不可用的时间内提供服务。如果您遇到这样的问题,任何人都可以帮我解决这个问题。非常感谢!

import numpy as np
import simpy

def interarrival():
    return(np.random.exponential(10))

def servicetime():
    return(np.random.exponential(20))


def servicing(env, servers_1):
    i = 0
    while(True):
        i = i+1
        yield env.timeout(interarrival())
        print("Customer "+str(i)+ " arrived in the process at "+str(env.now))
        state = 0
        env.process(items(env, i, servers_array, state))

def items(env, customer_id, servers_array, state):
    with servers_array[state].request() as request:
        yield request
        t_arrival = env.now
        print("Customer "+str(customer_id)+ " arrived in "+str(state)+ "  at "+str(t_arrival))
        yield env.timeout(servicetime())
        t_depart = env.now
        print("Customer "+str(customer_id)+ " departed from "+str(state)+ "  at "+str(t_depart))
        if (state == 1):
            print("Customer exists")
        else:
            state = 1
            env.process(items(env, customer_id, servers_array, state))

def delay(env, servers_array):
    while(True):
        if (env.now%1440 >= 540 and env.now <= 1080):
            yield(1080 - env.now%1440)
        else:
            print(str(env.now), "resources will be blocked")
            resource_unavailability_dict = dict()
            resource_unavailability_dict[0] = []
            resource_unavailability_dict[1] = []
            for nodes in resource_unavailability_dict:
                for _ in range(servers_array[nodes].capacity):
                    resource_unavailability_dict[nodes].append(servers_array[nodes].request())
            print(resource_unavailability_dict)
            for nodes in resource_unavailability_dict:
                yield env.all_of(resource_unavailability_dict[nodes])
            if (env.now < 540):
                yield env.timeout(540)
            else:
                yield env.timeout((int(env.now/1440)+1)*1440+540 - env.now)
            for nodes in resource_unavailability_dict:
                for request in resource_unavailability_dict[nodes]:
                    servers_array[nodes].release(request)
            print(str(env.now), "resources are released")
            

env = simpy.Environment()
servers_array = []
servers_array.append(simpy.Resource(env, capacity = 5))
servers_array.append(simpy.Resource(env, capacity = 7))
env.process(servicing(env, servers_array))
env.process(delay(env,servers_array))
env.run(until=2880)

上面给出了代码。实际上,我有两个节点 0 和 1,其中服务器容量分别为 5 和 7。服务器在每天上午 9 点(从午夜起 540 分钟)和下午 6 点之后不可用。我正在尝试使用超时创建不可用但不工作。你能建议我如何修改代码来合并它吗?

我收到错误AttributeError: 'int' object has no attribute 'callbacks'我不知道为什么?

【问题讨论】:

  • 您使用的是什么类型的资源。当正在使用的资源不可用时,应该如何处理它们?
  • 我更新了另一个帖子

标签: resources simpy


【解决方案1】:

所以简单资源的问题是容量是只读属性。为了解决这个问题,您需要一些东西来抓住并保持资源离线。所以本质上,我有两种类型的用户,一种是做“真正的工作”,另一种是控制容量。我正在使用一个简单的资源,这意味着计划时间的队列将在容量更改发生之前得到处理。使用优先资源意味着资源的当前用户可以在容量变化发生之前完成他们的进程,或者您可以使用抢占式资源在预定时间用资源中断用户。这是我的代码

"""
one way to change a resouce capacity on a schedule
note the the capacity of a resource is a read only atribute

Programmer: Michael R. Gibbs
"""

import simpy
import random

def schedRes(env, res):
    """
    Performs maintenance at time 100 and 200

    waits till all the resources have been seized 
    and then spend 25 time units doing maintenace 
    and then release

    since I am using a simple resource, maintenance
    will wait of all request that are already in 
    the queue when maintenace starts to finish

    you can change this behavior with a priority resource 
    or pre-emptive resource
    """

    # wait till first scheduled maintenance
    yield env.timeout(100)

    # build a list of requests for each resource
    # then wait till all requests are filled
    res_maint_list = []
    print(env.now, "Starting maintenance")
    for _ in range(res.capacity):
        res_maint_list.append(res.request())

    yield env.all_of(res_maint_list)
    print(env.now, "All resources seized for maintenance")

    # do maintenance
    yield env.timeout(25)
    print(env.now, "Maintenance fisish")

    # release all the resources
    for req in res_maint_list:
        res.release(req)

    print(env.now,"All resources released from maint")

    # wait till next scheduled maintenance
    dur_to_next_maint = 200 -env.now

    if dur_to_next_maint > 0:
        yield env.timeout(dur_to_next_maint)

    # do it all again
    res_maint_list = []
    print(env.now, "Starting maintenance")
    for _ in range(res.capacity):
        res_maint_list.append(res.request())

    yield env.all_of(res_maint_list)
    print(env.now, "All resources seized for maintenance")

    yield env.timeout(25)
    print(env.now, "Maintenance fisish")

    for req in res_maint_list:
        res.release(req)

    print(env.now,"All resources released from maint")


def use(env, res, dur):
    """
    Simple process of a user seizing a resource 
    and keeping it for a little while
    """
    with res.request() as req:
        print(env.now, f"User is in queue of size {len(res.queue)}")
        yield req
        print(env.now, "User has seized a resource")
        yield env.timeout(dur)
    print(env.now, "User has released a resource")

def genUsers(env,res):
    """
    generate users to seize resources
    """
    while True:
        yield env.timeout(10)
        env.process(use(env,res,21))
    
# set up 
env = simpy.Environment()
res = simpy.Resource(env,capacity=2) # may want to use a priority or preemtive resource
env.process(genUsers(env,res))
env.process(schedRes(env, res))

# start
env.run(300)

【讨论】:

  • 非常感谢迈克尔。这是黄金。让我自己以及在我的上下文中尝试一下。同时,您能否以代码块的形式给我一个优先级或抢占式资源的示例。
  • replace: res = simpy.Resource(env,capacity=2) with: res = simpy.PriorityResource(env, capacity=2) in the user procedure replace with res.request() as req:使用 with resource.request(priority=2) as req: 并在 schedRes 中将 res_maint_list.append(res.request()) 替换为 res_maint_list.append(res.request(priority=1))
  • 如果你喜欢这个答案,你可以选择它为正确的吗?
  • 嗨迈克尔,当我根据您的建议运行问题正文中给出的修改后的代码时,我收到错误 AttributeError: 'int' object has no attribute 'callbacks'。可以请你看一次吗?
【解决方案2】:

一种方法是使用抢占式资源。到了资源不可用的时候,发出一堆优先级最高的请求来抢占空闲资源,抢占当前正在使用的资源。然后,这些请求将在需要再次使资源可用时释放资源。请注意,一旦资源再次可用,您将需要添加一些关于抢占进程如何恢复的逻辑。如果你不需要抢占进程,你可以只使用优先资源而不是抢占资源

【讨论】:

  • 嗨迈克尔,我已经更新了这个问题。你能看一下吗。任何帮助将不胜感激。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-03
  • 2014-09-22
  • 1970-01-01
  • 2014-07-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多