Batching
Any unfamiliar word is in the glossary.
A batch is work that runs together: a furnace load, an oven, a plating tank. The resource processes the whole batch in one operation, so the time is the batch's, not the sum of its parts.
resource: furnace
process_seconds: { kind: constant, value: 14400 }
batch: { min_pieces: 75, max_pieces: 150, group: furnace_load }
Every key
| key | type | required | what it means |
|---|---|---|---|
min_pieces | integer | yes | Fewest pieces a batch may start with. ⚠️ A hard floor with no look-ahead — the batcher never delays a load hoping for an arrival that has not happened — and a hard floor in time too unless timeout_seconds says otherwise. A batcher that starts a partial batch after waiting produces a tidier operating curve than the real plant has, and destroys the low-load anomaly that is this model's best structural test, so the deadline is opt-in. |
max_pieces | integer | yes | Most pieces a batch may hold. |
timeout_seconds | number | no | How long a load may wait for its minimum before running short. Absent means for ever, which is what every model written before this key existed does. 0 means never wait: the load starts with whatever is present the moment a machine is free. ⚠️ Measured from when the load's first lot joined the pool, not its last — from the last, a trickle of arrivals would postpone the deadline indefinitely, which is the one thing a deadline exists to prevent. |
group | string | no | Which lots may batch together. Absent means only lots at this exact step of this exact product. Name the same group on several steps to let their lots share a load. ⚠️ Pool only where the data says so: pooling where it should not fills batches far faster than the real plant, and nothing in the cycle time shows it. |
group decides what may batch with what
Steps that name the same group pool their waiting work together; a step with no group
gets one of its own.
group must agree about timeout_secondsThe engine reads the deadline from whichever lot happens to lead the pool — the same place it reads the sizes from. A disagreement about size changes how many pieces a load holds; a disagreement about the deadline decides whether the load ever runs. Measured on one furnace, one group, two products, a minimum of four and two lots, with only the arrival order swapped: the deadline applied and two lots finished, or it did not and none did. So it is refused — otherwise the answer would turn on which lot arrived first, which is an outcome of the run rather than something this document says.
It does not mean "batches with every other ungrouped step". That distinction matters the moment two unrelated steps both omit the key.
The step's process_seconds is charged once for the whole load, which is what makes a
batch a batch: eight lots in one furnace cost one furnace cycle, not eight.
A minimum the arrivals cannot reach is a deadlock with no error. In one published dataset a mis-read batch group left a product waiting seven days for a partner that was never coming, and its cycle time read 3.51 days against a published 1.9 — while nothing in the run looked broken, because a pool that never fills produces no queue, no wait and no utilisation.
Real equipment does not do that: a furnace waits a bounded time and then runs short. Setting
timeout_seconds is both the faithful model and a structural defence, because a
mis-specified group then shows up as a plant full of undersized batches, which is loud,
instead of one that quietly stops.
⭐ And whether or not you set it, a pool that spends most of the run unfilled is named in
stalled_resources.
timeout_seconds: 0 does not make the machine an ordinary queueIt removes the holding, not the batching. A pool that happens to hold three lots when a
machine frees still runs all three together in one process_seconds, which no single-server
queue does. What 0 guarantees is that no lot is ever kept waiting for company.
⚠️ It does not guarantee a wait of zero on a machine that cannot keep up. Measured on
deterministic arrivals with a minimum of four: arriving every 60 s against a 30 s process —
so every arrival finds the machine free — the batch-forming wait is exactly 0 against
a(k-1)/2 = 90 s without the deadline. Arriving every 30 s against a 60 s process, where the
machine is the constraint, it is 12,000 s over 801 loads: the lots are not waiting for
company, they are waiting for the machine, and a deadline cannot shorten that.
With uniform lots a batcher can fill greedily and stop at the first that does not fit. The moment lots differ in size that is catastrophic: a 6-to-8 furnace facing lots of 3, 2 and 4 takes the 3 and the 2, reaches 5, meets the 4, and stops one short — permanently. The engine passes over a lot that cannot fit and keeps looking.