Skip to content

Instantly share code, notes, and snippets.

@mutru
Last active Dec 17, 2021
Embed
What would you like to do?
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
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