Vary Arrivals by Time
Change the arrival rate and the staffing at set times, such as a rush at lunch or a second packer for an afternoon, and know exactly which events a change reaches.
Before You Start
- Changing Demand asks what a rush does to waits.
- Live Parameters explains registry paths and scenario steps.
Steps
- Find the registry path of each parameter that changes:
Shop.arrival.orders.ratefor an exponential arrival,Shop.resources.packers.current_capfor the number of packers. - Write one step for each change, with the simulation time it applies at,
at, in seconds or as a duration such as20 min. - Return each parameter to its usual value with a later step. A schedule does not repeat on its own.
The blueprint of the same name in Changing Demand runs for an hour and packs in a constant 1.5 seconds. Its rush lasts from 20 to 40 minutes, with an order every 1.11 seconds on average (rate: 0.9). The example below, examples/yaml/changing_demand.yaml, runs for 5 minutes, and packing takes 1 to 3 seconds, most often 2 (a triangular distribution). From 120 to 180 seconds orders arrive twice as fast, an order every 1.25 seconds on average (rate: 0.8), and a second packer works for that time:
add_step(at, path=..., value=...) adds one step. A step can also carry a record, a ground-truth label, or an interrupt.
run_scenario(env, SCHEDULE, until=300) is the SimPy process that applies the steps. Start it with env.process, beside the arrivals.
The steps change the registry, so everything that reads the path follows: the next arrival gap is drawn from the new rate, and the packers grant or owe units as on Resources.
Check the Result
Run the changing_demand example below and read its statistics, published every 60 seconds. Shop.stats.resources.packers.capacity is 1 at 120 seconds, 2 at 180 seconds, and 1 again at 240 seconds, so the second packer worked from 120 to 180 seconds. The reading at 120 seconds still shows 1 because the packers apply a capacity change in a process of their own, which runs after the statistics reading due at that time.
Boundaries
A step that applies at the same time as another event has to come first or second, and a run that ends at a step's time has to apply it or not. Both are settled the way SimPy settles its own end time:
- A step at time t applies before every other event at t. It is scheduled as an urgent event, as SimPy's
run(until=t)is. So an arrival at t draws its next gap from the new value. - Steps at the same time apply in the order written.
- A step at or after
untilnever applies, as an event due at exactlyuntildoes not run.
This shop has an order every 10 seconds, and a step at 30 seconds that makes the gap 5 seconds. The blueprint publishes an event as each order arrives, and the scripts collect the arrival times:
desflow run time_varying_arrivals.yaml and arrivals(50) give arrivals at 10, 20, 30, 35, 40 and 45 seconds, and the gap in force at the end is 5 seconds: the order that arrived at 30 drew its gap after the step. With --until 30, or arrivals(30), the arrivals are at 10 and 20 seconds, and the gap in force at the end is 10 seconds. The step at 30 is at until, so it never applies. The arrival due at 30 never happens either.
Example
The changing_demand example is the model above: one packer, an order every 2.5 seconds on average (rate: 0.4), and a rush with a second packer from 120 to 180 seconds. It needs no Docker service and ends on its own after 300 simulation seconds.
Quick Start
desflow examples get downloads the example at the release you install, into a folder of its own. Pick uv or pip:
Quick Start
desflow examples get downloads the example at the release you install, into a folder of its own. Pick uv or pip:
Quick Start
desflow examples get downloads the example at the release you install, into a folder of its own. Pick uv or pip: