MEIO V4 Worked Numbers — Every Figure, Traced¶
Status: Companion walkthrough for the implemented MEIO V4 release (Aug 2026). Every number below is exact arithmetic on the stated inputs, computed by the same formulas the optimizer runs (
files/meio_network_topology.py,files/meio_runner.py::_attach_v4_network,files/MEIO_v3/src/marginal.rs).How to read this page: first the toy network, then every input with its master-data source, then the numbered computations. Each computation says what, why, and where it shows up (Network Diagnostics panel, MEIO results). Nothing here is approximated — reproduce it on a calculator and you get the optimizer's numbers.
1. The toy network (in gps_1 geography)¶
A small version of the crates network — the same site names you see in gps_1, with round numbers for easy checking. One returnable crate (item 7, the "GPS Standard Crate"):
flowchart LR
WH["Bremen Supplier (100)"] -->|"TRANSFER 6 wk (standard)"| S1["Frankfurt DC (81)"]
S2["Rotterdam DC (80)"] -->|"BALANCING 0.25 wk (rescue)"| S1
S3["Continental Hannover (84)"] -->|"RETURN 1 wk (dirty crates)"| F["Rotterdam Wash (facility)"]
F -->|"REPAIR 3 wk, yield 0.8, quota 1"| S1
F -->|"REPAIR 3 wk, yield 0.8, quota 3"| S2
- The GPS Europe zone contains Frankfurt (81) and Rotterdam (80) for item 7 (
config_zone_parameter), so theBALANCINGroute between them classifies as a rescue edge — exactly like the real routes 7/11 in gps_1. - Bremen Supplier → Frankfurt is a
TRANSFERroute: standard hierarchy replenishment. - Continental → Rotterdam Wash is the only dirty-crate inflow of the facility (a
RETURNroute) — the tyre plant does not get its own crates back. - Rotterdam Wash sends repaired good units to Frankfurt and Rotterdam — not back to Continental. This is the pooled repair model: whatever arrives at the facility repairs whoever the output quotas say.
2. All inputs, with their master-data source¶
| # | Input | Value | Comes from |
|---|---|---|---|
| I1 | Item | 7 ("GPS Standard Crate") | every route's item_id |
| I2 | Zone membership | item 7, zone "GPS Europe", members {81 Frankfurt, 80 Rotterdam}, participation 1 | config_zone_parameter |
| I3 | Demand at Frankfurt | λ = 4 units/week | master.demand_actuals → SKU total_demand_rate |
| I4 | Demand at Rotterdam | λ = 4 units/week | same |
| I5 | Demand at Continental | λ = 6 units/week | same |
| I6 | TRANSFER Bremen→Frankfurt lead time | 6 weeks, network_role empty |
master.route (LT days / 7) |
| I7 | BALANCING Rotterdam→Frankfurt lead time | 0.25 weeks, network_role empty |
master.route. 0.25 wk ≈ 1.75 days |
| I8 | RETURN Continental→Rotterdam Wash | return_rate 0, push_quota 0.5, return_wash_rate 0.2, LT 1 week |
master.route |
| I9 | REPAIR Wash→Frankfurt | repair_yield 0.8, shop LT 3 weeks, wip_qty 6, capacity resource 42 (3 units/week), push_quota 1.0 |
master.route + route_resource/capacity_id → {schema}.pipe_supply_capacity |
| I10 | REPAIR Wash→Rotterdam | repair_yield 0.8, push_quota 3.0 |
same |
| I11 | Fill-rate TARGET | 0.95 for the zone/segment group | segment MEIO parameter set (config_meio_parameter_set) — this is the goal you configure (your 95%/98% values in gps_1) |
| I12 | Rotterdam leg lead time | 1 week | route blend → SKU leg_lead_time |
| I13 | Frankfurt leg lead time | 1 week | same |
network_role empty everywhere on purpose: the whole classification comes from route type + zone membership — the default the customer sees without touching the Routes grid.
Optimizer state — NOT inputs (used in the arithmetic below)¶
Two values in the computations that follow look like inputs but are mid-run optimizer state, not master data or configuration:
| State value | Toy value | Where it comes from |
|---|---|---|
| Bremen Supplier current fill rate | FR = 0.90 | The fill rate the supplier's currently committed buffer produces at the moment the optimizer evaluates the next investment step. It starts low (little or no buffer) and is recomputed after every committed step as the buffer grows toward the target. |
| Frankfurt current fill rate | FR = 0.60 | Same for Frankfurt — a snapshot from partway through the greedy loop, not a setting. |
Do not confuse these with the target (I11): the target is what you configure (0.95/0.98 in gps_1); the current FR is what the optimizer has achieved so far. The formulas need the current value because the marginal questions are state-dependent:
- hierarchy wait (N2):
parent_wait = LT × (1 − FR_supplier_current)— the more stocked the supplier already is, the less the child suffers; - shortage claim (N5):
(1 − FR_Frankfurt_current) × λ × horizon— the remaining gap the rescue could cover, which shrinks as Frankfurt's own buffer grows.
In the toy arithmetic the values 0.90 and 0.60 were picked as convenient mid-run snapshots; in a live run they move at every iteration.
What leg_lead_time actually is (I12–I13)¶
leg_lead_time is not something you type anywhere — it is computed by the engine from your routes:
leg_lead_time(item, site) = Σ(coverage_pct_i × LT_i) / Σ(coverage_pct_i)
over every BUY / TRANSFER / MAKE route arriving at (item, site)
- Per route, the lead time is the route's total days converted to weeks:
(lead_time + transit_time + pick_pack_time) / 7frommaster.route. - The blend (
route_lt_blendinmeio_runner.py): when several replenishment routes serve the same SKU at the same site, the leg is the coverage-weighted average of their lead times — the route that physically supplies 60% of the flow contributes 60% of the leg. If no route carries acoverage_pct, they split equally. - Meaning: the deterministic time between "I order from my standard supplier(s)" and "stock is on my shelf" — before any parent wait. Your full horizon is
leg + wait: the leg is your route's fault, the wait is your upstream parent's fault (N2). - Zone scenarios (
enable_zone_pass) deliberately swap this for an all-route blend (every arriving route type, not just BUY/TRANSFER/MAKE), so warehouses replenished by REPAIR/BALANCING loops still get a real lead time for the pooled zone pass.
Toy values are round (1 week for both warehouses) to keep the arithmetic clean. For reference, the gps_1 live runs produced: Rotterdam 0.0 wk (its replenishment is the on-site wash line — no transit), Frankfurt 10.0 wk, Memphis 9.0 wk, Detroit 0.0 wk, and the producers ≈ 0.4–0.6 wk (their crate supply is local).
3. Edge classification (N1)¶
Classification precedence: explicit network_role → zone-aware default → standard.
| Route | Type | Co-zonal for item 7? | Classified as | Why |
|---|---|---|---|---|
| Bremen→Frankfurt | TRANSFER | n/a | Standard replenishment | TRANSFER is always the hierarchy (forward), never rescue, unless the planner sets network_role='rescue'. |
| Rotterdam→Frankfurt | BALANCING | yes (both in the GPS Europe zone for item 7) | Lateral rescue | intra-zone balancing = the default rescue lane. |
| Continental→Rotterdam Wash | RETURN | n/a | Repair pool inflow | RETURN never serves demand; it replenishes the facility's bad pool. |
| Wash→Frankfurt, Wash→Rotterdam | REPAIR | n/a | Repair pool outputs | good output of the shared facility pool, split by push_quota. |
The Network Diagnostics panel lists exactly these four edge groups for the scenario.
4. Hierarchy wait — the standard branch (N2)¶
The Bremen supplier replenishes Frankfurt. The hierarchy wait Frankfurt suffers when the supplier is stocked out:
That 0.6 weeks is Frankfurt's base wait (stored as current_base_wait_time — the pre-rescue hierarchy wait the optimizer can always recover).
Frankfurt's standard resupply horizon (no rescue, no repair):
5. Rescue: how much stock can Rotterdam actually lend? (N3–N7)¶
N3 — Rotterdam's protected stock (a source never sacrifices itself)¶
Rotterdam's own pipeline requirement (demand over its own effective lead time):
Rotterdam has no configured min floor (sku_min_sl_qty = 0), so the protection is this pipeline baseline. (With an ASL floor configured, the protection would be that floor instead.)
N4 — Rotterdam's free (shareable) stock¶
Fill rate is not availability: Rotterdam's FR is 0.92, but only 2 units are lendable — 4 units are busy covering its own demand. This is the number the old proposal's FR × dilution formula could not produce.
N5 — Frankfurt's shortage claim¶
N6 — Allocation of Rotterdam's free stock¶
Frankfurt is Rotterdam's only claimant (one-hop rescue edge). The BALANCING route has no capacity resource, so the lane is uncapped:
Arrival probability: the rescue lead time (0.25 wk) beats the standard horizon (1.6 wk) with certainty, and there is no configured lead-time variability on this route:
P(arrival ≤ H_Frankfurt) = 1.0 (0.25 ≤ 1.6, deterministic)
useful = alloc × reliability × P(arrival) = 2 × 1.0 × 1.0 = 2 units
N7 — Rescued fraction and the blended wait¶
Frankfurt's effective wait blends the fast rescue arrival with the slow hierarchy wait:
wait_Frankfurt = (1 − 0.78125) × 0.6 + 0.78125 × 0.25
= 0.21875 × 0.6 + 0.1953
= 0.13125 + 0.1953
= 0.327 weeks (was 0.6 without rescue)
New effective horizon:
Every unit the optimizer adds at Rotterdam is priced with this horizon reduction for Frankfurt — the source's buffer helps its peer by exactly the allocated quantity, not by a diluted fill rate.
6. Repair as a pooled, timed supply process (N8–N12)¶
N8 — The wash facility's inflow pool¶
The RETURN route carries return_rate = 0, so the dual-convention rule uses the bad_forecast formula:
fraction = push_quota × (1 − return_wash_rate)
= 0.5 × (1 − 0.2)
= 0.40 of Continental's demand returning as dirty crates
pool_inflow = 0.40 × λ_Continental = 0.40 × 6 = 2.4 units/week
(The other convention — a return_rate > 0 on the RETURN route — would win over this formula when set. Both are explicit master data; nothing is guessed.)
The pool-inlet lead time is the fraction-weighted mean of the facility's RETURN routes. Only one route exists:
N9 — Capacity and output split¶
The wash line allows 3 units/week; inflow is 2.4:
The facility's two REPAIR outputs split by push_quota (source-side outflow policy):
(If all quotas at a facility were NULL/0, the split would be equal — the same normalization the indirect-demand rollup uses for coverage.)
N10 — Yield and the wire values sent to the optimizer (Frankfurt)¶
The Python pre-pass writes, on Frankfurt's repair process edge:
| Wire field | Value | Meaning |
|---|---|---|
return_rate |
0.48 / 4 = 0.12 | allocated good units as a fraction of Frankfurt's demand |
repair_yield |
1.0 | yield already applied once — the Rust side must not re-apply it |
capacity_per_week |
0.48 | allocated good units; the engine's min(inflow, cap) stays harmless |
current_wip_qty |
6 × 0.8 = 4.8 | WIP pre-multiplied by yield for exactly the same reason |
total_cycle_weeks |
return 1 + shop 3 = 4 weeks | the repair branch's own lead time |
N11 — Net demand after timed repair (Rust side)¶
bad_inflow = λ_Frankfurt × return_rate = 4 × 0.12 = 0.48 units/week
throughput = min(bad_inflow, capacity) = min(0.48, 0.48) = 0.48
good_out = throughput × repair_yield = 0.48 × 1.0 = 0.48
net_demand = max(0, λ − good_out) = 4 − 0.48 = 3.52 units/week
Legacy V3 netting would have computed the same net demand here — the difference comes next.
N12 — WIP phased by horizon, and the horizon blend¶
Legacy netting credited all WIP×yield immediately (4.8 units as if on the shelf). V4 only credits what can finish inside Frankfurt's own resupply horizon:
cycle = 4 weeks
horizon = H'_Frankfurt = 1.327 weeks (from N7)
phase = min(1, horizon / cycle) = min(1, 1.327 / 4) = 0.3318
WIP_credit = 4.8 × 0.3318 = 1.59 units (legacy: 4.8 — three times as much)
And the demand covered by repair accrues over the repair cycle, not over the procurement horizon (the horizon blend):
procurement-side demand over horizon = net_demand × H'_Frankfurt
= 3.52 × 1.327 = 4.671 units
repair-side demand over cycle = good_out × cycle
= 0.48 × 4 = 1.92 units
effective demand-over-lead-time = 4.671 + 1.92 = 6.59 units
If the wash facility takes 8 weeks instead of 4, the second term doubles to 3.84 and the total becomes 8.51 — a longer repair lead time genuinely raises Frankfurt's stock requirement, which the legacy netting could not express at all.
Sanity table — legacy V3 vs V4 for Frankfurt¶
| Quantity | Legacy netting (V3 mode) | Timed repair (V4 mode) |
|---|---|---|
| Net weekly demand | 3.52 | 3.52 |
| Demand over effective LT | 3.52 × 1.6* = 5.63 | 4.671 + 1.92 = 6.59 |
| WIP credit | 4.8 (immediate) | 1.59 (phased) |
| Repair lead time | invisible | explicit driver of stock |
* V3 also had no rescue, so its horizon is the un-blended 1.6 weeks (leg + hierarchy wait). V4 mixes both effects into one effective requirement — this is the full picture of what changed.
7. Two claimants, one pool — the allocation policy (N13)¶
Independent second example. Suppose Rotterdam had two rescue claimants: Frankfurt (criticality 2, shortage 3.2) and Detroit DC (criticality 1, shortage 1.6), and Rotterdam's free stock were 3 units.
Priority-then-proportional (locked policy): criticality tiers are served first; equal tiers split proportionally to their claims.
Tier crit=2: claims 3.2, pool 3 → pool exhausted within the tier
Frankfurt gets min(3.2, 3) = 3 units (proportional split inside one-claimant tier)
Tier crit=1: claims 1.6, pool left 0
Detroit gets 0 units
If Rotterdam's free stock were 4.6 instead:
Tier crit=2: 3.2 ≤ 4.6 → Frankfurt gets its full 3.2; pool left = 1.4
Tier crit=1: Detroit gets min(1.6, 1.4) = 1.4
The allocation is source-conserving in every case: the sums never exceed the free pool, so one unit of backup can never be credited to two destinations at once.
8. Where each number shows up¶
| Number | Surface |
|---|---|
| Edge classes (N1) | Network Diagnostics panel — Rescue / Standard/edge tables |
| Base wait (N2) | internal (current_base_wait_time); diagnostics show the hierarchy edges |
| Free stock (N3–N4) | not displayed directly; drives the rescue-credit computation |
| Allocation & rescued fraction (N6–N7) | changes Frankfurt's effective wait → MEIO results wait time column |
| Pool inflow/split (N8–N9) | Network Diagnostics — Timed repair processes table (inflow via facility row, quota per output) |
| Wire values (N10) | internal; the table above is exactly the payload |
| Net demand, WIP, horizon blend (N11–N12) | internal; reflected in Frankfurt's committed buffer (MEIO results Committed buffer) |
9. One-paragraph version for the customer¶
Rotterdam DC carries six crates of stock. Four are busy feeding its own demand, so two are lendable. Its sister depot Frankfurt, in the same GPS Europe zone, has an expected gap of 2.56 crates over its six-week supplier resupply, so it takes those two — its effective wait drops from 0.6 to 0.33 weeks. Meanwhile the Rotterdam wash line receives 2.4 dirty crates per week from Continental Hannover, keeps them under its 3-per-week line, repairs eight out of ten, and sends a quarter of the output to Frankfurt: 0.48 good crates per week arriving four weeks after the crates got dirty. That stream covers part of Frankfurt's demand, but only 1.6 of the 4.8 WIP units count as available today — because the rest cannot finish inside Frankfurt's 1.3-week window. The optimizer sizes Frankfurt's buffer on 6.59 crates of demand-over-lead-time instead of 5.63, because repaired supply is supply with a lead time of its own, and sibling stock only counts when it is actually free, allocated, and close enough to matter.
Appendix — full arithmetic in one column¶
parent_wait (Bremen) = 6 × (1−0.90) = 0.600 wk
protected_Rotterdam = 4 × (1+0) = 4.000 units
free_Rotterdam = max(0, 6 − 4) = 2.000 units
H_Frankfurt = 1 + 0.6 = 1.600 wk
shortage_Frankfurt = 0.40 × 4 × 1.6 = 2.560 units
alloc_Rot→Fra = min(2.56, 2) = 2.000 units
useful = 2 × 1.0 × 1.0 = 2.000 units
rescued_fraction = 2 / 2.56 = 0.78125
wait_Frankfurt = 0.21875×0.6 + 0.78125×0.25 = 0.327 wk
H'_Frankfurt = 1 + 0.327 = 1.327 wk
return fraction = 0.5 × (1−0.2) = 0.400
pool_inflow (Continental) = 0.4 × 6 = 2.400 units/wk
pool_available = min(2.4, 3) = 2.400 units/wk
quota split = 1:(1+3), 3:(1+3) = 0.25 / 0.75
pool_to_Frankfurt = 2.4 × 0.25 = 0.600 units/wk
good_units_Frankfurt = 0.6 × 0.8 = 0.480 units/wk
wire return_rate = 0.48 / 4 = 0.120
net_demand = 4 − 0.48 = 3.520 units/wk
wire WIP = 6 × 0.8 = 4.800 units
cycle = 1 + 3 = 4.000 wk
WIP phase = min(1, 1.327/4) = 0.3318
WIP_credit = 4.8 × 0.3318 = 1.590 units
demand over LT = 3.52×1.327 + 0.48×4 = 6.590 units
Case study — gps_1 crates network (live data, Aug 2026)¶
Same formulas, real tenant. Scenario "V4 Network Rescue" (id 3) bound to pipelines 2 (MRP) and 3 (LP); item 7 "GPS Standard Crate" (unit cost 5.0).
Classification produced 21 edges¶
| Class | Count | Which |
|---|---|---|
| Lateral rescue | 4 | BALANCING pairs 80↔81 (Rotterdam↔Frankfurt) and 85↔86 (Memphis↔Detroit), τ = 2 days = 0.286 wk — intra-zone in config_zone_parameter |
| Forward replenishment | 12 | TRANSFER/inter-zone routes |
| Use (consumption) | 5 | USE routes to the tyre plants |
| Repair process | 2 | facility 80 (Rotterdam wash) and facility 85 (Memphis wash) |
Repair pool arithmetic (exact, from the engine's own batch demand rates)¶
Facility 80 — Rotterdam wash. Only RETURN inflow: route 56, Continental Hannover (84) → 80, return_rate=0.8, LT 4 days = 0.571 wk. Only REPAIR output: route 12, 80 → 80, shop LT 7 days = 1.0 wk, yield 0.92, WASH resource cap 400 units/wk, quota 1.0 (sole output → share 1.0).
λ(item7 @ Continental 84) = 808.3482 units/wk (batch demand signal)
pool inflow = 0.8 × 808.3482 = 646.679 units/wk
pool available = min(646.679, 400) = 400.000 units/wk ← capacity caps
good units to Rotterdam = 400 × 0.92 = 368.000 units/wk
wire return_rate = 368 / 703.5683 = 0.523048
λ(item7 @ Rotterdam 80) = 703.5683 units/wk
net demand after repair = 703.5683 − 368 = 335.568 units/wk (−52.3%)
repair cycle = 0.571 + 1.0 = 1.571 wk
Facility 85 — Memphis wash. RETURN route 22 from Cooper Tire Findlay (88), return_rate=0.8, LT 3 days = 0.429 wk. REPAIR route 21, 85 → 85, yield 0.92, cap 100 units/wk.
λ(item7 @ Cooper 88) = 230.7305 units/wk
pool inflow = 0.8 × 230.7305 = 184.584 units/wk
pool available = min(184.584, 100) = 100.000 units/wk ← capacity caps
good units to Memphis = 100 × 0.92 = 92.000 units/wk
wire return_rate = 92 / 291.5685 = 0.315535
net demand at Memphis = 291.5685 − 92 = 199.569 units/wk (−31.6%)
repair cycle = 0.429 + 1.0 = 1.429 wk
Rescue arithmetic (why the effect is tiny on this network)¶
Route 7, Rotterdam(80) → Frankfurt(81): the source's protection is its own demand over its own horizon — Rotterdam's leg is 0 weeks, so:
protected_80 = net_rate × (leg + wait) = 335.568 × (0 + 0) = 0
free_80 = committed ROP − 0 = 1 − 0 = 1 unit only
shortage_81 = (1 − 0.0000) × 376.5935 × (10 + 0) = 3765.9 units
alloc = min(3765.9, 1) = 1 unit
rescued_fraction = 1 / 3765.9 = 0.00027
blended horizon = (1−0.00027)×10 + 0.00027×0.286 = 9.997 wk (from 10)
Route 20, Detroit(86) → Memphis(85): Detroit also holds 1 unit → rescued_fraction ≈ 0.0018, horizon 9 → 8.984 wk. The optimizer's answer on this data: rescue lanes exist but the sources hold no surplus, so almost nothing flows — and it does not pay to stock Rotterdam/Detroit just to feed their sisters. That is a legitimate planning conclusion, visible for the first time, not a model failure.
Results written (pipeline 2, archive 2026-07-27, scenario 3)¶
| Site | rop | safety stock | fill rate | wait | leg | Note |
|---|---|---|---|---|---|---|
| 80 Rotterdam | 1.0 | 1.0 | 1.0000 | 0.0 | 0.0 | zero lead time + 52% repair coverage → floor buffer |
| 81 Frankfurt | 250.0 | 0.0 | 0.0000 | 0.0 | 10.0 | indirect-only demand under direct scope (identical in V3) |
| 82 Michelin | 16650.0 | 16417.9 | 0.7500 | 0.0 | 0.43 | direct demand 541.6/wk |
| 83 Bridgestone | 9950.0 | 9759.6 | 0.7917 | 0.0 | 0.57 | direct demand 333.3/wk |
| 85 Memphis | 2651.0 | 26.9 | 0.6976 | 0.0 | 9.0 | net demand 199.6/wk after repair |
| 86 Detroit | 1.0 | 1.0 | 1.0000 | 0.0 | 0.0 | floor buffer |
| 87 Goodyear | 12700.0 | 12506.8 | 0.8333 | 0.0 | 0.49 | direct demand 397.8/wk |
All waits are 0.0000 because no parent imposes one: every TRANSFER-free network edge is USE/REPAIR/BALANCING, and the hierarchy propagation only follows TRANSFER routes. Rescue therefore acts on the horizon (leg-shortening), not on a parent wait — the V4 runs moved Memphis from 2687 → 2651 units (−36 × €5 = −€180) when the horizon-blend correction landed.
Why Frankfurt shows zero safety stock and Memphis does not (the two real blockers)¶
Both sites are indirect-only warehouses — but neither outcome is caused by the demand scope. The debug trace of the same run proves it:
Frankfurt (81) is clamped by its depot storage cap. The ASL floor (sku_min_fill_rate = 0.7 from the catch-all parameter set) computed its ideal buffer:
ASL buffer (Frankfurt) ≈ 3766 units (λ 376.59/wk × 10-wk horizon + safety → fr 0.697)
location cap (Frankfurt DC) = 250 units ← master.site.max_capacity_qty
committed buffer = min(3798, 250) = 250
fill rate at 250 vs demand-over-LT 3765.9 ≈ 0.0000 ← the displayed 0.0000
Memphis (85) is parked by the max fill-rate ceiling. ASL pushed it to buffer 2651 (fr 0.6976); the greedy loop's next step would take it from 0.6976 to 1.0000, which exceeds the catch-all parameter set's sku_max_fill_rate = 0.999 → below_max=false → the SKU is exhausted and receives no further investment. It stays at 0.6976 — above its 0.7 floor region, below the 0.95 target, blocked by the ceiling.
Consequence for configuration: switching demand_scope to total changes nothing on these two sites because they are constraint-limited, not reward-limited. Total scope pays off when the greedy loop's reward decides the investment (e.g. uncapped indirect warehouses without a max-fill collision). To move these two: raise Frankfurt's max_capacity_qty (master data, via import.site) if 250 is a placeholder, and/or raise the segment's sku_max_fill_rate toward 1.0 if parking at 0.6976 is undesired.
The leg blend in gps_1, decomposed per site¶
Only Goodyear Akron actually exercises the weighted average — every other site has exactly one replenishment route (or none):
| Site | Route | Type | Source | LT (days) | coverage_pct | Weight share | LT×share |
|---|---|---|---|---|---|---|---|
| Frankfurt DC (81) | 35 | BUY | external supplier | 70 | NULL → 1.0 | 1.000 | 10.000 wk |
| Michelin Clermont-Ferrand (82) | 57 | TRANSFER | Rotterdam DC | 3 | 1.0 | 1.000 | 0.429 wk |
| Bridgestone Béthune (83) | 50 | TRANSFER | Frankfurt DC | 4 | 1.0 | 1.000 | 0.571 wk |
| Memphis DC (85) | 49 | BUY | external supplier | 63 | NULL → 1.0 | 1.000 | 9.000 wk |
| Goodyear Akron (87) | 5 | TRANSFER | Memphis DC | 3 | 0.6 | 0.600 | 0.257 wk |
| 〃 | 6 | TRANSFER | Detroit DC | 4 | 0.4 | 0.400 | 0.229 wk |
| 〃 | blend | Σ = 1.0 | 0.486 wk |
Goodyear's leg: 0.6 × (3/7) + 0.4 × (4/7) = 0.257 + 0.229 = 0.486 wk. Rotterdam (80) and Detroit (86) have no BUY/TRANSFER/MAKE route arriving — their replenishment is the on-site REPAIR wash loop, which the standard blend deliberately excludes — so their leg is 0.0 wk (their supply timing comes from the repair process edges, N8–N12, not from the leg blend).
Install-base direct demand (Aug 2026 addition)¶
The producers (Michelin Clermont-Ferrand 82, Bridgestone Béthune 83, Goodyear Akron 87) are flagged is_install_base — their demand is direct customer demand for the GPS depots. The first-hop TRANSFER rollup now tags those good_replenishment rows is_install_base_direct = 1 and MEIO counts them as direct demand at the receiving depot:
Rotterdam (80) ← Michelin (82): 29,140 units tagged direct → ddr = 135.2/wk
Frankfurt (81) ← Bridgestone (83): 17,641 units tagged direct → ddr = 89.1/wk
Memphis (85) ← Goodyear (87): 13,607 units tagged direct → ddr = 62.8/wk
Detroit (86) ← Goodyear (87): 9,071 units tagged direct → ddr = 41.5/wk
All four depots now carry is_direct_demand = 1 in PIPE_meio_results — they earn group reward and are sized as customer-facing stocking points, while their total sizing signal is unchanged (the split moves attribution, not volume).
How to check every number yourself¶
- Edge classification: MEIO Scenarios → edit "V4 Network Rescue" → Network Diagnostics (V4) panel — 4 rescue edges, 12 standard, 2 repair processes, each with LT/cap/yield.
- Route inputs: Settings → Master Data → Routes — routes 7/11/16/20 (BALANCING, 2-day lead), 56/22 (RETURN,
return_rate0.8), 12/21 (REPAIR, yield 0.92). Net Role column empty → default classification. - Pool inputs: the inflow fractions and quotas in SQL —
SELECT r.id, r.item_id, r.site_id, r.source_site_id, rt.planning_type,
r.return_rate, r.push_quota, r.repair_yield
FROM master.route r JOIN master.route_type rt ON rt.id = r.type_id
WHERE rt.planning_type IN ('RETURN','REPAIR');
- Capacity:
SELECT * FROM gps_1.pipe_supply_capacity WHERE resource_type='WASH' AND scenario_id IS NULL→ 400/wk (80), 100/wk (85). - Results: in ClickHouse —
SELECT site_id, rop, safety_stock, fill_rate, wait_time, leg_lead_time, direct_demand_rate
FROM gps_1.PIPE_meio_results
WHERE pipeline_id = 2 AND scenario_id = 3 AND item_id = 7
AND archive_date = (SELECT max(archive_date) FROM gps_1.PIPE_meio_results WHERE pipeline_id = 2)
ORDER BY site_id;
- Recompute the pools by hand with the formulas in §6 and this page's appendix — every figure matches the engine's wire values exactly (verified against
_load_sku_records+_allocate_repair_capacityoutput).