Skip to main content

Overview

An Entity is an item that flows through a simulation, a work order, a finished good, a pallet, a batch, a patient, a truck. Every simulation revolves around entities being created, routed, processed, and terminated. What makes entities powerful in ProDex isn’t the concept of “things flowing through a graph”: it’s that entities carry typed attributes with them, and expressions across the model can read and act on those attributes. An entity isn’t just an anonymous token; it’s a bundle of typed data that components inspect, route on, time-process differently, and aggregate. This is the mechanism that turns a static flow diagram into a model that responds to the specific work being done. Entity types are one of the first things you define when building a model — see Key concepts for where they sit in the Factory > Models hierarchy, and the Simulation overview for the modeling workflow around them.

Attribute Types

Each entity type defines a set of named attributes. The attribute Type dropdown offers five types. A Number attribute also has a Domain control, Real (the default) or Integer; that’s a setting on Number, not a separate type. The List types are enums, not lists. A Text List attribute doesn’t hold multiple strings: it holds one string, picked from a fixed set of allowed values declared on the entity type. Same for Number List: the attribute’s value is one number chosen from a predefined set. Think of them as constrained categorical values, not arrays. Use Text List or Number List when you want an attribute to be categorical and you want the platform to enforce valid values. Use Text or Number when the attribute is open-ended. Attribute types are fixed on the entity type: you can’t store a number in a Text attribute. The expression language respects these types when you reference attributes by name.

How Attributes Flow

Attributes set on an entity persist with it through the entire flow. Once assigned, downstream components can read them without any explicit propagation.
  • Create / assign: attributes are assigned any time a component produces a new entity. That’s on Sources (creating initial entities), Combiners (output entity of a batch), Separators (output entities of a split), Transformers (output entity of a type change), and material releases on either a Source or a Buffer in a schedule. A Separator has a separate set of assignments for each output entity type, because one split can emit several output types.
  • Read: any downstream expression in a single-entity context can reference the attribute by bare name (priority, weight).
  • Change identity: a Transformer produces a new entity of a different type with its own attribute assignments. It doesn’t mutate the input entity’s attributes in place: it emits a different entity, typed differently, with its own attribute values.
  • Aggregate: when entities are combined, the output entity’s attributes are computed from the set of inputs using aggregation functions like SUM(weight) or MAX(priority) in the Combiner’s multi-entity context.
Transformer attribute carryover is not automatic. When a Transformer emits an output entity, none of the input entity’s attributes are copied across by default. Every attribute you want on the output must be explicitly assigned, most commonly as a DSL expression referencing the input attribute by bare name. Skip an assignment and the value simply isn’t carried — silent data loss. Separator outputs behave the same way.
The DSL doesn’t require a prefix to read attributes: just use the bare name. priority and product_class are valid identifiers in any expression that has an entity in scope.

Which context each assignment runs in

The single biggest authoring trap with attributes is forgetting which expression context an assignment evaluates in: Attribute names also can’t collide with the DSL’s reserved keywords — the validator rejects an entity type whose attribute shadows one.

Assignment Strategies

Whenever a component assigns an attribute on a new entity (on a Source, Combiner, Separator, or Transformer), you pick a Strategy for it. The dropdown offers different strategies depending on the attribute’s type:
Random and Distribution are different strategies. Random picks uniformly from the attribute’s declared choices (Text List / Number List). Distribution samples a number from a probability distribution (Number only).
Don’t pick DSL Expression for a Text List or Number List attribute. The dropdown lists it for those types, but validation rejects it. For categorical values, use Random, Round Robin, or Weighted.
Material releases in a schedule also assign attributes. In the Schedule Editor you set a fixed value for each attribute.

Strategy Details

Fixed: Same value on every entity. Useful for attributes that don’t vary across items, or as a placeholder before you wire in real variability. On Text List / Number List attributes the fixed value must be one of the declared choices. DSL Expression: The value is the result of a DSL expression evaluated when the entity is created. Use when the value depends on simulation state, other attributes, or the current time: IF(SIM_TIME < SHIFT_1_END, "day", "night") or LOOKUP(priority_by_class, product_class). Not valid for Text List or Number List: use Weighted or Random for categorical selection. Round Robin: The first entity gets the first choice, the second gets the second, and so on, cycling back to the first after the last. Useful for evenly distributing entities across categories without randomness. Round Robin carries no choices of its own — it cycles through the choices declared on the attribute. Random: Uniform random pick from the attribute’s declared choices. Every choice has equal probability. Distribution: Samples from a distribution (normal, exponential, triangular, etc.). Useful for natural variability: entity weights drawn from a normal, service-time requirements drawn from triangular, or arrival intervals drawn from exponential. Weighted: Pick from the attribute’s choices with per-choice weights. Specify a weight for each option; relative weights determine selection probability. If you need weights that change with simulation state, ask Dexter to set them as expressions.

