Simulating Two-Level Systems, and the KSL Supply Chain Package

Manuel D. Rossetti, PhD P.E.

Agenda

  • Why a simulation carries the coupling chapters 9 and 10 approximated
  • METRIC or VARI-METRIC for the utility’s transformers, settled
  • The cutout’s hub and storerooms reproduced, and what four missed intervals mean
  • The cutout in job lots, the case chapter 10 handed on
  • The same network built with the KSL’s supply chain package
  • The chapter’s classes: three nouns, and no class for a two-level system

The Coupling, Carried Whole

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. A two-level model is the single-location model twice, with one location as the other’s supplier.

The validation follows the chapter’s pattern:

  1. reproduce every quantity chapter 9 computed exactly, then settle the one in dispute;
  2. reproduce chapter 10’s exact system with batching at the hub;
  3. run the case nothing exact covers.

METRIC or VARI-METRIC?

Four storerooms, each seeing 45 failures a year, rebuild three in ten in their own shop in 30 days and send the rest to a depot: 10 days’ transit, 60 days’ repair. \(S_0 = 16\) at the depot, \(S_j = 4\) at each storeroom. 1,000-year replications, \(n = 30\).

Measure METRIC VARI-METRIC Status Simulated
\(\bar{B}_0\), depot 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 3.2276 3.2276 exact 3.2234 to 3.2282, each \(\pm\) 0.008
\(\bar{I}_j - \bar{B}_j\) 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
Backorders, four storerooms 1.6218 1.9259 in dispute 1.9269

The check: the exact rows are covered, so the disputed rows can be read. VARI-METRIC’s 0.4815 lies inside every storeroom’s interval; METRIC’s 0.4055 lies far below. METRIC understates by about 16%.

The Cutout’s Hub and Storerooms

Four storerooms, one cutout a week each, base stock \(S_j = 3\), a one-week transit from a hub running \((r_0, Q_0) = (9, 8)\) against a three-week supplier. Chapter 10 computed every measure exactly. Let \(W\) represent the time a storeroom’s request waits at the hub.

Measure Exact Simulated
\(\bar{B}_0\), hub 1.0273 1.0173 \(\pm\) 0.0087
\(\overline{\mathit{RR}}_0\) 0.6030 0.6045 \(\pm\) 0.0021
\(\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
\(\bar{B}_j\), per storeroom 0.0726 0.0707 to 0.0724, each \(\pm\) 0.0016

The check: \(P(W = 0)\) is the hub’s ready rate, 0.6051 against 0.6045; and Little’s law gives \(\bar{W} = \bar{B}_0/4 = 1.0173/4 = 0.2543\) against 0.2547.

Four Intervals Miss, Together

Read this run slowly: four intervals miss, the hub’s backorders, its mean wait, \(P(W = 0)\) and \(P(W \le 1)\), 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 depending on it moved the same way.

That is what correlated intervals from one set of runs do. Checked as a family at the Bonferroni level, \(1 - 0.05/k\) for \(k\) measures, 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, beside chapter 10’s routes: exact 0.0726, conditioned on the wait 0.0726, two moments 0.0712, mean wait only 0.0505. The simulation sits with the first three: the mean wait alone understates a storeroom’s backorders by 30%, seen from outside the mathematics.

The Cutout in Job Lots

Chapter 10 set both policies by iteration and said nothing exact covers the case. Lots of 1, 2 or 4 at 150 a year at the storeroom; the hub serves 250 lots a year of its own; two-month supplier, one-month transfer; \(k = \$82.50\), \(h = \$28.75\), storeroom \(b = \$287.50\), hub \(b_0 = \$115\). Policies \((25, 49)\) at the storeroom and \((120, 92)\) at the hub.

Storeroom, predicted simulated Hub, predicted simulated
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
Lot fill rate 0.9108 \(\pm\) 0.0011 0.8001 \(\pm\) 0.0017

The check: order rate is units over batch: \(300/49 = 6.12\) at the storeroom and \((500 + 300)/92 = 8.70\) at the hub, which sees the storeroom’s 300 units a year in orders of 49.

The iteration’s policies cost less than it said: $57.58 less at the storeroom and $79.67 at the hub, about 4% at each. The moment route is conservative here, the safe direction.

The KSL Supply Chain Package

The chapter’s own classes show the mechanism. A network of realistic size needs more: several items per location, transport between locations, costs by location and cost line, and a report a manager can read. ksl.modeling.supplychain supplies those.

A network is a tree of inventory holding points, each holding one or more items, each item running its own policy, rooted at an external supplier, with customer demand at the leaves and a transport time on each edge.

This book The package
\((r, Q)\); \((s, S)\); \((R, s, S)\) sQ(s, Q); sS(s, S); sSPeriodic(s, S, reviewInterval)
Base stock at level \(S\) sQ(s = S - 1, Q = 1)
\(\bar{I}\), \(\overline{\mathit{IO}}\), \(\bar{B}\) On Hand, On Order, Amt BackLogged
\(1 - \overline{\mathit{RR}}\) Fraction of Time w/o Stock
Lot fill rate; unit fill rate First Fill Rate; Unit Fill Rate

The package is released as experimental, and its interface may change between KSL versions. Everything here was written against KSL R1.7.1; check the release notes before relying on a name or default with a later version.

The Same Network, Specified

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()))
        }
    }
}
Measure Exact The chapter’s classes The package
Hub on hand 2.5273 2.5334 \(\pm\) 0.0124 2.5334 \(\pm\) 0.0124
Hub backorders 1.0273 1.0173 \(\pm\) 0.0087 1.0173 \(\pm\) 0.0087
Storeroom 1 backorders 0.0726 0.0721 \(\pm\) 0.0016 0.0721 \(\pm\) 0.0016

