Skip to main content

Overview

A Schedule is what anchors a simulation to real-world timing. Without a schedule, a model runs in abstract time with synthetic arrivals — useful for exploratory work, but not for comparing against your actual floor. With a schedule, the simulation is anchored to real dates, real shift patterns, and real production plans. Material enters when your plan says it does, shift transitions fire at specific wall-clock times, and results are comparable directly to what your floor produced. Every serious use of ProDex involves at least one schedule. Most models have several — one for the “normal” plan, a few for alternative scenarios you’re comparing. Schedules live alongside Checkpoints as the two things an Experiment case combines. A checkpoint freezes the model; a schedule fixes the timing.

What a Schedule Contains

A schedule is a sequence of material releases and scheduled actions, each stamped with a specific absolute wall-clock time. A schedule also declares:
  • start_time — ISO datetime when the simulation begins (e.g., 2024-11-01T06:00:00Z)
  • end_time (optional) — ISO datetime when the simulation ends. If provided, end_time overrides the model’s duration_seconds setting.
Every material release and scheduled action has an absolute ISO datetime — not a relative offset from start_time. The simulation runs from start_time to end_time (or for the model’s configured duration if end_time isn’t set), and each scheduled event fires when wall-clock simulation time reaches its timestamp.

Material Releases

A material release tells a Source or BufferNode to emit one or more entities at a specific wall-clock time. Each release specifies:
  • Target component — the id of a Source or BufferNode the release fires from (the component’s id, not its display name). Qualified paths apply when targeting a component inside a Model Node.
  • Entity type — which entity type to create (by slug)
  • Count — a positive integer (>= 1). Not a DSL expression.
  • release_time — absolute ISO datetime (e.g., 2024-11-01T07:00:00Z) — when the release fires
  • Attribute assignments — values to set on the newly created entities using the assignment strategies (fixed, dsl_expr, round_robin, random_choice, random, weighted)
Material releases are how you model “demand that actually happened.” Instead of a Source with a synthetic EXPONENTIAL(60) arrival rate, you give it a sequence of real orders: at 07:00 release 50 units of Product A with priority="rush" and due_priority=5; at 09:00 release 30 units of Product B with priority="standard"; and so on.

Scheduled Actions

A scheduled action fires at a specific wall-clock time without being tied to any component’s lifecycle event. Scheduled actions are restricted to two types: Component-bound actions (pause, resume, set_capacity, release_entity) are not valid as scheduled actions directly. If you need a scheduled capacity change, the pattern is:
  1. Scheduled emit fires at the shift boundary — e.g., emit("shift_start_night")
  2. An Event Hook on the resource subscribes to that topic and runs set_capacity(resource, night_capacity)
This separation keeps schedules declarative (“at 2024-11-01T18:00:00Z, announce that the night shift has started”) and lets Event Hooks handle the component-level side effects.

The Shift Scheduling Pattern

Most factories have shift-based capacity that changes through the day and week. The idiomatic way to model this in ProDex combines schedules, topics, state variables, and event hooks:
  1. A shift state variablecurrent_shift, type text, initial value "day"
  2. Scheduled emits at shift boundariesemit("shift_day") at each day-shift start, emit("shift_night") at each night-shift start, each entry stamped with its specific ISO datetime
  3. An Event Hook on each affected resource subscribing to the shift topics — when shift_night is emitted, run set_capacity(cnc_machines, 2) and assign(current_shift, "night")
  4. Expressions reference current_shift — arrival rates, priority scoring, and anything else that varies by shift reads the state variable and branches accordingly
This decomposition keeps the shift logic in one place (the Event Hook on the resource) and the shift timing in the schedule. Swap the schedule for a different shift plan and the capacity changes flow through automatically.

Multiple Schedules per Model

A model can have multiple schedules defined simultaneously. Each is a complete set of material releases and scheduled actions with its own start_time and end_time; you pick which one to use when running a simulation or setting up an experiment case. Typical uses:
  • Baseline vs. stress scenarios — a “normal” schedule and a “demand surge” schedule, compared in the same experiment
  • Historical replay — last month’s actual demand as one schedule, a planned demand forecast as another
  • Shift variations — a standard five-day schedule and an alternative seven-day weekend-coverage schedule, to evaluate capacity policy changes
An Experiment case pairs a Checkpoint with a schedule. Varying the schedule while holding the checkpoint constant lets you ask “how does this model configuration perform under different demand profiles?” Varying the checkpoint while holding the schedule constant lets you ask “which configuration is best for this demand?”

start_time and end_time

  • start_time is the wall-clock moment simulation begins. Every material release and scheduled action timestamp must fall at or after start_time.
  • end_time, if provided, is when simulation ends. Useful for running the same schedule against a shorter or longer window without editing the schedule’s events.
  • If end_time is omitted, the simulation runs for the model’s configured duration_seconds from start_time.
  • Events timestamped after end_time (or after start_time + duration_seconds if no end_time is set) never fire.
Both start_time and end_time are ISO 8601 timestamps. Time zones matter — the same schedule run with start_time in UTC vs. local time will produce different results for shift boundaries unless the shift events are stamped in the same zone.

Tips

  • Every serious model needs a schedule. Synthetic arrivals are fine for the first pass; real schedules are required for comparable results.
  • Use absolute ISO timestamps consistently. It’s tempting to think in relative offsets (“release at +3600s”) but the schedule format requires absolute datetimes. If you’re generating a schedule programmatically, compute the absolute timestamps from your base start_time.
  • Keep schedule-level logic in the schedule, component-level logic in Event Hooks. The schedule emits the signal; the hooks handle the side effects.
  • Use multiple schedules for experiments. The whole point of experiments is comparison — schedules are one axis of variation, checkpoints the other.
  • Two events at the same timestamp fire in an unspecified order. If ordering matters, stagger them by a small amount (a second) or chain them through a topic.