Overview
The Modeler is where a simulation model gets built: a directed graph of components on a canvas, plus the entities, expressions, reference data, and event logic that make it behave like your operation. This page is the working reference for that surface — the top-bar controls, every component type and its configuration, the expression language, the Library, and how a model actually runs. If you haven’t built a model before, walk through Your First Simulation once first. And you never have to drive the canvas by hand: Dexter builds and edits models conversationally, already knows which model you have open, and mixes freely with manual edits.What discrete event simulation is
Discrete event simulation (DES) represents an operation as a sequence of instants at which something changes — an order arrives, a machine finishes a cycle, a resource frees up. Between events nothing happens, so simulated time jumps from one event to the next; that’s why a model of a month of production runs in seconds. Change a capacity, a distribution, or a buffer and you see the downstream effects immediately, without touching the real system. You build the model visually and ProDex’s simulation engine executes it directly. The canvas is the source of truth — there is no engine code to write.Building on the Canvas
A model is a directed graph: components are nodes, connections are edges, and entities flow along the edges. Drag components out of the Modeler’s left panel, drop them on the canvas, wire each component’s output handle to the next component’s input handle, and click any component to open its configuration panel. The minimum viable model is Source → Process → Sink. Everything else — buffers, routers, stations, event logic — earns its place as your questions demand it.The Top Bar
- Model selector — the active model carries a checkmark; the menu also holds + New Model, Rename, and Delete.
- Schedule selector — picks what drives timing:
Default (no schedule)or any schedule defined for the model. WithDefault (no schedule)active, a Duration field (DDD:HH:MM:SS) sets the run length. With a named schedule active, the duration field gives way to a pencil icon that opens the schedule editor, and the schedule’s own Start and End Times drive the run. - Save snapshot (disk icon) — opens the Create Snapshot dialog: name required, description optional. A Snapshot is an immutable capture of the model plus its active schedule — not a save; the Modeler autosaves continuously.
- Snapshot history (clock icon) — a searchable picker of existing snapshots. Picking one loads it onto the canvas.
- Undo / Redo — edit history for the current session.
Component Types
Every flow component’s panel also carries an Event Hooks and an Event Listeners section — the reaction logic covered in The Event System below.Source
Where entities enter the model.- Entity type — which entity this Source produces.
- Arrival logic — the inter-arrival time (time between arrivals, not a rate), drawn from the distribution picker or a DSL expression.
- Initial attribute values — per attribute, a Strategy: Fixed, DSL Expression, Round Robin, Random Choice, Random (sample a distribution), or Weighted (a value/weight table). The dropdown narrows to the strategies valid for the attribute’s type — see the type-by-strategy matrix. Note that a DSL assignment at a Source runs before the entity exists, so it can’t read the new entity’s other attributes.
- Events — fires entity created per produced entity.
Process
A step that takes time and may consume resources.- Entity Type — scopes the rest of the panel to one entity type.
- Processing time — a distribution or DSL expression.
- Resource requirements — a multi-row table (+ Add Row) of resource → quantity. Quantities accept expressions, and a requirement whose quantity evaluates to 0 is skipped for that entity — the mechanism behind cross-training and substitution patterns.
- Station — optionally places the Process inside a Station.
- Events — process started, process completed.
Resource
A capacity pool — workers, machines, fixtures — that Processes draw from. Resources aren’t draggable canvas nodes: they’re model-scoped pools managed in the side panel and referenced from Process requirement tables.- Capacity — number of parallel slots.
- Allocation Discipline — FIFO, LIFO, or Priority (a DSL key with ascending/descending ordering).
- Changeover Times — a table of (from process, to process) → duration rows. Same-process pairs are allowed, and each duration can be a fixed value, a distribution, or a DSL expression. Because that expression can read the changeover-only identifiers for the exiting and entering entities — their types and their attributes — a single changeover time can vary with the (exiting entity, entering entity) pair rather than being keyed only by process.
- Events — slot freed, slot working. A set capacity action reacting to shift topics is the standard shift scheduling pattern; the same mechanism models breakdowns, maintenance windows, and staffing changes.
Changeover keys are processes, not entity types. A resource that handles two products through the same process incurs no changeover; switching between two processes (even on the same entity type) does. If your changeover model is keyed by entity type today, rework it around the processes that actually demand the setup.
Buffer
A waiting area between components.- Entity Type, and Capacity with an explicit Infinite toggle.
- Queue Discipline — FIFO, LIFO, or Priority.
- Release Mode — Push (auto-release) sends entities downstream as soon as there’s room; Hold (manual release) keeps them until a release action fires — the kanban/pull pattern.
- Events — entity entered, entity exited, contents changed. Buffers and Stations are the components that emit the per-entity entered/exited pair; Processes signal through process started/completed instead.
Router
Splits entity flow across outgoing connections based on its Logic Type:
Routers fire entity routed per entity. Each Conditional or Probabilistic rule row has a See expression / AI explanation toggle that flips between the raw DSL and a plain-English explanation — the fastest way to confirm a rule does what you think it does.
Combiner, Separator, and Transformer
The batching components, covered in depth in Combiners, Separators & Transformers:- Combiner — merges multiple inputs into one output (assembly). Batches form either from static per-input quantities or from a dynamic batch expression evaluated on each arrival. Output attribute assignments run in multi-entity context, so aggregations apply —
SUM,MEAN,MAX,MIN,COUNT,ANY,ALL,MODE,N_UNIQUEover the batch (e.g.SUM(weight),MAX(priority),ALL(qc_passed)). An aggregated attribute must exist on every input type — give a default to inputs that don’t naturally carry it rather than leaving it absent. - Separator — splits one input into several outputs: an Output Batch table pairs each output entity type with a count expression, with per-output attribute assignments (Fixed or DSL).
- Transformer — one in, one out. Changing the entity type is only half its job: configuring the same input and output type is the standard way to mutate attributes mid-flow (incrementing a rework counter, stamping a QC result).
Station
A capacity-constrained container representing a physical space or work center. Capacity is a per-entity-type table (e.g., Tube = 500, Tray = 100), so one station can hold different quantities of different items at once; leave a type unbounded when the station isn’t the constraint. Stations also group related components, which keeps large models navigable — and emit entity entered, entity exited, and contents changed (multi-entity context over the current contents, the usual seat of WIP gauges).Sink
The exit point. Entity Type is required — only matching entities may enter — and entities that arrive are consumed, counted, and fire entity terminated.Model Node
Embeds another model from the same factory as a single component — the key to hierarchical modeling. Model Nodes aren’t in the component palette: from the Modeler’s left panel, use + Import Model to pick another model in the factory, then drag its card onto the canvas. Each instance maps its outer connections to the sub-model’s internal sources and sinks, and can alias resources, topics, and state variables per instance; nested components are addressed withparent::child qualified paths. See Model Nodes & Hierarchical Modeling.
Connections
Drag from a component’s output handle to another’s input handle to define flow. Entities move along a connection when the downstream component can accept them — or, for Hold-mode Buffers, when explicitly released. Two topology rules worth knowing up front: connections can’t start or end at a Station (wire the components inside it instead), and a Router’s rules attach to its outgoing connections. Validation enforces the full ruleset as you edit.The Event System
Flow connections describe how entities move; the event system describes how the model reacts. Two primitives, both configured on every flow component’s panel:- Event Hooks fire on the component’s own lifecycle events — the entity created / process completed / contents changed events listed per component above. The hook’s expression context follows the event: single-entity for per-entity lifecycles, multi-entity for batch and contents-changed events, no-entity for resource slot events.
- Event Listeners fire when a subscribed topic is emitted anywhere in the model — and always run in no-entity context: a listener can read state variables, constants, lookups, and component queries, but never the emitting entity’s attributes. When cross-component logic needs per-entity data, the pattern is: a hook writes what it needs into state and emits; the listener reads state.
Expressions and the DSL
Most numeric and logical fields accept either a literal or an expression in ProDex’s DSL, which is how models become dynamic and data-driven: routing conditions over attributes, per-entity resource needs, durations that depend on state. Identifiers available everywhere:SIM_TIME (current simulation time) and SIM_DURATION (the configured run length, not the time remaining). In entity contexts: ENTITY_TYPE (the entity’s type slug) and ENTITY_AGE. In hooks and listeners: SELF, the hosting component’s id — which makes rules copy-pasteable across components.
Component queries, usable in every context: BUFFER_LEVEL(id), BUFFER_CAPACITY(id), RESOURCE_AVAILABLE(id), RESOURCE_CAPACITY(id), STATION_WIP(id) — and LOOKUP(table, key1, key2, ..., default:=value) reads a lookup table by one or more keys.
Which fields run in which context — and the full catalog of functions and aggregations — lives in The Expression Language.
Distributions are picked from the eleven-option dropdown (Fixed, Normal, Exponential, Uniform, Lognormal, Lognormal from mean/CV, Weibull, Triangular, Erlang, Beta, Gamma), not written as DSL calls. Lognormal from mean/CV is a distinct entry from Lognormal — it takes a real-world mean plus a coefficient of variation rather than the underlying normal’s μ and σ, the form to reach for when a duration is stated as “mean X with CV Y.” Every parameter of every distribution accepts a literal number or a per-sample DSL expression, so any of them can vary by entity or state. See Distributions for parameter conventions and which to reach for.
The Library
The Library is the shared reference data your models draw from. Everything in it is factory-scoped — defined once, available to every model in the factory. You’ll meet it in two places: the Modeler’s left panel (the in-context view for dragging entities and components while you build) and the Data page (the factory-wide management surface). The Metrics tab overlays live KPI values onto canvas components after a run — useful for spotting where the slowdown actually happens without leaving the graph.Entities
The items that flow through your simulation: raw materials, WIP, finished goods. Every entity referenced by a Source, Transformer, or BOM must be defined in the Library first — open the Entities modal from the button at the bottom of the left panel. Each entity type carries typed attributes (Boolean, Number, Text, Text List, Number List), referenced by bare name in single-entity contexts — noself. prefix. Attributes persist with the entity through the whole flow. Note that the two list types are discrete choice sets — despite the name, each holds a single member of its declared choices, not a collection. They accept only a fixed or sampled value; a DSL-computed assignment is rejected in validation. If a downstream node needs to compute or thread the value, make the attribute a scalar Number or Text instead.
Constants
Named, factory-scoped parameters — Text, Number, or Boolean — referenced by bare name in any expression:PROCESSING_TIME_MINUTES * SHIFT_EFFICIENCY_FACTOR. Names use SCREAMING_SNAKE_CASE by convention and can’t collide with reserved words, component ids, or entity slugs. Constants are the right home for any value that appears in several places or that you’ll sweep in an experiment: change it once, and every referencing field updates.
Lookup Tables
Keyed tables queryable from any expression —LOOKUP(cycle_times, ENTITY_TYPE) — with one or more key columns and Text/Number/Boolean values. A missing key returns the default:= you pass, or a type-specific zero (0, "", FALSE) if you don’t. Typical uses: cycle time by product, yield by material, routing weight by order class. See Constants & Lookup Tables.
State Variables
Model-level mutable values that persist across entities: current shift, an inventory level, a rolling average. Read them by bare name in any context; write them with an assign action on a hook, listener, or scheduled action. Names follow the same SCREAMING_SNAKE_CASE rule. Use a state variable when the value belongs to the system; use an entity attribute for per-entity data.Topics
Named pub/sub channels: a component publishes with an emit action, and any component whose Event Listener subscribes to the topic reacts — coordination without a flow connection between them. Constants, Lookup Tables, State Variables, and Topics share one four-tab modal, opened from the Lookups button at the bottom of the left panel (next to Entities).Schedules
A model runs in abstract time until you pair it with a schedule, which anchors execution to wall-clock time: material releases inject specific entities at specific moments (in parallel with Source arrival logic, not instead of it), and scheduled actions fire assign and emit at specific times — the component-control actions remain hook-only. A model can hold multiple schedules — baseline week, stress scenario, historical replay — and you pick the active one in the top bar. A snapshot saved while a schedule is active embeds that schedule for downstream experiment and Monte Carlo runs.Running a Simulation
The run controls sit at the bottom of the canvas:- Run simulation (green play) — executes the model to completion.
- Fast forward (skip-forward icon) — jumps the on-canvas playback straight to the end of the run; available once a run has produced data to replay.
- Playback speed — controls the on-canvas animation only. The engine always runs at full speed.
Default (no schedule) the axis follows the Duration field; with a schedule active it switches to wall-clock dates spanning the schedule’s Start and End Times. Scan it before running to confirm the schedule lines up with what you expect.
Runs execute against the live working model — tweak, run, repeat. Snapshots come in when you need a frozen configuration to compare: Experiments and Monte Carlo both replay snapshots, not the live model. Each execution creates a run whose KPIs and charts compute in a second pass after the simulation finishes — a run showing pending isn’t broken, just still computing. Read the output in Results and Analytics.
The bottom-right of the canvas holds the view controls: Zoom In / Zoom Out, Fit View, Auto format layout (re-arranges nodes), and Find node (⌘F / Ctrl+F).
Tips and Best Practices
- Start simple. Source → Process → Sink validates your setup before you add complexity.
- Use constants for anything you’ll change between runs — scenario sweeps become one-field edits.
- Name everything in the operator’s terms. Component names surface in results, event logs, and charts; good names pay off every time you read output.
- Use stations to group related components — large models get hard to navigate without structure.
- Watch the play button. Green means valid; red names a specific blocker, and Fix with Assistant hands it to Dexter.
- Snapshot at milestones. Snapshots are what experiments and Monte Carlo replay — you can’t compare against a configuration you didn’t capture.

