It descends from Hadley and Whitin and appears in most textbooks.
\[ C(r,Q) \approx \frac{k\lambda}{Q} + h\left(\frac{Q}{2} + r - \theta\right) + \frac{\pi\lambda}{Q}\,G^{1}(r) \]
It is not unreasonable. It is worth knowing exactly what it assumes, because the assumptions are not stated where you can see them.
At most one order is outstanding, so the cycle is clean.
Shortages are priced per cycle, with \(\pi\) a cost per unit short rather than per unit per unit time.
The on-hand level is \(Q/2 + r - \theta\), which drops the backorder term.
And in most presentations, a continuous family is fitted to a count, usually the normal.
On the transformer, against the exact answer:
| Source | Effect on reported cost |
|---|---|
| The structural assumptions | \(-3.98\%\) |
| Fitting a continuous family | \(+6.34\%\) |
| What is reported | \(\mathbf{+2.11\%}\) |
A method that comes close because two errors offset has not been validated by coming close.
Nothing guarantees the offset on the next item.
The exact evaluation is a short table of loss functions.
The approximation is a closed form that needs the same table anyway if you want \(G^{1}(r)\).
The approximation was a computational convenience in 1963. It is not one now.
The optimal band straddles the optimal base-stock level:
\[ r^{*} < S^{*} \le r^{*} + Q^{*} \]
And the optimal cost is bracketed between the deterministic cost and the two reference costs added in quadrature.
Both are cheap, and both are checks you can run on an answer produced by software you did not write.
The bounds say that everything the deterministic chapters established about what drives performance continues to hold once demand is random.
\(Q\) is still driven by the ordering cost against the holding cost.
The randomness adds a layer; it does not overturn the structure.
\[ C(r,Q) = \frac{k\lambda}{Q} + \frac{1}{Q}\sum_{s=r+1}^{r+Q}C(s) \]
where \(C(s)\) is the base-stock cost at level \(s\).
An \((r,Q)\) policy costs the ordering term plus the average of \(Q\) consecutive base-stock costs.
And \(C(s)\) is convex.
The best \(r\) for a given \(Q\) takes the \(Q\) smallest values of \(C(s)\).
Convexity puts those next to one another.
Adding one more value lowers the average exactly when the value added is below it.
That is a stopping rule, not a convergence criterion.
optimize(r, Q):
// 0, initialize at the base-stock optimum
find S*, the smallest S with G(S) >= b/(b+h)
Q <- 1
r <- S* - 1
Cstar <- k*lambda + C(S*)
loop:
// 1, the next smallest base-stock cost
c <- min( C(r), C(r+Q+1) )
// 2, stop
if c >= Cstar: return r, Q, Cstar
// 3, widen the window
Q <- Q + 1
Cstar <- Cstar - (Cstar - c)/Q
if C(r) was the smaller: r <- r - 1
The exact integer optimum, in a finite number of steps.
No search in two dimensions. No derivative. Nothing to converge.
The loop runs at most \(Q^{*}\) times.
A worksheet cannot loop, and it does not have to: lay out one row per step and let each row read the row above.
\(\lambda = 45\), \(k = \$220\), \(h = \$950\), \(b = \$8{,}550\), \(\theta = 7.5\).
\[ r^{*} = 8, \qquad Q^{*} = 7, \qquad C^{*} = \$7{,}225.15 \]
Check the bound: \(S^{*} = 11\), and indeed \(8 < 11 \le 15\). ✓
The window \(\{9, \ldots, 15\}\) holds the seven cheapest base-stock levels.
\(Q^{*} = 7\) against an EOQ of 5: the randomness widened the batch a little, but the ordering economics still set its scale.
The approximation on this item reports about 2 percent high, and lands on a neighbouring policy. On a fast mover it does better; on a slow expensive one it does worse.
The exact method costs nothing extra. Use it.
An item whose optimal batch is 2,842 is not a curiosity.
The algorithm still terminates, but the loop runs \(Q^{*}\) times.
This is where a worksheet gives out: it can only unroll as many rows as you laid down.
It is the reason to write a program at all.
Next: what to do when nobody will name a backorder cost, when demand arrives in lots, and when you cannot watch the item continuously.