Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Transfer and Reverse Replenishment Engine

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.


Contents

  1. What it does and the pipeline it closes
  2. The priority ladder
  3. Candidate generation
  4. The optimizer
  5. Evaluation and results
  6. Limitations
  7. Future work
  8. Using the engine
  9. Project structure
  10. References

1. What it does and the pipeline it closes

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.


2. The priority ladder

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:

  1. 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.
  2. Confirmed outbound today, overdue orders first.
  3. Near-term demand over the next few days.
  4. Forward replenishment when on-hand is below MIN, toward OPHQ, fast movers first.
  5. Visitor repatriation, misplaced stock home or to reserve.
  6. 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.


3. Candidate generation

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.


4. The optimizer

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.


5. Evaluation and results

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.

Outbound served and the ladder in action

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.


6. Limitations

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.


7. Future work

  • 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.

8. Using the engine

Standalone, on the included synthetic network:

pip install -r requirements.txt
python scripts/run_demo.py

As 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.


9. Project structure

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

10. References

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.)

About

Plans the day's transfers on a six-tier priority ladder under transfer capacity, and reads inbound ETAs so it does not move stock that is about to arrive.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages