简单的资源不可用

Simpy resource unavialbality

我试图在 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'我不明白为什么?

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

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

"""
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)