I have been struggling with coding this Discrete Event Simulation for a couple of days now. I got some answers of of this website, but still cannot run my simulation properly.
The problem that arises is: The first customer (thus every customer) does get through the queue of the first service, but can never actually enter the server for some reason. I hope some experts are able to pinpoint the problem quickly, as it is probably just a stupid mistake. The customer does go through the zero'th server and the queue for server 1.
I added #### just before and after the line where the mistake is.
Thanks in advance.
class Entity(object):
pass
def process0(env, entity, process_0_res, process_1_q):
print(f' {env.now} customer {entity.id} is in system')
with process_0_res.request() as res_req:
yield res_req
print(f'{env.now} customer {entity.id} is in queue 1')
yield process_1_q.put(entity)
def process1_broker(env, process_1_q, process_1_res):
while True:
# is resource available?
res_req = process_1_res.request()
yield res_req
# is customer available?
entity = yield process_1_q.get()
# save resource request to release later
entity.res_req = res_req
# start process
env.process(process1(env,entity,process_1_res, process_2_q))
def process1(env, entity, process_1_res, process_2_q):
with process_1_res.request() as res_req:
print(f'{env.now} customer {entity.id} should now request server 1')
#########
yield res_req
#########
print(f' {env.now} customer {entity.id} in process 1')
yield env.timeout(2)
yield process_2_q.put(entity)
def process2_broker(env, process_2_q, process_2_res):
while True:
res_req = process_2_res.request()
yield res_req
entity = yield process_2_q.get()
entity.res_req = res_req
env.process(process2(env,entity,process_2_res, process_3_q))
def process2(env, entity, process_2_res, process_3_q):
print(f' {env.now} customer {entity.id} in process 2')
with process_2_res.request() as res_req:
yield res_req
yield env.timeout(np.random.exponential(mu[1]))
yield process_3_q.put(entity)
def process3_broker(env, process_3_q, process_3_res):
while True:
res_req = process_3_res.request()
yield res_req
entity = yield process_3_q.get()
entity.res_req = res_req
env.process(process3(env,entity,process_3_res, process_4_q))
def process3(env, entity, process_3_res, process_4_q):
print(f' {env.now} customer {entity.id} in process 3')
with process_3_res.request() as res_req:
yield res_req
yield env.timeout(np.random.exponential(mu[2]))
yield process_4_q.put(entity)
def process4_broker(env, process_4_q, process_4_res):
while True:
res_req = process_4_res.request()
yield res_req
entity = yield process_3_q.get()
entity.res_req = res_req
env.process(process4(env,entity,process_4_res))
def process4(env, entity, process_4_res):
print(f' {env.now} customer {entity.id} in process 4')
with process_4_res.request() as res_req:
yield res_req
yield env.timeout(np.random.exponential(mu[3]))
yield process_4_res.release(entity.res_req)
print(f' {env.now} customer {entity.id} leaves system')
def gen_entities(env, process_0_res, process_1_q):
next_id = 1
while True:
yield env.timeout(np.random.exponential(labda))
entity = Entity()
entity.id = next_id
next_id += 1
env.process(process0(env, entity, process_0_res, process_1_q))
env = simpy.Environment()
process_0_res = simpy.Resource(env, capacity = 1)
process_1_res = simpy.Resource(env, capacity = 1)
process_2_res = simpy.Resource(env, capacity = 1)
process_3_res = simpy.Resource(env, capacity = 1)
process_4_res = simpy.Resource(env, capacity = 1)
process_1_q = simpy.Store(env, capacity = 5)
process_2_q = simpy.Store(env, capacity = 4)
process_3_q = simpy.Store(env, capacity = 3)
process_4_q = simpy.Store(env, capacity = 2)
env.process(gen_entities(env, process_0_res, process_1_q))
env.process(process1_broker(env, process_1_q, process_1_res))
env.process(process2_broker(env, process_2_q, process_2_res))
env.process(process3_broker(env, process_3_q, process_3_res))
env.process(process4_broker(env, process_4_q, process_4_res))
env.run(10)
In your code you are seizing resources twice, once in the broker, and then again in the process. so if you only have one resource, the second seize will never happen. also, you are only releasing one of the two resources, so you will run out of resources at some point.
Since the broker already seizes a resource and saves it in the entity, the process does not need to do a second seize. However, the process will still need to release the resource that was seized in the broker.
I think I fixed your code
import simpy
import random
import numpy as np
class Entity(object):
pass
def process0(env, entity, process_0_res, process_1_q):
print(f' {env.now} customer {entity.id} is in system')
with process_0_res.request() as res_req:
yield res_req
yield process_1_q.put(entity)
print(f'{env.now} customer {entity.id} is in queue 1')
def process1_broker(env, process_1_q, process_1_res):
while True:
# is resource available?
res_req = process_1_res.request()
yield res_req
# is customer available?
entity = yield process_1_q.get()
# save resource request to release later
entity.res_req = res_req
# start process
env.process(process1(env,entity,process_1_res, process_2_q))
def process1(env, entity, process_1_res, process_2_q):
# the resouce for process 1 has already been seized by the broker
print(f' {env.now} customer {entity.id} in process 1')
with entity.res_req:
#print(f'{env.now} customer {entity.id} should now request server 1')
#########
#yield res_req
#########
#print(f' {env.now} customer {entity.id} in process 1')
yield env.timeout(2)
yield process_2_q.put(entity)
def process2_broker(env, process_2_q, process_2_res):
while True:
res_req = process_2_res.request()
yield res_req
entity = yield process_2_q.get()
entity.res_req = res_req
env.process(process2(env,entity,process_2_res, process_3_q))
def process2(env, entity, process_2_res, process_3_q):
print(f' {env.now} customer {entity.id} in process 2')
with entity.res_req:
#yield res_req
yield env.timeout(np.random.exponential(2))
yield process_3_q.put(entity)
def process3_broker(env, process_3_q, process_3_res):
while True:
res_req = process_3_res.request()
yield res_req
entity = yield process_3_q.get()
entity.res_req = res_req
env.process(process3(env,entity,process_3_res, process_4_q))
def process3(env, entity, process_3_res, process_4_q):
print(f' {env.now} customer {entity.id} in process 3')
with entity.res_req:
#yield res_req
yield env.timeout(np.random.exponential(2))
yield process_4_q.put(entity)
def process4_broker(env, process_4_q, process_4_res):
while True:
res_req = process_4_res.request()
yield res_req
entity = yield process_4_q.get()
entity.res_req = res_req
env.process(process4(env,entity,process_4_res))
def process4(env, entity, process_4_res):
print(f' {env.now} customer {entity.id} in process 4')
with entity.res_req:
#yield res_req
yield env.timeout(np.random.exponential(2))
#yield process_4_res.release(entity.res_req)
print(f' {env.now} customer {entity.id} leaves system')
def gen_entities(env, process_0_res, process_1_q):
next_id = 1
while True:
yield env.timeout(np.random.exponential(2))
entity = Entity()
entity.id = next_id
next_id += 1
env.process(process0(env, entity, process_0_res, process_1_q))
env = simpy.Environment()
process_0_res = simpy.Resource(env, capacity = 1)
process_1_res = simpy.Resource(env, capacity = 1)
process_2_res = simpy.Resource(env, capacity = 1)
process_3_res = simpy.Resource(env, capacity = 1)
process_4_res = simpy.Resource(env, capacity = 1)
process_1_q = simpy.Store(env, capacity = 5)
process_2_q = simpy.Store(env, capacity = 4)
process_3_q = simpy.Store(env, capacity = 3)
process_4_q = simpy.Store(env, capacity = 2)
env.process(gen_entities(env, process_0_res, process_1_q))
env.process(process1_broker(env, process_1_q, process_1_res))
env.process(process2_broker(env, process_2_q, process_2_res))
env.process(process3_broker(env, process_3_q, process_3_res))
env.process(process4_broker(env, process_4_q, process_4_res))
env.run(100)