Pearl Layer 2 — Intervention
Canonical do-calculusP(Y | do(X)) — sever incoming edges to X, re-simulate, report ATE
How to read this output
The result has three sections: (1) intervention summary chips, (2) Mean ATE tiles per outcome, (3) one factual-vs-intervention line chart per outcome. Read them as 'what happens to Y if I force X = x going forward.'
e.g. do(substitution_elasticity=0.8) → that parameter is held at 0.8 for the entire run, regardless of upstream causes
e.g. ATE(P) = −0.015 → on average, the intervention lowered price by 0.015 normalised units across the horizon
e.g. If the indigo line sits below the gray line for most of the horizon, the intervention reduced that outcome on average
Key takeaway: L2 ATE is a forward-looking expectation: 'what would Y look like on average if we forced X = x from now on?' It is NOT 'what would have happened in some specific past' — that's L3.
What L2 (Intervention) computes
Formal: P(Y | do(X = x)) — sever the structural equation for X, pin X = x, re-simulate
Graph surgery (mutilated SCM)
Original SCM: X_t = f_X( parents(X)_t , noise_X_t ) After do(X=x): X_t := x (incoming edges to X removed) All other structural equations of the model remain unchanged.
Example structural equation (substitution supply)
Q_sub_t = shock.export_restriction_t · Q_t
· clamp( 0, sub_cap,
sub_elasticity · max(0, P_t/P_ref − 1) )
do(sub_elasticity = 0.8) replaces the 'sub_elasticity' literal in
the equation above — the rest of the ODE continues to run.Average Treatment Effect per outcome
ATE_t (Y) = Y_t^(intervention) − Y_t^(factual) mean ATE(Y) = (1/T) · Σ_t ATE_t (Y) [reported per outcome]
Caveat: L2 answers 'what would Y look like if we forced X = x going forward?'. It runs a fresh forward simulation under the intervened SCM — it does NOT condition on a specific past trajectory. For that, use L3.
Source: src/minerals/pearl_layers.py — do_compare(), mutilated_graph_for_do(); model in src/minerals/model.py
No L2 intervention run yet
Pick a scenario, enable parameters to intervene on, set their values, then click Run L2 Intervention. The engine performs graph surgery on the SCM and returns factual vs. intervened trajectories with per-outcome ATE.