โ QueueSim home ยท All models
A continuous-review inventory model simulating an (s, S) reorder policy.
A single-item inventory is managed with a continuous-review policy. Demand arrives exponentially, with each demand pulling a random quantity of units. The "inventory position" is tracked as the sum of on-hand and on-order inventory minus backorders. Whenever the position drops below a reorder point s, an order is placed to bring the position back up to a target level S. Replenishment arrives after a random lead time.
The goal is to balance the cost of holding inventory against the cost of customer backorders.
This is based on the continuous-review formulation in Law-SMA and Example 9 of the Schriber-GPSS/H textbook.
The model is centered around a Shop state and utilizes a "monitor" pattern:
Demand_Gen puck (lines 64-93): Drives stochastic customer demand and handles the immediate fulfillment or backordering of units.Reorder_Monitor puck (lines 101-144): An active object that watches the inventory position. It uses sim.wait_until to suspend itself until the position drops below s. When triggered, it calculates the required order size and spawns a replenishment process.Replenishment puck (lines 148-168): Represents the lead-time delay. Upon completion, it adds units to the on-hand stock and fulfills outstanding backorders.sim.Notify_Var (line 33): The position of the shop is wrapped in a notify variable. This allows the monitor puck to sleep efficiently rather than polling the state.The use of sim.Notify_Var and sim.wait_until (lines 112-116) is the architectural highlight. In traditional GPSS, this was achieved with SAVEVALUE and TEST. In the puck idiom, the monitor is an autonomous agent that only wakes up when the specific state it cares about changes. This decouples the demand process from the ordering process.
The model uses a custom flush_stats procedure (lines 48-58) to perform continuous integration of the on-hand and backorder levels. This provides an exact time-weighted average without needing to sample the system at arbitrary intervals.
periodic_inventory) implements a check every \(R\) days. The continuous review here is more complex to implement because the trigger is state-dependent, not time-dependent.sim.Notify_Var and sim.wait_until to implement event-driven triggers based on scalar values../order_point_inventory [options]
Add --json to emit the uniform envelope (metadata, execution_stats,
metrics, details) instead of the default text output.
| Flag | Type | Default | Description |
|---|---|---|---|
--days |
float | 365 |
Simulation horizon in days. |
--warmup |
float | 30 |
Warmup cutoff in days; stats before this are ignored. |
--s |
int | 50 |
Reorder point (s). |
--S |
int | 150 |
Order-up-to level (S). |
--seed |
int | 42 |
RNG seed. |
--sweep |
bool | false |
Run an (s, S) grid sweep instead of a single policy. |
--json |
bool | false |
Emit uniform JSON envelope instead of text. |
With --sweep, the model ignores --s and --S and walks a grid of
(s, S) combinations to help locate the cost-optimal policy.
Example runs:
./order_point_inventory # default text run
./order_point_inventory --json # uniform envelope
./order_point_inventory --days=90 --s=20 --S=60 --json # custom policy, JSON
./order_point_inventory --sweep --json # grid sweep as JSON
odin run examples/order_point_inventory
examples/periodic_inventory for the tradeoff between continuous and periodic review.