The package and the chapter’s classes agree exactly, to every digit: they draw the demand streams from the same stream numbers and implement the same assumptions, so they follow the same sample path event for event. That is the strongest agreement two independent programs can show.

What the Package Does Not Do Yet

Lost sales are not available through a specification. A lost-sales system can be built object by object, but its fill rates then count only demands that were not lost, so they overstate service. The lost-sales example used the chapter’s own classes for that reason.

A node has one supplier. The network is a tree, so a storeroom sending some requests to its own shop and the rest to a depot is outside what a specification describes.

A periodic review interval is a constant, which covers every periodic example in the book.

Random number streams are the modeler’s responsibility. Identical streams with an identical structure give an identical sample path. That makes common random numbers possible, and it is also why runs meant to be independent must be given different streams.

Three Nouns, and What Is Not a Class

The chapter’s package inventory.simulation has three nouns that become classes: the stock point, the policy it runs, and the supplier that fills its orders.

The event is not a class. A demand and a receipt are methods of the stock point, scheduled on the KSL’s calendar: two event methods and one decision method, where the event table puts them.

Lost sales is not a subclass. Whether an unmet demand waits is a property of the demand, so it is a flag; 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, the review; under it the stock point’s decision method does nothing on a demand.

A two-level system is not a class. A stock point obtains stock by asking an InventoryFillerIfc to fill an order. A supplier with a lead time is one kind of filler, and so is another stock point behind a TransitLink. The coupling chapters 9 and 10 worked so hard to approximate is, here, simply the order of the calls.

Assembled From the Same Classes

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

The storeroom’s filler is a TransitLink to the hub: each storeroom order becomes a demand at the hub, and what the hub ships arrives a month later. Nothing else distinguishes a hub from a storeroom.

The Two Routes Must Agree

There is one test for every example with an exact column, and each asserts the agreement the example states: the ledger test asserts equality row by row, since nothing in it is random, and every other test asserts that each interval covers the exact value.

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 builds its intervals at the Bonferroni level, \(1 - 0.05/k\) for \(k\) measures, so a correct model passes the whole family at 95%.

The tests run at a fixed seed, so a test that passes once passes every time. They do not pin the printed simulated digits, which a later KSL version may move within a half-width. What they guarantee is what matters: every interval still covers the exact value it was printed beside.

What We Did Today

A two-level simulation carries the coupling whole, as one stock point supplying another.

VARI-METRIC is right to the third decimal on the utility’s plan; METRIC understates storeroom backorders by about 16%.

Four correlated misses are one event, passed as a family at the Bonferroni level and covered by longer runs; the mean-wait route understates storeroom backorders by 30%.

Chapter 10’s job-lot policies cost about 4% less than predicted: the moment route is conservative.

The KSL package reproduces the network to every digit, with stated limits.

No class is a two-level system; the coupling is the order of the calls, and every exact example is a test.

For Next Time

This was the last session of the course material.

Today’s material was Multi-Echelon Systems, The KSL Supply Chain Package and Designing the Software.

For review:

  • Every model in the course minimizes the same objective under different assumptions about what is known and what may be decided
  • Where a formula exists it comes first; where it stops, a simulation that has first reproduced the formula takes over
  • A simulated number is reported with its half-width, its run settings, and the exact result it was checked against

The chapter’s summary collects the rules of this unit in one place, and is worth reading as a review of the whole course.

⌂ Index