Rounding Is Part of the Optimization Model
Why solving a continuous approximation and rounding afterward can quietly destroy feasibility, economics, and the decision you thought you optimized.
A surprisingly common optimization architecture looks like this:
- Solve an easier continuous problem.
- Get a beautiful answer like 137.4 units.
- Round it to something executable.
- Send the rounded answer downstream.
This can work. It can also completely change the problem.
If the business buys in cases of 24, books full trucks, opens suppliers only after a minimum commitment, or shares a vendor MOQ across dozens of SKUs, then 137.4 was never an executable decision. The actual decision might be 120 or 144. And those two choices can have very different economics.
The mistake is treating rounding as formatting.
Rounding is often decision logic.
Start with the decision the business can actually make
Suppose a planner decides how much to order for SKU (i). If arbitrary units are allowed, we might write
[ x_i \ge 0. ]
But suppose the supplier ships only in cases of (p_i) units. Then the executable decision is better represented as
[ x_i = p_i k_i, ]
where
[ k_i \in \mathbb{Z}_{+}. ]
That integer variable is not mathematical decoration. It represents the actual action available to the business.
This sounds obvious when written down. In production systems it gets blurred constantly. One service optimizes units, another service converts units to cases, another applies MOQ rules, and a final service caps the recommendation against capacity. By the time the order reaches the supplier, nobody can reproduce the economics of the original optimization run.
Before writing the model, ask:
- What exactly can the operator commit to?
- In what increments?
- Which increments are SKU-specific, vendor-specific, lane-specific, or facility-specific?
- Which decisions trigger fixed costs?
- Which minimums apply to individual items and which apply to groups?
- Can quantities be rounded up, rounded down, or only changed through a specific feasible move?
- What happens when two rounding rules conflict?
Those questions define the action space.
Why nearest-integer rounding is not neutral
Consider a simple inventory decision. The continuous model recommends 137 units. The product ships in cases of 24.
The nearby feasible choices are 120 and 144.
A generic rounding rule might choose 144 because it is numerically closer. But numerical distance from 137 is irrelevant to the business objective.
Suppose the expected economics are:
| Quantity | Expected lost-margin cost | Expected holding/markdown cost | Total expected cost |
|---|---|---|---|
| 120 | $310 | $70 | $380 |
| 144 | $90 | $190 | $280 |
| 168 | $45 | $410 | $455 |
Then 144 is sensible, but not because it is closest to 137. It is sensible because it has the best expected economics among the executable choices.
Change the margin, remaining shelf life, demand distribution, or lead time and 120 may become better.
The correct rounding direction is state dependent.
Shared constraints make local rounding dangerous
The problem becomes more serious when decisions are coupled.
Suppose a vendor has 100 SKUs and a purchase-order minimum of $50,000. The continuous solution assigns quantities independently and totals $49,600.
A post-processing script now has to somehow add $400 of product.
Which SKU should receive it?
The one with the largest forecast?
The highest margin?
The smallest case pack?
The item closest to stocking out?
None of those rules is generally correct. The relevant question is which feasible increment has the highest marginal economic value given the current state and all other constraints.
If the model already knows the vendor MOQ, case packs, capacity, demand economics, and inventory position, pushing that decision into a generic rounding layer throws away exactly the information needed to make it well.
This is why local rounding can destroy a globally sensible solution.
The action space may be discrete in more than one way
Real supply-chain decisions rarely have only one integer rule.
You may have:
- eaches packed into cases,
- cases packed onto pallets,
- pallet minimums by SKU,
- dollar MOQs across a vendor,
- container capacity across SKUs,
- fixed fees for opening a purchase order,
- tiered freight rates,
- supplier production batches,
- facility receiving limits,
- budget shared across vendors.
A useful formulation might include variables such as
[ k_i = \text{number of cases ordered for SKU } i, ]
[ y_v = \begin{cases} 1 & \text{if vendor } v \text{ is activated},\ 0 & \text{otherwise}, \end{cases} ]
and
[ z_t = \text{number of trucks or containers used}. ]
Then quantities follow from the physical structure:
[ x_i = p_i k_i. ]
A vendor MOQ might be
[ \sum_{i \in I_v} c_i x_i \ge M_v y_v, ]
with linking constraints preventing purchases when the vendor is not opened.
Transportation might require
[ \sum_i w_i x_i \le C z_t. ]
Now the model is choosing among executable bundles rather than inventing a fractional plan and hoping a downstream script can repair it.
But do not make everything integer just because you can
The opposite mistake is also common.
Someone notices rounding errors and converts every variable in the model to integer. Runtime explodes. The team concludes that MILP cannot scale.
The right question is not, “Can this variable be integer?”
It is, “Does the business actually make this decision discretely?”
Inventory balance variables often do not need to be integer even if order quantities do. Cost variables usually do not need integrality. Auxiliary quantities may remain continuous. Some large-volume flows are operationally divisible enough that treating them as continuous is perfectly reasonable.
Integrality should follow the action, not anxiety about decimals.
Sometimes optimize first and repair second is exactly right
There are cases where embedding every discrete detail directly in one MILP is too expensive.
That does not mean you should round blindly. It means the repair problem deserves its own objective and constraints.
Suppose the main optimization produces a target vector (x^*). You can solve a smaller repair problem over executable quantities (x):
[ \min_x \quad \text{economic loss}(x) + \lambda D(x,x^*) ]
subject to the actual pack, MOQ, capacity, and budget constraints.
The distance term (D(x,x^*)) keeps the repaired plan near the original solution when that is useful, but economic loss should remain visible. Otherwise the repair model can preserve numerical similarity while destroying business value.
For some systems, a decomposition works well:
- Solve a relaxed global allocation problem.
- Identify the discrete boundaries that matter.
- Build a smaller integer repair problem around those boundaries.
- Re-evaluate the repaired plan under the original economics.
This can be much better than either extreme: a massive monolithic MILP or naive per-variable rounding.
Uncertainty makes rounding more important, not less
Under uncertainty, the value of the next case is not determined by the point forecast.
Suppose current inventory is 80 units and the next case adds 24. Demand over the relevant exposure period is uncertain.
The incremental value of that case depends on the distribution of outcomes where those 24 units actually change what happens. In low-demand scenarios they may become excess. In high-demand scenarios they may prevent lost sales. In some scenarios the order may arrive too late to matter because lead time is also uncertain.
A simulation-based estimate of the incremental value can be written conceptually as
[ \Delta V = \mathbb{E}[V(x+24, W) - V(x, W)], ]
where (W) represents uncertain demand, lead time, availability, returns, or other relevant information.
That expected marginal value is far more useful than asking whether 144 is mathematically closer to 137 than 120 is.
If tail outcomes matter, also inspect the distribution of (\Delta V), not just its mean. A case may have slightly negative expected value but materially reduce severe stockout exposure. Whether that trade is worthwhile depends on the actual economics and risk policy.
A practical policy structure
For very large ordering systems, directly solving every discrete decision globally may still be too expensive. A practical alternative is to define executable atomic moves.
For example, a move could be:
Add one case of SKU A to vendor V’s order.
Or:
Open this MOQ branch, which requires adding a bundle of cases across several SKUs.
Or:
Add the next pallet, which unlocks these quantities while consuming this much receiving capacity.
Each move has:
- incremental expected value,
- incremental cost,
- capacity consumption,
- feasibility implications,
- interaction with already selected moves.
The algorithm can repeatedly select attractive feasible moves and recompute values when coupling matters.
This is not generic rounding. It is discrete optimization expressed in the language of the business.
Measure decision regret, not rounding error
A common diagnostic is average absolute rounding error:
[ \frac{1}{n}\sum_i |x_i - x_i^*|. ]
That metric can be useful for debugging, but it says almost nothing about whether the resulting plan is good.
A one-unit difference on a low-value item may be irrelevant. Crossing a truck threshold by one case may add thousands of dollars. Missing a vendor MOQ by $1 can make the entire order infeasible.
Better metrics include:
- expected profit or cost after discretization,
- regret versus the best executable decision,
- feasibility-repair frequency,
- value lost in post-processing,
- number of recommendations changed by the rounding layer,
- capacity or MOQ violations before repair,
- service, stockout, markdown, and obsolescence outcomes,
- solver runtime added by explicit discreteness,
- stability of the executable decision across uncertainty samples.
One metric I particularly like is post-processing value loss:
[ L = V(x^*) - V(\hat{x}), ]
where (x^*) is the model’s intended plan and (\hat{x}) is what the business actually executes after rounding and repair.
If that number is large, your production optimization architecture has a hole in it.
Log the transformation chain
Production systems should make the decision trace reproducible.
For every recommendation, log at least:
- raw optimizer quantity,
- executable increment,
- rounded or repaired quantity,
- reason for the change,
- binding MOQ or capacity rule,
- objective value before repair,
- re-evaluated objective after repair,
- solver status and gap where relevant,
- model and policy version.
If a planner asks why the system ordered 144 units, “the optimizer said 137.4 and we rounded it” is not an acceptable explanation.
The answer should be closer to:
Orders must be placed in cases of 24. Among the feasible quantities around the relaxed target, 144 had the best expected economics after considering current inventory, demand uncertainty, the vendor MOQ, and available receiving capacity.
That is a decision explanation.
Failure modes I would actively test
1. Independent rounding violates a shared constraint
Every SKU looks fine alone, but the combined plan exceeds a truck, budget, production, or warehouse limit.
Test: round all variables exactly as production does, then run a full feasibility check against the original business constraints.
2. Rounding down destroys service economics
A conservative rounding rule systematically under-orders items with asymmetric stockout costs.
Test: compare up/down alternatives using common uncertainty scenarios.
3. Rounding up creates hidden excess
The system always rounds to the next case to avoid stockouts, accumulating slow-moving inventory across thousands of SKUs.
Test: measure incremental holding, markdown, and obsolescence cost attributable specifically to discretization.
4. Repair order determines the answer
A sequential script fixes SKU A, then B, then C. Changing the processing order produces a different plan.
That is a sign the repair procedure is solving a coupled optimization problem badly.
Test: randomize processing order. If economics move materially, replace the sequence with an explicit repair optimization or better global heuristic.
5. The model optimizes units while finance pays for thresholds
Freight, setup, handling, or supplier fees jump at discrete boundaries, but the objective smooths them away.
Test: reconcile modeled costs against the actual invoice logic at every threshold.
6. Integrality is added everywhere and runtime collapses
The team fixes a real rounding problem by making unrelated state and accounting variables integer.
Test: classify every integer variable by the physical or contractual action it represents. If nobody can explain the discreteness, relax it and benchmark again.
What I would do in practice
Start by mapping the executable action space. Do not start with solver settings.
Take a representative set of real decisions and document the chain from optimizer output to executed order. Find every place where quantities are rounded, capped, bumped to a minimum, converted to packs, combined into a shipment, or manually repaired.
Then quantify how much those transformations matter economically.
If post-processing almost never changes the recommendation and the value loss is negligible, keep the architecture simple. You do not get extra points for turning a harmless approximation into a giant MILP.
If post-processing frequently changes decisions, breaks constraints, or creates material economic loss, move the important discrete logic closer to the optimization. That might mean explicit integer variables, a structured repair MILP, executable atomic moves, or a simulation-based discrete search.
Finally, evaluate the executed policy, not the elegant pre-rounded solution. Run the complete production transformation inside your historical replay or simulation harness. If the backtest evaluates 137.4 units but production orders 144, you are testing a policy that does not exist.
The larger lesson
Optimization is supposed to choose actions.
A fractional quantity can be a useful mathematical intermediate. It is not automatically a business decision.
When the world is discrete, the boundaries matter: cases, pallets, trucks, MOQs, setup decisions, budgets, capacity blocks, and contractual thresholds. Those boundaries are often exactly where the economics become interesting.
So do not ask whether your rounded solution is close to the continuous solution.
Ask whether it is the best decision you can actually execute.