Defining an Entity Type

Entity types are managed in the Entities dialog. Open it with the pencil (View and manage all) on the Entities section of the Modeler’s Overview. The dialog lists every entity type in the factory on the left; select one to edit it in the detail pane, or click New entity to create one. Each type has:
  • A name and Description
  • A Unit — a free-text label (default "EA") that drives quantity labels in reporting and KPIs. It is a label only: ProDex does not perform dimensional conversion between units.
  • A set of typed Attributes (with Choices on Text List and Number List attributes, optional Min / Max / Exclude zero and Domain on Number attributes, and optional Max length on Text)
Entity types belong to the factory, but a model only uses the entity types you add to it. Add one from the dialog’s detail pane with Add to model, or from the Add entity row at the bottom of the Entities section (which can also create a new one). The row’s × (Remove from model) takes it out of the model without deleting it, and is disabled while something in the model still uses it. Sources, Transformers, BOM nodes, Combiners, and Separators that produce entities of that type share the same attribute definitions: if you add an attribute to the type, every place that creates or modifies the entity can now set it.
The same entity types back your BOMs. An entity type isn’t simulation-only. A BOM references an entity type, and its conditions read the type’s attributes by name — the two features share the factory’s one list of entity types. Define an entity type once and it’s available to both the simulation model and the BOM/planning side; edit its attributes and both see the change.
Renaming an entity type or attribute propagates widely. Entity types are referenced by Sources, Transformers (input and output entity), Separators (input entity and output batch), Combiners (output entity), schedule material releases, BOMs, and Configuration Templates. Attribute names appear in BOM conditions and DSL expressions across the model. Rename with a global search, not in isolation.

Authoring Entity Types with Dexter

Ask Dexter to create or extend entity types — for example from a spreadsheet you’ve uploaded. It profiles the data and defines the entity types and their typed attributes for you.

Attributes in Results Data

Attributes are queryable after a run, but they live in a dimension table, not inline on every lifecycle row:
  • Each entity_lifecycle row carries an attributes_hash. Join it to the entity_attribute table, which has one row per (attributes_hash, attribute_name).
  • entity_attribute columns: attributes_hash, attribute_name, value_type ("number", "text", or "boolean"), and typed value columns value_number / value_text / value_boolean. Booleans land in value_boolean, never value_number; Text List values land in value_text and Number List values in value_number (there are only three value buckets).
  • Rows are written the first time each distinct attributes_hash is seen and never re-emitted; the table carries no entity identity of its own — the hash on entity_lifecycle is the only route back to entities.
See available dataframes for the full catalog.

Patterns

Classification attribute driving routing. A product_class Text List attribute set at the Source (one of "rush" or "standard") drives a Router that sends rush items to the express line. Numeric attribute driving processing time. A complexity_factor Number attribute (drawn from a distribution via the Distribution strategy) multiplies the base processing time on each Process. Type change in a Transformer. A Transformer reassigns the entity to a new type painted_part (from raw_part), with explicit DSL-expression assignments that carry forward every attribute the downstream model cares about. Aggregation in a Combiner. When three components are combined into an assembly, the output entity’s total_weight is SUM(weight), priority is MAX(priority), and qc_passed is ALL(qc_passed). The full aggregation set is SUM, MEAN, COUNT, MAX, MIN, MODE, N_UNIQUE, ANY, and ALL — COUNT and N_UNIQUE always return numbers, ANY and ALL are the boolean aggregations (over boolean attributes), and MAX / MIN / MODE work on numbers or text.

Tips

  • Model the attributes you’ll query. If you care about “cycle time by product class” in your results, product_class has to be an attribute on the entity, otherwise the join isn’t available in the simulation dataframes.
  • Use Text List or Number List for categorical constraints. They’re enums: the platform enforces that the value is one of the declared choices. Prefer these over free-form Text when the attribute has a known finite set of valid values.
  • Prefer entity attributes over state variables for per-entity data. State variables are for facts about the system. Attributes are for facts about a specific entity.
  • For dynamic categorical selection, use Weighted with expression weights. That’s the only way to drive list-type attributes from expressions, since DSL Expression isn’t valid for list types. The editor takes numeric weights; ask Dexter to set expression weights.
  • Explicit attribute carryover: every output attribute on a Transformer or Separator must be assigned. There’s no auto-copy from the input.
  • Check provenance on assignment values. Choices, weights, and expressions that Dexter authors carry the same Data / Stated / Assumed marking as everything else in the Evidence panel — assumed values surface in an assumptions review.
  • entity_id doesn’t survive transformation. Transformers, Combiners, and Separators emit new entities with new ids. If you need to trace one unit end-to-end in results, carry a stable business identifier (order number, serial) as an attribute.