11 Simulating Inventory Systems
After reading this chapter you should be able to:
- recognize when an inventory question requires simulation rather than analysis, and say what a simulated answer costs
- represent the state variables of an inventory policy as a sequence of events
- compute time averages from a sample path as a simulation computes them
- validate a simulation against an exact result before trusting it beyond one
- apply appropriate output analysis to a non-terminating inventory simulation
- simulate continuous review, periodic review and two-level systems, and compare policies using common random numbers
- build a small supply network with the KSL’s supply chain package
11.1 When the Formulas Stop
Ten chapters have computed the performance of inventory policies, and every computation has had the same shape. A model was stated, its assumptions were listed, and a number came out that was exact when the assumptions held. Where they did not hold, an approximation took over, and the chapter priced what the approximation cost. This chapter adds a third route to the same numbers, and the only one that reaches every case.
11.1.1 Three Routes to One Number
Recall from Section 7.10 that the book has simulated once already. The newsvendor’s expected profit was estimated by sampling 100,000 demands at each of five quantities, and every estimate in Table 7.8 covered the exact value. That section drew a conclusion that this chapter adopts as its method: simulation belongs after the closed form, not instead of it.
The reason is that a simulation is a program, and a program can be wrong without saying so. An exact formula is checked once, by derivation. A simulation is checked by running it on a case whose answer is already known and seeing the answer come back. That is, the agreement in Table 7.8 was not a curiosity; it was the evidence that the sampling code computed the newsvendor’s cost and not something near it. Section 7.12.4 made the same point about the software: two routes that share one cost function can be checked against each other, and two that do not, cannot.
A simulation is trusted only after it reproduces a number the book has already derived. Every model in this chapter is built to that rule. It first reproduces a result from an earlier chapter, inside its half-width, and only then is one assumption behind that result removed. For example, Section 11.3 simulates the transformer at its optimal policy \((8, 7)\) and checks the estimate against the exact cost of $7,225.15 from Example 8.7. Section 11.5 then lets the transformer’s orders cross, and no formula in the book is available to check that case.
11.1.2 Where the Exact Route Ends
Each earlier chapter said where its exactness ended. Four of those boundaries are crossed by nothing in the book except this chapter.
Lost sales. Recall from Section 1.3.2 that a demand which cannot be filled may depart rather than wait. Every formula of Chapter 8 assumes that it waits. The usual remedy is to charge a lost sale as though it were a backorder, and whether that remedy is close for a given item is a question only a model of the lost-sales system can answer.
Orders that overtake one another. Section 8.5.4 showed that a random lead time leaves the \((r, Q)\) formulas intact, provided orders arrive in the sequence they were placed. Section 10.11 repeated the condition and called the correction beyond its scope. A simulation has no such condition. It delivers each order when that order’s own lead time ends, in whatever sequence results.
Job lots at a batching hub. Example 10.10 found policies for a two-level system whose customers take one, two or four units at a time. Nothing exact covers that case, and the example closed by handing it to this chapter.
How wrong METRIC is for a particular system. Example 9.4 predicted 0.4055 backorders per storeroom for the transformer, and Example 9.5 predicted 0.4815 for the same system. The two differ by 19%, and Graves (1985) tells us how often each one errs across many systems. Neither tells us which one is closer for this one. A simulation of the two-level system does.
In addition, some answers in the book are exact but were hard to reach. The \((s, S)\) costs of Section 8.12 came from solving a Markov chain, and a simulation of the same policy is a second, independent route to them. That is the agreement rule used in reverse: an exact result the reader cannot easily recompute is checked by a simulation they can.
11.1.3 What a Simulated Answer Costs
A simulation answers questions no formula reaches, and it charges for the service in three ways.
Every answer is an estimate. A simulated cost is a sample average with a half-width, and a cost reported without its half-width reports a number that is not there. Recall from Section 7.10 that the half-width shrinks with the square root of the run. Thus, ten times the precision costs a hundred times the run.
Every answer is for one policy. The exact route of Section 8.8 searched a cost function it could evaluate exactly at any policy it chose. A simulation evaluates one policy per run, with noise, so finding the best policy is a search over noisy estimates. That is a harder problem than the one it replaces, and Section 11.7 treats it only briefly.
The run is measured in demands, not in years. The transformer sees 45 demands a year. A thousand simulated years is 45,000 demands, which is a modest sample for estimating a backorder that occurs a few times a year. Section 11.4 turns that into a run length.
None of these costs applies to the formulas, which is why the formulas come first wherever they exist.
11.1.4 What This Chapter Assumes
The chapter builds its models with the KSL, the Kotlin Simulation Library, and it assumes the reader has met discrete-event simulation. The mechanics of the event calendar, of replications, and of the statistical analysis of simulation output are the subject of Rossetti (2026), and this chapter refers to that book rather than repeating it. Its chapter on output analysis and its chapter on event modeling are the two this chapter leans on most. Appendix E shows how to run the companion code.
What this chapter adds is the inventory side. That is, it says which events an inventory policy consists of, which statistics a stock point needs, and how each model is checked against the analysis in the earlier chapters. The next section starts with the events.
11.2 The Inventory Processes as Events
Recall from Section 8.1 that an \((r, Q)\) system carries five state variables: \(I(t)\) on hand, \(\mathit{IO}(t)\) on order, \(B(t)\) backordered, the net inventory \(\mathit{IN}(t) = I(t) - B(t)\), and the inventory position \(\mathit{IP}(t) = I(t) + \mathit{IO}(t) - B(t)\). Table 8.2 traced them through thirteen weeks at the storeroom. This section traces the same thirteen weeks again, this time the way a simulation does.
11.2.1 What Changes the State
An event is an instant at which the state of the system changes. Between two events nothing changes, so each state variable is constant from one event to the next. Thus, the five variables are step functions of time, and a simulation needs to compute them only at the events.
An \((r, Q)\) system with backorders has two events.
- A demand. One unit is requested. If the shelf has stock, \(I\) falls by one; otherwise \(B\) rises by one. Either way, \(\mathit{IP}\) falls by one.
- A receipt. An order of \(Q\) units arrives. \(\mathit{IO}\) falls by \(Q\) and \(I\) rises by \(Q\), and then the backorders are filled from the new stock, first come first served. \(\mathit{IP}\) does not change.
Notice what is missing from the list: placing an order. Placing an order changes \(\mathit{IO}\) and \(\mathit{IP}\), but it never happens at an instant of its own. It happens inside a demand, at the moment the demand lowers the position to \(r\). That is, an order is a decision taken during an event, not an event.
What the decision does is schedule one. An order placed at time \(t\) creates a receipt at time \(t + L\), and that receipt waits in the event calendar, the list of future events in time order. The simulation proceeds by removing the earliest event from the calendar, advancing the clock to its time, and carrying out its changes, which may add new events to the calendar. Table 11.1 lists both events, the changes each one makes, and what each one schedules.
| Event | Changes to the state | Decision taken | Schedules |
|---|---|---|---|
| Demand | \(I \leftarrow I - 1\) if \(I > 0\), otherwise \(B \leftarrow B + 1\); \(\mathit{IP} \leftarrow \mathit{IP} - 1\) | If \(\mathit{IP} \le r\), order \(Q\): \(\mathit{IO} \leftarrow \mathit{IO} + Q\), \(\mathit{IP} \leftarrow \mathit{IP} + Q\) | The next demand; a receipt at \(t + L\) if an order was placed |
| Receipt | \(\mathit{IO} \leftarrow \mathit{IO} - Q\), \(I \leftarrow I + Q\), then fill \(\min(B, I)\) backorders | None | Nothing |
Notice that the demand event schedules its own successor. Demands arrive in a Poisson process, so the time to the next demand is exponential with mean \(1/\lambda\), and the simulation samples it when the current demand occurs. In Table 8.2 the demand times were simply given. A simulation draws them.
11.2.2 Averages Over Time, Accumulated at Events
The measures of Section 8.2 are time averages. Recall from Section 9.5.3.1 that a time average weights each value by how long it held, and that averaging the rows of a ledger instead gives a number that is not an average of anything the system did. A simulation never makes that mistake, because it never sees the rows. It sees the intervals between them.
Let \(t_0 = 0 < t_1 < t_2 < \cdots\) represent the times of successive events, and let \(A_I(t) = \int_0^t I(u)\,du\) represent the area under the on-hand curve up to time \(t\). Since \(I\) is constant between events, the area grows by a rectangle at each one:
\[ A_I(t_n) = A_I(t_{n-1}) + I(t_{n-1})\,(t_n - t_{n-1}) \tag{11.1}\]
The order of operations is the whole of the method. The area is updated before the event changes the state, using the value that held during the interval just ended. Updating it afterward would credit the interval with the new value, which the system did not hold.
The same rule accumulates \(A_B(t)\), the area under \(B(t)\). Let \(A_{+}(t)\) represent the total time up to \(t\) during which \(I > 0\), accumulated the same way with \(I(t_{n-1})\) replaced by 1 when the shelf held stock and by 0 when it did not. At the end of an observation of length \(T\), the averages are areas divided by time:
\[ \bar{I} = \frac{A_I(T)}{T}, \qquad \bar{B} = \frac{A_B(T)}{T}, \qquad \overline{\mathit{RR}} = \frac{A_{+}(T)}{T} \tag{11.2}\]
Rossetti (2026) calls a quantity averaged this way time-persistent, and the KSL’s TWResponse class computes it with exactly the update of Equation 11.1. A quantity recorded once per occurrence, such as whether a demand was filled, is observation-based, and its average is a plain average over the occurrences; the KSL’s Response class collects it. The fill rate is the second kind. Let \(N_D(t)\) represent the number of demands up to time \(t\) and \(N_F(t)\) the number filled from the shelf on arrival. Then
\[ \overline{\mathit{FR}} = \frac{N_F(T)}{N_D(T)} \tag{11.3}\]
Notice that the two service measures of Section 8.2.2 come out of different machinery. The ready rate is a time-persistent average and the fill rate is an observation-based one. That is why they can differ on any finite run, whatever the demand process.
11.2.3 The Storeroom’s Thirteen Weeks as Events
Example 11.1 (The storeroom ledger, accumulated as a simulation would) We return to the storeroom of Example 8.1. The transformer has demand of \(\lambda = 45\) units a year arriving one at a time, an eight-week lead time, and the policy \((r, Q) = (4, 5)\). The observation starts with 6 on hand, none on order and nothing owed. The ten demands arrive in weeks 1, 2, 3, 5, 6, 7, 8, 9, 11 and 13, exactly as before, and the observation closes at week 13.
What is stocked? One item, the transformer.
What is the demand process? Single-unit demands; in this example their times are given rather than sampled.
When is inventory reviewed? Continuously, at every demand.
What triggers replenishment, and how much? The position reaching \(r = 4\) or below, and the order is for \(Q = 5\).
What happens to unmet demand? It is backordered and filled first come first served.
What costs are incurred, and when? None is needed here. The example computes the averages that Equation 8.1 prices.
Notation. The ledger carries \(I\), \(B\) and \(\mathit{IP}\) after each event, the areas \(A_I\), \(A_B\) and \(A_{+}\) through each event’s time, and the calendar’s receipts. \(\mathit{IO}\) is five times the number of receipts on the calendar, so it is not carried as a column.
We begin at \(t_0 = 0\) with \(I = 6\), \(B = 0\), \(\mathit{IP} = 6\), all three areas at zero, and an empty calendar.
The demand at week 1 is the first event. Before the state changes, the interval from week 0 to week 1 is credited: \(A_I\) grows by \(6 \times 1 = 6\), and \(A_{+}\) grows by 1 because the shelf held stock. Then the demand is filled, so \(I\) and \(\mathit{IP}\) fall to 5.
The demand at week 2 credits \(5 \times 1\) to \(A_I\), making 11, and one more week to \(A_{+}\). Then \(I\) and \(\mathit{IP}\) fall to 4, the position has reached \(r\), and the decision is taken: order 5. The position rises to 9, and a receipt is scheduled for week \(2 + 8 = 10\).
The table has been updated as follows.
| Week | Event | \(I\) | \(B\) | \(\mathit{IP}\) | \(A_I\) | \(A_B\) | \(A_{+}\) | Receipts due |
|---|---|---|---|---|---|---|---|---|
| 0 | start | 6 | 0 | 6 | 0 | 0 | 0 | none |
| 1 | demand | 5 | 0 | 5 | 6 | 0 | 1 | none |
| 2 | demand, order 5 | 4 | 0 | 9 | 11 | 0 | 2 | week 10 |
The demands at weeks 3, 5, 6 and 7 are each filled. The interval before week 5 is two weeks long, so that event credits \(3 \times 2 = 6\) to \(A_I\), which is where row averaging and time averaging part company. By week 7 the shelf is empty and \(A_I = 24\). The interval from week 7 to week 8 is then credited with nothing, since \(I = 0\) throughout it, and \(A_{+}\) stops growing at 7.
The demand at week 8 finds the shelf empty and is backordered, so \(B\) becomes 1 and the position falls to 4. The decision is taken again: order 5, the position returns to 9, and a second receipt joins the calendar for week 16. The demand at week 9 first credits one backorder-week to \(A_B\), since \(B = 1\) held from week 8 to week 9, and is then backordered itself, so \(B\) becomes 2.
The table has been updated as follows.
| Week | Event | \(I\) | \(B\) | \(\mathit{IP}\) | \(A_I\) | \(A_B\) | \(A_{+}\) | Receipts due |
|---|---|---|---|---|---|---|---|---|
| 0 | start | 6 | 0 | 6 | 0 | 0 | 0 | none |
| 1 | demand | 5 | 0 | 5 | 6 | 0 | 1 | none |
| 2 | demand, order 5 | 4 | 0 | 9 | 11 | 0 | 2 | week 10 |
| 3 | demand | 3 | 0 | 8 | 15 | 0 | 3 | week 10 |
| 5 | demand | 2 | 0 | 7 | 21 | 0 | 5 | week 10 |
| 6 | demand | 1 | 0 | 6 | 23 | 0 | 6 | week 10 |
| 7 | demand | 0 | 0 | 5 | 24 | 0 | 7 | week 10 |
| 8 | demand backordered, order 5 | 0 | 1 | 9 | 24 | 0 | 7 | weeks 10, 16 |
| 9 | demand backordered | 0 | 2 | 8 | 24 | 1 | 7 | weeks 10, 16 |
The receipt at week 10 is the earliest event on the calendar, ahead of the demand at week 11, so the clock advances to it. It first credits the interval from week 9 to week 10, during which \(B = 2\), so \(A_B\) becomes 3. Then the five units arrive, the two backorders are filled from them, and \(I = 3\) with \(B = 0\). The position stays at 8, as a receipt’s always does. The demands at weeks 11 and 13 are filled, the second one crediting \(2 \times 2 = 4\) for the two weeks before it.
| Week | Event | \(I\) | \(B\) | \(\mathit{IP}\) | \(A_I\) | \(A_B\) | \(A_{+}\) | Receipts due |
|---|---|---|---|---|---|---|---|---|
| 0 | start | 6 | 0 | 6 | 0 | 0 | 0 | none |
| 1 | demand | 5 | 0 | 5 | 6 | 0 | 1 | none |
| 2 | demand, order 5 | 4 | 0 | 9 | 11 | 0 | 2 | week 10 |
| 3 | demand | 3 | 0 | 8 | 15 | 0 | 3 | week 10 |
| 5 | demand | 2 | 0 | 7 | 21 | 0 | 5 | week 10 |
| 6 | demand | 1 | 0 | 6 | 23 | 0 | 6 | week 10 |
| 7 | demand | 0 | 0 | 5 | 24 | 0 | 7 | week 10 |
| 8 | demand backordered, order 5 | 0 | 1 | 9 | 24 | 0 | 7 | weeks 10, 16 |
| 9 | demand backordered | 0 | 2 | 8 | 24 | 1 | 7 | weeks 10, 16 |
| 10 | receipt of 5 | 3 | 0 | 8 | 24 | 3 | 7 | week 16 |
| 11 | demand | 2 | 0 | 7 | 27 | 3 | 8 | week 16 |
| 13 | demand | 1 | 0 | 6 | 31 | 3 | 10 | week 16 |
With \(T = 13\) weeks, Equation 11.2 and Equation 11.3 give
\[ \bar{I} = \frac{31}{13} = 2.3846, \qquad \bar{B} = \frac{3}{13} = 0.2308, \qquad \overline{\mathit{RR}} = \frac{10}{13} = 0.7692, \qquad \overline{\mathit{FR}} = \frac{8}{10} = 0.8000 \]
and the storeroom placed two orders, a rate of \(2/13 = 0.1538\) a week.
The check. Two identities must hold, and both catch a misplaced credit. First, the shelf was empty from week 7 to week 10, so \(A_{+}(13)\) plus those three weeks must be the whole observation: \(10 + 3 = 13\). Second, the area under \(B\) is the total time demands spent waiting. The week 8 demand waited two weeks and the week 9 demand waited one, which is 3 backorder-weeks, and \(A_B(13) = 3\). That is Little’s law, exactly as Section 9.5.3.1 found it, and it gives the average wait per demand as \(3/10 = 0.3\) weeks either way. That check is worth performing on every event ledger, because an area credited after the state changed fails it at once.
Interpretation. Averaging the rows of Table 11.4 would give \(27/12 = 2.25\) for on hand and \(3/12 = 0.25\) for backorders. Both are wrong, and the second is wrong by the same 0.25 against 0.2308 that Section 9.5.3.1 warned about. Notice also that the ready rate, 0.7692, and the fill rate, 0.8000, disagree although nothing here is unusual. Ten demands is a small sample of the shelf’s state, and Equation 8.2 is a statement about the long run.
Validation, and its limit. Given these demand times, there is nothing random left, so a correct simulation must reproduce Table 11.4 exactly, row for row, and not merely within a half-width. That makes the ledger the first test of the companion code: the model of Section 11.3 is driven by these ten demand times and its trace is compared with the table.
The companion code passes that test. Driven by these ten demand times, the model of Section 11.3 posts eleven events whose states and areas equal Table 11.4 to the last digit, and it ends at week 13 with \(A_I = 31\), \(A_B = 3\) and \(A_{+} = 10\). Its two orders and its receipt fall on the same rows as the ledger’s.
What the ledger cannot test is everything that depends on chance: whether the demand times are sampled correctly, and whether the long-run averages approach the values of Chapter 8. In addition, the observation starts with 6 on hand and nothing on order, which is not where the system usually is, and a thirteen-week average is dominated by that start. Section 11.3 takes up the first question and Section 11.4 the second.
The event view adds nothing to the policy. The changes in Table 11.1 are the rows of Table 8.2, stated once as rules instead of once per week. What it adds is a way of computing averages that cannot be done by hand for a year of demands, and does not need to be: Equation 11.1 is the same rectangle each time. Section 11.3 turns these rules into a KSL model and asks it the question the ledger could not, which is whether its long-run averages agree with the exact ones.
11.3 Building the (r, Q) Model
The model of this section is the one Rossetti (2026) builds in its chapter on event modeling. The companion code copies it rather than depending on it, so that its names can follow this book’s notation and it can carry the options the later sections need. Its structure is Table 11.1 turned into code. The demand event is a method that fills the unit from the shelf or owes it, and then takes the decision. The receipt event is a method that moves units from on order to on hand and fills what is owed. The decision is a third method, which compares the position with \(r\) and orders the fewest whole batches that lift it above \(r\). With demand one unit at a time that is always one batch; with demand in lots it can be more, and Section 11.5 needs it to be right.
Notice what the stock point does not know: how its orders are filled. It hands each order to a supplier, an object whose only obligation is to deliver the order eventually, and the supplier decides when. Here the supplier waits a constant two months. Section 11.5 replaces it with one whose lead times vary, and Section 11.8 with another stock point, and the stock point’s own code changes in neither case. Section 11.10 lists the classes.
The decision is the shortest of the three, and it is the policy:
override fun checkPosition() {
if (inventoryPosition <= reorderPoint) {
val batches = (reorderPoint - inventoryPosition) / orderQuantity + 1
placeOrder(batches * orderQuantity)
}
}Here inventoryPosition is \(\mathit{IP} = I + \mathit{IO} - B\), and reorderPoint and orderQuantity are \(r\) and \(Q\). The division is between whole numbers, so batches is \(\lfloor (r - \mathit{IP})/Q \rfloor + 1\), the fewest batches that lift the position above \(r\). placeOrder adds the order to \(\mathit{IO}\) and hands it to the supplier.
The demand event takes what the shelf can give and owes the rest:
val now = minOf(onHand, amount)
if (now > 0) {
myOnHand.decrement(now.toDouble())
receiver?.receive(now)
}
val rest = amount - now
// ...
myBackordered.increment(rest.toDouble())
myOwed.enqueue(Owed(rest, receiver, time))
// ...
checkPosition()myOnHand and myBackordered are \(I\) and \(B\), each a KSL TWResponse, so every change to them closes a rectangle of Equation 11.1. myOwed is the queue of backordered demands, filled first come first served. receiver is null for a customer and is the ordering stock point when the demand is another location’s order, which is the seam Section 11.10.2 builds on. The decision comes last, after the state has changed.
The receipt reverses the order of the demand’s bookkeeping:
fun receiveReplenishment(amount: Int) {
myOnOrder.decrement(amount.toDouble())
myOnHand.increment(amount.toDouble())
fillOwed()
checkPosition()
// ...
}myOnOrder is \(\mathit{IO}\). fillOwed gives the new stock to the backorder queue in its order, part of a lot if only part is on hand. Notice that the receipt calls the decision too, although under \((r, Q)\) it can never order: a receipt leaves the position where it was. The call costs nothing and keeps every policy free to react to a receipt.
Example 11.2 (The transformer at its optimal policy, simulated) The storeroom runs the transformer at the policy Example 8.7 found, \((r, Q) = (8, 7)\). Demand is \(\lambda = 45\) units a year, the supplier takes exactly two months, an order costs \(k = \$220\), a unit held costs \(h = \$950\) a year, and a unit owed costs \(b = \$8{,}550\) a year. Every measure of this policy is known exactly, so the simulation has nothing to discover. Its purpose is to show that it can reproduce what is known.
What is stocked? One item, the pad-mount transformer.
What is the demand process? Poisson at 45 a year, one unit per demand.
When is inventory reviewed? Continuously, at every demand.
What triggers replenishment, and how much? The position reaching \(r = 8\) or below, and the order is for \(Q = 7\).
What happens to unmet demand? It is backordered and filled first come first served.
What costs are incurred, and when? \(k\) for each order placed, \(h\) per unit per year on hand, and \(b\) per unit per year owed, as Equation 8.1 prices them.
Notation. The model works in years, so the lead time is \(L = 1/6\) year and the time between demands is exponential with mean \(1/45\) year. The run settings are the chapter’s standard ones from Section 11.4.3: \(n = 30\) replications of \(T = 1{,}000\) years after a warm-up of \(T_w = 20\) years. Each replication starts with \(r + Q = 15\) on hand and nothing on order.
The values to reproduce. Table 11.5 lists every measure the model reports, with its exact value from Example 8.7 and Example 8.12.
| Measure | Exact | Simulated |
|---|---|---|
| \(\bar{I}\), units | 4.6617 | 4.6570 \(\pm\) 0.0107 |
| \(\bar{B}\), units | 0.1617 | 0.1628 \(\pm\) 0.0020 |
| \(\overline{\mathit{RR}}\) | 0.8781 | 0.8779 \(\pm\) 0.0009 |
| \(\overline{\mathit{FR}}\) | 0.8781 | 0.8776 \(\pm\) 0.0010 |
| \(\overline{\mathit{OF}}\), orders a year | 6.4286 | 6.4333 \(\pm\) 0.0105 |
| Ordering cost | $1,414.29 | $1,415.32 \(\pm\) 2.30 |
| Holding cost | $4,428.59 | $4,424.13 \(\pm\) 10.20 |
| Backorder cost | $1,382.28 | $1,392.05 \(\pm\) 16.94 |
| Total cost | $7,225.15 | $7,231.50 \(\pm\) 15.42 |
The check. Each exact value should lie inside its interval. With nine measures at 95% each, one miss is not alarming and two are worth a look; the intervals are not independent, since all nine come from the same runs. Two identities must also hold within each replication, whatever the random numbers: \(\bar{I} - \bar{B}\) must equal the average net inventory, and the ready rate and fill rate must agree to within their half-widths, by Equation 8.2.
Every one of the nine intervals covers its exact value, and the ready rate and fill rate agree to the third decimal, 0.8779 against 0.8776, as Equation 8.2 requires.
Interpretation. A storeroom running \((8, 7)\) holds about four and two thirds transformers on average, owes about one sixth of one, and orders six or seven times a year, at a cost the simulation puts at $7,231.50 \(\pm\) $15.42 a year. None of that is news; chapter 8 said it exactly. What the agreement licenses is the machinery: the events, the decision, the supplier and the areas all do what Section 11.2 says they do, on a run of 45,000 demands per replication in which a systematic error of a fraction of a unit would have shown.
Validation, and its limit. Agreement here establishes the model under two assumptions, a constant lead time and single-unit Poisson demand, and under no others. Section 11.5 removes them one at a time, and from then on there is no exact column to compare with.
11.3.1 Where This Leaves Us
The model reproduces chapter 8 where chapter 8 is exact. Before it is trusted anywhere else, the run settings it used need justifying: how long to run, where to start, and how many replications to make. Section 11.4 does that.
11.4 Output Analysis for a Stock Point
Example 11.1 produced four averages from thirteen weeks, and none of them is an estimate of anything Chapter 8 computed. The run was too short, it started from a state chosen for convenience, and it was one run. This section says how long to run, how to begin, how many runs to make, and how to report what comes out. The methods are those of Rossetti (2026), whose chapter on the analysis of simulation output treats them in full. What follows is their use on a stock point, and the two places where a stock point needs more care than a queue.
11.4.1 A Stock Point Never Terminates
Rossetti (2026) separates simulations whose runs have a natural end from those that do not. A bank that closes at five o’clock is the first kind. A storeroom is the second: the item is stocked permanently and demand arrives forever, so there is no last customer to stop at. Every measure in Chapter 8 is a long-run average, the value the time average approaches as the observation grows without bound. Thus, a simulation of a stock point is a non-terminating simulation, and what it estimates is the steady state.
That has two consequences. The run must be long enough for its average to be close to the long-run one, and it must not be distorted by where it began. The second is the one specific to inventory, so we take it first.
11.4.2 Where to Start the Run
A run has to begin somewhere, and no state the modeler writes down is typical. Example 8.1 began with 6 on hand and nothing on order. The KSL book’s inventory model begins by default with \(r + Q\) on hand and nothing on order. Both are states the system passes through, but in the long run it is rarely in either. For the transformer at \((8, 7)\), starting with 15 on hand and nothing on order puts the shelf far above its long-run average of 4.66 units. With nothing in transit, the whole position is on the shelf, and it stays there until demand draws it down.
The bias of the start is temporary, and for an \((r, Q)\) policy its length can be reasoned out. Recall Equation 8.17: the net inventory at time \(t\) is the position at time \(t - L\) less the demand in between. Thus, the start is forgotten once two things have happened. A lead time must have passed, so that every unit in transit was ordered by the policy rather than assumed at the start. In addition, the position must have cycled through its band of \(Q\) values often enough that its value is no longer predictable from the start, which takes a few multiples of \(Q/\lambda\), the time to consume one batch.
For the transformer at \((8, 7)\) that is a lead time of one sixth of a year and a cycle of \(7/45 = 0.16\) years. A year of simulated time, about 45 demands, is several of each, and the start should be forgotten well within it.
That argument is particular to this policy. For a system that offers no such argument, the general method is the Welch plot of Rossetti (2026): plot the on-hand level averaged across replications at each instant, smooth it with a moving window, and choose the warm-up \(T_w\) as the time after which the smoothed curve no longer trends. Statistics collected before \(T_w\) are discarded, and the averages are taken over the remainder of the run.
Choose the warm-up long rather than short. The cost of discarding too much is run time, which is cheap for a stock point. The cost of discarding too little is a bias that no number of replications removes, because every replication carries the same one. The chapter’s runs use \(T_w = 20\) years for the transformer, which is far longer than the reasoning above requires, and it costs 2% of the run.
11.4.3 Replications and Their Length
The method used throughout this chapter is replication-deletion. Let \(n\) represent the number of replications, let \(T\) represent the length of each replication after its warm-up, and let \(Y_j\) represent the time average of some measure over replication \(j\), for \(j = 1, \ldots, n\). The replications use independent random numbers, so \(Y_1, \ldots, Y_n\) are independent and identically distributed, and the textbook confidence interval applies to them:
\[ \bar{Y} = \frac{1}{n}\sum_{j=1}^{n} Y_j, \qquad \mathit{hw} = t_{n-1,\,\alpha/2}\,\frac{s_Y}{\sqrt{n}} \tag{11.4}\]
Here \(s_Y\) is the sample standard deviation of the \(Y_j\) and \(\mathit{hw}\) is the half-width of a \(100(1-\alpha)\%\) confidence interval, \(\bar{Y} \pm \mathit{hw}\). Recall from Section B.2.2 that the half-width falls with \(\sqrt{n}\).
Notice what is being averaged. Within one replication, successive values of \(I(t)\) are strongly dependent: the shelf an hour from now is nearly the shelf now. Equation 11.4 never uses those values directly. It uses one number per replication, and the dependence within a replication is absorbed into that number’s variance. That is why the method is safe, and it is also why each replication must be long. A short replication produces an average dominated by a few lead times, and the \(Y_j\) then scatter widely.
The alternative is batch means, one long run cut into consecutive batches whose averages are treated as nearly independent. It spends the warm-up once rather than \(n\) times. For a stock point, whose warm-up is short, that saving is small, and replication-deletion is the simpler of the two to report. The interested reader should refer to Rossetti (2026) for batch means and for the tests that justify a batch size.
Measure the run in demands, not in years. Information arrives with demands. The transformer sees 45 a year, so a run of \(T = 1{,}000\) years is 45,000 demands, about 6,400 orders, and about 5,500 backordered demands at the optimal policy’s fill rate of 0.8781. The fuse cutout of Section 8.11 sees 400 job lots a year, so the same number of demands takes about 112 years. Thus, run lengths are stated per item, and a run length copied from one item to another is a guess.
The chapter’s standard settings for the transformer are \(n = 30\) replications of \(T = 1{,}000\) years after a warm-up of \(T_w = 20\) years. The rest of this section explains how to check whether they are enough.
11.4.4 Three Fill Rates, and How to Average Each
Recall from Equation 11.3 that a replication’s fill rate is a ratio of two counts, \(N_F(T)/N_D(T)\). Across replications there are two ways to combine those ratios. One averages the \(n\) ratios. The other adds up the counts first and divides once, \(\sum N_F / \sum N_D\). When every replication sees nearly the same number of demands, the two agree to several decimals. The interval should be computed from the per-replication ratios, since those are the independent observations Equation 11.4 needs.
The larger question is which ratio to collect, and it arises as soon as a demand can be for more than one unit. Recall from Section 8.11.4 that job lots split the fill rate in two. The unit fill rate is the proportion of units demanded that are filled from the shelf on arrival, and the lot fill rate is the proportion of lots filled complete on arrival. The ready rate, the proportion of time with stock on the shelf, is a third measure. Under single-unit Poisson demand all three coincide by Equation 8.2. Under job lots they separate. For example, a lot of four that finds two on the shelf counts as unfilled for the lot fill rate and as two of four units for the unit fill rate, while it arrived at an instant that counts toward the ready rate.
Chapter 8 computed all three exactly for the fuse cutout at \((r, Q) = (25, 75)\): a ready rate of 0.9060, a unit fill rate of 0.8978 and a lot fill rate of 0.8957 (Table 8.21). A simulation can collect all three at no extra cost: a counter for lots filled complete, a counter for units filled, and a time-persistent indicator of stock on hand. Name the one you report. Section 11.5 runs the cutout, reproduces those three figures, and then measures them under an \((s, S)\) policy, where chapter 8 did not compute them.
11.4.5 How Many Replications
Fix the precision first and let it set \(n\). Suppose we want the cost of the transformer at \((8, 7)\) to within 1% of its value, that is, a half-width of about $72 on $7,225.15. A pilot run of \(n_0\) replications gives a sample standard deviation \(s_0\) and a half-width \(\mathit{hw}_0\). Since the half-width falls with \(\sqrt{n}\), the number of replications needed for a target half-width \(\mathit{hw}^{*}\) is approximately
\[ n \approx n_0 \left(\frac{\mathit{hw}_0}{\mathit{hw}^{*}}\right)^{2} \tag{11.5}\]
rounded up. Rossetti (2026) gives the more careful version, which iterates on the \(t\) quantile; at the sample sizes used here the difference is a replication or two.
For the transformer at \((8, 7)\), a pilot of \(n_0 = 10\) replications of \(T = 1{,}000\) years gives \(s_0 = \$33.69\) and \(\mathit{hw}_0 = \$24.10\). That is already a third of the target, and Equation 11.5 gives
\[ n \approx 10\left(\frac{24.10}{72}\right)^{2} = 1.1 \]
so the pilot itself meets the 1% target with room, and the standard \(n = 30\), whose half-width is $15.42 in Table 11.5, meets it easily. Shorter replications change the answer. With \(T = 100\) years the pilot gives \(s_0 = \$120.41\) and \(\mathit{hw}_0 = \$86.14\), and
\[ n \approx 10\left(\frac{86.14}{72}\right)^{2} = 14.3 \]
so 15 replications of a hundred years are needed for the same precision.
Notice that \(n\) and \(T\) trade against each other. Doubling \(T\) roughly halves the variance of each \(Y_j\), which does what doubling \(n\) does, at the same total run time. The trade is not quite even, because each replication spends a warm-up, but for a stock point the warm-up is short and either lever works.
11.4.6 The Measure That Needs the Longest Run
A single run length does not deliver the same precision for every measure. The cost and the on-hand average are estimated well by a modest run, because they change at every demand. The backorder average is the hard one.
Recall from Example 8.4 that at \((9, 5)\) the mean backorder level is 0.1202 units but its standard deviation is 0.582, nearly five times larger. The typical state is no backorders at all, interrupted by occasional episodes of several. A time average of such a process is driven by how many episodes the run contains, and episodes are rare. Thus, the relative half-width \(\mathit{hw}/\bar{Y}\) of \(\bar{B}\) is far larger than that of \(\bar{I}\) from the same run, and it grows as the policy improves. At \((11, 5)\), where the fill rate is 0.9683, a demand is backordered about a third as often as at \((9, 5)\).
The standard runs show it. At \((8, 7)\) the relative half-widths are 0.23% for \(\bar{I}\), 1.22% for \(\bar{B}\), 0.12% for the fill rate and 0.21% for the cost. At \((11, 5)\) they are 0.20%, 2.24%, 0.06% and 0.11%. Thus, the backorder level is the least precise measure by a factor of five or more, and it is the only one that gets less precise as the service improves.
The rule that follows is simple. Set the run length by the hardest measure you will quote, which is usually the backorder level of a well-served item, and check its relative half-width before quoting it. At \((11, 5)\) the cost is known to about a tenth of a percent while the backorder level is known only to about two percent, because backorders are a small share of the cost, and a report that quotes both should say so.
None of this can be checked against a formula until a model exists to run. Section 11.3 builds it, and the first thing it does is run the transformer at \((8, 7)\) with these settings and compare every measure with Example 8.7.
11.5 Where the (r, Q) Formulas Stop
Example 11.2 rests on three assumptions that the formulas of Section 8.5 need and the model does not: orders arrive in the sequence they were placed, demand arrives one unit at a time, and a demand that finds the shelf empty waits. This section removes them one at a time. Each example changes one component of the validated model and nothing else: the supplier, then the demand process with the policy that suits it, then the rule for an unmet demand. Thus, whatever changes in the results is the effect of the assumption removed, and not of a new model.
11.5.1 Orders That Overtake One Another
Example 11.3 (The transformer from an unreliable supplier) The transformer’s supplier no longer delivers in exactly two months. As in case 3 of Example 8.2, each order passes through four stages averaging half a month each, a purchase order, a production slot, a shipment and a receiving inspection, so its lead time is Erlang with shape 4 and rate 24 a year: two months on average, with a standard deviation of one month. Table 8.7 found the best policy for this supplier at \((r, Q) = (10, 8)\), costing $11,079.73 a year, and Section 8.5.4 stated the condition under which that figure holds: orders must arrive in the sequence they were placed.
Two supply arrangements give each order the same Erlang lead time and differ only in that condition.
- Independent lead times. Each order takes its own lead time, whatever happened to earlier orders, so a later order can arrive first.
- One supply line. Orders queue for the four stages in sequence, so an order is received at its own lead time or at the receipt of the order before it, whichever is later. No order overtakes another, and an order can be delayed by its predecessor.
Neither arrangement is the one Table 8.7 assumed, since independent lead times and an unbroken sequence cannot both hold. The question is how far each is from the figure chapter 8 computed, and in which direction.
What is stocked? One item, the pad-mount transformer.
What is the demand process? Poisson at 45 a year, one unit per demand.
When is inventory reviewed? Continuously, at every demand.
What triggers replenishment, and how much? The position reaching \(r = 10\) or below, and the order is for \(Q = 8\).
What happens to unmet demand? It is backordered and filled first come first served.
What costs are incurred, and when? \(k = \$220\) an order, \(h = \$950\) per unit per year on hand and \(b = \$8{,}550\) per unit per year owed.
Notation. Let \(L_m\) represent the lead time drawn for the \(m\)-th order and \(t_m\) the time it was placed. Under independent lead times the \(m\)-th order is received at \(t_m + L_m\). Under one supply line it is received at \(\max(t_m + L_m,\ \text{the receipt time of order } m - 1)\). The model records, for each order, whether it arrived ahead of an order placed before it. The standard run settings apply.
The prediction. With lead time demand negative binomial with \(r = 4\) and \(p = 0.3478\), exact for an Erlang lead time by Example 8.2, the formulas of Section 8.5 give Table 11.6.
Both arrangements are run with common random numbers. They face the same demands, and since the decision never looks at when an order will arrive, they place the same orders and draw the same lead times for them. Only the rule for delivering an order differs.
| Measure | Chapter 8 | Independent lead times | One supply line |
|---|---|---|---|
| \(\bar{I}\), units | 7.3360 | 7.1860 \(\pm\) 0.0250 | 7.0717 \(\pm\) 0.0257 |
| \(\bar{B}\), units | 0.3360 | 0.2047 \(\pm\) 0.0044 | 0.3652 \(\pm\) 0.0079 |
| \(\overline{\mathit{FR}}\) | 0.8913 | 0.9053 \(\pm\) 0.0012 | 0.8822 \(\pm\) 0.0015 |
| \(\overline{\mathit{OF}}\), orders a year | 5.6250 | 5.6290 \(\pm\) 0.0092 | 5.6290 \(\pm\) 0.0092 |
| \(\overline{\mathit{IO}}\), units | 7.5 | 7.5183 \(\pm\) 0.0271 | 7.7930 \(\pm\) 0.0309 |
| Orders that overtake another | none | 9.11% \(\pm\) 0.16% | none |
| Total cost | $11,079.73 | $9,815.07 \(\pm\) 31.47 | $11,078.65 \(\pm\) 55.13 |
The check. Two relations must hold under both arrangements. The order rate is \(\lambda/Q = 5.625\) a year whatever the lead times do, since every order is for eight units and all demand is eventually filled. In addition, the average net inventory is the average position less the average number of units on order: \(\bar{I} - \bar{B} = r + (Q+1)/2 - \overline{\mathit{IO}}\), which is \(14.5 - \overline{\mathit{IO}}\) here. By Little’s law \(\overline{\mathit{IO}}\) is \(\lambda\) times the average time an order spends outstanding. Under independent lead times that time is \(1/6\) year and \(\overline{\mathit{IO}} = 7.5\); under one supply line it is longer, because an order can wait for its predecessor, and the model measures it.
Both relations hold. The order rates cover 5.625. Under independent lead times \(\bar{I} - \bar{B} = 6.9813\) against \(14.5 - 7.5183 = 6.9817\), and an order is outstanding 0.1670 year on average. Under one supply line \(\bar{I} - \bar{B} = 6.7065\) against \(14.5 - 7.7930 = 6.7070\), and an order is outstanding 0.1731 year, about two days longer, because one order in eleven waits for the order ahead of it.
Interpretation. Under independent lead times, about one order in eleven overtakes an earlier one, and the policy runs $1,264.66 a year, or 11.4%, cheaper than chapter 8 predicts, with 39% fewer backorders. Section 10.11 said the model over-protects when orders overtake one another, and this is by how much. A supplier whose orders cross is better than the formula gives it credit for, because a late order is often covered by the next one arriving early.
Under one supply line, the cost matches chapter 8 to within its half-width, but not because the formula describes that arrangement. The supply line holds orders back, so there are fewer units on hand and more owed than the formula predicts, and the two errors nearly cancel in the cost. Thus, the agreement of a total is weak evidence that a model is right. Here the components disagree, and the components are what the storeroom would see.
Validation, and its limit. The lead time machinery has its own exact check. At base stock 11, which is \((r, Q) = (10, 1)\), Section B.3.3 says the number of units on order is Poisson with mean 7.5 whatever the lead time distribution, so the measures are those of Example 8.3 even with Erlang lead times and orders crossing. The simulation gives 7.5049 \(\pm\) 0.0128 on order, a ready rate of 0.8621 \(\pm\) 0.0014 against 0.8622, backorders of 0.1616 \(\pm\) 0.0024 against 0.1616, and on hand of 3.6567 \(\pm\) 0.0114 against 3.6616. Nothing exact covers \(Q = 8\), which is the point of the example. In addition, the policy \((10, 8)\) was chosen for chapter 8’s formula; under independent lead times a lower reorder point may be cheaper still, and Exercise 11.6 asks a related question.
11.5.2 Job Lots and the (s, S) Policy
Example 11.4 (The cutout under an order-up-to rule, simulated) The fuse cutout of Example 8.8 is drawn in job lots of one, two or four units, with probabilities 0.40, 0.40 and 0.20, at 400 lots a year. The supplier takes two weeks. An order costs \(k = \$82.50\), a unit held costs \(h = \$28.75\) a year and a unit owed costs \(b = \$287.50\) a year. Example 8.9 priced two \((s, S)\) policies exactly, by solving the Markov chain of the inventory position, and this example reproduces those prices by a different route.
What is stocked? One item, the fuse cutout.
What is the demand process? Lots arrive in a Poisson process at 400 a year, each of one, two or four units.
When is inventory reviewed? Continuously, at every lot.
What triggers replenishment, and how much? The position reaching \(s\) or below, and the order brings it up to \(S\), so the order size is random.
What happens to unmet demand? A lot is filled from what is on the shelf and the remainder is backordered, first come first served, as Section 8.11 assumed.
What costs are incurred, and when? \(k\) for each order placed, \(h\) per unit per year on hand, and \(b\) per unit per year owed.
Notation. The model works in years, with \(L = 1/26\) year. Let \(U\) represent the undershoot of Equation 8.55, recorded at every order. The run is measured in lots, so \(T = 112\) years gives about the 45,000 demands of the transformer’s standard run; \(n = 30\) and \(T_w = 5\) years.
The values to reproduce. Table 11.7 collects what Example 8.9 computed at two policies: one where the spread \(S - s\) is wide and the \((r, Q)\) approximation is good, and one where it is narrow and the correction of Equation 8.59 is needed.
| \((36, 56)\) exact | simulated | \((25, 100)\) exact | simulated | |
|---|---|---|---|---|
| \(S - s\) | 20 | 75 | ||
| Cost, a year | $3,755.69 | $3,755.96 \(\pm\) 5.88 | $2,010.10 | $2,009.86 \(\pm\) 2.66 |
| Orders a year | 38.462 | 38.466 \(\pm\) 0.066 | 10.554 | 10.558 \(\pm\) 0.018 |
| \(E[U]\), units | 0.8 | 0.8015 \(\pm\) 0.0068 | 0.8 | 0.7966 \(\pm\) 0.0086 |
The undershoot has the distribution Example 8.9 gave: 0 half the time, 1 unit three times in ten, and 2 or 3 units one time in ten each. The simulation observes 0.5009, 0.2975, 0.1008 and 0.1008 at \((36, 56)\), and 0.4995, 0.3021, 0.1007 and 0.0977 at \((25, 100)\).
| Ready rate | Unit fill rate | Lot fill rate | |
|---|---|---|---|
| \((r, Q) = (25, 75)\), exact | 0.9060 | 0.8978 | 0.8957 |
| \((r, Q) = (25, 75)\), simulated | 0.9059 \(\pm\) 0.0010 | 0.8977 \(\pm\) 0.0010 | 0.8958 \(\pm\) 0.0010 |
| \((s, S) = (25, 100)\), simulated | 0.9072 \(\pm\) 0.0011 | 0.8989 \(\pm\) 0.0011 | 0.8968 \(\pm\) 0.0011 |
| \((s, S) = (36, 56)\), simulated | 0.9219 \(\pm\) 0.0009 | 0.9107 \(\pm\) 0.0012 | 0.9076 \(\pm\) 0.0012 |
The check. The observed undershoot distribution should match the equilibrium distribution of Equation 8.56 closely, value by value, since both spreads are wide compared with a lot of at most four, and the mean order size must be \(S - s + E[U]\) by Equation 8.58. Both are checks on how the model handles a lot that carries the position past \(s\).
Both hold. The observed frequencies match the equilibrium distribution to the second decimal at both spreads, and the mean order size is 20.8015 at \((36, 56)\) and 75.7966 at \((25, 100)\), which is \(S - s\) plus the observed undershoot in each case.
Interpretation. Every exact figure is covered: the two costs, the two order rates, the undershoots, and in Table 11.8 all three of chapter 8’s service measures at \((25, 75)\). The three measures, which coincided for the transformer, separate here by about a point: the ready rate exceeds the unit fill rate, which exceeds the lot fill rate, at every policy. Thus, a storeroom quoting its ready rate of 0.92 at \((36, 56)\) is filling 0.91 of the units its crews ask for and 0.91 of their job lots complete, and the difference is the lots that arrive to a shelf holding some cutouts but not enough. Notice also that \((s, S) = (25, 100)\) and \((r, Q) = (25, 75)\) are indistinguishable on service and on cost; Table 8.23 said as much, since a spread of 75 against lots of at most four leaves the undershoot nothing to do.
Validation, and its limit. The costs are exact, and so are the three service measures at \((r, Q) = (25, 75)\), so together they validate the model under job lots. The service measures under \((s, S)\) are where the simulation reports something Chapter 8 did not compute.
11.5.3 Demand That Is Lost
Example 11.5 (The transformer when a crew will not wait) A crew that finds no transformer on the shelf now buys one from another utility at $9,500, against a stock price of $3,800, and the storeroom’s demand is lost. That is the shortage cost \(\pi = \$5{,}700\) per unit short of Example 8.6, and with it chapter 8’s exact search found the best \((r, Q)\) at \((13, 6)\), costing $11,892.91 a year. That figure treats a unit short as owed. This example asks what happens when it is lost instead.
What is stocked? One item, the pad-mount transformer.
What is the demand process? Poisson at 45 a year, one unit per demand.
When is inventory reviewed? Continuously, at every demand that is filled.
What triggers replenishment, and how much? The position reaching \(r\) or below, and the order is for \(Q = 6\).
What happens to unmet demand? It is lost. The demand departs and nothing is owed, so a lost demand does not lower the inventory position.
What costs are incurred, and when? \(k = \$220\) for each order placed, \(h = \$950\) per unit per year on hand, and \(\pi = \$5{,}700\) for each unit lost.
Notation. Let \(N_L(T)\) represent the number of demands lost by time \(T\), so the lost sales rate is \(N_L(T)/T\). Under lost sales \(B(t) = 0\) throughout, and the position is \(I(t) + \mathit{IO}(t)\). The standard run settings apply, at two policies: \((13, 6)\), where a shortage is rare, and \((8, 6)\), where it is not.
The prediction. Charging a lost unit as though it were backordered gives the figures of Table 11.9, computed exactly from Equation 8.19 and Equation 8.20 with shortages counted at the rate \(\lambda(1 - \overline{\mathit{FR}})\).
| \((13, 6)\), backorder model | lost sales, simulated | \((8, 6)\), backorder model | lost sales, simulated | |
|---|---|---|---|---|
| \(\overline{\mathit{FR}}\) | 0.9934 | 0.9944 \(\pm\) 0.0002 | 0.8595 | 0.9070 \(\pm\) 0.0006 |
| Units short a year | 0.2961 | 0.2530 \(\pm\) 0.0077 | 6.3214 | 4.1872 \(\pm\) 0.0334 |
| \(\bar{I}\), units | 9.0052 | 9.0469 \(\pm\) 0.0131 | 4.1873 | 4.7400 \(\pm\) 0.0087 |
| Orders a year | 7.5 | 7.4633 \(\pm\) 0.0122 | 7.5 | 6.8075 \(\pm\) 0.0086 |
| Ordering cost | $1,650.00 | $1,641.92 \(\pm\) 2.69 | $1,650.00 | $1,497.64 \(\pm\) 1.89 |
| Holding cost | $8,554.91 | $8,594.53 \(\pm\) 12.45 | $3,977.94 | $4,503.04 \(\pm\) 8.29 |
| Shortage cost | $1,688.00 | $1,442.29 \(\pm\) 43.84 | $36,032.23 | $23,867.23 \(\pm\) 190.34 |
| Total cost | $11,892.91 | $11,678.73 \(\pm\) 46.09 | $41,660.17 | $29,867.92 \(\pm\) 186.80 |
The check. Every demand is either filled or lost, so the fill rate and the lost fraction must add to one exactly in each replication. In addition, orders are placed at the rate filled demand consumes stock, so the order rate must be \(\lambda\,\overline{\mathit{FR}}/Q\), which is below the \(\lambda/Q = 7.5\) a year the backorder model charges for.
Both hold. At \((13, 6)\) the lost fraction is \(0.2530/45 = 0.0056\), which is \(1 - 0.9944\), and \(45(0.9944)/6 = 7.458\) orders a year lies inside the simulated 7.4633 \(\pm\) 0.0122. At \((8, 6)\) the lost fraction is \(4.1872/45 = 0.0930 = 1 - 0.9070\), and \(45(0.9070)/6 = 6.8025\) lies inside 6.8075 \(\pm\) 0.0086.
Interpretation. At \((13, 6)\) the backorder model is close. It overstates the cost by $214, or 1.8%, almost all of it in the shortage term, because fewer units go short when a lost demand leaves the position where it was. Shortages are rare at this policy, so it hardly matters what happens to them. At \((8, 6)\) it is far off: the backorder model charges 6.3 units short a year, the lost-sales system loses 4.2, and the total is overstated by $11,792, or 39% of the true cost. The mechanism is the one the check exposed. A lost demand never lowers the position, so the system orders less often, the shelf recovers before the next demand finds it empty, and the fill rate rises from the backorder model’s 0.8595 to 0.9070. Thus, charging lost sales as backorders is safe for a policy that seldom runs short, which is the only kind worth running at \(\pi = \$5{,}700\), and badly pessimistic for one that runs short often.
Validation, and its limit. Nothing in the book computes a lost-sales system, so the only checks are the identities above and the agreement of the lost-sales model with the validated backorder model when \(r\) is high enough that no demand is short. The example is the case Section 1.3.2 anticipated, and the remedy it tests is the one Section 11.1 named.
11.5.4 Where This Leaves Us
Each of the three examples changed one component and kept the rest, which is the discipline that lets a simulated difference be read as the effect of one assumption. Section 11.6 changes a different thing: not what happens to demand, but when anyone looks at the stock.
11.6 Periodic Review
Periodic review changes when the decision is taken. Under \((r, Q)\) the decision rides on the demand event. Under periodic review it rides on a review, a third event that the policy schedules for itself every \(R\) time units, starting when the replication starts. A demand still changes \(I\), \(B\) and \(\mathit{IP}\), but it takes no decision. That is the only change to the model. Thus, Example 11.6 can validate it against the exact formulas of Section 8.13 before the next two examples use it for questions those formulas answer only by comparison or by approximation.
Example 11.6 (The transformer reviewed monthly, simulated) The storeroom reviews the transformer once a month and orders up to \(S = 14\), the level Example 8.11 found optimal. The supplier takes exactly two months, demand is 45 a year, and the costs are those of Example 11.2.
What is stocked? One item, the pad-mount transformer.
What is the demand process? Poisson at 45 a year, one unit per demand.
When is inventory reviewed? Once a month, at the start of each month.
What triggers replenishment, and how much? Every review, for \(S - \mathit{IP}\) units, when that is positive.
What happens to unmet demand? It is backordered and filled first come first served.
What costs are incurred, and when? \(k = \$220\) for each order placed, \(h = \$950\) per unit per year on hand and \(b = \$8{,}550\) per unit per year owed.
Notation. Let \(R = 1/12\) year represent the review interval and \(L = 1/6\) year the lead time. The model schedules a review at times \(0, R, 2R, \ldots\), and the review event observes the position and places the order. Demands and receipts are the events of Table 11.1, except that a demand no longer takes a decision. The standard run settings apply.
The values to reproduce. From Example 8.11:
| Measure | Exact | Simulated |
|---|---|---|
| \(\bar{I}\), units | 4.7751 | 4.7696 \(\pm\) 0.0143 |
| \(\bar{B}\), units | 0.1501 | 0.1507 \(\pm\) 0.0025 |
| \(\overline{\mathit{RR}}\) | 0.8928 | 0.8925 \(\pm\) 0.0012 |
| \(\overline{\mathit{FR}}\) | 0.8928 | 0.8929 \(\pm\) 0.0013 |
| Orders a year, Equation 8.64 | 11.7178 | 11.7194 \(\pm\) 0.0068 |
| Ordering cost | $2,577.91 | $2,578.28 \(\pm\) 1.50 |
| Total cost | $8,397.22 | $8,397.75 \(\pm\) 19.49 |
The check. The simulation counts reviews and orders separately, and the two need not agree. A month with no demand at all leaves the position at \(S\) and nothing to order, which Equation 8.64 counts: with Poisson demand it happens with probability \(e^{-\lambda R} = e^{-3.75} = 0.0235\), so the order rate is \(12(1 - 0.0235) = 11.72\) a year. The interval for the order rate should cover 11.7178, and the fraction of reviews that place no order should cover 0.0235.
Both do. The simulation reviews twelve times a year and orders 11.7194 times, and the fraction of reviews that place an order is 0.9767 \(\pm\) 0.0006 against \(1 - 0.0235 = 0.9765\).
Interpretation. Every measure is covered. The review event behaves as the analysis of Section 8.13 assumes, down to the one review in forty-three that finds nothing to order.
Validation, and its limit. Agreement validates the review event. The policy it validates is the one Section 8.13 analyzed exactly, so the next two examples use it to answer questions that section answered only by comparison or approximation.
Example 11.8 (How far the position falls past the trigger) Section 8.13.5 showed that under periodic review the position passes below the reorder point even when demand arrives one unit at a time. It put the mean undershoot at \(\lambda R/2 = 1.875\) units for the transformer reviewed monthly when the spread \(S - s\) is wide compared with a review interval’s demand, and at exactly 2.8403 units at the narrow extreme, the \((R, S)\) policy itself. Between the two, chapter 8 said only that the spread decides. This example measures the undershoot at three spreads to find out how quickly.
What is stocked? One item, the pad-mount transformer.
What is the demand process? Poisson at 45 a year, one unit per demand.
When is inventory reviewed? Once a month.
What triggers replenishment, and how much? A review finding the position at or below \(s\), and the order brings it up to \(S = 14\).
What happens to unmet demand? It is backordered.
What costs are incurred, and when? None are needed. The example measures the undershoot.
Notation. As in Example 11.6, with \(s\) set to 13, 10 and 6. Let \(U = s - \mathit{IP}\) represent the undershoot of Equation 8.55, recorded at every review that places an order. The standard run settings apply.
The predictions. At \(s = 13\) the policy is \((R, S)\), and Section 8.13.5 gives \(E[U] = 2.8403\) units exactly. At \(s = 10\) and \(s = 6\), spreads of four and eight units against 3.75 units of demand a month, Equation 8.75 predicts 1.875 units.
| \(s\) | \(S - s\) | Prediction | Mean undershoot | Reviews that order |
|---|---|---|---|---|
| 13 | 1 | 2.8403, exact | 2.8422 \(\pm\) 0.0062 | 0.9767 \(\pm\) 0.0006 |
| 10 | 4 | 1.875 | 1.7981 \(\pm\) 0.0081 | 0.6472 \(\pm\) 0.0009 |
| 6 | 8 | 1.875 | 1.8796 \(\pm\) 0.0077 | 0.3798 \(\pm\) 0.0006 |
The check. At \(s = 13\) the prediction is exact, so the interval must cover 2.8403. That validates the recording of \(U\) before it is used where the prediction is only a limit. It does: 2.8422 \(\pm\) 0.0062.
Interpretation. At a spread of eight units, about two months of demand, Equation 8.75 is right to the second decimal: 1.8796 against 1.875. At a spread of four, about one month of demand, it is 4% high, and the error is not in the direction a reader might guess: the undershoot is smaller than the long-run figure, not larger. Only at the narrowest spread, where every review orders, does it jump to the 2.84 of \((R, S)\). Thus, the formula serves any \((R, s, S)\) policy whose spread holds two review intervals of demand or more, which is the case Section 8.13.5 said the policy is for.
Validation, and its limit. Section 8.13.5 left the exact treatment of \((R, s, S)\) to Zipkin (2000). The simulation does not replace it; it measures how good the approximation is on this item, which is the question a planner actually has.
11.6.1 Where This Leaves Us
Example 11.7 compared two policies by running them against the same demands, and the comparison was sharper for it. Section 11.7 makes that a method, and asks what it takes to choose among policies whose costs are close.
11.7 Comparing and Choosing Policies
Choosing a policy by simulation means comparing estimates, and an estimate carries noise. Two devices from Rossetti (2026) keep the noise from deciding the comparison: common random numbers, which make the policies face the same demands, and multiple comparison with the best, which says which policies can be told apart and which cannot. This section shows both on a comparison whose answer is already known.
11.7.1 Common Random Numbers
Let \(C_1\) and \(C_2\) represent the simulated costs of two policies in one replication. The quantity of interest is their difference, and its variance is
\[ \mathit{Var}[C_1 - C_2] = \mathit{Var}[C_1] + \mathit{Var}[C_2] - 2\,\mathit{Cov}[C_1, C_2] \tag{11.6}\]
Run independently, the two policies have no covariance, and the difference is noisier than either cost. Run against the same demands, a replication with unusually heavy demand is expensive for both, the covariance is positive, and the difference is quieter than either. That is, common random numbers do not make either estimate more precise; they make the comparison more precise, which is the thing being asked. Recall from Section 7.10 that the newsvendor did the same with resetStartStream, so that every quantity faced the same hundred thousand demands.
An inventory model needs one precaution the newsvendor did not. Two policies place different numbers of orders, so if demand times and lead times are drawn from one stream, the policies’ draws drift apart after the first order that one places and the other does not, and the demands are no longer common. Give each source of randomness its own stream. The demand process then supplies the same demand times to every policy, whatever the policies do with them. Under a constant lead time, as in the transformer examples, the lead times are common automatically.
11.7.2 Choosing the Best
With more than two policies, the question becomes which of them is best, and how sure we can be. Multiple comparison with the best, which Rossetti (2026) develops, compares each policy with the best of the others and returns the subset of policies that cannot be ruled out. Let \(\delta\) represent the indifference zone, the smallest difference in cost worth distinguishing. A difference below \(\delta\) is one the planner has declared not to matter, and the procedure is entitled to call it a tie.
Choosing \(\delta\) is a decision about the item, not about statistics. The transformer’s costs run to about $7,400 a year, so a difference of $75, 1% of it, is a fair threshold: a planner would not reorganize a storeroom for less. Example 11.9 runs the procedure where the true ranking is known.
Example 11.9 (Five reorder points near the optimum) Table 8.5 evaluated the transformer at \(Q = 5\) for reorder points 7 through 11 and found \(r = 9\) best. The costs near the optimum are close: \(r = 8\) costs $9.17 a year more than \(r = 9\), about 0.12%. This example asks what it takes to see that by simulation.
What is stocked? One item, the pad-mount transformer.
What is the demand process? Poisson at 45 a year, one unit per demand.
When is inventory reviewed? Continuously.
What triggers replenishment, and how much? The position reaching \(r\) or below, for \(Q = 5\), with \(r\) from 7 to 11.
What happens to unmet demand? It is backordered.
What costs are incurred, and when? Those of Example 11.2.
Notation. Let \(C_r\) represent the simulated cost rate at reorder point \(r\) in one replication. All five policies face the same demand times. Let \(\delta\) represent the indifference zone of the multiple comparison, the smallest difference in cost worth distinguishing, set here at $75 a year, about 1% of the cost. The standard run settings apply.
The values to reproduce.
| \(r\) | 7 | 8 | 9 | 10 | 11 |
|---|---|---|---|---|---|
| Exact cost, a year | $8,016.43 | $7,405.97 | $7,396.80 | $7,792.96 | $8,442.11 |
| Above the best | $619.63 | $9.17 | $396.16 | $1,045.31 | |
| Simulated cost | $8,033.53 | $7,419.78 | $7,405.71 | $7,798.73 | $8,445.30 |
| Half-width | $29.03 | $19.41 | $13.38 | $9.93 | $9.32 |
| MCB interval, \(\delta = \$75\) | \([0, 702.82]\) | \([-60.92, 89.08]\) | \([-89.08, 60.92]\) | \([0, 468.02]\) | \([0, 1114.59]\) |
The check. Every interval should cover its exact cost, and the procedure should return a subset containing \(r = 9\).
Both hold. The five intervals cover the five exact costs, the smallest average is at \(r = 9\), and the MCB intervals of \(r = 8\) and \(r = 9\) are the two that contain zero.
Interpretation. With \(\delta = \$75\), multiple comparison with the best keeps \(r = 8\) and \(r = 9\) and rules out the other three. That is the right answer to the question the planner asked, which was which policies are worth considering: the two differ by $9.17 a year, far inside the $75 the planner said was not worth distinguishing.
The paired difference says something sharper, and it is worth seeing why it does not change the answer. With common random numbers, the cost at \(r = 8\) less the cost at \(r = 9\) is $14.08 \(\pm\) $9.45, an interval that excludes zero, so even 30 replications can tell the two apart. The paired differences have a standard deviation of $25.31, so by Equation 11.5 about 32 replications would put the half-width at $9.17, the size of the true difference. Thus, separating the two policies is cheap. It is also pointless. A statistically significant difference of nine dollars a year on a $7,400 item is not a reason to prefer one reorder point to the other, and the indifference zone is how the planner says so before the run rather than after it.
Validation, and its limit. With the exact costs known, the example shows what the comparison procedure does when the answer is a near tie. When no exact cost is available, as under lost sales, the same procedure is all there is.
11.7.3 Searching for a Policy
Comparing a handful of policies is enumeration. When the candidates number in the hundreds, or the cost surface has no formula to guide the search, the problem is simulation optimization: a search over policies in which every evaluation is a noisy estimate. The solvers for it, among them cross-entropy, simulated annealing and R-SPLINE, are the subject of a chapter of Rossetti (2026), which builds a problem definition for the \((r, Q)\) policy and runs each solver on it. The interested reader should refer to it.
Two pieces of advice carry over from the earlier chapters of this book. Start the search from the exact answer to the nearest model the book can solve: for the transformer under lost sales, Example 11.5, that is the backorder optimum \((13, 6)\). And confirm the search’s final candidates with common random numbers and a multiple comparison, since a search over noisy estimates reports the candidate that was luckiest as readily as the one that is best. Exercise 11.15 does the search by enumeration.
11.7.4 Where This Leaves Us
Every model so far has had one stock point. Section 11.8 builds the two-level systems of chapters 9 and 10 from the same classes, which is where the approximations those chapters needed can finally be tested.
11.8 Multi-Echelon Systems
Chapters 9 and 10 needed approximations for one reason. The upper level’s backorders make each lower location’s resupply time random, and the waits of different requests move together, and no formula carries that coupling whole. A simulation carries it because it has no choice: a storeroom’s request waits at the depot exactly as long as the depot’s queue makes it wait, and the storeroom’s stock reflects that wait. Thus, a two-level model is the single-location model twice, with one location as the other’s supplier, as Section 11.10.2 explains.
The validation follows the chapter’s pattern. Example 11.10 first reproduces every quantity chapter 9 computed exactly and then settles the one in dispute. Example 11.11 reproduces chapter 10’s exact system with batching at the hub. Example 11.12 then runs the case nothing exact covers.
Example 11.10 (METRIC or VARI-METRIC for the utility’s transformers) The utility of Example 9.4 runs four storerooms supported by a central depot. Each storeroom sees 45 failures a year, rebuilds three in ten in its own shop in 30 days, and sends the rest to the depot, from which a serviceable unit takes 10 days to arrive. The depot repairs what it receives in 60 days. The plan holds \(S_0 = 16\) transformers at the depot and \(S_j = 4\) at each storeroom. METRIC predicted 0.4055 backorders at each storeroom and VARI-METRIC predicted 0.4815, and this example measures which is closer.
What is stocked? One item at five locations, the pad-mount transformer.
What is the demand process? Poisson at 45 failures a year at each storeroom, one unit at a time.
When is inventory reviewed? Continuously, at every location.
What triggers replenishment, and how much? Every failure, for one unit, at both levels.
What happens to unmet demand? It is backordered, at the storeroom against a waiting crew and at the depot against a waiting storeroom, first come first served at each.
What costs are incurred, and when? None are needed. The example measures backorders.
Notation. As in Example 9.4. The model works in days, with the repair and shipping times taken as constants: 30 days for a local repair, 10 for a shipment and 60 for a depot repair. Every mean in Table 11.14 holds for any repair time distribution with these means, by Theorem 9.1 and Little’s law. The disputed rows may depend on the shapes of those times, which Example 9.4 did not state and neither model uses; constants are the simplest choice consistent with the stated averages. Each failure is sent to the depot with probability 0.7, independently. The run is \(n = 30\) replications of \(T = 1{,}000\) years after \(T_w = 5\) years; the system sees 180 failures a year.
The values to reproduce, and the value in dispute. Recall from Section 9.7.2 that every mean METRIC computes is exact, and that only the storeroom’s backorders depend on the shape of its pipeline.
| Measure | METRIC | VARI-METRIC | Status | Simulated |
|---|---|---|---|---|
| \(\bar{B}_0\), depot, units | 5.0201 | 5.0201 | exact | 5.0098 \(\pm\) 0.0216 |
| \(\bar{W}\), days | 14.54 | 14.54 | exact | 14.52 \(\pm\) 0.05 |
| \(\mu_j\), storeroom pipeline, units | 3.2276 | 3.2276 | exact | 3.2234 to 3.2282, each \(\pm\) 0.008 |
| \(\bar{I}_j - \bar{B}_j\), units | 0.7724 | 0.7724 | exact | 0.7719 to 0.7767 |
| \(\bar{B}_j\), per storeroom | 0.4055 | 0.4815 | in dispute | 0.4813 to 0.4825, each \(\pm\) 0.004 |
| \(\bar{I}_j\), per storeroom | 1.1779 | 1.2539 | in dispute | 1.2537 to 1.2580, each \(\pm\) 0.005 |
| Backorders across four storerooms | 1.6218 | 1.9259 | in dispute | 1.9269 |
The check. The four exact rows must be covered. If they are not, the model is wrong, and the disputed rows mean nothing.
They are: the depot’s backorders and wait, and each storeroom’s pipeline, cover the values both models share.
Interpretation. Each storeroom owes its crews 0.4817 transformers on average, across the four. VARI-METRIC’s 0.4815 lies inside every storeroom’s interval, and METRIC’s 0.4055 lies far below all of them. Thus, on this plan METRIC understates the storerooms’ backorders by about 16%, and VARI-METRIC is right to the third decimal. For the utility that is the difference between planning for 1.6 crews waiting at any moment and finding 1.9. Sherbrooke (1986) said METRIC understates; this plan shows by how much, and shows no sign that VARI-METRIC overstates.
Validation, and its limit. This is one plan on one system. Graves (1985) is the reference for how often each model chooses the wrong stock levels across many systems, and the example does not generalize from one case to that.
Example 11.11 (The cutout’s hub and storerooms, simulated) The running example of Section 10.2 has four storerooms, each seeing one fuse cutout demanded a week and running base stock \(S_j = 3\), supplied by a hub that runs \((r_0, Q_0) = (9, 8)\) against a supplier taking three weeks. A shipment from the hub to a storeroom takes one week. Holding costs \(h = \$0.5529\) per unit per week at both levels, and a storeroom’s crews are owed at \(b = \$5.5288\) per unit per week. Example 10.3 computed every measure of this system exactly.
What is stocked? One item at five locations, the fuse cutout.
What is the demand process? Poisson at one unit a week at each storeroom.
When is inventory reviewed? Continuously, at every location.
What triggers replenishment, and how much? At a storeroom, every demand, for one unit. At the hub, its position reaching 9 or below, for 8 units.
What happens to unmet demand? It is backordered at both levels. The hub fills its requests first come first served.
What costs are incurred, and when? Holding at both levels and backorders at the storerooms, at the rates above. There is no ordering cost in this example.
Notation. As in Section 10.2. Let \(W\) represent the time a storeroom’s request waits at the hub, recorded for every request. The model works in weeks. The hub sees four requests a week, so a run of \(T = 12{,}000\) weeks gives about the transformer’s 45,000 demands at the hub; \(n = 30\) and \(T_w = 50\) weeks.
The values to reproduce.
| Measure | Exact | Simulated |
|---|---|---|
| \(\bar{B}_0\), hub, units | 1.0273 | 1.0173 \(\pm\) 0.0087 |
| \(\overline{\mathit{RR}}_0\) | 0.6030 | 0.6045 \(\pm\) 0.0021 |
| \(\bar{I}_0\), units | 2.5273 | 2.5334 \(\pm\) 0.0124 |
| \(\bar{W}\), weeks | 0.2568 | 0.2547 \(\pm\) 0.0018 |
| \(P(W = 0)\) | 0.6030 | 0.6051 \(\pm\) 0.0020 |
| \(P(W \le 1)\) | 0.9117 | 0.9129 \(\pm\) 0.0009 |
| \(P(W \le 2)\) | 0.9985 | 0.9985 \(\pm\) 0.0001 |
| \(\bar{B}_j\), per storeroom | 0.0726 | 0.0707 to 0.0724, each \(\pm\) 0.0016 |
| System cost, a week | $7.0195 | $7.0081 |
The check. \(P(W = 0)\) must equal the hub’s ready rate, as it did in Example 10.2, since a request ships at once exactly when the hub has stock. In addition, Little’s law gives \(\bar{W} = \bar{B}_0 / 4\) within each replication, and the model reports both sides.
Both hold: \(P(W = 0)\) is 0.6051 against a ready rate of 0.6045, and \(\bar{B}_0/4 = 0.2543\) against a mean wait of 0.2547.
Interpretation. This run is worth reading slowly, because four of its intervals miss: the hub’s backorders, its mean wait, \(P(W = 0)\) and \(P(W \le 1)\), together with one storeroom’s backorders. They miss together, and in one direction: the hub had slightly more stock than its long-run average across these thirty replications, and every measure that depends on it moved the same way. That is what correlated intervals from one set of runs do, and it is why Section 11.10.4 checks such a family at the Bonferroni level, at which this run passes. Two further runs of 300 replications on other streams put the hub’s backorders at 1.0283 \(\pm\) 0.0027 and 1.0263 \(\pm\) 0.0027, both covering 1.0273. The model is right; the first thirty replications were a little lucky.
The storerooms’ backorders average 0.0717 across the four, beside the routes of Table 10.2: exact 0.0726, conditioned on the wait 0.0726, two moments 0.0712, and the mean wait only 0.0505. The simulation sits with the first three and far from the last, which is chapter 10’s lesson that the mean wait alone understates a storeroom’s backorders by 30%, seen from outside the mathematics.
Validation, and its limit. Every figure here is exact, so this example validates the two-level model with batching at the hub. The next example keeps the model and changes only the customers.
Example 11.12 (The cutout in job lots, the case chapter 10 handed on) Example 10.10 set both policies for the cutout drawn in job lots, by the iteration of Algorithm 10.1, and closed by saying that nothing exact covers the case. A storeroom’s crews draw lots of one, two or four units, with probabilities 0.40, 0.40 and 0.20, at 150 lots a year. The hub serves 250 lots a year of its own from the same distribution and also supplies the storeroom. The hub’s supplier takes two months, and a transfer from the hub to the storeroom takes one. Both locations pay \(k = \$82.50\) an order and \(h = \$28.75\) a unit a year to hold; the storeroom’s crews are owed at \(b = \$287.50\) a unit a year, and the hub carries \(b_0 = \$115\), from its target of 0.8. The iteration converged to \((25, 49)\) at the storeroom and \((120, 92)\) at the hub.
What is stocked? One item at two locations, the fuse cutout.
What is the demand process? Compound Poisson at both locations: lots at 150 a year at the storeroom and 250 a year of the hub’s own, each of one, two or four units.
When is inventory reviewed? Continuously, at both locations.
What triggers replenishment, and how much? At the storeroom, its position reaching 25 or below, for 49 units. At the hub, its position reaching 120 or below, for 92 units.
What happens to unmet demand? It is backordered at both. The hub fills its own customers and the storeroom’s orders in one first-come-first-served queue, and ships part of a storeroom order when it has only part, as Section 10.2 specified.
What costs are incurred, and when? At each location, Equation 10.14: ordering, holding, and backorders at that location’s rate.
Notation. The model works in years. Let \(W\) represent the time from a storeroom order’s arrival at the hub until its last unit ships. The storeroom sees 150 lots a year, so \(T = 300\) years gives 45,000 of them; \(n = 30\) and \(T_w = 5\) years.
The predictions. From Example 10.10: the storeroom costs $1,371.26 a year and the hub $2,279.69, and a request at the hub waits 0.0054 year on average, about two days. These come from the moment route, which carries two moments of each location’s lead time demand and no more.
| Storeroom, predicted | simulated | Hub, predicted | simulated | |
|---|---|---|---|---|
| Ordering | $504.52 \(\pm\) 0.94 | $717.22 \(\pm\) 0.87 | ||
| Holding | $686.16 \(\pm\) 1.66 | $1,059.20 \(\pm\) 4.52 | ||
| Backorder | $123.00 \(\pm\) 2.95 | $423.61 \(\pm\) 4.79 | ||
| Total, a year | $1,371.26 | $1,313.68 \(\pm\) 2.46 | $2,279.69 | $2,200.02 \(\pm\) 3.69 |
| Orders a year | 6.12 | 6.1153 \(\pm\) 0.0114 | 8.70 | 8.6936 \(\pm\) 0.0106 |
| Ready rate | 0.9227 \(\pm\) 0.0011 | 0.8083 \(\pm\) 0.0017 | ||
| Unit fill rate | 0.9134 \(\pm\) 0.0012 | 0.8018 \(\pm\) 0.0016 | ||
| Lot fill rate | 0.9108 \(\pm\) 0.0011 | 0.8001 \(\pm\) 0.0017 |
The hub’s own customers wait 0.0043 \(\pm\) 0.0001 year on average. A storeroom’s order waits 0.0109 \(\pm\) 0.0001 year for its last unit to ship, and 56.9% of the storeroom’s orders ship complete the moment they arrive.
The check. Each location’s order rate must be its demand in units divided by its batch: \(300/49 = 6.12\) orders a year at the storeroom and \((500 + 300)/92 = 8.70\) at the hub, since every storeroom order is for exactly 49 units and so the hub sees 300 units a year from it.
The order rates cover 6.12 and 8.70, as the check requires.
Interpretation. This is the paragraph that closes the validation Example 10.10 left open. The iteration’s policies cost less than the iteration said: $57.58 a year less at the storeroom and $79.67 less at the hub, an overstatement of about 4% at each. The moment route is conservative here, which is the safe direction for a planner, and the policies it chose are reasonable ones to run.
The wait shows where the moment route simplified. It carried one wait for every request at the hub, 0.0054 year. The hub’s own customers, whose lots are small, wait less than that, 0.0043. A storeroom’s order of 49 waits for its last unit, and nearly half of them cannot ship complete on arrival, so it waits twice as long, 0.0109. The storeroom’s 25-unit reorder point covers the difference, and its crews still find a cutout on the shelf 92% of the time.
Validation, and its limit. Nothing exact covers this case. The model was validated on the same structure in Example 11.11, and under job lots in Example 11.4, so what is new here is only the combination.
11.8.1 Where This Leaves Us
The chapter’s own classes have now reached every system the book analyzed, and one it could not. Section 11.9 builds the same two-level system with the KSL’s supply chain package, which is what you would use for a network of realistic size.
11.9 The KSL Supply Chain Package
The chapter’s own classes show the mechanism, and they are small enough to read in full. A network of realistic size needs more: several items at each location, transport between locations, cost accounting by location and by cost line, and a report a manager can read. The KSL’s supply chain package, ksl.modeling.supplychain, supplies those. This section builds one small network with it, checks the result against a system the book has already solved, and says what the package does not yet do.
The package is released as experimental, and its interface may change between versions of the KSL. Everything in this section was written against KSL R1.7.1, the version the companion code declares. Check the release notes before relying on a name or a default with a later version.
11.9.1 What the Package Provides
A network in the package is a tree of inventory holding points, each holding an inventory of one or more items, each item’s inventory running its own policy. The root of the tree is an external supplier. Customer demand is attached to the holding points that face customers, and each edge of the tree carries a transport time. Three policies are provided: \((r, Q)\), \((s, S)\), and periodic \((s, S)\) with a constant review interval. A base-stock policy at level \(S\) is the \((r, Q)\) policy with \(r = S - 1\) and \(Q = 1\), as Section 10.2 wrote it.
A network can be described in three ways, which produce the same model: a Kotlin specification language, a specification file in TOML or JSON, or calls that build it object by object. The specification language is the readable one, and it is the one Example 11.13 uses. At the end of a run, the network produces a structured report with the layout of the network, the costs by location and by cost line, and each holding point’s on-hand level, fill rate and waiting time.
11.9.2 The Package’s Names for the Book’s Quantities
The package names its quantities for supply chains in general, and this book named them for the analysis of a stock point. Table 11.17 translates.
| This book | The package |
|---|---|
| A stock point | An inventory holding point, holding one Inventory per item |
| \((r, Q)\) | the sQ(s, Q) policy |
| \((s, S)\) | the sS(s, S) policy |
| \((R, s, S)\) | the sSPeriodic(s, S, reviewInterval) policy |
| Base stock at level \(S\) | sQ(s = S - 1, Q = 1) |
| The outside supplier and its lead time | the external supplier |
| The transit time \(O_j\) | the transport time from the parent node |
| \(\bar{I}\), \(\overline{\mathit{IO}}\), \(\bar{B}\) | On Hand, On Order, Amt BackLogged |
| \(1 - \overline{\mathit{RR}}\) | Fraction of Time w/o Stock |
| The lot fill rate | First Fill Rate |
| The unit fill rate | Unit Fill Rate |
Notice the two fill rates. The package’s First Fill Rate scores each demand filled complete or not, which is the lot fill rate of Section 8.11.4, and its Unit Fill Rate is the unit fill rate. With demand one unit at a time they agree, as Section 11.4.4 said they must.
Example 11.13 (The cutout’s hub and storerooms, built with the package) Rebuild the running example of Example 11.11 with the package: four storerooms, each seeing one fuse cutout demanded a week and running base stock \(S_j = 3\), supplied over a one-week transit by a hub that runs \((r_0, Q_0) = (9, 8)\) against a supplier taking three weeks.
The modeling questions have the answers given in Example 11.11, since the system has not changed. Only the software has.
Notation. In the package’s terms, the hub is a holding point attached to the external supplier with an sQ(s = 9, Q = 8) inventory, and each storeroom is a holding point beneath it with an sQ(s = 2, Q = 1) inventory, a transport time of one week from its parent, and demand arriving with exponential times between demands of mean one week. The run settings are those of Example 11.11, and each source of randomness has its own stream.
The values to reproduce. Every row of Table 11.15, and the simulated figures of Example 11.11 from the chapter’s own classes.
The specification, in the package’s Kotlin language:
supplyChain("CutoutNetwork") {
transportStrategy = perIHPTimeBased
val cutout = item("Cutout", leadTime = constant(3.0), unitCost = 115.0)
holdingPoint("Hub") {
attachedToExternalSupplier()
inventory(cutout) { sQ(s = 9, Q = 8, initialOnHand = 17) }
tier(count = 4, namePrefix = "Store", transportTime = constant(1.0)) {
inventory(cutout) { sQ(s = 2, Q = 1, initialOnHand = 3) }
demand(cutout, exponential(mean = 1.0, stream = autoStream()))
}
}
}item declares the cutout and the external supplier’s lead time of three weeks. holdingPoint and tier lay out the tree: the hub beneath the external supplier, and four storerooms named Store1 to Store4 beneath the hub, each a week’s transport away. sQ is the \((r, Q)\) policy, and autoStream gives each storeroom’s demand its own random number stream. The run is SupplyChainBuilder.build(model, spec) followed by model.simulate().
The structured report’s summary of the holding points, pasted as it prints:
|IHP| Level| On hand| On order| Backordered| Fill rate| Avg wait|
|:---| ---:| ---:| ---:| ---:| :---| ---:|
|Hub| 1| 2.53| 11.98| 1.02| 60.5%| 0.64|
|Store1| 2| 1.82| 1.25| 0.07| 85.9%| 0.51|
|Store2| 2| 1.82| 1.25| 0.07| 86.0%| 0.51|
|Store3| 2| 1.82| 1.25| 0.07| 86.2%| 0.51|
|Store4| 2| 1.82| 1.25| 0.07| 85.9%| 0.51|
Notice that the report’s “Avg wait” is the package’s Backorder Wait Time, the wait of the demands that had to wait, and not the mean over all demands that Table 11.15 reports.
First Fill Rate in the package and \(P(W = 0)\) in the chapter’s classes.
| Measure | Exact | The chapter’s classes | The package |
|---|---|---|---|
| Hub on hand, units | 2.5273 | 2.5334 \(\pm\) 0.0124 | 2.5334 \(\pm\) 0.0124 |
| Hub backorders, units | 1.0273 | 1.0173 \(\pm\) 0.0087 | 1.0173 \(\pm\) 0.0087 |
| Hub fill rate | 0.6030 | 0.6051 \(\pm\) 0.0020 | 0.6051 \(\pm\) 0.0020 |
| Storeroom 1 backorders, units | 0.0726 | 0.0721 \(\pm\) 0.0016 | 0.0721 \(\pm\) 0.0016 |
The check. At each storeroom, demand is single-unit Poisson, so First Fill Rate, Unit Fill Rate and one less Fraction of Time w/o Stock must agree within their half-widths. At the hub, the requests are single units too, so the same holds there.
They do: at storeroom 1, First Fill Rate and Unit Fill Rate are both 0.8592 \(\pm\) 0.0019, and one less Fraction of Time w/o Stock is \(1 - 0.1403 = 0.8597\).
Interpretation. The package and the chapter’s own classes agree not to within their half-widths but exactly, to every digit printed. They draw the four demand streams from the same stream numbers, they implement the same assumptions, and so they follow the same sample path, event for event. That is the strongest agreement two independent programs can show, and it is why the package’s figures inherit the reading Example 11.11 gave its own: the run is slightly lucky at the hub, and longer runs cover every exact value.
Validation, and its limit. Agreement with the exact figures validates the package on this system, and agreement with the chapter’s own model shows that two independent implementations of the same assumptions give the same answer. It says nothing about the parts of the package this system does not use, such as shipment formation and cost lines beyond holding and backorders.
11.9.3 What the Package Does Not Do Yet
Four limits matter for the systems of this book, and they are stated here so that you meet them in a paragraph rather than in a failed run.
Lost sales are not available through a specification. Demand in a network built from a specification is backordered. A lost-sales system can be built object by object, but the package’s fill rates then count only the demands that were not lost, so they overstate service. Example 11.5 uses the chapter’s own classes for that reason.
A node has one supplier. The network is a tree, so a storeroom that sends some requests to its own repair shop and the rest to a depot, as in Example 11.10, is outside what a specification can describe.
A periodic review interval is a constant. That covers every periodic example in this book.
Random number streams are the modeler’s responsibility. Every random quantity in a specification names its stream, and identical streams with an identical structure give an identical sample path. That is what makes common random numbers possible, and it is also why two runs that were meant to be independent must be given different streams.
11.9.4 Where This Leaves Us
The package reproduces the system the chapter’s own classes reproduced, by a different route, and with far less code for the modeler to write. The next section sets out how the chapter’s own classes are organized, which is also a description of what the package does at a much larger scale.
11.10 Designing the Software
The package is inventory.simulation. Its core is the event model of the \((r, Q)\) policy in Rossetti (2026), copied into the companion code and adapted: the names follow this book’s notation, the reorder decision orders as many batches as it takes to clear the reorder point, and the model gains the options the chapter’s examples need. Every other package in the companion code computes; this one is the first that runs a model through time, and it is built on the KSL’s ModelElement rather than on its distributions alone.
11.10.1 What the Software Must Do
Reading back over the examples, the software has to
- run one stock point under \((r, Q)\), \((s, S)\) or \((R, s, S)\), which includes \((R, S)\) as \(s = S - 1\), with demand either backordered or lost,
- accept demand in lots of a stated distribution, filling a lot partly when the shelf holds part of it and owing the rest first come first served,
- draw each lead time from any distribution, deliver orders either independently or in one supply line, and record when an order overtakes another,
- be driven by a script of demand times as well as by a sampled demand process, so that Example 11.1 is a test and not only an illustration,
- collect the time-persistent measures of Equation 11.2 and the observation-based measures of Section 11.4.4, together with the undershoot, the order sizes, the waits and the cost terms of Equation 8.1, or a cost per unit lost under lost sales,
- let one stock point be another’s supplier over a transit time, filling the lower location’s orders first come first served and shipping part of an order when it holds only part of it, and let a lower location send some of its requests elsewhere, as a storeroom with its own repair shop does, and
- report each measure as an interval and compare it, field by field, with the exact model of the same policy.
11.10.2 The Nouns
Three nouns become classes: the stock point, the policy it runs, and the supplier that fills its orders. Several others do not, and the reasons are the design.
The event is not a class. A demand and a receipt are methods of the stock point, scheduled on the KSL’s calendar. Table 11.1 lists two events and one decision, and the code has two event methods and one decision method in the same places.
Lost sales is not a subclass. Whether an unmet demand waits or departs is a property of the demand, not a different kind of stock point, so it is a flag on the stock point. Every policy runs under either setting without being written twice.
Periodic review is a policy, not a stock point. It is the one policy that owns an event of its own, the review, which it schedules on the calendar when the replication starts. A demand under periodic review takes no decision, so the stock point’s decision method simply does nothing for it.
A two-level system is not a class. The KSL book’s model gives a stock point one way to obtain stock: it asks an InventoryFillerIfc to fill an order. A supplier with a lead time is one kind of filler, and so is another stock point. Thus a storeroom supplied by a hub is a stock point whose filler is the hub, seen through a transit link that adds \(O_j\), and a storeroom that rebuilds some of its failures is a stock point whose filler sends each request one way or the other. The two-level examples of Section 11.8 are assembled from the same three classes as the single location of Example 11.2. Notice that this is the coupling chapters 9 and 10 worked so hard to approximate: here it is simply the order of the calls.
11.10.3 The Classes
| Class | Knows | Does |
|---|---|---|
InventoryFillerIfc |
nothing | accepts a request for a quantity; the one thing a supplier must do |
SimInventory |
\(I\), \(\mathit{IO}\) and \(B\) as time-weighted responses, the backorder queue, the lost-sales flag, the cost rates | the demand and receipt events of Table 11.1; Equation 11.1, through TWResponse; the unit fill rate, lot fill rate and ready rate; the cost terms at the end of each replication; fills a lower location’s orders as an InventoryFillerIfc |
RQSimInventory |
\(r\) and \(Q\) | the decision of Table 11.1, ordering \(\lfloor (r - \mathit{IP})/Q \rfloor + 1\) batches |
SSSimInventory |
\(s\) and \(S\) | orders \(S - \mathit{IP}\), and records the undershoot of Equation 8.55 |
PeriodicSimInventory |
\(R\), \(s\) and \(S\) | schedules the review; counts reviews and orders separately, as Equation 8.64 requires; records the undershoot |
LeadTimeSupplier |
a lead time distribution, and whether orders queue | fills after \(L\), or at the later of \(t + L\) and the previous receipt; records crossings and the time each order is outstanding |
TransitLink |
a stock point and a transit time | makes a stock point a supplier, adding \(O_j\) after it ships, and records each request’s wait |
RoutingFiller |
several fillers and the probability of each | sends each request to one of them, as the storeroom’s own shop and the depot of Example 11.10 share its failures |
SimStockPoint |
an inventory, a filler, and a demand process given by a rate and a lot size distribution, or by a script | assembles one location as a KSL ModelElement, the role of the KSL book’s RQInventorySystem |
Estimate |
an average, a half-width and a count | whether the interval covers a value |
SimulatedPerformance |
an Estimate for each measure |
compares itself with chapter 8’s RQPerformance or RSPerformance, measure by measure |
Notice what is missing: a class for the two-level system, for the hub, or for the depot. A hub is SimInventory running \((r, Q)\) with a LeadTimeSupplier behind it and TransitLinks in front of it. The depot of Example 11.10 is the same thing running \((S_0 - 1, 1)\), since a one-for-one stock point replenished after a constant repair time behaves exactly as one replenished by a supplier with that lead time.
11.10.4 The Two Routes Must Agree
Recall from Section 7.12.4 that two routes sharing one cost structure can be checked against each other. Here the exact route is the code of chapters 8 to 10 and the simulated route is this package, and the check is the chapter’s thesis written as tests.
There is one test for every example that has an exact column, and each test asserts the agreement the example states. The ledger test of Example 11.1 asserts equality, row by row, since nothing in it is random. Every other test asserts that each interval covers the exact value: Table 11.5, Table 11.10, the costs and service measures of Table 11.7, the order rates and undershoots of the periodic examples, the four exact rows of Table 11.14, and Table 11.15. The tests run at a fixed seed, so a test that passes once passes every time.
One detail of the tests deserves stating, because a test written naively would fail a correct model. A test that checks eleven measures from the same runs, each at 95%, will find a miss among them more often than not, and the measures of one run tend to miss together. Each test therefore builds its intervals at the Bonferroni level for the number of measures it checks, \(1 - 0.05/k\) for \(k\) measures, so that a correct model passes the whole family at 95%. The chapter prints ordinary 95% intervals, and Example 11.2 said what one miss among them does and does not mean.
The tests do not pin the simulated figures the chapter prints. Those figures are reported with their half-widths, at the seed and the KSL version stated with each run, and a later version of the library may move a printed digit within its half-width. What the tests guarantee is the thing that matters: that every interval still covers the exact value it was printed beside.
11.10.5 Running the Chapter’s Examples
The transformer of Example 11.2 is three objects and a model:
val m = Model("TransformerRQ")
val supplier = LeadTimeSupplier(m, ConstantRV(1.0 / 6.0), name = "Supplier")
val store = RQSimInventory(m, 8, 7, filler = supplier, name = "Transformer").apply {
orderCost = 220.0; holdingCost = 950.0; backorderCost = 8550.0
}
CustomerDemand(m, store, ExponentialRV(1.0 / 45.0, streamNum = 1), name = "Crews")
m.numberOfReplications = 30
m.lengthOfReplication = 1020.0
m.lengthOfReplicationWarmUp = 20.0
m.simulate()LeadTimeSupplier is the supplier, here with a constant lead time of \(L = 1/6\) year. RQSimInventory is the stock point running \((r, Q) = (8, 7)\), with the three cost rates of Equation 8.1. CustomerDemand sends it demands at exponential intervals of mean \(1/45\) year, on stream 1. The last four lines are the run settings of Section 11.4.3.
The comparison is one call, against chapter 8’s RQModel evaluated at the same policy:
SimulatedPerformance.of(store).against(exact).forEach(::println)on hand exact 4.6617 simulated 4.6570 +/- 0.0107 covered
backorders exact 0.1617 simulated 0.1628 +/- 0.0020 covered
ready rate exact 0.8781 simulated 0.8779 +/- 0.0009 covered
fill rate exact 0.8781 simulated 0.8776 +/- 0.0010 covered
order frequency exact 6.4286 simulated 6.4333 +/- 0.0105 covered
ordering cost exact 1414.2857 simulated 1415.3187 +/- 2.3038 covered
holding cost exact 4428.5863 simulated 4424.1250 +/- 10.2001 covered
backorder cost exact 1382.2771 simulated 1392.0530 +/- 16.9403 covered
total cost exact 7225.1492 simulated 7231.4967 +/- 15.4165 covered
A two-level system is assembled from the same classes. The job-lot example of Example 11.12, in years:
val hub = RQSimInventory(m, 120, 92,
filler = LeadTimeSupplier(m, ConstantRV(2.0 / 12.0), name = "Supplier"), name = "Hub")
val store = RQSimInventory(m, 25, 49,
filler = TransitLink(m, hub, ConstantRV(1.0 / 12.0), name = "Transfer"), name = "Storeroom")
CustomerDemand(m, hub, ExponentialRV(1.0 / 250.0, streamNum = 1), lots(2), name = "HubCrews")
CustomerDemand(m, store, ExponentialRV(1.0 / 150.0, streamNum = 3), lots(4), name = "StoreCrews")The storeroom’s filler is a TransitLink to the hub, which turns each of the storeroom’s orders into a demand at the hub and delivers what the hub ships a month later. lots is the lot-size distribution of Table 8.20, on its own stream. Nothing else distinguishes a hub from a storeroom.
### the cutout in job lots: storeroom (25, 49), hub (120, 92), in years
Storeroom:
ordering 504.5150 +/- 0.9402
holding 686.1641 +/- 1.6630
backorder 123.0035 +/- 2.9464
total 1313.6826 +/- 2.4588
orders a year 6.1153 +/- 0.0114
Every example of the chapter is a function of the program Section11Listings.kt, which runs them all in about fifteen seconds:
./gradlew run -PmainClass=inventory.simulation.Section11ListingsKtThe agreement tests of Section 11.10.4 are in the package’s test directory and run with the rest of the companion code’s tests.
11.10.6 Where This Leaves Us
Every example in the chapter is an assembly of the same few classes, and every one that has an exact answer is checked against it by a test. That is what allows the examples without an exact answer to be believed.
11.11 Summary
A simulation is trusted only after it reproduces a number the book has already derived. A simulation is a program, and a program can be wrong without saying so. Every model in the chapter therefore first reproduces a result from chapters 8 to 10 inside its half-width, and only then is one assumption behind that result removed. Simulation belongs after the closed form, not instead of it, and the closed form is what makes the simulation believable where no closed form exists.
An inventory policy is two events and one decision. A demand and a receipt change the state; placing an order is a decision taken inside a demand, which schedules a receipt one lead time later. Periodic review adds a third event, the review, which the policy schedules for itself and which takes the decision in the demand’s place. Everything the chapter simulates is assembled from those events.
A time average is an area, accumulated at the events. Between events the state is constant, so the area under each state variable grows by one rectangle per event, credited with the value that held before the event changed it. The ready rate is an average of that kind; the fill rates are averages over demands. Averaging the rows of a ledger gives neither, and Example 11.1 showed by how much on chapter 8’s own thirteen weeks.
A stock point never terminates, and its run is measured in demands. The target is the long-run average, so the start is discarded after a warm-up, which for an \((r, Q)\) policy can be reasoned out from Equation 8.17 and is then confirmed by a Welch plot. Replications are long and independent, and their number follows from a pilot run and the precision wanted. The backorder level needs the longest run, because backorders come in rare episodes, and the run should be set by the hardest measure the report will quote.
Under job lots there are three service measures, and a report must name the one it quotes. The ready rate counts time, the unit fill rate counts units and the lot fill rate counts lots. They coincide for single-unit Poisson demand and separate under lots, and a simulation collects all three at no extra cost.
Each assumption is removed by changing one component of a validated model. Orders that overtake one another change the supplier; job lots change the demand process and the policy that suits it; lost sales change what happens to an unmet demand. Because nothing else changes, a difference in the results is the effect of the assumption removed and not of a new model.
Policies are compared against the same demands. Common random numbers make the difference between two policies more precise without making either cost more precise, and in an inventory model they need a separate stream for each source of randomness, since policies place different numbers of orders. Near an optimum the cost surface is flat, and a multiple comparison with an indifference zone says which policies are worth telling apart. A difference can be cheap to detect and still not worth acting on.
A two-level system is two stock points, one supplying the other. The coupling chapters 9 and 10 had to approximate, a lower location’s resupply delayed by the upper location’s backorders, is in the model simply because one location’s order waits in the other’s queue. That is what lets the simulation reproduce the exact figures where they exist, settle how far METRIC errs on one system, and check the job-lot case chapter 10 handed on.
The KSL’s supply chain package builds the same systems at a larger scale. It provides holding points, policies, transport and cost accounting, and a structured report, and on the chapter 10 example it is checked against the same exact figures as the chapter’s own classes. It is experimental, a node has one supplier, and lost sales are not available through a specification, so a model should be checked against the limits of Section 11.9.3 before it is built.
| Symbol | Meaning |
|---|---|
| \(t_n\) | the time of the \(n\)-th event |
| \(A_I(t)\), \(A_B(t)\) | the areas under \(I\) and \(B\) from time 0 to \(t\) |
| \(A_{+}(t)\) | the total time up to \(t\) with stock on the shelf |
| \(N_D(T)\), \(N_F(T)\), \(N_L(T)\) | the demands, the demands filled on arrival, and the demands lost, by time \(T\) |
| \(T\), \(T_w\) | the length of a replication after its warm-up, and the warm-up |
| \(n\), \(Y_j\) | the number of replications, and a measure’s time average over replication \(j\) |
| \(s_Y\), \(\mathit{hw}\) | the sample standard deviation of the \(Y_j\), and the half-width of the confidence interval |
| \(n_0\), \(\mathit{hw}_0\), \(\mathit{hw}^{*}\) | a pilot’s replications and half-width, and the half-width wanted |
| \(L_m\), \(t_m\) | the lead time drawn for the \(m\)-th order, and the time it was placed |
| \(C_c\), \(C_p\), \(\Delta\) | the simulated cost rates of a continuous and a periodic policy, and their difference |
| \(C_r\), \(\delta\) | the simulated cost rate at reorder point \(r\), and the indifference zone |
| \(W\) | the time a request waits at the upper location before it ships |
11.12 Exercises
Unless an exercise says otherwise, use the conventions of Section 1.8 and the chapter’s standard run settings of Section 11.4.3: \(n = 30\) replications, each of \(T = 1{,}000\) years after a warm-up of \(T_w = 20\) years, with the KSL’s default random number streams, so that a student and the instructor who use the companion code reach the same intervals. Demand is backordered and filled first come first served unless the exercise says it is lost. Report every simulated figure as an average with its 95% half-width, probabilities and rates to four decimals, and costs to the cent.
11.12.1 Working the Model by Hand
Exercise 11.1 Answer each in a sentence or two, naming the section or equation that settles it.
- True or false: averaging the on-hand column of an event ledger such as Table 11.4 gives the time average of the on-hand level.
- True or false: under single-unit Poisson demand, a simulation’s ready rate and fill rate must agree in every replication.
- True or false: lengthening the warm-up reduces the bias of an estimate, and it costs nothing but run time.
- True or false: common random numbers reduce the variance of each policy’s estimated cost.
- A simulation of an \((r, Q)\) system reports a cost with a relative half-width of 0.8% and a backorder level with a relative half-width of 12%, from the same runs. Which is the most likely reason? (i) The warm-up is too short. (ii) Backorders come in rare episodes, so few independent episodes inform their average. (iii) The model is wrong. (iv) The replications are not independent. Say why each of the others is wrong.
- A supplier’s lead times are random, and its orders can overtake one another. In which direction does Section 8.5.4’s treatment of a random lead time err, and which example of this chapter measures it?
Exercise 11.2 Continue Example 11.1 past week 13, in the same storeroom and under the same policy. Further demands arrive in weeks 14, 15 and 18, and the order placed in week 8 is received in week 16. The observation now closes at week 18.
- Post one row for each event, carrying \(I\), \(B\), \(\mathit{IP}\), the areas \(A_I\), \(A_B\) and \(A_{+}\), and the receipts due, and say at each row whether an order is placed. Remember that each area is credited before the event changes the state.
- Compute \(\bar{I}\), \(\bar{B}\), \(\overline{\mathit{RR}}\) and \(\overline{\mathit{FR}}\) over the eighteen weeks.
- Verify the two identities of Example 11.1’s check: the time with stock plus the time without is eighteen weeks, and \(A_B\) equals the total time demands spent waiting.
- Average the rows of the on-hand and backorder columns instead, and compare.
Exercise 11.3 Five replications of the cutout under job lots, each of 112 years after its warm-up, recorded the counts below.
| Replication | Lots | Lots filled complete | Units demanded | Units filled on arrival |
|---|---|---|---|---|
| 1 | 44,802 | 40,165 | 89,644 | 80,527 |
| 2 | 44,795 | 40,212 | 89,519 | 80,410 |
| 3 | 44,910 | 40,071 | 89,876 | 80,333 |
| 4 | 44,688 | 40,104 | 89,402 | 80,409 |
| 5 | 44,851 | 40,138 | 89,723 | 80,546 |
- Compute the lot fill rate and the unit fill rate of each replication.
- Combine the five replications in the two ways of Section 11.4.4, as the average of the five ratios and as the ratio of the totals, for each measure. How far apart are the two?
- Give a 95% confidence interval for each measure from the five per-replication ratios, using \(t_{4,\,0.025} = 2.776\), and say why the interval is built from those and not from the totals.
- Which of the two fill rates is larger here? A large lot is both more likely to go unfilled and worth more units; say how each of those pulls the two measures apart.
11.12.2 Using the Software
Exercise 11.4 Example 8.6 used the approximate model of Section 8.6 on the transformer, with \(\lambda = 45\) a year, \(k = \$220\), \(h = \$950\) per unit per year, a two-month lead time, and a shortage cost of \(\pi = \$5{,}700\) per unit short. The approximation recommended \((r, Q) = (14, 6)\) and reported a cost of $12,174.25 a year, against $11,922.90 from the exact formulas.
- Simulate the policy \((14, 6)\) and estimate its cost rate, \(k\) times the order rate plus \(h\bar{I}\) plus \(\pi\) times the number of units backordered per year, with a 95% confidence interval. Which of the two reported costs does the interval cover?
- Estimate the fill rate, and compare it with the fill rate the approximate model implies and with the one Equation 8.19 gives.
- Account for the discrepancy in (b) with Table 8.12. Which of the approximation’s assumptions does the simulation make, and which does it not?
Exercise 11.5 Table 8.5 gives the exact cost of four policies for the transformer with \(Q = 5\) and \(r = 8\), 9, 10 and 11, under the costs of Example 8.4: \(k = \$220\), \(h = \$950\) and \(b = \$8{,}550\) per unit per year.
- Simulate the four policies with independent random numbers, and report each policy’s cost with a 95% confidence interval and the six pairwise differences, each with its interval.
- Repeat (a) with common random numbers, so that every policy faces the same demands, and report the same intervals.
- For each pairwise difference, report the ratio of its variance under (a) to its variance under (b). Which differences gain the most from common random numbers, and why those?
- Which policy do you recommend, and is the recommendation the one Table 8.5 makes? Which pairs could the simulation not tell apart?
Exercise 11.6 Example 11.3 gave the transformer an Erlang lead time, two months on average with a standard deviation of one month, and ran the policy \((10, 8)\) under two supply arrangements. Keep everything else and give the lead time a lognormal distribution with the same mean and standard deviation.
- Simulate both arrangements, and report each measure of Table 11.6 and the fraction of orders that overtake an earlier one.
- Set the results beside Example 11.3’s. Chapter 8’s treatment uses only the lead time’s mean and variance, through case 3 of Table 8.3, so it predicts the same figures for both shapes. Does the shape matter, and under which arrangement does it matter more?
- A lognormal has a longer right tail than an Erlang of the same mean and variance. Say how that tail shows up in the fraction of orders that overtake another.
Exercise 11.7 Take the cutout of Example 11.4, in job lots, with the same costs and lead time, and use common random numbers throughout.
- Simulate \((s, S) = (36, 56)\) and \((r, Q) = (36, 20)\), the policy Section 8.12.2 approximates it with. Report each cost, the paired difference with its interval, and each policy’s mean order size. Table 8.23 gives the exact costs, $3,755.69 and $3,876.25; does the interval for the difference cover $120.56?
- Explain the difference using the undershoot. Which policy pays for it, and in which cost term?
- Repeat (a) for \((s, S) = (25, 100)\) against \((r, Q) = (25, 75)\), whose exact costs differ by $0.12. Can the simulation tell them apart, and should it need to?
- At both pairs, report the three service measures of Section 11.4.4 and say which of them the undershoot affects.
Exercise 11.8 Run a \(2^2\) factorial experiment on the transformer of Example 11.2, with the reorder point at 7 and 9 and the order quantity at 5 and 7, using common random numbers across the four design points.
- Report the simulated cost at each design point, and compute each exact cost with
RQModel. - Fit the regression of cost on the two factors and their interaction, and report the coefficients with their intervals.
- Compute the exact cross-difference \(C(9,7) - C(7,7) - C(9,5) + C(7,5)\), and compare its sign and size with the fitted interaction, which estimates a quarter of it. What does the interaction say about choosing \(r\) and \(Q\) one at a time?
Exercise 11.9 Take four items of Table 4.5 with demand arriving one unit at a time: the transformer (\(\lambda = 45\), \(c = \$3{,}800\), \(k = \$220\), a two-month lead time), the fuse cutout (\(\lambda = 800\), \(c = \$115\), \(k = \$82.50\), two weeks), the ground rod (\(\lambda = 2{,}400\), \(c = \$14\), \(k = \$41.25\), two weeks) and the compression connector (\(\lambda = 6{,}000\), \(c = \$3.40\), \(k = \$27.50\), two weeks). Holding costs \(h_j = 0.25c_j\) a year, and the storeroom charges one backorder cost, \(b = \$287.50\) per unit per year, to every item, as Section 8.14.3 supposes.
- Optimize each item’s \((r, Q)\) with
RQOptimizer, and report each item’s exact fill rate and the system fill rate, the demand-weighted average \(\sum_j \lambda_j \overline{\mathit{FR}}_j / \sum_j \lambda_j\). - The utility commits to a system fill rate of at least 0.99. Starting from (a), raise one reorder point by one unit at a time, each time choosing the item that adds the most exact system fill rate per dollar of added exact cost, until the target is met. Report the final policies and their cost.
- Simulate the four items under the final policies and report the system fill rate with its interval. Does the interval lie above 0.99? If it straddles 0.99, say what that means for the commitment.
- Compare each item’s fill rate with the implied service of Table 8.30, and explain the pattern.
Exercise 11.10 Take the running example of Example 11.11, the hub at \((9, 8)\) and four storerooms at base stock 3, but suppose a crew that finds its storeroom empty draws a cutout from a neighboring utility instead of waiting, so the storerooms’ demand is lost. The hub still backorders the storerooms’ requests.
- Simulate the system and report each storeroom’s lost sales rate, ready rate and on-hand level, and the hub’s backorders, ready rate and the mean wait of a request.
- Compare each with Table 11.15, the same system with backorders. Which measures move, in which direction, and why does the hub improve when the storerooms lose sales?
- Nothing exact covers this system. Which of the chapter’s validated examples does its model share every component with, and what does that agreement license here?
Exercise 11.11 This exercise needs sampling but no event model. Take the transformer of case 3 of Example 8.2: Poisson demand at 45 a year over a lead time that is Erlang with shape 4 and rate 24 a year.
- Sample 100,000 lead time demands, each by drawing a lead time and then a Poisson count over it. Compare the observed frequencies of 0 through 20 units with the negative binomial with \(r = 4\) and \(p = 0.3478\), and report the largest difference.
- Estimate \(P\{D(L) \ge 12\}\) with a 95% interval, and compare it with the exact negative binomial value.
- Repeat (a) with a lognormal lead time of the same mean and standard deviation. Does the negative binomial still describe the result, and what does that say about Section 8.3.2?
Exercise 11.13 Take the transformer reviewed every two weeks, so that \(\lambda R = 1.73\) units, with \(S = 14\).
- Simulate \((R, s, S)\) at \(s = 13\), 10 and 6, and report the mean undershoot and the fraction of reviews that place an order at each.
- Compare each mean undershoot with \(\lambda R/2\) from Equation 8.75 and with the \((R, S)\) value derived in Section 8.13.5.
- Compare the results with Example 11.8, where a review interval held 3.75 units. How does the length of the review interval change how wide the spread must be before \(\lambda R/2\) applies?
Exercise 11.14 Take the utility of Example 11.10, with \(S_j = 4\) at each storeroom.
- For \(S_0 = 16\), 18, 20, 22, 24 and 26, simulate the system and report each storeroom’s backorders. Set them beside METRIC’s column of Table 9.3 and VARI-METRIC’s, computed with the chapter 9 code.
- For each \(S_0\), find the smallest \(S_j\) that holds a storeroom’s backorders at or below 0.10 by each of the three routes. At which depot stock levels does METRIC choose a different \(S_j\) from the simulation?
- Relate the finding to the 11% of Graves (1985) that Section 9.7.2 quotes.
Exercise 11.15 Take the transformer of Example 11.5, with demand lost and a cost of \(\pi = \$5{,}700\) per unit lost.
- With \(Q = 6\), simulate every reorder point from 10 to 15 using common random numbers, and find the best by the method of Section 11.7.
- Compare it with \((13, 6)\), the best policy when shortages are charged as backorders. Is the difference in cost worth anything?
- Using Example 11.5, say when charging a lost sale as a backorder misleads a planner and when it does not.
Exercise 11.16 Take the transformer at \(Q = 5\) with \(r = 8\) and \(r = 9\), whose exact costs differ by $9.17 a year.
- Run a pilot of \(n_0 = 10\) replications of each, with common random numbers, and report the variance of the paired difference in cost.
- Using Equation 11.5, how many replications would give a 95% interval for the difference that excludes zero, if the true difference is $9.17?
- Repeat (a) and (b) with independent random numbers.
- Is it worth running? Say what a planner gains from knowing which of the two policies is cheaper.
Exercise 11.17 Rebuild the running example of Example 11.11 with the KSL’s supply chain package, as Section 11.9 does, but with a transit time of two weeks from the hub to each storeroom.
- Report the hub’s backorders and each storeroom’s backorders from the package’s results report.
- Compute the exact figures for a two-week transit with the chapter 10 code,
AxsaterBatchOrdering, and say whether the package’s intervals cover them. - Repeat (a) with the chapter’s own classes, using the same transit time, and compare the two simulations with each other.
11.12.3 Reading the Literature
Exercise 11.18 Read Graves (1985).
- State how the comparison was designed: what was compared with what, and how the reference answer was obtained.
- State the conditions under which METRIC’s stock levels were most often wrong.
- Take one of the test systems the paper describes. Compute its backorders by METRIC and by VARI-METRIC with the chapter 9 code, and estimate them by simulation with this chapter’s classes. Which model is closer, and is the result consistent with the paper’s finding?