Theory
The intuition behind the construction — condensed from the full paper
This page is a short, web-friendly walkthrough of the ideas behind grocery-sim. It is deliberately condensed — for the complete derivations, notation, and every calibrated parameter, see the full paper (PDF).
The problem with the usual two options
Hand an analyst a real business’s spreadsheet, and she can check whether her conclusions sound reasonable — but not whether they are true, because nobody, not her, not the business itself, actually knows the mechanism that produced the numbers. Hand her a spreadsheet generated by drawing every column from a convenient distribution, and she can check her work against the generating code, but there’s nothing underneath worth discovering: no owner who misread a signal, no competitor who mattered less than everyone assumed, no honest mess in the paperwork to clean up before the real question can even be asked.
grocery-sim is a third option: build the business first, as a world with people, budgets, and a street, and only afterward let the paperwork fall out of what that world actually did. The result is a dataset messy enough to feel real, where every number still has a traceable cause — a conclusion can be checked not just for plausibility but for truth.
Two layers, and the rule that never gets broken
The world is built from two layers that are never allowed to blend into one another:
- The micro layer — decisions. A customer choosing between two cartons of milk. An owner choosing where to open a store before a single customer has walked through the door. The same owner choosing, later, whether to hire, and whether to expand, under capital he does not have room to lose. Every one of these is a real decision, built from plain human intuition first and only then written as a precise mathematical object.
- The macro layer — the script. The weather, the calendar, and the macroeconomic shocks are scripted in advance and never listen to anything the simulated people do. A supply shock happens on a fixed date whether or not the owner reacts well to it.
The distinction is not a modeling convenience — it’s the whole point. It’s what lets a later reader ask what would have happened without the storm, or without the competitor, and get an answer that is exactly true rather than merely estimated.
Why the split makes counterfactuals free
Because the macro layer is written entirely in advance and never listens to the micro layer, a counterfactual world costs almost nothing to produce: edit the script — delete the scripted shock, disable the expansion threshold, remove the competitor entirely — and replay the identical daily market mechanism with every other random draw held fixed. The difference between the original run and the edited run is the causal effect of the edit, not merely an estimate of it.
This only works because of one discipline applied from the first line of the implementation: every random draw is keyed by the stable identity of the entity it concerns — a specific customer on a specific day, a specific product on a specific night — using independently spawned child streams, rather than one long sequential stream. If draws were sequential, deleting a single event partway through the year would shift every subsequent draw, and the comparison between two runs would be contaminated by reshuffled randomness that has nothing to do with the edit. Keying every draw by identity means a customer untouched by the edit reproduces the identical decision, bit for bit, in both runs — the common random numbers (CRN) technique from the simulation literature, load-bearing rather than retrofitted.
Two concrete twins in the three-year story cash this out into real numbers: one twin disables the expansion decision entirely; comparing it to the real run shows the expansion’s true cost over its first fourteen months substantially exceeds the margin it generates. A second twin removes the competitor entirely; comparing it to the real run prices exactly what the competitor cost the owner, as opposed to what he believes it cost him. The capital decision, it turns out, very often costs the business more than the competitive entry — even though the competitor is the more visible, more emotionally salient event to an owner living through it. That’s exactly why an instructor can hand a learner the owner’s own conviction that the competitor is to blame, and let the twins settle the question instead.
The three profit figures
With a full year performed, three profit figures become computable side by side:
\[ \pi_{\text{believed}} \quad\text{(the opening MILP's own objective value)} \] \[ \pi_{\text{realized}} \quad\text{(what the ledger actually shows, after a full year of realistic behavior)} \] \[ \pi_{\text{oracle}} \quad\text{(what a perfectly informed operator could have earned — same world, same script, true demand instead of a censored, backward-looking forecast)} \]
The two gaps between them are exact differences between fully computed runs of the same mechanism, not estimates:
\[ \Delta_{\text{optimism}} = \pi_{\text{realized}} - \pi_{\text{believed}} \qquad \Delta_{\text{analytics}} = \pi_{\text{oracle}} - \pi_{\text{realized}} \]
The first measures the cost of the owner’s initial overoptimism; the second measures the value of better information and better decisions — the single number this entire construction exists to make credible by actually computing it, rather than asserting a plausible size for it.
Read more
- The Analysis catalog turns this theory into a concrete, gradeable set of questions.
- The full paper covers the customer’s purchase decision, the owner’s opening MILP, adaptive day-to-day policy, the expansion decision, the customer panel as a stochastic flow, and the entire macro script (calendar, weather, cost shocks, taxation) in complete derivations — read it here.