Allocate by Breakpoint, Not by Unit
How to turn slow unit-by-unit supply allocation into a fast, auditable algorithm using marginal value curves and breakpoints.
A surprisingly large number of supply allocation algorithms are slow for a stupid reason.
They allocate one unit at a time.
Take the location with the highest current marginal value. Give it one unit. Recalculate. Repeat.
If you have 200,000 units of supply, you may run that loop 200,000 times.
The algorithm can be logically correct and still be operationally ridiculous.
The better question is not:
Which location should receive the next unit?
It is:
How many units can I give this location before the economic ranking changes?
That small change in framing can turn an algorithm that scales with total supply into one that scales with the number of meaningful economic breakpoints.
In many real supply chain problems, that is the difference between hundreds of thousands of iterations and a few dozen.
The actual decision
Suppose you have a limited quantity of product and many competing destinations.
The destinations could be:
- Stores.
- Fulfillment centers.
- Regions.
- Dealers.
- Customers.
- Plants.
- Programs.
For destination i, let:
x_i = units allocated to destination i
The basic problem is:
maximize sum_i V_i(x_i)
subject to sum_i x_i <= S
where S is the globally available supply and V_i(x_i) is the economic value of allocating x_i units to destination i.
That value might include:
- Expected sales.
- Expected gross margin.
- Lost-sales avoidance.
- Service protection.
- Inventory holding cost.
- Markdown risk.
- Expediting cost.
- Strategic guardrails.
The hard part is rarely writing x_i.
The hard part is defining V_i(x_i) honestly.
Ask these questions before building the allocator
Before choosing an algorithm, ask:
- What is actually scarce?
- What can the business really control?
- At what level is the allocation executed?
- When does the value of another unit change?
- Are units truly interchangeable?
- Which constraints are hard and which are policy preferences?
- What happens after this allocation is executed?
- How often will the decision be rerun?
These questions matter more than whether the final implementation uses a heap, a MILP, dynamic programming, or a custom greedy algorithm.
If the warehouse can only ship full cases, the decision variable should not pretend individual units are executable.
If a location can only receive one truck per day, transportation structure matters.
If the business reruns allocation tomorrow with new information, you may not need to solve a perfect 26-week deterministic plan today.
Model the decision you actually have.
The slow version
Assume each destination has a marginal value curve.
For example, the first units sent to a location may be extremely valuable because they prevent stockouts. Later units may still be useful but less urgent. Eventually, more inventory creates little value or even destroys value through holding cost and markdown risk.
A simple allocator might do this:
- Compute the current marginal value of one more unit for every destination.
- Select the destination with the highest value.
- Allocate one unit.
- Update that destination’s marginal value.
- Repeat until supply is exhausted.
This can work.
It can also be painfully slow.
If supply is 200,000 units, the outer loop may run 200,000 times even when the economic ranking changes only 80 times.
The algorithm is paying for physical units when the problem is structured around economic breakpoints.
The key observation
Suppose a destination’s marginal value is constant over a range.
For example:
- Units 0-20 have marginal value 14.
- Units 21-50 have marginal value 9.
- Units 51-90 have marginal value 4.
- Units above 90 have marginal value 0.
If that destination currently has the highest marginal value, there is no reason to allocate one unit, compare again, allocate another unit, and repeat twenty times.
Nothing changed.
The ranking cannot change until one of these things happens:
- The destination reaches its next value breakpoint.
- Another destination becomes more attractive.
- A capacity limit is reached.
- A guardrail activates.
- Global supply is exhausted.
So allocate directly to the next event.
That is chunked allocation.
A practical policy structure
For each destination i, represent the value curve as segments:
(b_i0, b_i1, m_i1)
(b_i1, b_i2, m_i2)
...
where:
b_i,kis a breakpoint.m_i,kis the marginal value within that segment.
At any point, the policy is:
- Find the destination with the highest current marginal value.
- Determine how far it can move before its marginal value changes.
- Apply any remaining caps or guardrails.
- Allocate that entire chunk.
- Advance to the next segment.
- Repeat.
Conceptually:
Delta_i = min(
next breakpoint distance,
remaining cap,
remaining global supply
)
Then:
x_i <- x_i + Delta_i
You are still following marginal value priority.
You are just not pretending that identical decisions need to be reconsidered one unit at a time.
A small example
Suppose three locations compete for 100 units.
Location A:
- First 30 units: marginal value 12.
- Next 40 units: marginal value 6.
Location B:
- First 20 units: marginal value 10.
- Next 50 units: marginal value 5.
Location C:
- First 25 units: marginal value 8.
- Next 50 units: marginal value 3.
The allocation sequence is:
- Give A 30 units at value 12.
- Give B 20 units at value 10.
- Give C 25 units at value 8.
- Give A the remaining 25 units at value 6.
The unit-by-unit version makes 100 allocation decisions.
The breakpoint version makes four.
Same economic logic.
Very different runtime behavior.
Can the same curve be selected twice?
Yes.
This is important.
A destination can be best now, lose priority after reaching a breakpoint, and become relevant again later.
Suppose A has marginal values:
- 12 for the first 30 units.
- 6 for the next 40.
B has:
- 10 for the first 20.
- 5 after that.
A is selected first at 12.
Then B is selected at 10.
Then A is selected again at 6.
So chunking does not mean allocating each destination once.
It means allocating until the ranking can change.
That distinction matters.
Where the curves come from
The breakpoint algorithm is the easy part.
The value curves are the real model.
They can come from several places.
Analytical economics
For simple inventory problems, marginal value can be derived from expected underage and overage costs.
A unit may be valuable because it reduces expected lost margin, but less valuable as inventory coverage increases.
Probabilistic forecasts
A demand distribution can be converted into expected economic value at different inventory positions.
This is better than treating the point forecast as truth.
The question is not:
Is demand 100?
The question is:
What is the expected economic consequence of moving inventory position from 80 to 90 given what we currently know?
Simulation
If the system is too complicated for a clean formula, simulate the consequences of different target positions or policy parameters.
For each candidate level, estimate metrics such as:
- Expected profit.
- Fill rate.
- Lost sales.
- Ending inventory.
- Markdown exposure.
- Expedites.
Then convert the evaluated response surface into usable marginal-value segments.
Optimization subproblems
Sometimes the value of supply at a node comes from a downstream optimization problem.
That can work, but be careful. If every marginal-value query requires solving another expensive model, you may move the runtime problem instead of solving it.
Precomputation, caching, approximation, and breakpoint extraction become important.
Uncertainty is not an afterthought
A deterministic value curve built from one forecast can be dangerously confident.
Real supply allocation faces uncertainty in:
- Demand.
- Lead time.
- Supplier reliability.
- Existing inventory accuracy.
- Future replenishment.
- Returns.
- Cancellations.
- Substitution.
- Execution timing.
There are several practical ways to handle this.
One is to build the value curve from expected economics over scenarios:
V_i(x_i) = E_omega[C_i(x_i, omega)]
Another is to include explicit risk terms:
V_i_risk(x_i) = E[C_i] - lambda * Risk_i(x_i)
You can also evaluate the final allocation policy through replay or Monte Carlo simulation.
The important point is that the allocator should not confuse the forecast with the decision.
A forecast describes uncertainty.
The value curve translates that uncertainty into economics.
The allocator makes the decision.
Constraints that break naive greedy logic
Breakpoint allocation works beautifully when the problem is mostly separable and the scarce resource is global supply.
Real systems are often messier.
Common constraints include:
- Minimum shipment quantities.
- Case packs.
- Truck capacities.
- Vendor minimums.
- Regional quotas.
- Store presentation minimums.
- Fairness requirements.
- Maximum days of supply.
- Warehouse throughput.
- Budget limits.
- Product substitution.
- Shared capacity across products.
Some can be handled directly in the chunk logic.
Others create coupling that can invalidate a simple greedy ranking.
For example, if sending any quantity to a location triggers a fixed truck cost, the value of the first unit depends on whether the rest of the shipment is sent.
That is not a clean independent marginal curve.
Likewise, if products share a constrained truck and have different cube, the scarce resource may be cubic volume rather than units.
Do not force every problem into water-filling because the algorithm is fast.
Use it when the economics support it.
When to use a MILP instead
A MILP is often the better choice when you have strong combinatorial coupling:
- Fixed-charge decisions.
- Binary activation.
- Complex logical constraints.
- Shared capacities across many dimensions.
- Sequence dependencies.
- Network design choices.
You can also combine approaches.
A practical architecture might be:
- Use probabilistic economics to build value curves.
- Use breakpoint allocation for the large separable part of the problem.
- Use a MILP for the smaller coupled decision layer.
- Simulate the final policy under uncertainty.
The goal is not to prove loyalty to one algorithm.
The goal is to make a good decision in time to execute it.
Implementation notes
Use a priority queue
Maintain the current segment for each destination in a max-heap keyed by marginal value.
The loop becomes:
- Pop the best current segment.
- Allocate the feasible chunk.
- If the destination has another segment, push it back with its new marginal value.
Runtime is then driven by segment transitions rather than units allocated.
Make tie-breaking deterministic
Equal marginal values are common.
Define a stable tie-break rule such as:
- Higher strategic priority.
- Lower current coverage.
- Earlier need date.
- Stable destination ID.
If tie-breaking is random or dependent on data ordering, planners will see unexplained allocation changes between runs.
That destroys trust quickly.
Keep an audit trail
For every chunk, record:
- Destination.
- Starting allocation.
- Ending allocation.
- Marginal value.
- Breakpoint reached.
- Constraint that stopped the chunk.
- Remaining global supply.
A fast allocator that nobody can explain is not production-ready.
Validate equivalence
If you are replacing a unit-by-unit algorithm, run both implementations on small and medium historical cases.
Compare:
- Final allocation.
- Objective value.
- Constraint violations.
- Tie-breaking behavior.
- Runtime.
Do not assume the chunked version is equivalent because it looks mathematically obvious.
Guardrails, rounding, floating-point tolerances, and hidden side effects can change behavior.
Metrics that actually matter
Do not stop at runtime.
Track:
- Economic objective value.
- Expected profit or cost.
- Service outcomes.
- Lost sales.
- Excess inventory.
- Allocation stability.
- Number of breakpoint events.
- Runtime by stage.
- Percentage of supply constrained by guardrails.
- Percentage of recommendations overridden.
A 100x faster algorithm is not better if planners override half the output.
Likewise, a mathematically elegant allocator is not useful if it finishes after the shipping cutoff.
Common failure modes
Building curves from a point forecast
This creates false precision and often pushes too much inventory toward locations with noisy upside.
Use distributions or scenario-based economics when uncertainty matters.
Too many artificial breakpoints
If every unit becomes its own segment, you have rebuilt the unit-by-unit algorithm with more code.
Compress ranges where marginal value is effectively constant.
Ignoring the real scarce resource
If truck cube is constrained but you rank by value per unit, the allocation can be economically wrong.
Rank against the resource that is actually scarce.
Hiding policy rules inside the code
Hard-coded spill logic, fairness adjustments, and exceptions eventually become invisible business policy.
Represent them explicitly and log when they bind.
Comparing only final totals
Two algorithms can allocate the same total supply and produce very different economic outcomes.
Compare destination-level decisions and downstream results.
Optimizing the algorithm before validating the economics
A bad value curve evaluated quickly is still a bad decision system.
Get the economic ordering right first.
Then make it fast.
What to do in practice
Start with the current allocator.
Ask one question:
When does the ranking actually change?
If the answer is “only when a target, cap, or value threshold is reached,” then you probably do not need to move one unit at a time.
Identify those events.
Turn them into breakpoints.
Allocate directly to the next event.
Then validate the new algorithm against the old one, preserve deterministic tie-breaking, log every chunk, and evaluate the final policy under uncertainty.
The broader lesson is bigger than supply allocation.
Many slow algorithms repeat decisions even when nothing meaningful has changed.
Good optimization is often not about finding a more exotic solver.
Sometimes it is just recognizing the structure that was already there.