Created
November 1, 2017 00:13
-
-
Save christlc/02a1878b8350c3785071058f7bd4b20f to your computer and use it in GitHub Desktop.
A task simulation tool to illustrate load factor vs wait time in Simpy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Adapted from https://simpy.readthedocs.io/en/latest/examples/bank_renege.html | |
Bank renege example | |
Covers: | |
- Resources: Resource | |
- Condition events | |
Scenario: | |
A counter with a random service time and customers who renege. Based on the | |
program bank08.py from TheBank tutorial of SimPy 2. (KGM) | |
""" | |
import random | |
import simpy | |
import simpy.rt | |
def start_simulation(RANDOM_SEED = 1098, | |
NEW_CUSTOMERS = 250, # Total number of customers | |
INTERVAL_CUSTOMERS = 1.0, # Generate new customers roughly every x seconds | |
PATIENCE = 100000000, # customer patience | |
TIME_IN_JOB = 1.0, | |
RANDOM_TYPE = True, | |
REALTIME = 0.5, | |
VERBOSE = True): | |
# Setup and start the simulation | |
def source(env, number, interval, counter, verbose): | |
"""Source generates customers randomly""" | |
env.work_time = [] | |
env.wait_time = [] | |
for i in range(number): | |
c = customer(env, 'Task%02d' % i, counter, time_in_bank=TIME_IN_JOB, verbose=verbose) | |
env.process(c) | |
if(RANDOM_TYPE): | |
t = random.expovariate(1.0 / interval) | |
else: | |
t = interval | |
yield env.timeout(t) | |
def customer(env, name, counter, time_in_bank, verbose=True): | |
"""Customer arrives, is served and leaves.""" | |
arrive = env.now | |
if(verbose): | |
print('%7.4f %s: Here I am' % (arrive, name)) | |
with counter.request() as req: | |
patience = PATIENCE | |
# Wait for the counter or abort at the end of our tether | |
results = yield req | env.timeout(patience) | |
wait = env.now - arrive | |
env.wait_time.append(wait) | |
if req in results: | |
# We got to the counter | |
if(verbose): | |
print('%7.4f %s: Waited %6.3f' % (env.now, name, wait)) | |
if(RANDOM_TYPE): | |
tib = random.expovariate(1.0 / time_in_bank) | |
else: | |
tib = time_in_bank | |
env.work_time.append(tib) | |
yield env.timeout(tib) | |
if(verbose): | |
print('%7.4f %s: Finished' % (env.now, name)) | |
else: | |
# We reneged | |
if(verbose): | |
print('%7.4f %s: RENEGED after %6.3f' % (env.now, name, wait)) | |
print('Task Simulation') | |
random.seed(RANDOM_SEED) | |
if(REALTIME is not None): | |
env = simpy.rt.RealtimeEnvironment(factor=REALTIME) | |
else: | |
env = simpy.Environment() | |
# Start processes and run | |
counter = simpy.Resource(env, capacity=1) | |
proc = env.process(source(env, NEW_CUSTOMERS, INTERVAL_CUSTOMERS, counter, VERBOSE)) | |
env.run(until=proc) | |
print("Simulated number of tasks: %d" %NEW_CUSTOMERS) | |
print("Average task length: %7.2f" % (sum(env.work_time)/NEW_CUSTOMERS)) | |
print("Average wait time: %7.2f" % (sum(env.wait_time)/NEW_CUSTOMERS)) | |
print("Total time taken %7.2f" % float(env.now)) | |
print("Period Busy %2.2f %%" % (float(sum(env.work_time))/float(env.now)*100)) | |
## | |
# CASE 1 | |
start_simulation(NEW_CUSTOMERS = 100, # Total number of customers | |
INTERVAL_CUSTOMERS = 1.0, # Generate new customers roughly every x seconds | |
TIME_IN_JOB = 1.0, | |
RANDOM_TYPE = False, | |
VERBOSE = True | |
) | |
# CASE 2 | |
start_simulation(NEW_CUSTOMERS = 100, | |
RANDOM_TYPE=True) | |
# CASE 2b | |
# Wait time actually grows over time | |
start_simulation(NEW_CUSTOMERS = 250, RANDOM_TYPE=True, REALTIME=None) | |
start_simulation(NEW_CUSTOMERS=750, RANDOM_TYPE=True, VERBOSE=False, REALTIME=None) | |
start_simulation(NEW_CUSTOMERS=5000, RANDOM_TYPE=True, VERBOSE=False, REALTIME=None) | |
# Solution | |
# Tasks coming in slightly faster | |
start_simulation(RANDOM_TYPE=True, INTERVAL_CUSTOMERS=1.0, TIME_IN_JOB=0.8) | |
start_simulation(NEW_CUSTOMERS=100000, RANDOM_TYPE=True, INTERVAL_CUSTOMERS=1.0, TIME_IN_JOB=0.8, VERBOSE=False, REALTIME=None) | |
start_simulation(NEW_CUSTOMERS=100000, RANDOM_TYPE=True, INTERVAL_CUSTOMERS=1.0, TIME_IN_JOB=0.9, VERBOSE=False, REALTIME=None) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment