Last active
December 17, 2021 18:48
-
-
Save mutru/fd28e3c3425bc03ae31074f3e4d058c8 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
import itertools | |
import random | |
import simpy | |
def visitor(name, env, coffee_process, coffee_supply, mug_size, waittimes): | |
print("%s arriving at coffee station at %.1f" % (name, env.now)) | |
with coffee_process.request() as req: | |
start = env.now | |
# Request coffee_supply | |
yield req | |
# Get the required amount of coffee | |
yield coffee_supply.get(mug_size) | |
yield env.timeout(0) | |
waittime = env.now - start | |
waittimes.append(waittime) | |
print("%s got cofefe in %.1f seconds." % (name, waittime)) | |
def coffee_supply_control(env, coffee_supply, threshold, pot_size, brew_time): | |
"""Periodically check the level of the *coffee_supply* and brew when we have just little""" | |
while True: | |
if coffee_supply.level / coffee_supply.capacity <= threshold: | |
print("Starting to brew coffee at %d" % env.now) | |
yield env.process(brew(env, coffee_supply, pot_size, brew_time)) | |
yield env.timeout(1) # Check every 10 seconds | |
def brew(env, coffee_supply, pot_size, brew_time): | |
yield env.timeout(brew_time) | |
print("Brewed new pot at time %d" % env.now) | |
yield coffee_supply.put(pot_size) | |
def visitor_generator(env, coffee_process, coffee_supply, mug_size, rate, waittimes): | |
for i in itertools.count(): | |
yield env.timeout(random.expovariate(rate)) | |
env.process( | |
visitor( | |
"Drinker %d" % i, | |
env, | |
coffee_process, | |
coffee_supply, | |
mug_size, | |
waittimes, | |
) | |
) | |
def build_simulation(parameters, waittimes): | |
capacity = parameters["num_pots"] * parameters["pot_size"] | |
threshold = (capacity - parameters["pot_size"] + 0.1) / capacity | |
env = simpy.Environment() | |
coffee_process = simpy.Resource(env, 1) | |
coffee_supply = simpy.Container( | |
env, | |
capacity, | |
init=capacity, | |
) | |
env.process( | |
coffee_supply_control( | |
env, | |
coffee_supply, | |
threshold, | |
parameters["pot_size"], | |
parameters["brew_time"], | |
) | |
) | |
env.process( | |
visitor_generator( | |
env, | |
coffee_process, | |
coffee_supply, | |
parameters["mug_size"], | |
parameters["rate"], | |
waittimes, | |
) | |
) | |
return env |
This file contains hidden or 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
from coffeeprocess import build_simulation | |
import pandas as pd | |
import matplotlib.pyplot as plt | |
SIM_TIME = 60 * 60 * 8 * 30 | |
simulated_rates = [1, 3, 5, 10] | |
pot_counts = [1, 2, 3] | |
plt.rcParams["figure.figsize"] = (16, 16) | |
fig, axes = plt.subplots(len(simulated_rates), len(pot_counts)) | |
for row, rate in enumerate(simulated_rates): | |
for col, pot_count in enumerate(pot_counts): | |
waittimes = [] | |
params = { | |
'num_pots': pot_count, | |
'pot_size': 1, | |
'mug_size': 0.2, | |
'brew_time': 10 * 60, | |
'rate': (1 / rate) / 60 | |
} | |
simulation_env = build_simulation(params, waittimes) | |
simulation_env.run(until=SIM_TIME) | |
waittimes = [waittime / 60 for waittime in waittimes] | |
df = pd.Series(waittimes) | |
df.hist(ax=axes[row, col]) | |
p95 = round(df.quantile(0.95)) | |
axes[row, col].set_title(f"Rate: 1 per {rate} min - {pot_count} pots - p95: {p95}") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment