Decides what inventory moves across the network today: which stock to pull to which building to serve demand, which misplaced stock to bring home, and which excess to push back to reserve, all under a daily transfer capacity that binds. It is a network optimizer that returns a ranked plan and explains every move.
This is the layer that closes the loop. It consumes the MIN and MAX from the inventory policy engine as its replenishment triggers, the visitor stock the container engine flags as repatriation candidates, and the container engine's ETAs so it does not move what an inbound is about to deliver.
- What it does and the pipeline it closes
- The priority ladder
- Candidate generation
- The optimizer
- Evaluation and results
- Limitations
- Future work
- Using the engine
- Project structure
- References
Stock is rarely where demand is. Orders ship from forward buildings, safety stock and excess sit in reserve, and some stock lands at the wrong building and becomes a visitor. Every day, a limited number of transfers can be made, so the question is which moves buy the most. This engine answers it.
It is the transfer optimization layer of the network system, the piece that ties the others together. From the policy engine it takes each item's MIN and MAX: quantity below MIN pulls stock up toward OPHQ, and quantity above MAX pushes excess back to reserve, which is reverse replenishment. From the container engine it takes the flagged visitors and the inbound ETAs. So this is the first engine whose inputs are mostly other engines' outputs.
When transfers compete for the daily capacity, they are ranked by a six-tier ladder, highest first. The demand tiers came from the operation; capacity relief and inbound awareness were added in review:
- Capacity relief. Move stock out of a forward building that is over its limit, or will be once an imminent inbound lands, so receiving is not blocked. A hard constraint above the objective.
- Confirmed outbound today, overdue orders first.
- Near-term demand over the next few days.
- Forward replenishment when on-hand is below MIN, toward OPHQ, fast movers first.
- Visitor repatriation, misplaced stock home or to reserve.
- Excess relief, stock above MAX back to reserve toward OPHQ.
Two rules cut across the tiers rather than sitting in them. Inbound awareness suppresses a forward need that a container arriving within the horizon will cover, so the engine never moves what the dock is about to deliver. Smart sourcing fills a forward need from a visitor or above-MAX location first when one holds the item, so a single move covers the shortage and clears the visitor or excess at once, with reserve as the fallback. A need that nothing can source is flagged as a purchasing gap rather than silently dropped.
For each item, the engine computes escalating on-hand targets, today's orders, then orders plus near-term demand, then OPHQ if below MIN, and turns the gap at each level into a candidate at that tier. Inbound coverage is subtracted first so imminent arrivals suppress transfers. Each forward need is sourced visitor-first, then reserve, and any remainder becomes an unsourceable flag. Capacity relief candidates are generated for any forward building whose current fill plus imminent inbound exceeds its limit, evicting the least critical stock first: above-MAX excess, then visitors, then low-velocity items, and never stock needed for today's orders.
Candidates are taken strictly in tier order, and within a tier by priority, until the daily capacity is spent. Every selected move must have room at its destination, since forward buildings are finite; reserve is effectively unbounded. What does not fit is deferred to a later day, and unsourceable needs are set aside.
There is a real interaction worth naming. A forward building that starts full blocks every move into it, so outbound cannot be delivered there until space is freed. That is why capacity relief is tier 0: relieving first is what unblocks the outbound delivery that follows. An engine that relieves late, or at random, tries to fill a full building and its outbound moves get blocked. This is the mechanism behind the results below.
The engine is compared to a tier-blind baseline that uses the same capacity but ignores priority, so the value of prioritizing is measured. The headline metric is the share of the outbound shortfall closed: of the confirmed order demand that home stock cannot cover on its own, how much did the plan make coverable.
Results on the synthetic network (140 items across two forward buildings and a reserve, 60 transfers per day, one forward building starting over capacity). Illustrative, from the included generator:
| plan | outbound shortfall closed | outbound fill rate | visitor units cleared | excess units relieved | forward within capacity |
|---|---|---|---|---|---|
| ladder (engine) | 0.848 | 0.959 | 527 | 229 | yes |
| tier-blind baseline | 0.330 | 0.818 | 1009 | 281 | yes |
On the same 60 transfers, the ladder closes 85 percent of the outbound shortfall against the baseline's 33, because it relieves the full building first and then spends the capacity on today's orders instead of scattering it. Inbound awareness suppressed about 303 units of transfers that arriving containers will cover, and 28 needs were flagged as purchasing gaps that no transfer can fix.
The baseline clears more visitors and more excess, and that is the point, not a loss. The ladder deliberately defers housekeeping when orders need the trucks; the baseline does housekeeping and misses shipments. Reverse replenishment still happens under the ladder, through tier-0 relief and visitor-first sourcing rather than through the low-priority tiers, which is why hundreds of visitor and excess units clear even though tiers 4 and 5 barely run.
The right panel shows the ladder spending capacity top down: full capacity relief and outbound, most of near-term, then part of forward replenishment before the day's transfers run out, leaving visitor return and excess relief for tomorrow.
Transfers are counted in moves and stock in units. A production version would work in LPN or pallet units and round accordingly. Same-campus versus cross-campus friction is not costed yet; every move is treated as equally easy. Greedy is near-optimal under a capacity constraint, not exact. The demo runs on synthetic state so it is inspectable without proprietary data.
- LPN and pallet rounding, and a same-campus versus cross-campus friction cost so the optimizer prefers cheaper moves.
- A rolling multi-day plan that re-solves as ETAs, orders, and positions change.
- A cost-based objective, weighing a move's cost against the stockout it prevents, which would let lower tiers outrank a higher one when the economics justify it.
- An exact formulation to bound the greedy gap on small instances.
- The deferred housekeeping tiers, obsolescence and consolidation moves, added explicitly rather than left implicit.
Standalone, on the included synthetic network:
pip install -r requirements.txt
python scripts/run_demo.pyAs a module:
from transfer_engine import generate, plan, compare
state = generate() # or supply your own state
result = plan(state) # result["chosen"] is the day's transfer plan
result["chosen"] # item, from, to, qty, tier, reason
comparison, _, suppressed = compare(state)Inputs are items with a home and an adopted MIN, OPHQ, MAX policy, on-hand by location, today's orders, near-term demand, inbound ETAs, and a daily transfer capacity. The policy comes from the inventory policy engine and the visitors and ETAs from the container engine.
transfer-replenishment-engine/
README.md this document
requirements.txt
src/transfer_engine/
nodes.py functional locations and capacity
data.py synthetic network state generator
candidates.py tier 0 to 5 candidate generation, inbound-aware, visitor-first
optimize.py greedy lexicographic selection under capacity and space
evaluate.py ladder versus tier-blind, outbound and housekeeping metrics
pipeline.py plan(): state in, transfer plan out
scripts/run_demo.py end-to-end demo, figure and exports
tests/ capacity, sourcing, tier order, outbound win, suppression
assets/ generated figure
data/ sample state and transfer plan output
Chopra, S., and Meindl, P. (2016). Supply Chain Management: Strategy, Planning, and Operation, 6th ed. Pearson. (Network flow, transshipment, and inventory positioning.)
Nemhauser, G. L., Wolsey, L. A., and Fisher, M. L. (1978). An analysis of approximations for maximizing submodular set functions I. Mathematical Programming, 14(1), 265-294. (Greedy selection under a capacity constraint.)
Paterson, C., Kiesmuller, G., Teunter, R., and Glazebrook, K. (2011). Inventory models with lateral transshipments: a review. European Journal of Operational Research, 210(2), 125-136. (The lateral transshipment and rebalancing literature.)
Silver, E. A., Pyke, D. F., and Peterson, R. (1998). Inventory Management and Production Planning and Scheduling, 3rd ed. Wiley. (Min-max replenishment triggers.)
