Skip to main content

Overview

Combiners, Separators, and Transformers are the three Modeler components that reshape entity flow rather than simply routing or delaying entities. They’re how you model assembly, disassembly, batching, kitting, packaging, and any operation where the entities going in aren’t the same as the entities going out. These components look simple — a box with inputs and outputs — but each has specific behavior worth understanding before you build an assembly or disassembly operation, especially around how they interact with Station capacity.

Combiner

A Combiner merges multiple input entities into a single output entity. Use it to model assembly (parts → product), batching (individual items → pallet), kitting (components → kit), or any operation where several items become one.

Input Batches

A Combiner waits until it has enough inputs to form a batch, then emits one output. Batch size is configured two ways:
  • Fixed count — always assemble N inputs into one output. N = 3 means “wait for 3 entities, then combine.”
  • DSL-driven — the batch size is an expression evaluated when the Combiner is ready to start assembling. Use this when batch size depends on state: batch larger under low demand, smaller under high demand, based on a state variable or entity attribute.

Multi-Entity Context for Output Attributes

A Combiner output assignment expression runs in a multi-entity context — several input entities are in scope at once. Bare attribute references like weight are ambiguous (which input’s weight?), so they must be wrapped in aggregation functions:
# Output attribute: total_weight — sum of input weights
SUM(weight)

# Output attribute: priority — max across inputs
MAX(priority)

# Output attribute: is_rush — true if any input is rush
ANY(is_rush)

# Output attribute: qc_passed — true only if all inputs passed
ALL(qc_passed)
The same constraint applies to any condition the Combiner evaluates — batch-level triggers, quality gates, routing conditions after assembly.

Interaction with Station Capacity

When a Combiner sits inside a Station, understand how station capacity works with lineage tracking:
  • Entities consume slots on entry. Each input entity that enters the station takes one capacity slot.
  • The Combiner merges inputs into an output. If the batch size is 3 and three inputs have entered the station, those three input entities occupy three slots while the Combiner assembles them.
  • Slots are freed via lineage. All three slots are freed only when the output entity — which is a descendant of the three inputs — exits the station.
The practical effect: station capacity limits the number of input entities that can be inside the station simultaneously, not the number of active batches. A station with capacity 5 and a Combiner batching 3 inputs can hold up to 5 input entities at a time; partial batches (fewer than 3 inputs in the station yet) still count against capacity. The capacity constraint is about how many items the physical space holds, not about how many assembly operations are “active.” If the station looks blocked at low utilization, it’s usually because input entities have piled up and are waiting for their batch to complete and exit. Raising station capacity or restructuring so the Combiner sits outside the station are the two common fixes.

Separator

A Separator splits one input entity into multiple output entities. Use it to model disassembly (kit → components), unbatching (pallet → individual items), or any “one in, many out” operation.

Output Count

The number of output entities per input can be:
  • Fixed — always emit N outputs per input
  • DSL-driven — the output count is an expression evaluated when the Separator runs, potentially depending on the input entity’s attributes (“split into quantity units where quantity is an attribute on the input”)

Output Attributes

Separator output attribute assignments run in a single-entity context with the input entity’s attributes in scope — references to weight, priority, etc. read the input entity, and the assignment produces values for the output entity being created. A common pattern: divide a quantity across outputs evenly (weight / output_count) or copy a classification from input to every output. A Separator also has two event hooks with different contexts: on_entity_created fires in single-entity context for each output being created (useful for per-output logic), and on_batch_created fires in multi-entity context with all outputs in scope (useful for aggregate logic across the batch of outputs).

Interaction with Station Capacity

Separator lineage in a station is often misunderstood. The correct model:
  • The input entity consumes one capacity slot when it enters the station.
  • The Separator splits that input into several output entities. The outputs are descendants of the input — they share the input’s lineage.
  • The single slot is freed only when all descendants have exited the station. If three outputs were produced, the slot stays occupied until all three of them leave.
The outputs don’t each consume their own slot. They share the ancestor’s slot via the lineage-tracking rule. So a station with capacity 5 can hold 5 Separator inputs at a time regardless of how many outputs each produces — but each input’s slot stays occupied longer if it produces more outputs (because the “all descendants have exited” condition takes longer to satisfy). If outputs pile up in the station and block further Separator runs, the downstream path out of the station is the usual culprit. Make sure the outputs have a clear exit path.

Transformer

A Transformer produces a new output entity of a different type, replacing the input in the flow. The entity count is unchanged (one in, one out), but downstream components see a different typed entity after the Transformer. Use a Transformer to model operations where the thing being worked on becomes a different thing after processing: raw material → WIP, WIP → finished good, blank → painted, component → inspected-component.

Attribute Assignment on the Output

A Transformer emits a new entity of a different type, with its own attribute assignments. Assignments run in a single-entity context with the input entity’s attributes accessible and can reference:
  • The input entity’s attributes — useful for carrying context forward
  • Simulation stateSIM_TIME to stamp when the transformation happened
  • State variables and constants — to apply shift- or operation-specific values
The Transformer doesn’t mutate the input entity; it produces a different output entity of the new type, which is what downstream components see.

When to Use a Transformer vs. a Process

If all you need is “the entity is delayed by X minutes, optionally holding a resource,” use a Process. Use a Transformer when:
  • The entity’s downstream routing depends on its type (sent to different processes for different types)
  • Results analysis groups by entity type (throughput by product, not aggregated)
  • The entity conceptually becomes something different as part of the operation
A Transformer does not consume processing time by itself — if the transformation takes real time, pair it with a preceding Process.

Patterns

Assembly cell: Sources → Buffers → Combiner inside a Station → Sink. Each Source feeds a different component type; the Combiner assembles them into a product; the Station models the physical workspace constraint. Station capacity limits how many input components can be in the cell at once. Kit packaging: Process (pick components) → Combiner (batch into kit) → Process (seal/label) → Sink. The Combiner produces the kit entity; downstream processes operate on kits. Disassembly for rework: Router (send rework candidates here) → Separator (split the kit back into components) → individual component buffers. Each output inherits relevant attributes from the input (rework_reason, original_kit_id). Paint line: Source (raw parts) → Process (paint) → Transformer (raw_part → painted_part) → Process (inspect) → Router (route by qc_passed). The type change after paint lets downstream processes specialize on painted_part.

Tips

  • Combiners are where aggregation lives. If you’re trying to compute a sum or max across a group of entities anywhere else, you’re probably fighting the model — restructure so the aggregation happens at a Combiner output.
  • Lineage-based capacity is the reason stations with Combiners or Separators can behave counter-intuitively. Slots are consumed on entry and freed when all lineage descendants exit — not based on batch size or output count arithmetic.
  • Transformer over Process when type matters downstream. Processes change state; Transformers change identity. Use each for its purpose.
  • Attribute carryover isn’t automatic on Separators. Each output’s attributes must be assigned explicitly. If you want an attribute on every output copy of what’s on the input, assign it explicitly.