Checking ground truth

How grading actually works, and every hidden table this package ships

Every page on this site claims an estimate is “gradeable” or “checkable against ground truth.” This page is what that actually means, in code, plus a full reference of every hidden table available to check against.

The mechanism

Every generated arm ships two views of itself. The visible/ folder (or sim.data() / sim.db() called with no arguments) is the only thing a real analyst would ever see: receipts, invoices, a ledger, nothing else. Passing include_hidden = True to either method additionally loads a second set of tables, each prefixed hidden_, one per generating mechanism: the true customer panel, the true demand behind every stockout, the paperwork-defect log, and so on.

An analysis is done entirely against the visible tables, start to finish. The hidden tables exist purely to grade the answer afterward, never to shortcut the analysis itself. Joining them in earlier would be grading your own exam with the answer key already open.

A worked example

The Analysis catalog’s first question, 0.1, works entirely blind: from the receipts table alone, an all-even grouping trick flags 34 receipts as probable duplicates (a POS retry re-posting a whole transaction leaves every line of it byte-identical and doubled). hidden_imperfections is the actual, planted answer key for every recording-layer defect in that run, one row per defect, with a kind column naming which of the ten defect families it belongs to. Checking the blind estimate against it is one set comparison:

from grocery_sim import GroceryStoreSimulation
import polars as pl

sim = GroceryStoreSimulation()
sim.setup(dict(basic = dict(year = 1)))
sim.simulate()
con = sim.db()
receipts = con.sql("SELECT * FROM receipts").pl()

# the blind estimate: works from receipts alone, no hidden table involved
mult = receipts.group_by(receipts.columns).agg(pl.len().alias("n"))
all_even = mult.group_by("receipt_id").agg((pl.col("n") % 2 == 0).all().alias("all_even"))
blind_flagged = set(all_even.filter(pl.col("all_even"))["receipt_id"])

# only now, to grade it, load the answer key
tables = sim.data(include_hidden = True)
imp = pl.from_pandas(tables.hidden_imperfections)
true_flagged = set(imp.filter(pl.col("kind") == "dup_receipt")["key"])

print(f"blind: {len(blind_flagged)}, true: {len(true_flagged)}, "
      f"exact match: {blind_flagged == true_flagged}")
# -> blind: 34, true: 34, exact match: True

The blind detector’s 34 and the answer key’s 34 are the same 34 receipts, not just the same count. That’s what “gradeable” means everywhere on this site: not that a number sounds plausible, but that it can be checked against a specific, planted row set and shown to be exactly right, exactly wrong, or wrong in a specific, explainable way.

Every hidden table

sim.data(include_hidden = True) and sim.db(include_hidden = True) both expose all eighteen. Every one is keyed so it can be joined back onto the matching visible table (by uid, customer_id, date/t, or location_id).

Table Granularity What it grades
hidden_imperfections one row per defect The paperwork-defect answer key: kind (one of the ten defect families, e.g. dup_receipt, void_pair, missing_invoice), table and key (which visible row it touched), delta. Used by the Analysis catalog’s Layer 0 and the worked example above.
hidden_hidden_demand one row per purchase attempt The full per-attempt demand log, including attempts that never became a sale (cause: stockout, budget, outside_option, closed). The ground truth behind every “where did the missing demand go” question.
hidden_customers one row per customer The persistent panel’s true parameters: weekly_budget, price_sens, brand_affinity, persistence (rooted/transient), arrival_date/departure_date, plus a per-week presence flag (w0w156). Grades churn and RFM-segmentation questions.
hidden_spell_flags one row per customer A per-week flag, same shape as hidden_customers, marking which weeks each customer was in a scripted tight-spell or splurge. Grades whether a detected budget shock is real or a false positive.
hidden_guests one row per passing-trade visit Non-panel, one-off guest transactions (token, payment, value), kept separate from the persistent panel. Grades regulars-vs-passing-trade splits.
hidden_owner_forecasts one row per category-week The owner’s own trailing-average forecast (forecast_weekly) next to the true, uncensored demand (oracle), for every category and week. Grades forecast-accuracy and censoring-spiral questions.
hidden_decision_t0 one row per SKU The opening-day MILP’s own output: whether the SKU was listed, the quantity ordered (q0), and believed sales. Grades the opening-decision overstocking claim directly.
hidden_location_category one row per location-category True demand (true_demand) next to the owner’s belief (believed_demand) and the gap between them (belief_delta), per location and category. The ground truth behind the true and believed demand terms in Theory’s opening-decision section.
hidden_locations_full one row per candidate location Every site-scouting fact the owner had before opening: quality, households, and the cost structure, for every candidate location, not just the one chosen.
hidden_category_loadings one row per category The demand-modifier parameters a (seasonal amplitude), kappa (weather loading), h (holiday loading), i.e. the coefficients behind the demand-modifier equation in Theory. Grades “is this category’s seasonality real or budget-mediated” questions.
hidden_demand_modifiers one row per day The true daily demand modifier per category (M_<category>) and the true traffic modifier (traffic), the exact quantities a visible-data estimate is trying to recover.
hidden_tilts one row per day The fine-grained seasonal tilt for the handful of products whose seasonality deliberately contradicts their category’s average (ice cream, coffee, tea).
hidden_cost_paths one row per day The true wholesale cost multiplier per category (cost_<category>), plus the true wage and storage rate paths. Grades cost-shock detection and instrument-validity questions (e.g. the advanced methods demonstration’s difference-in-differences design).
hidden_event_log one row per macro event Every scripted shock’s true parameters (type, start, ramp, decay, which categories it hit), the schedule a visible-data analysis is trying to reconstruct from cost and price movements alone.
hidden_spoil_factors one row per day The true spoilage factor per perishable category, behind the spoilage binomial in Theory. Grades “what actually drives spoilage” questions.
hidden_weather_full one row per day Weather decomposed into its seasonal component, the anomaly, and the standardized anomaly z, separately from the raw temp_C the visible weather table shows. This is exactly the temp_anom construction the advanced methods demonstration’s GLM depends on, gradeable against the true decomposition.
hidden_budget_paths one row per customer Each customer’s real weekly budget realization (w1w156), the household-budget process a visible-data estimate of spending power can only infer indirectly.
hidden_profit_triptych one row total The three profit figures from Theory computed directly: believed_profit_month1, realized_profit_year (and after-tax), oracle_profit_year (and after-tax). Grades any independent recomputation of the believed, realized, and oracle profit figures.

Read more

  • Theory: the model each of these tables is the ground truth for.
  • Complete DGP: where each hidden table sits in the full causal graph, including the one-way tap from true state into the recording layer that makes this grading possible.
  • Analysis catalog: the 62 questions these tables make gradeable.
  • API reference: the full signature and parameters of .data() and .db().