Two engines for a ring-conveyor picking system
A QPS puts picking stations around a ring conveyor. Where each SKU lives and in what order boxes enter decide whether the line flows or queues. This post describes the allocation and reordering engines that now run in a logistics centre's regular operations, and lets you run a re-implementation of both.
Decisions on two clocks
Logistics centre operations depend on order volume, worker and equipment status, task priority and bottlenecks. In a QPS, two decisions dominate throughput, and they are made on different clocks. Which SKU goes to which station is decided once per batch, when the stations are set up. In what order boxes are injected is decided again and again while the batch runs, because the floor changes. Treating them as one problem makes both slow; splitting them by decision cycle gives a batch engine and an operating engine that share a single sequencing core.
| Engine | When | Decides | Returns |
|---|---|---|---|
| Allocation | Once per batch | SKU → station, how many stations to open | Several alternatives by station count, each with expected duration and man-hours |
| Reordering | Repeatedly during operation | Injection order of the boxes not yet injected | A new sequence, with already-injected boxes fixed in place |
Allocation: put together what is picked together
A box visits every station that holds one of its SKUs, so the cost of an allocation is mostly how many stations each box must visit and how evenly the picking load spreads. The engine first measures which SKUs are ordered together — a Jaccard overlap weighted by how often the pair co-occurs — and then builds the allocation in stages rather than solving one monolithic model.
- Anchors. One seed SKU per station, chosen to be strongly connected to others but weakly connected to the other anchors, so the stations start apart.
- Five rounds of knapsack. Stations are filled to 20%, 40% … 100% of their cells in turn. For one station in one round, an exact two-dimensional 0/1 knapsack picks the SKUs that maximize
load + α · affinitywithin the remaining cells and a load target — so good SKUs are not swallowed by whichever station is filled first. - Polish. Greedy placement of leftovers, affinity-driven moves under a load cap, and 1:1 swaps between the heaviest and lightest stations.
A dedicated station type (for items that must be handled separately) is respected at every stage: ordinary SKUs never enter it. The engine then repeats the whole build for one more station, and one more, and returns the alternatives — the floor chooses how many stations to staff, with the predicted duration and man-hours next to each option.
Both rings replay the simulation of the same batch on the same SKU placement; only the injection order differs. Watch queues build at stations and boxes bypass when a queue is full. Switch the station count to see makespan fall and then rise again when a low-load dedicated station is opened; "New batch" solves a fresh batch on the server. The full control panel adds the allocation stages, Gantt and mid-batch re-sequencing.
Injection order: simulate, then search
The order is a permutation of boxes on fixed injection slots. Each candidate order is scored by a next-event simulation of the ring: a box arrives at a station; if it has nothing to pick there it passes in three seconds; if the queue has room it waits for the single worker, who needs ten seconds per distinct SKU; if the queue is full it is bypassed and comes back after a full lap. The objective is the time the last box finishes plus the number of bypasses.
The search is deliberately plain. A few hundred random permutations seed a best-so-far; then a Tabu Search repeatedly samples position-pair swaps, simulates each, moves to the best one even if it is worse, and forbids reversing recent swaps. The final sequence is not the permutation itself but the order in which boxes first start picking when that permutation is simulated — the number the floor actually needs. During operation the boxes already injected form a fixed prefix and only the tail is re-searched, batch after batch.
One deliberate compromise sits on top: a post-process that groups boxes of the same box type into contiguous runs, because excessive alternation between box types slows injection on the floor. It does not re-simulate, so it can give back a little of the makespan it was handed. The live model shows both numbers so the trade-off is visible.
In operation
The engines run behind an asynchronous API: a request is acknowledged immediately, the optimization runs in the background, and the result is delivered back to the operating system by callback. Candidate evaluation is compiled and parallelized so a reorder call fits the floor's response window. Alongside the engines, an LLM-agent "AI Floor Supervisor" interprets real-time conditions, watches workload and bottleneck signals, and recommends allocation and priority adjustments to field managers.
The result showed that AI can support real-time logistics decisions rather than remain an offline analysis tool, and it supported the rollout to a second centre and the wider logistics AI roadmap, including cart picking optimization.
Limitations
- The reordering simulation approximates boxes already on the ring by re-injecting them from the start of the horizon; it does not track their true position. This is the "simulation fidelity" gap that kept reinforcement learning out of scope.
- There are no due dates or priorities in the objective — only completion time and bypasses.
- Box-type grouping is applied after the search and is not re-evaluated against the simulation.
- The live model uses reduced search budgets and a simplified station-selection rule; the production engines and their integration code are not published.
About the demo and confidentiality
The orders, SKUs, stations and box types in the embedded model are generated from a seed. No equipment, centre, system or table names appear, and the engines shown are a re-implementation of the decision logic validated against the original on random instances — not the production code.