I'm currently trying to simulate a store in Discrete Event Simulation using Simply. Due to the fact that my python knowledge is limited I am stuck with a problem. The store repairs broken products for their customers, however, my simulation is not working as intended. I’ve tried to find a similar problem on stack overflow, but I could not find it, therefore I am asking. If a similar question has already been solved could you please provide the link?
I am simulating a shop where customers arrive with their broken product, a cashier helps them by swapping the broken product for a repaired product. The customer leaves with a repaired product and the broken product is later repaired in the store. After it is repaired it can be used to help another customer.
The problem I experience is in the bottleneck of my simulation, which is the repair of the product. When a repairman is requested, python immediately assumes the requested repairman is busy. However, in my simulation there are some conditions the must be fulfilled before the repairman can start with the repair. One of these conditions is that a repairman must be available to repair the product, however since python assumes the repairman is busy after the request the process cannot commence since the condition cannot be met. If I would not request a repairman before my while statement the queue would not be recorded correctly, therefore I opted to do it this way.
I have provided a slimmed down piece of my entire code in which the problem occurs. In the code provided the problem occurs when the third broken product should be repaired. This is because the simulation has 3 repairmen available. If I would have 8 repairmen available the problem would occur for the eighth broken product.
Are there ways to solve or circumvent my problem? Thank you in advance.
import simply
class Store(object):
def __init__(self, env, num_cashiers, num_repairman):
self.env = env
self.num_cashiers = num_cashiers
self.num_repairman = num_repairman
self.cashiers = simpy.Resource(env, capacity=num_cashiers)
self.repairman = simpy.Resource(env, capacity=num_repairman)
self.total_customers = 0
self.broken_product = 0
self.repaired_product = 25
self.resource_data = []
def customer_generator(self, env):
customer_buffer = 5
product_id = 1
customer_interarrival_time = 100
while True: #always generate customers during simulation
if len(self.cashiers.queue) >= customer_buffer: #if customer queue is full, customer is lost
self.lost_customers +=1
else: #If queue not full, start the process in the store
env.process(self.store_operations(env, product_id))
yield env.timeout(customer_interarrival_time) #wait for next customer
product_id+=1
self.total_customers +=1
def serve_customer(self, product_id):
yield self.env.timeout(90)
self.broken_product +=1
self.repaired_product -=1
def repair_product(self, product_id):
yield self.env.timeout(300)
self.broken_product -=1
self.repaired_product +=1
def store_operations(self, env, product_id):
'''This function is where the problem persists
While statement 1 exists the check if there are repaired products and a cashier available to help the customer
otherwise timeout until both are available
if statement 1 helps the customer by swapping a broken product for a repaired product
while statement 2 exists to check if there are broken product to be repaired and whether a repairman is available
otherwise timeout until both are available
if statement 2 is where the repairman repairs a broken product'''
# print(env.now, ', RP inv', self.repaired_product, ', BP inv', self.broken_product, ', busy cashiers', self.cashiers.count, ', cashier q', len(self.cashiers.queue))
request_cashier = self.cashiers.request()
yield request_cashier
# print(env.now, ', RP inv', self.repaired_product, ', BP inv', self.broken_product, ', busy cashiers', self.cashiers.count, ', cashier q', len(self.cashiers.queue))
while self.repaired_product==0 or self.cashiers.count==self.num_cashiers:
yield env.timeout(1)
if self.repaired_product>0 and self.cashiers.count<self.num_cashiers:
# print(env.now, ', RP inv', self.repaired_product, ', BP inv', self.broken_product, ', busy cashiers', self.cashiers.count, ', cashier q', len(self.cashiers.queue))
yield env.process(self.serve_customer(product_id))
self.cashiers.release(request_cashier)
# print(env.now, ', RP inv', self.repaired_product, ', BP inv', self.broken_product, ', busy cashiers', self.cashiers.count, ', cashier q', len(self.cashiers.queue))
print('product', product_id, 't before req', env.now, ', RP inv', self.repaired_product, ', BP inv', self.broken_product, ', busy repairmen', self.repairman.count, ', cashier q', len(self.repairman.queue))
request_repair = self.repairman.request()
yield request_repair
print('product', product_id,'t after req', env.now, ', RP inv', self.repaired_product, ', BP inv', self.broken_product, ', busy repairmen', self.repairman.count, ', cashier q', len(self.repairman.queue))
while self.broken_product==0 or self.repairman.count==self.num_repairman:
yield env.timeout(1)
print(env.now,'product', product_id, 'wait for repairman')
if self.broken_product>0 and self.repairman.count<self.num_repairman:
print('product', product_id,'t before repair proces', env.now, ', RP inv', self.repaired_product, ', BP inv', self.broken_product, ', busy repairmen', self.repairman.count, ', cashier q', len(self.repairman.queue))
yield env.process(self.repair_product(product_id))
self.repairman.release(request_repair)
print('product', product_id,'t after repair process',env.now, ', RP inv', self.repaired_product, ', BP inv', self.broken_product, ', busy repairmen', self.repairman.count, ', cashier q', len(self.repairman.queue))
self.resource_data.append({
'time' : env.now,
'broken product inv' : self.broken_product,
'repaired product inv': self.repaired_product,
'busy cashiers' : self.cashiers.count,
'cashier queue' : len(self.cashiers.queue),
'busy repairmen' : self.repairman.count,
'repairmen queue' : len(self.repairman.queue)})
return self.resource_data
env = simpy.Environment()
store1 = Store(env, 3, 3)
env.process(store1.customer_generator(env))
env.run(500)
print(store1.resource_data[0])
print(store1.resource_data[1])
print(store1.resource_data[2])
print(store1.resource_data[3])
print(store1.resource_data[4])
print(store1.resource_data[5])
print(store1.resource_data[6])