Theory
Model specification, condensed from the full paper
This page states the model grocery-sim implements: the decision problems solved by each agent, the exogenous processes governing the macro environment, and the identity results that follow from their separation. Every equation is reproduced unchanged from the generating code, not a simplified stand-in for it. Complete derivations, every calibrated parameter, and the causal-graph figures are in the full paper (PDF).
1. Model structure
Definition 1 (Two-layer decomposition). The economy is partitioned into a micro layer and a macro layer, and no variable is a member of both.
- The micro layer consists of every decision solved by an agent given the information available at the time of the decision: a customer’s purchase, an owner’s opening allocation, an owner’s restocking and pricing policy, an owner’s expansion decision, and a household’s tenure in the customer panel.
- The macro layer consists of every process fixed in advance of the simulation and independent of realized micro-layer outcomes: the calendar, weather, macroeconomic cost shocks, and the tax schedule.
This partition is an identifying assumption, not a modeling convenience. Section 8 states the counterfactual-identification result that follows from it.
2. The customer’s purchase decision
Customer \(i\)’s utility for product \(s\) is
\[ U_{is} = \theta_{ic} + a_s + \gamma\left(1 - \left|b_i - \text{BrandLevel}_s\right|\right) - \beta_i\,\text{Price}_s , \]
where \(\theta_{ic}\) is the customer’s current need for category \(c\), \(b_i\) is brand affinity, \(\text{BrandLevel}_s\) is the product’s position on the same scale, \(\gamma\) weights the brand-match term, \(\beta_i\) is price sensitivity, and \(a_s \sim \text{Normal}(0, 0.8)\) is an unmodeled per-product intercept standing in for idiosyncratic appeal not otherwise represented in the model. An outside option \(U_0\) is available alongside every stocked product, and the realized choice is
\[ \text{choice} \sim \text{Categorical}\big(\text{softmax}(U_{is_1}, \ldots, U_{is_K}, U_0)\big) . \]
Remark 1. The softmax form is not an approximation device. If each product’s utility is perturbed by an independent, identically distributed Gumbel shock and the customer selects the maximum, the induced choice probabilities are exactly the softmax of the mean utilities (McFadden’s random utility result). This is also the model a discrete-choice estimator would fit to purchase histories, so a later exercise’s recovered parameters are directly comparable to the true generating values.
Need \(\theta_{ict}\) is a state variable, not an i.i.d. draw. It is governed by a pantry process,
\[ P_{ic,t+1} \overset{\leftarrow}{=} \max(0,\ P_{ict} - r_{ict}) + \text{units purchased} \]
\[ \theta_{ict} = \alpha\,\frac{\max(0,\ P^{\text{tgt}}_{ic} - P_{ict})}{P^{\text{tgt}}_{ic}} \]
the shortfall against a target of ten days’ cover. The drain rate \(r_{ict}\) scales with the seasonal demand modifier rather than entering \(\theta\) directly, so a demand shock operates through consumption of existing stock rather than through an independent increment to desire. When the selected product is out of stock, the original choice is recorded as a latent outcome under cause stockout, and the softmax is re-evaluated over the remaining assortment.
3. The owner’s opening decision
The true demand potential of location \(l\) for category \(c\) is \(D_{cl} = \text{Households}_l \cdot \mu_c\), unobserved by the owner. The owner’s belief is a log-normal perturbation of this quantity,
\[ \hat{D}_{cl} = D_{cl}\,e^{\delta_c} \]
\[ \delta_c \sim \text{Normal}(0.10,\ 0.25) \]
with the positive mean encoding a calibrated overoptimism parameter. The opening decision, conditional on beliefs, costs, and a fixed markup \(m_c\), safety-stock fraction \(\eta = 0.30\), and category-share cap \(\rho = 0.05\), is the following mixed integer linear program (MILP), with decision variables \(y_l \in \{0,1\}\) (location choice), \(x_s \in \{0,1\}\) (whether product \(s\) is listed), \(q_s \geq 0\) (quantity ordered), and \(u_s \geq 0\) (believed sales quantity):
\[ \max_{y,\,x,\,q,\,u} \;\; \sum_{c}\sum_{s \in S_c} (1+m_c)\,\text{Cost}_s \cdot u_s \;-\; \text{TotalCost}_0 \]
subject to
\[ \sum_l y_l = 1 \]
\[ u_s \leq q_s \]
\[ \sum_{s \in S_c} u_s \leq \sum_l y_l\,\hat{D}_{cl} \]
\[ \sum_s x_s \leq \sum_l y_l\,\text{ShelfSlots}_l \]
\[ \text{TotalCost}_0 \leq \text{InitialCapital}_0 \]
\[ y_l \in \{0,1\}, \qquad x_s \in \{0,1\}, \qquad q_s \geq 0, \qquad u_s \geq 0 \]
The last line is the integrality constraint that makes this a MILP rather than a continuous LP: \(y_l\) and \(x_s\) are binary (location and listing are yes/no decisions), while \(q_s\) and \(u_s\) are continuous given a fixed location and listing. Every constraint above is linear conditional on \(y\) and \(x\), so the problem is a mixed integer linear program specifically, solvable with standard branch-and-bound/cut MILP solvers rather than requiring general mixed integer nonlinear methods.
Proposition 1. Since \(\mathbb{E}[\delta_c] > 0\), the optimal solution \(u_s^*, q_s^*\) systematically overstocks relative to the true optimum under \(D_{cl}\). The magnitude of overstocking is a deterministic function of \(\delta_c\) and is therefore computable exactly from the model parameters, not merely observable as an empirical regularity.
4. Day-to-day adaptive policy
Restocking after opening is sized from a trailing four-week average of recorded sales,
\[ \hat{D}^{\text{op}}_{cw} \overset{\leftarrow}{=} \frac{1}{4}\sum_{j=1}^{4} \text{Sales}_{c,w-j} \]
\[ \text{Target}_{sw} = \left(\tfrac{R+L}{7} + \eta\,\tfrac{30}{7}\right) \hat{D}^{\text{op}}_{cw}\,\tilde{\sigma}_{sw} \]
with \(R = 7\) days between reviews and \(L = 2\) days lead time. The rule has two structural properties, both retained deliberately rather than corrected. It is backward-looking: a trend change is detected only after it has already occurred. It is not censoring-aware: \(\text{Sales}\) is itself truncated by prior stockouts, producing a feedback loop in which an under-ordered product reports depressed sales, receives a smaller subsequent order, and stocks out again.
Perishable inventory spoils according to
\[ \text{Spoiled}_{st} \sim \text{Binomial}\big(\text{OnHand}_{st},\ \min(0.35,\ \lambda^d_{c(s)}\,f_{c(s),t})\big) , \]
with the spoilage factor \(f_{ct}\) a log-additive function of a temperature term, a cold-chain strain term linked to the macro cost shocks of Section 6, and an idiosyncratic batch-level term.
5. The expansion decision
From the start of year two, the owner retains a share \(\rho_{RE} = 0.5\) of after-tax profit in profitable months,
\[ \text{draw}_m = (1-\rho_{RE})\,\max(0, \pi_m) , \]
with no draw or retention in loss months. The expansion trigger is a joint threshold condition,
\[ \text{RE}_m \geq K_{\text{exp}} \]
\[ \text{cash}_m - \text{tax\_reserve}_m \geq C_{\text{exp}} \]
evaluated monthly. Expansion occurs on the first day of the following month once both thresholds are met. This is a threshold decision rule conditioned on affordable loss rather than a discounted-cash-flow optimization, consistent with the effectuation framework in entrepreneurship research rather than a net-present-value calculation. Disabling this rule as a counterfactual shows the expansion’s realized cost over its first fourteen months exceeds the incremental margin generated, since a fixed wage obligation is incurred in full while incremental revenue is realized at the category’s ordinary margin.
6. The macro layer: weather, demand, and cost processes
Temperature follows a deterministic annual cycle with a persistent stochastic anomaly,
\[ T_t = \mu_T(t) + \varepsilon_t \]
\[ \mu_T(t) = 12 + 9\cos\!\left(\tfrac{2\pi(t-200)}{365}\right) \]
\[ \varepsilon_t = \phi\,\varepsilon_{t-1} + \text{Normal}(0,\sigma_\varepsilon) \]
with \(\phi = 0.7\). This is the maximum-entropy stationary process consistent with a fixed marginal spread and positive autocorrelation in anomalies, the two properties calibration targets.
The per-category demand modifier is log-additive in three components,
\[ \log M_{ct} = a_c \cos\!\left(\tfrac{2\pi(t-200)}{365}\right) + \kappa_c\, z_t + h_c\, H_t , \]
with \(z_t\) the standardized temperature anomaly, \(H_t\) a pre-holiday indicator, \(a_c\) the seasonal amplitude, \(\kappa_c\) the weather loading, and \(h_c\) the holiday loading. One category is parameterized with \(a_c = \kappa_c = h_c = 0\), and its observed sales nonetheless retain seasonal variation via the shared household budget constraint, since other categories’ seasonal surges displace it. This is a designed identification check for distinguishing a direct preference effect from a budget-mediated one.
Wholesale cost shocks follow a marked point process, \(K \sim \text{Poisson}(1.5)\) events at \(\tau_k \sim \text{Uniform}(1,365)\), each with magnitude \(\zeta_k \sim \text{LogNormal}(\log\zeta_0,\ 0.3)\) and trajectory
\[ g_k(t) = \zeta_k \cdot \min\!\left(1,\ \tfrac{t-\tau_k}{14}\right) \cdot \exp\!\left(-\tfrac{(t-\tau_k-14)_+}{\rho_k}\right) , \]
a two-week ramp followed by exponential decay. Category cost multipliers aggregate the inflation drift and every active shock,
\[ \log \text{CostMult}_{ct} = \frac{\pi t}{365} + \sum_k g_k(t)\,\mathbb{1}[c \in A_k] . \]
The owner observes only supplier invoices, tracked as an exponentially smoothed trend, and adjusts the shelf price only once the smoothed trend deviates from the current price by more than three percent (menu-cost pricing). One scripted shock (the energy crisis) additionally shifts household budgets through a separate channel, making it a biased instrument for cost pass-through with a bias term that is, in principle, computable exactly from the model.
7. Taxation
Value-added tax applies at category-specific rate \(r_c(t)\). Profit tax applies at a flat rate to positive annual surplus,
\[ \text{ProfitTax} = r^{\pi}\cdot\max(0,\ \text{ProfitBeforeTax}) \]
\[ r^\pi = 0.20 \]
Proposition 2. Because profit tax is a flat rate on a non-negative base,
\[ \arg\max_{\text{decisions}} (1-r^\pi)\,\pi(\text{decisions}) = \arg\max_{\text{decisions}} \pi(\text{decisions}) , \]
so an owner who disregards profit tax when making operating decisions loses nothing relative to one who optimizes around it. This invariance does not extend to value-added tax, whose category-specific rate structure changes relative prices across categories, a margin the owner does not exploit and which is left open as a prescriptive question.
8. Identification: counterfactual replay
Proposition 3. Because the macro layer is independent of micro-layer outcomes by Definition 1, a counterfactual world is constructed by editing the macro script alone (removing a scripted shock, disabling the expansion threshold, removing the competitor) and replaying the identical mechanism with all other random draws held fixed. The difference between the original and edited runs is the exact causal effect of the edit, not an estimate of it.
This result depends on one further condition: every random draw must be keyed to the stable identity of the entity it concerns (a specific customer on a specific day, a specific product on a specific night), drawn from independently spawned child streams rather than one sequential stream. Under sequential draws, deleting a single event would shift every subsequent draw, confounding the comparison with reshuffled randomness unrelated to the edit. Under identity-keyed draws, an entity unaffected by the edit reproduces an identical realization in both runs, the common random numbers (CRN) variance-reduction technique, applied here as an identification device rather than a variance-reduction one.
Two counterfactual comparisons in the three-year arm illustrate the result. Disabling the expansion decision and comparing to the realized run isolates the expansion’s exact cost, which exceeds the margin it generates over its first fourteen months. Removing the competitor and comparing to the realized run isolates the competitor’s exact cost to the owner, which is smaller than the expansion’s cost despite being the more salient event in the owner’s own account.
9. The three profit figures
Given a completed run, three profit quantities are simultaneously computable:
- \(\pi_{\text{believed}}\): the opening MILP’s objective value.
- \(\pi_{\text{realized}}\): the realized ledger result under the owner’s actual policies.
- \(\pi_{\text{oracle}}\): the result obtainable under the same world and script with uncensored demand in place of the owner’s forecast.
The two differences are exact, not estimated, since both quantities are computed from fully realized runs of the same mechanism:
\[ \Delta_{\text{optimism}} = \pi_{\text{realized}} - \pi_{\text{believed}} \]
\[ \Delta_{\text{analytics}} = \pi_{\text{oracle}} - \pi_{\text{realized}} \]
\(\Delta_{\text{optimism}}\) is the cost of the owner’s initial belief error. \(\Delta_{\text{analytics}}\) is the value attributable to information and decision quality, the quantity this construction is designed to make computable rather than merely asserted.
10. The recording layer
The recording layer is a third component, distinct from both the micro and macro layers: low-rate, independently keyed defects applied only at export, which do not affect the underlying simulated state. Let \(D_{st}\) denote a product’s cumulative book-minus-true discrepancy on day \(t\). The inventory quantity available to an analyst is book stock, not true stock,
\[ B_{st} = S_{st} + D_{st} - \sum_{c\le t} A_{sc} , \]
with \(A_{sc}\) the cumulative correction posted at each monthly physical count. Every defect is logged simultaneously to a separate answer key, so reconciliation of the recorded data against ground truth is itself a gradable task, independent of the underlying simulated state that Section 8’s identification result depends on.
References
- Complete DGP draws every mechanism above as one causal graph, from the macro layer through the recording layer.
- The Analysis catalog operationalizes this specification as a graded set of 62 questions.
- The full paper states the customer’s purchase decision, the owner’s opening MILP, the adaptive policy, the expansion decision, the customer panel as a stochastic flow, and the complete macro script (calendar, weather, cost shocks, taxation), with full derivations: read it here.