simulation.py
Inventory oscillation from delayed orders
A store targets a fixed inventory level. When stock falls below that it orders enough to fill the gap. Orders take a few days to arrive and the manager ignores what is already on the way, so shipments pile up and then run out, creating a bullwhip-like cycle.
from tys import probe, progress
def simulate(cfg: dict):
import simpy
env = simpy.Environment()
inventory = cfg["initial_inventory"]
target = cfg["target_inventory"]
daily_demand = cfg["daily_demand"]
lead_time = cfg["lead_time"]
review_period = cfg["review_period"]
sim_time = cfg["sim_time"]
pipeline = [] # list of (arrival_time, qty)
done = env.event()
def run():
nonlocal inventory, pipeline
for day in range(sim_time):
demand depletes stock
inventory = max(inventory - daily_demand, 0)
receive any orders that have arrived
arrivals = [qty for (t, qty) in pipeline if t == day]
for qty in arrivals:
inventory += qty
pipeline = [(t, q) for (t, q) in pipeline if t != day]
periodic review and naive reordering
if day % review_period == 0:
order_qty = max(target - inventory, 0)
if order_qty > 0:
pipeline.append((day + lead_time, order_qty))
probe("inventory", env.now, inventory)
probe("pipeline", env.now, sum(q for _, q in pipeline))
progress(int(100 * (day + 1) / sim_time))
yield env.timeout(1)
done.succeed({"final_inventory": inventory})
env.process(run())
env.run(until=done)
return done.value
def requirements():
return {
"builtin": ["micropip", "pyyaml"],
"external": ["simpy==4.1.1"],
}
Default.yaml
initial_inventory: 100
target_inventory: 100
daily_demand: 10
lead_time: 3
review_period: 1
sim_time: 60
Charts (Default)
Final Results (Default)
Metric | Value |
---|---|
final_inventory | 80.00 |