Panel.Estimand­Characterization.Imputation­Event­Study

Borusyak-Jaravel-Spiess: the imputation estimator and the efficiency/characterization results for staggered adoption.

Imputation 16 core · 4 supporting This file gives a finite-cell population formulation of the Borusyak-Jaravel-Spiess imputation functional. ★ bjs_imputation_identification

Borusyak-Jaravel-Spiess Imputation

This file gives a finite-cell population formulation of the Borusyak-Jaravel-Spiess imputation functional. The core structure BJSPanel stores treated and untreated cell rows, target weights, observed and untreated cell means, the untreated-outcome nuisance vector, and treated-cell effects. It defines the target theta, prediction-span witnesses ImputationWeights, the observed imputation functional psiImp, and the identification theorem bjs_imputation_identification. It also defines the finite linear-estimator API and the witness lemma linear_unbiased_of_imputation_representation; the substrate-based construction of those witnesses lives in PanelBridge.lean.

def dot reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy

Finite dot product for regressor rows and nuisance vectors.

Definition (Lean source)
def dot (x beta : Regressor → ℝ) : ℝ := ∑ r : Regressor, x r * beta r
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.dot · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Imputation.lean:42
structure BJSPanel reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy

A finite treated/untreated cell design for the BJS imputation decomposition, storing treated cells' regressor rows and untreated cells' regressor rows, an arbitrary — possibly signed and non-normalized — target weight on treated cells, the observed-law means on treated and untreated cells, the untreated-potential-outcome means on treated and untreated cells, a nuisance vector for the untreated-outcome model, and treated-cell causal effects.

Definition (Lean source)
Treated Untreated Regressor :
Type*
Fintype Treated
Fintype Untreated
Fintype Regressor
Regressor row for a treated cell.
qT :
Treated → Regressor → ℝ
Regressor row for an untreated cell.
qU :
Untreated → Regressor → ℝ
Arbitrary target weight on treated cells.
a :
Treated → ℝ
Observed-law mean for treated cells.
EY_T :
Treated → ℝ
Observed-law mean for untreated cells.
EY_U :
Untreated → ℝ
Untreated potential-outcome mean for treated cells.
EY0_T :
Treated → ℝ
Untreated potential-outcome mean for untreated cells.
EY0_U :
Untreated → ℝ
Nuisance vector in the untreated outcome model.
beta0 :
Regressor → ℝ
Treated-cell causal effects.
tau :
Treated → ℝ
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Imputation.lean:46
def theta reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel

Target weighted sum over treated-cell effects. No positivity or normalization of a is imposed.

Definition (Lean source)
def theta : ℝ := ∑ c : Treated, P.a c * P.tau c
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.theta · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Imputation.lean:83 · uses BJSPanel
def targetForTau reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel

Target value for an arbitrary unrestricted treated-effect vector.

Definition (Lean source)
def targetForTau (tau' : Treated → ℝ) : ℝ := ∑ c : Treated, P.a c * tau' c
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.targetForTau · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Imputation.lean:88 · uses BJSPanel
def UntreatedOutcomeModel reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel

Deterministic untreated-outcome mean model and untreated-cell no-anticipation / observation equation.

Definition (Lean source)
def UntreatedOutcomeModel : Prop := (∀ c : Treated, P.EY0_T c = dot (P.qT c) P.beta0) ∧ (∀ u : Untreated, P.EY0_U u = dot (P.qU u) P.beta0) ∧ (∀ u : Untreated, P.EY_U u = P.EY0_U u)
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.UntreatedOutcomeModel · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Imputation.lean:92 · uses BJSPanel
def TreatmentEffectFixed reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel

Treated-cell effects are fixed at the observed-law mean level: treated observed means equal untreated means plus tau.

Definition (Lean source)
def TreatmentEffectFixed : Prop := ∀ c : Treated, P.EY_T c = P.EY0_T c + P.tau c
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.TreatmentEffectFixed · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Imputation.lean:99 · uses BJSPanel
structure ImputationWeights reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel

Witness-form prediction span / imputation weights.

Definition (Lean source)
Weight assigned to untreated cell `u` when imputing treated cell `c`.
weight :
Treated → Untreated → ℝ
Target-relevant treated rows are linear combinations of untreated rows.
row_identity :
∀ c : Treated
if
P.a c ≠ 0
then
∀ r : Regressor, ∑ u : Untreated, weight c u * P.qU u r = P.qT c r
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.ImputationWeights · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Imputation.lean:104 · uses BJSPanel
def PredictionIdentified reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel

Existence form of the target-relevant prediction-span condition.

Definition (Lean source)
def PredictionIdentified : Prop := Nonempty P.ImputationWeights
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.PredictionIdentified · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Imputation.lean:117 · uses BJSPanel
def psiImp reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel

Observed-law population imputation functional for arbitrary imputation weights. The row identity is a theorem hypothesis, not part of this functional's definition.

Definition (Lean source)
def psiImp (h : Treated → Untreated → ℝ) : ℝ := ∑ c : Treated, P.a c * (P.EY_T c - ∑ u : Untreated, h c u * P.EY_U u)
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.psiImp · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Imputation.lean:121 · uses BJSPanel
theorem bjs_imputation_identification reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel

Population BJS imputation identification. Suppose the untreated outcome mean follows a deterministic linear model in the regressors, and each untreated cell's observed mean equals that untreated model mean (untreated outcome model), there exist imputation weights whose row identity expresses every target-relevant treated cell's regressor row as a weighted combination of untreated-cell rows (target-relevant prediction span), and each treated cell's observed mean equals its untreated potential-outcome mean plus its treatment effect (treatment effect fixed). Then there is an imputation-weight witness for which the observed-law imputation functional psiImp equals the target weighted sum of treatment effects theta.

Formal statement
hUntreatedModel :
P.UntreatedOutcomeModel
hPredictionSpan :
P.PredictionIdentified
hTreatmentEffectFixed :
P.TreatmentEffectFixed
∃ h : P.ImputationWeights, P.psiImp h.weight = P.theta
Proof (Lean source)
theorem bjs_imputation_identification (hUntreatedModel : P.UntreatedOutcomeModel) (hPredictionSpan : P.PredictionIdentified) (hTreatmentEffectFixed : P.TreatmentEffectFixed) : ∃ h : P.ImputationWeights, P.psiImp h.weight = P.theta := by classical let H : P.ImputationWeights := Classical.choice hPredictionSpan refine ⟨H, ?_⟩ unfold psiImp theta refine Finset.sum_congr rfl ?_ intro c hc by_cases hA : P.a c = 0 · simp [hA] · have hEYU : ∀ u : Untreated, P.EY_U u = dot (P.qU u) P.beta0 := by intro u rw [hUntreatedModel.2.2 u, hUntreatedModel.2.1 u] have hImpute : (∑ u : Untreated, H.weight c u * P.EY_U u) = dot (P.qT c) P.beta0 := by unfold dot calc (∑ u : Untreated, H.weight c u * P.EY_U u) = ∑ u : Untreated, H.weight c u * ∑ r : Regressor, P.qU u r * P.beta0 r := by apply Finset.sum_congr rfl intro u hu rw [hEYU u] rfl _ = ∑ u : Untreated, ∑ r : Regressor, (H.weight c u * P.qU u r) * P.beta0 r := by apply Finset.sum_congr rfl intro u hu rw [Finset.mul_sum] apply Finset.sum_congr rfl intro r hr rw [mul_assoc] _ = ∑ r : Regressor, ∑ u : Untreated, (H.weight c u * P.qU u r) * P.beta0 r := by rw [Finset.sum_comm] _ = ∑ r : Regressor, (∑ u : Untreated, H.weight c u * P.qU u r) * P.beta0 r := by apply Finset.sum_congr rfl intro r hr rw [Finset.sum_mul] _ = ∑ r : Regressor, P.qT c r * P.beta0 r := by apply Finset.sum_congr rfl intro r hr rw [H.row_identity c hA r] have hYT : P.EY_T c = dot (P.qT c) P.beta0 + P.tau c := by rw [hTreatmentEffectFixed c, hUntreatedModel.1 c] rw [hYT, hImpute] simp [add_sub_cancel_left]
structure LinearEstimator reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel

A linear functional of treated and untreated observed cell outcomes.

Definition (Lean source)
P :
BJSPanel Treated Untreated Regressor
Coefficients on treated observed means.
vT :
Treated → ℝ
Coefficients on untreated observed means.
vU :
Untreated → ℝ
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.LinearEstimator · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Imputation.lean:199 · uses BJSPanel
def value reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.LinearEstimator

Value of a treated-plus-untreated linear estimator at arbitrary cell outcome arrays.

Definition (Lean source)
def value (L : P.LinearEstimator) (YT : Treated → ℝ) (YU : Untreated → ℝ) : ℝ := (∑ c : Treated, L.vT c * YT c) + ∑ u : Untreated, L.vU u * YU u
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.LinearEstimator.value · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Imputation.lean:210 · uses BJSPanel , LinearEstimator
def observedValue reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.LinearEstimator

Observed-law value of the linear estimator on the panel means.

Definition (Lean source)
def observedValue (L : P.LinearEstimator) : ℝ := L.value P.EY_T P.EY_U
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.LinearEstimator.observedValue · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Imputation.lean:215 · uses BJSPanel , LinearEstimator
def modelValue reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.LinearEstimator

Model-implied value for a nuisance vector and unrestricted treated-effect vector.

Definition (Lean source)
def modelValue (L : P.LinearEstimator) (beta : Regressor → ℝ) (tau' : Treated → ℝ) : ℝ := L.value (fun c : Treated => dot (P.qT c) beta + tau' c) (fun u : Untreated => dot (P.qU u) beta)
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.LinearEstimator.modelValue · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Imputation.lean:219 · uses BJSPanel , LinearEstimator
def unbiasedForAllTau reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.LinearEstimator

Linear unbiasedness over unrestricted treated effects and nuisance vectors in the finite-cell model.

Definition (Lean source)
def unbiasedForAllTau (L : P.LinearEstimator) : Prop := ∀ (beta : Regressor → ℝ) (tau' : Treated → ℝ), L.modelValue beta tau' = P.targetForTau tau'
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.LinearEstimator.unbiasedForAllTau · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Imputation.lean:227 · uses BJSPanel , LinearEstimator
structure HasImputationRepresentation reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.LinearEstimator

Explicit imputation representation witness for the linear-unbiased representation helper.

Definition (Lean source)
L :
P.LinearEstimator
Valid target-relevant imputation weights.
weights :
P.ImputationWeights
Untreated coefficients equal the negative target-weighted imputation weights.
untreated_weight_representation :
∀ u : Untreated, L.vU u = - ∑ c : Treated, P.a c * weights.weight c u
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.LinearEstimator.HasImputationRepresentation · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Imputation.lean:253 · uses BJSPanel , LinearEstimator
4 supporting declarations (lemmas, instances)
  • vT_eq_a lemma — Unrestricted treatment-effect heterogeneity forces the treated-cell weights to equal the target weights (vT = a). Proved by an indicator-tau test. Hoisted here so the efficiency layer can reuse it without re-running the argument.
    L :
    P.LinearEstimator
    h :
    L.unbiasedForAllTau
    c :
    Treated
    L.vT c = P.a c
    Proof (Lean source)
    lemma vT_eq_a (L : P.LinearEstimator) (h : L.unbiasedForAllTau) (c : Treated) : L.vT c = P.a c := by classical have hh := h (fun _ : Regressor => 0) (fun d : Treated => if d = c then (1 : ℝ) else 0) simpa [LinearEstimator.modelValue, LinearEstimator.value, targetForTau, dot] using hh
    Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.LinearEstimator.vT_eq_a · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Imputation.lean:233
  • nuisance_coord lemma — Nuisance unbiasedness for every beta gives the BJS left-null-space coordinate constraint aᵀ Q_T + vUᵀ Q_U = 0 (row by row). Hoisted for the efficiency layer.
    L :
    P.LinearEstimator
    h :
    L.unbiasedForAllTau
    r :
    Regressor
    (∑ c : Treated, P.a c * P.qT c r) + ∑ u : Untreated, L.vU u * P.qU u r = 0
    Proof (Lean source)
    lemma nuisance_coord (L : P.LinearEstimator) (h : L.unbiasedForAllTau) (r : Regressor) : (∑ c : Treated, P.a c * P.qT c r) + ∑ u : Untreated, L.vU u * P.qU u r = 0 := by classical have hh := h (fun r' : Regressor => if r' = r then (1 : ℝ) else 0) (fun _ : Treated => 0) simpa [LinearEstimator.modelValue, LinearEstimator.value, targetForTau, dot, L.vT_eq_a h] using hh
    Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.LinearEstimator.nuisance_coord · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Imputation.lean:243
  • linear_unbiased_of_imputation_representation_of_vT_eq_a theorem — Witness-based BJS linear-estimator representation from its treated coefficients and an imputation witness, exposed as an estimator identity for arbitrary outcome arrays.
    L :
    P.LinearEstimator
    hVT :
    ∀ c : Treated, L.vT c = P.a c
    hImputationWitness :
    L.HasImputationRepresentation
    ∃ H : P.ImputationWeights,
    (∀ c : Treated, L.vT c = P.a c) ∧
    (∀ u : Untreated, L.vU u = - ∑ c : Treated, P.a c * H.weight c u) ∧
    (∀ (YT : Treated → ℝ) (YU : Untreated → ℝ), L.value YT YU = ∑ c : Treated, P.a c * (YT c - ∑ u : Untreated, H.weight c u * YU u)) ∧
    L.observedValue = P.psiImp H.weight
    Proof (Lean source)
    theorem linear_unbiased_of_imputation_representation_of_vT_eq_a (L : P.LinearEstimator) (hVT : ∀ c : Treated, L.vT c = P.a c) (hImputationWitness : L.HasImputationRepresentation) : ∃ H : P.ImputationWeights, (∀ c : Treated, L.vT c = P.a c) ∧ (∀ u : Untreated, L.vU u = - ∑ c : Treated, P.a c * H.weight c u) ∧ (∀ (YT : Treated → ℝ) (YU : Untreated → ℝ), L.value YT YU = ∑ c : Treated, P.a c * (YT c - ∑ u : Untreated, H.weight c u * YU u)) ∧ L.observedValue = P.psiImp H.weight := by classical let H : P.ImputationWeights := hImputationWitness.weights have hVU : ∀ u : Untreated, L.vU u = - ∑ c : Treated, P.a c * H.weight c u := by intro u exact hImputationWitness.untreated_weight_representation u have hValue : ∀ (YT : Treated → ℝ) (YU : Untreated → ℝ), L.value YT YU = ∑ c : Treated, P.a c * (YT c - ∑ u : Untreated, H.weight c u * YU u) := by intro YT YU unfold LinearEstimator.value rw [show (∑ c : Treated, L.vT c * YT c) = ∑ c : Treated, P.a c * YT c from by apply Finset.sum_congr rfl intro c hc rw [hVT c]] rw [show (∑ u : Untreated, L.vU u * YU u) = ∑ u : Untreated, (-(∑ c : Treated, P.a c * H.weight c u)) * YU u from by apply Finset.sum_congr rfl intro u hu rw [hVU u]] have hNeg : (∑ u : Untreated, (-(∑ c : Treated, P.a c * H.weight c u)) * YU u) = -∑ u : Untreated, (∑ c : Treated, P.a c * H.weight c u) * YU u := by calc (∑ u : Untreated, (-(∑ c : Treated, P.a c * H.weight c u)) * YU u) = ∑ u : Untreated, -((∑ c : Treated, P.a c * H.weight c u) * YU u) := by apply Finset.sum_congr rfl intro u hu rw [neg_mul] _ = -∑ u : Untreated, (∑ c : Treated, P.a c * H.weight c u) * YU u := by rw [Finset.sum_neg_distrib] have hReindex : (∑ u : Untreated, (∑ c : Treated, P.a c * H.weight c u) * YU u) = ∑ c : Treated, ∑ u : Untreated, (P.a c * H.weight c u) * YU u := by calc (∑ u : Untreated, (∑ c : Treated, P.a c * H.weight c u) * YU u) = ∑ u : Untreated, ∑ c : Treated, (P.a c * H.weight c u) * YU u := by apply Finset.sum_congr rfl intro u hu rw [Finset.sum_mul] _ = ∑ c : Treated, ∑ u : Untreated, (P.a c * H.weight c u) * YU u := by rw [Finset.sum_comm] calc (∑ c : Treated, P.a c * YT c) + ∑ u : Untreated, (-(∑ c : Treated, P.a c * H.weight c u)) * YU u = (∑ c : Treated, P.a c * YT c) - ∑ u : Untreated, (∑ c : Treated, P.a c * H.weight c u) * YU u := by rw [hNeg, sub_eq_add_neg] _ = (∑ c : Treated, P.a c * YT c) - ∑ c : Treated, ∑ u : Untreated, (P.a c * H.weight c u) * YU u := by rw [hReindex] _ = ∑ c : Treated, (P.a c * YT c - ∑ u : Untreated, (P.a c * H.weight c u) * YU u) := by rw [Finset.sum_sub_distrib] _ = ∑ c : Treated, P.a c * (YT c - ∑ u : Untreated, H.weight c u * YU u) := by apply Finset.sum_congr rfl intro c hc rw [mul_sub] congr rw [Finset.mul_sum] apply Finset.sum_congr rfl intro u hu rw [mul_assoc] refine ⟨H, hVT, hVU, hValue, ?_⟩ unfold LinearEstimator.observedValue psiImp exact hValue P.EY_T P.EY_U
    Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.linear_unbiased_of_imputation_representation_of_vT_eq_a · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Imputation.lean:271
  • linear_unbiased_of_imputation_representation theorem — Universal unbiasedness supplies the treated-coefficient identity required by linear_unbiased_of_imputation_representation_of_vT_eq_a.
    L :
    P.LinearEstimator
    hUnbiasedForAllTau :
    L.unbiasedForAllTau
    hImputationWitness :
    L.HasImputationRepresentation
    ∃ H : P.ImputationWeights,
    (∀ c : Treated, L.vT c = P.a c) ∧
    (∀ u : Untreated, L.vU u = - ∑ c : Treated, P.a c * H.weight c u) ∧
    (∀ (YT : Treated → ℝ) (YU : Untreated → ℝ), L.value YT YU = ∑ c : Treated, P.a c * (YT c - ∑ u : Untreated, H.weight c u * YU u)) ∧
    L.observedValue = P.psiImp H.weight
    Proof (Lean source)
    theorem linear_unbiased_of_imputation_representation (L : P.LinearEstimator) (hUnbiasedForAllTau : L.unbiasedForAllTau) (hImputationWitness : L.HasImputationRepresentation) : ∃ H : P.ImputationWeights, (∀ c : Treated, L.vT c = P.a c) ∧ (∀ u : Untreated, L.vU u = - ∑ c : Treated, P.a c * H.weight c u) ∧ (∀ (YT : Treated → ℝ) (YU : Untreated → ℝ), L.value YT YU = ∑ c : Treated, P.a c * (YT c - ∑ u : Untreated, H.weight c u * YU u)) ∧ L.observedValue = P.psiImp H.weight := by classical apply linear_unbiased_of_imputation_representation_of_vT_eq_a P L ?_ hImputationWitness intro c have h := hUnbiasedForAllTau (fun _ : Regressor => 0) (fun d : Treated => if d = c then (1 : ℝ) else 0) simpa [LinearEstimator.modelValue, LinearEstimator.value, targetForTau, dot] using h
    Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.linear_unbiased_of_imputation_representation · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Imputation.lean:377
Efficiency 5 core · 3 supporting This file connects the finite BJS imputation design to Gauss-Markov efficiency. ★ bjs_ols_imputation_min_variance_spherical

Borusyak-Jaravel-Spiess Efficiency

This file connects the finite BJS imputation design to Gauss-Markov efficiency. It builds the full event-study design matrix and proves that the OLS imputation weights attain no larger variance than any linear unbiased estimator under spherical cell-outcome errors.

def designFull reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel

The event-study design matrix: rows are observed cells (Treated ⊕ Untreated), columns are treated-cell fixed effects (Treated, the τ part) stacked with covariates (Regressor, the β part). Treated rows carry the cell-indicator in the τ block and qT in the covariate block; untreated rows carry zeros in the τ block and qU in the covariate block.

Definition (Lean source)
def designFull (P : BJSPanel Treated Untreated Regressor) : Matrix (Treated ⊕ Untreated) (Treated ⊕ Regressor) ℝ := of (elim (fun c => elim (fun d => if c = d then (1 : ℝ) else 0) (fun r => P.qT c r)) (fun u => elim (fun _ => (0 : ℝ)) (fun r => P.qU u r)))
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.designFull · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Efficiency.lean:37 · uses BJSPanel
def cFull reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel

Target functional in design coordinates: target weights a on the τ block, zero on the covariate block.

Definition (Lean source)
def cFull (P : BJSPanel Treated Untreated Regressor) : Treated ⊕ Regressor → ℝ := elim P.a (fun _ => 0)
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.cFull · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Efficiency.lean:48 · uses BJSPanel
def weightOf reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel

A linear estimator's weight vector over all observed cells.

Definition (Lean source)
def weightOf {P : BJSPanel Treated Untreated Regressor} (L : P.LinearEstimator) : Treated ⊕ Untreated → ℝ := elim L.vT L.vU
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.weightOf · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Efficiency.lean:53 · uses BJSPanel , LinearEstimator
theorem bjs_ols_imputation_min_variance_spherical reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel

BJS efficiency: OLS imputation is BLUE under spherical errors. For a BJS event-study panel P and a family of cell outcomes Y on a probability space, suppose each cell outcome is square-integrable, the cell outcomes form a spherical family with common variance σ² — equal variances and zero cross-covariances, and the full event-study design matrix designFull P has full column rank. Then for any linear estimator L unbiased for every value of the treatment-effect vector, the variance of the OLS imputation estimator built from designFull P and the target functional cFull P is no larger than the variance of L.

Formal statement
P :
BJSPanel Treated Untreated Regressor
Ω :
Y :
Treated ⊕ Untreated → Ω → ℝ
hY :
∀ i, MemLp (Y i) 2 μ
σ :
hsph :
hRank :
L :
P.LinearEstimator
hL :
L.unbiasedForAllTau
Var[fun ω => ∑ i, olsWeight (designFull P) (cFull P) i * Y i ω; μ]
Var[fun ω => ∑ i, weightOf L i * Y i ω; μ]
Proof (Lean source)
theorem bjs_ols_imputation_min_variance_spherical {P : BJSPanel Treated Untreated Regressor} {Ω : Type*} {mΩ : MeasurableSpace Ω} {μ : Measure Ω} [IsProbabilityMeasure μ] (Y : Treated ⊕ Untreated → Ω → ℝ) (hY : ∀ i, MemLp (Y i) 2 μ) {σ : ℝ} (hsph : SphericalFamily Y μ σ) (hRank : IsUnit ((designFull P)ᵀ * designFull P).det) (L : P.LinearEstimator) (hL : L.unbiasedForAllTau) : Var[fun ω => ∑ i, olsWeight (designFull P) (cFull P) i * Y i ω; μ] ≤ Var[fun ω => ∑ i, weightOf L i * Y i ω; μ] := by exact variance_blue_spherical Y hY hsph (olsWeight_mem_colSpan (designFull P) (cFull P)) (olsWeight_unbiased (cFull P) hRank) (weightOf_vecMul_designFull L hL)
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.bjs_ols_imputation_min_variance_spherical · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Efficiency.lean:86 · uses SphericalFamily , olsWeight , BJSPanel , LinearEstimator , unbiasedForAllTau , cFull , designFull , weightOf
def treatedClassifier reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel

Classifier on observed cells sending each treated cell to its own label and every untreated cell to none. Its Some-indicators are the τ-columns of designFull.

Definition (Lean source)
def treatedClassifier : (Treated ⊕ Untreated) → Option Treated := elim (fun c => some c) (fun _ => none)
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.treatedClassifier · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/Efficiency.lean:120
3 supporting declarations (lemmas, instances)
Panel­Bridge 4 core · 5 supporting Provides the uniform untreated-cell WeightedSupport, the regressor column maps into Untreated → ℝ, their span, and the bridge identifying the BJS left-null-space condition with ip-orthogonality to that span. ★ bjs_linear_unbiased_iff_imputation_form

BJS panel-substrate bridge

Provides the uniform untreated-cell WeightedSupport, the regressor column maps into Untreated → ℝ, their span, and the bridge identifying the BJS left-null-space condition with ip-orthogonality to that span. The main public bridge is columnSpan_ip_orthogonal_iff; exists_imputationWeights_of_gap_orthogonal uses it to absorb a left-null-space gap into one target-relevant imputation row. The file then proves linear_unbiased_of_prediction_identified and bjs_linear_unbiased_iff_imputation_form, the linear-unbiased characterization theorems kept separate from the base finite imputation algebra.

def untreatedSupport reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy

The untreated cells equipped with the uniform weighted support ω_u ≡ 1/|U|. The OLS imputation estimator is the uniform-weight instance of the panel WLS substrate, so this is the WeightedSupport through which BJS consumes the ip / Subspace API.

Definition (Lean source)
def untreatedSupport (Untreated : Type*) [Fintype Untreated] [DecidableEq Untreated] [Nonempty Untreated] : WeightedSupport Untreated where observed := univ observed_nonempty := Finset.univ_nonempty weight := fun _ => (Fintype.card Untreated : ℝ)⁻¹ weight_pos := by intro u _ positivity weight_zero_off := by intro u hu exact absurd (Finset.mem_univ u) hu weight_sum_one := by rw [Finset.sum_const, Finset.card_univ, nsmul_eq_mul] exact mul_inv_cancel₀ (by exact_mod_cast Fintype.card_ne_zero)
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.untreatedSupport · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/PanelBridge.lean:52 · uses WeightedSupport
def regressorColumn reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel

The r-th regressor column as an array over the untreated cells: u ↦ q_{ur}.

Definition (Lean source)
def regressorColumn (r : Regressor) : Untreated → ℝ := fun u => P.qU u r
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.regressorColumn · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/PanelBridge.lean:75 · uses BJSPanel
def columnSpan reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel

The regressor column span inside Untreated → ℝ: the span of all columns u ↦ q_{ur}. Membership of a treated row's representation in (the analogous span over Regressor) is the BJS row-span condition; orthogonality to this span is the left-null-space condition.

Definition (Lean source)
def columnSpan : Submodule ℝ (Untreated → ℝ) := span ℝ (range P.regressorColumn)
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.columnSpan · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/PanelBridge.lean:79 · uses BJSPanel
theorem bjs_linear_unbiased_iff_imputation_form reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel

Combined iff characterization of the BJS linear-unbiased imputation class. Given a target-relevant prediction-span witness and at least one treated cell with nonzero target weight, a linear estimator L is unbiased for every value of the treatment-effect vector if and only if it admits a BJS imputation-weight representation: its treated coefficients match the target weights, its untreated coefficients equal the negative weighted imputation sum, its value equals the imputation contrast for every pair of treated/untreated observed outcomes, and its observed value equals the population imputation functional psiImp.

Formal statement
L :
P.LinearEstimator
hPredictionSpan :
P.PredictionIdentified
hNonzeroTargetWeight :
∃ c : Treated, P.a c ≠ 0
L.unbiasedForAllTau
↔ ∃ H : P.ImputationWeights, (∀ c : Treated, L.vT c = P.a c) ∧ (∀ u : Untreated, L.vU u = - ∑ c : Treated, P.a c * H.weight c u) ∧ (∀ (YT : Treated → ℝ) (YU : Untreated → ℝ), L.value YT YU = ∑ c : Treated, P.a c * (YT c - ∑ u : Untreated, H.weight c u * YU u)) ∧ L.observedValue = P.psiImp H.weight
Proof (Lean source)
theorem bjs_linear_unbiased_iff_imputation_form (L : P.LinearEstimator) (hPredictionSpan : P.PredictionIdentified) (hNonzeroTargetWeight : ∃ c : Treated, P.a c ≠ 0) : L.unbiasedForAllTau ↔ ∃ H : P.ImputationWeights, (∀ c : Treated, L.vT c = P.a c) ∧ (∀ u : Untreated, L.vU u = - ∑ c : Treated, P.a c * H.weight c u) ∧ (∀ (YT : Treated → ℝ) (YU : Untreated → ℝ), L.value YT YU = ∑ c : Treated, P.a c * (YT c - ∑ u : Untreated, H.weight c u * YU u)) ∧ L.observedValue = P.psiImp H.weight := by constructor · -- (⟹) linear unbiasedness ⟹ imputation form intro hUnbiased exact linear_unbiased_of_prediction_identified P L hUnbiased hPredictionSpan hNonzeroTargetWeight · -- (⟸) imputation form ⟹ linear unbiasedness for every (beta, tau') intro ⟨H, hVT, hVU, hValue, _⟩ beta tau' simp only [LinearEstimator.modelValue] rw [hValue] unfold targetForTau apply Finset.sum_congr rfl intro c _ by_cases hA : P.a c = 0 · simp [hA] · have hRowId : ∀ r : Regressor, ∑ u : Untreated, H.weight c u * P.qU u r = P.qT c r := H.row_identity c hA have hImpute : (∑ u : Untreated, H.weight c u * dot (P.qU u) beta) = dot (P.qT c) beta := by unfold dot calc (∑ u : Untreated, H.weight c u * ∑ r : Regressor, P.qU u r * beta r) = ∑ u : Untreated, ∑ r : Regressor, (H.weight c u * P.qU u r) * beta r := by apply Finset.sum_congr rfl intro u _ rw [Finset.mul_sum] apply Finset.sum_congr rfl intro r _ rw [mul_assoc] _ = ∑ r : Regressor, ∑ u : Untreated, (H.weight c u * P.qU u r) * beta r := by rw [Finset.sum_comm] _ = ∑ r : Regressor, (∑ u : Untreated, H.weight c u * P.qU u r) * beta r := by apply Finset.sum_congr rfl intro r _ rw [Finset.sum_mul] _ = ∑ r : Regressor, P.qT c r * beta r := by apply Finset.sum_congr rfl intro r _ rw [hRowId r] rw [hImpute] ring
5 supporting declarations (lemmas, instances)
  • ip_untreatedSupport_regressorColumn lemma — The panel inner product of an untreated-cell vector v with a regressor column is the BJS left-null-space sum, rescaled by the uniform weight.
    v :
    Untreated → ℝ
    r :
    Regressor
    (untreatedSupport Untreated).ip v (P.regressorColumn r)
    = (Fintype.card Untreated : ℝ)⁻¹ * ∑ u : Untreated, v u * P.qU u r
    Proof (Lean source)
    lemma ip_untreatedSupport_regressorColumn (v : Untreated → ℝ) (r : Regressor) : (untreatedSupport Untreated).ip v (P.regressorColumn r) = (Fintype.card Untreated : ℝ)⁻¹ * ∑ u : Untreated, v u * P.qU u r := by rw [WeightedSupport.ip_def, Finset.mul_sum] refine Finset.sum_congr rfl ?_ intro u _ simp only [untreatedSupport, regressorColumn] ring
    Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.ip_untreatedSupport_regressorColumn · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/PanelBridge.lean:88
  • ip_regressorColumn_eq_zero_iff lemma — ip-orthogonality to a single regressor column ⟺ that column's BJS left-null-space coordinate vanishes.
    v :
    Untreated → ℝ
    r :
    Regressor
    (untreatedSupport Untreated).ip v (P.regressorColumn r)
    = 0 ↔ ∑ u : Untreated, v u * P.qU u r = 0
    Proof (Lean source)
    lemma ip_regressorColumn_eq_zero_iff (v : Untreated → ℝ) (r : Regressor) : (untreatedSupport Untreated).ip v (P.regressorColumn r) = 0 ↔ ∑ u : Untreated, v u * P.qU u r = 0 := by rw [ip_untreatedSupport_regressorColumn] rw [mul_eq_zero] have hne : (Fintype.card Untreated : ℝ)⁻¹ ≠ 0 := by simp [Fintype.card_ne_zero] constructor · rintro (h | h) · exact absurd h hne · exact h · intro h; exact inr h
    Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.ip_regressorColumn_eq_zero_iff · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/PanelBridge.lean:99
  • columnSpan_ip_orthogonal_iff lemma — Keystone bridge. A vector over the untreated cells is ip-orthogonal to the whole regressor column span iff it satisfies the BJS left-null-space condition ∀ r, ∑_u v_u q_{ur} = 0. This is the panel-substrate restatement of "v lies in the left null space of Q_U".
    v :
    Untreated → ℝ
    (∀ h ∈ P.columnSpan, (untreatedSupport Untreated).ip v h = 0)
    ↔ ∀ r : Regressor, ∑ u : Untreated, v u * P.qU u r = 0
    Proof (Lean source)
    lemma columnSpan_ip_orthogonal_iff (v : Untreated → ℝ) : (∀ h ∈ P.columnSpan, (untreatedSupport Untreated).ip v h = 0) ↔ ∀ r : Regressor, ∑ u : Untreated, v u * P.qU u r = 0 := by constructor · intro h r rw [← ip_regressorColumn_eq_zero_iff] exact h (P.regressorColumn r) (Submodule.subset_span ⟨r, rfl⟩) · intro h have hcol : ∀ r : Regressor, (untreatedSupport Untreated).ip v (P.regressorColumn r) = 0 := by intro r; rw [ip_regressorColumn_eq_zero_iff]; exact h r -- The set of `w` with `ip v w = 0` is a submodule containing every column, -- hence contains the whole span. intro w hw refine Submodule.span_induction ?_ ?_ ?_ ?_ hw · rintro x ⟨r, rfl⟩; exact hcol r · simp [WeightedSupport.ip] · intro x y _ _ hx hy rw [WeightedSupport.ip_add_right, hx, hy, add_zero] · intro s x _ hx rw [WeightedSupport.ip_smul_right, hx, mul_zero]
    Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.columnSpan_ip_orthogonal_iff · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/PanelBridge.lean:114
  • exists_imputationWeights_of_gap_orthogonal theorem — Left-null-space row adjustment (audit M3), phrased through the panel substrate. Given base imputation weights H0, a nonzero target weight at c0, and a target untreated-coefficient vector vU whose gap gap u = vU u + ∑_c a_c · H0.weight c u is ip-orthogonal to the regressor column span (equivalently: gap lies in the left null space of Q_U), one nonzero target row of H0 can absorb the gap without disturbing any target-relevant row identity. The resulting imputation weights H represent the untreated coefficients: ∑_c a_c · H.weight c u = - vU u for every u.
    vU :
    Untreated → ℝ
    c0 :
    Treated
    hc0 :
    P.a c0 ≠ 0
    H0 :
    P.ImputationWeights
    hgap :
    ∀ h ∈ P.columnSpan,
    (untreatedSupport Untreated).ip (fun u => vU u + ∑ c : Treated, P.a c * H0.weight c u) h
    = 0
    ∃ H : P.ImputationWeights, ∀ u : Untreated, (∑ c : Treated, P.a c * H.weight c u) = - vU u
    Proof (Lean source)
    theorem exists_imputationWeights_of_gap_orthogonal (vU : Untreated → ℝ) {c0 : Treated} (hc0 : P.a c0 ≠ 0) (H0 : P.ImputationWeights) (hgap : ∀ h ∈ P.columnSpan, (untreatedSupport Untreated).ip (fun u => vU u + ∑ c : Treated, P.a c * H0.weight c u) h = 0) : ∃ H : P.ImputationWeights, ∀ u : Untreated, (∑ c : Treated, P.a c * H.weight c u) = - vU u := by classical let weightedUntreated : Untreated → ℝ := fun u => ∑ c : Treated, P.a c * H0.weight c u let correction : Untreated → ℝ := fun u => (P.a c0)⁻¹ * (-vU u - weightedUntreated u) -- The panel-substrate orthogonality hypothesis unpacks (via the keystone -- bridge) to the BJS left-null-space coordinate condition on the gap. have hWeightedCombined : ∀ r : Regressor, ∑ u : Untreated, (vU u + weightedUntreated u) * P.qU u r = 0 := (P.columnSpan_ip_orthogonal_iff _).mp hgap have hCorrectionNull : ∀ r : Regressor, ∑ u : Untreated, correction u * P.qU u r = 0 := by intro r have hNeg : ∑ u : Untreated, (-vU u - weightedUntreated u) * P.qU u r = 0 := by calc (∑ u : Untreated, (-vU u - weightedUntreated u) * P.qU u r) = -∑ u : Untreated, (vU u + weightedUntreated u) * P.qU u r := by rw [← Finset.sum_neg_distrib] apply Finset.sum_congr rfl intro u _ ring _ = 0 := by rw [hWeightedCombined r, neg_zero] calc (∑ u : Untreated, correction u * P.qU u r) = (P.a c0)⁻¹ * ∑ u : Untreated, (-vU u - weightedUntreated u) * P.qU u r := by simp only [correction] rw [Finset.mul_sum] apply Finset.sum_congr rfl intro u _ rw [mul_assoc] _ = 0 := by rw [hNeg, mul_zero] let HWeight : Treated → Untreated → ℝ := fun c u => if c = c0 then H0.weight c u + correction u else H0.weight c u have hHWeightSum : ∀ u : Untreated, (∑ c : Treated, P.a c * HWeight c u) = -vU u := by intro u have hUpdate : (∑ c : Treated, P.a c * HWeight c u) = (∑ c : Treated, P.a c * H0.weight c u) + P.a c0 * correction u := by calc (∑ c : Treated, P.a c * HWeight c u) = ∑ c : Treated, (P.a c * H0.weight c u + if c = c0 then P.a c * correction u else 0) := by apply Finset.sum_congr rfl intro c _ by_cases hC : c = c0 · subst c; simp [HWeight]; ring · simp [HWeight, hC] _ = (∑ c : Treated, P.a c * H0.weight c u) + ∑ c : Treated, (if c = c0 then P.a c * correction u else 0) := by rw [Finset.sum_add_distrib] _ = (∑ c : Treated, P.a c * H0.weight c u) + P.a c0 * correction u := by simp calc (∑ c : Treated, P.a c * HWeight c u) = weightedUntreated u + P.a c0 * correction u := by rw [hUpdate] _ = weightedUntreated u + P.a c0 * ((P.a c0)⁻¹ * (-vU u - weightedUntreated u)) := rfl _ = -vU u := by rw [← mul_assoc, mul_inv_cancel₀ hc0, one_mul]; ring refine ⟨{ weight := HWeight, row_identity := ?_ }, hHWeightSum⟩ intro c hA r by_cases hC : c = c0 · subst c calc (∑ u : Untreated, HWeight c0 u * P.qU u r) = ∑ u : Untreated, (H0.weight c0 u + correction u) * P.qU u r := by simp [HWeight] _ = (∑ u : Untreated, H0.weight c0 u * P.qU u r) + ∑ u : Untreated, correction u * P.qU u r := by rw [← Finset.sum_add_distrib] apply Finset.sum_congr rfl intro u _; rw [add_mul] _ = P.qT c0 r := by rw [H0.row_identity c0 hc0 r, hCorrectionNull r, add_zero] · simpa [HWeight, hC] using H0.row_identity c hA r
    Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.exists_imputationWeights_of_gap_orthogonal · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/PanelBridge.lean:140
  • linear_unbiased_of_prediction_identified theorem — BJS linear-unbiased representation from the primitive prediction-span condition.
    L :
    P.LinearEstimator
    hUnbiasedForAllTau :
    L.unbiasedForAllTau
    hPredictionSpan :
    P.PredictionIdentified
    hNonzeroTargetWeight :
    ∃ c : Treated, P.a c ≠ 0
    ∃ H : P.ImputationWeights,
    (∀ c : Treated, L.vT c = P.a c) ∧
    (∀ u : Untreated, L.vU u = - ∑ c : Treated, P.a c * H.weight c u) ∧
    (∀ (YT : Treated → ℝ) (YU : Untreated → ℝ), L.value YT YU = ∑ c : Treated, P.a c * (YT c - ∑ u : Untreated, H.weight c u * YU u)) ∧
    L.observedValue = P.psiImp H.weight
    Proof (Lean source)
    theorem linear_unbiased_of_prediction_identified (L : P.LinearEstimator) (hUnbiasedForAllTau : L.unbiasedForAllTau) (hPredictionSpan : P.PredictionIdentified) (hNonzeroTargetWeight : ∃ c : Treated, P.a c ≠ 0) : ∃ H : P.ImputationWeights, (∀ c : Treated, L.vT c = P.a c) ∧ (∀ u : Untreated, L.vU u = - ∑ c : Treated, P.a c * H.weight c u) ∧ (∀ (YT : Treated → ℝ) (YU : Untreated → ℝ), L.value YT YU = ∑ c : Treated, P.a c * (YT c - ∑ u : Untreated, H.weight c u * YU u)) ∧ L.observedValue = P.psiImp H.weight := by classical haveI : DecidableEq Untreated := Classical.decEq Untreated let H0 : P.ImputationWeights := Classical.choice hPredictionSpan rcases hNonzeroTargetWeight with ⟨c0, hc0⟩ have hVT : ∀ c : Treated, L.vT c = P.a c := by intro c have h := hUnbiasedForAllTau (fun _ : Regressor => 0) (fun d : Treated => if d = c then (1 : ℝ) else 0) simpa [LinearEstimator.modelValue, LinearEstimator.value, targetForTau, dot] using h let weightedUntreated : Untreated → ℝ := fun u => ∑ c : Treated, P.a c * H0.weight c u have hNuisanceCoord : ∀ r : Regressor, (∑ c : Treated, P.a c * P.qT c r) + ∑ u : Untreated, L.vU u * P.qU u r = 0 := by intro r let beta : Regressor → ℝ := fun r' => if r' = r then (1 : ℝ) else 0 have h := hUnbiasedForAllTau beta (fun _ : Treated => 0) simpa [LinearEstimator.modelValue, LinearEstimator.value, targetForTau, dot, beta, hVT] using h have hH0Aggregate : ∀ r : Regressor, (∑ c : Treated, P.a c * P.qT c r) = ∑ u : Untreated, weightedUntreated u * P.qU u r := by intro r calc (∑ c : Treated, P.a c * P.qT c r) = ∑ c : Treated, P.a c * ∑ u : Untreated, H0.weight c u * P.qU u r := by apply Finset.sum_congr rfl intro c hc by_cases hA : P.a c = 0 · simp [hA] · rw [H0.row_identity c hA r] _ = ∑ c : Treated, ∑ u : Untreated, P.a c * (H0.weight c u * P.qU u r) := by apply Finset.sum_congr rfl intro c hc rw [Finset.mul_sum] _ = ∑ u : Untreated, ∑ c : Treated, P.a c * (H0.weight c u * P.qU u r) := by rw [Finset.sum_comm] _ = ∑ u : Untreated, weightedUntreated u * P.qU u r := by apply Finset.sum_congr rfl intro u hu unfold weightedUntreated rw [Finset.sum_mul] apply Finset.sum_congr rfl intro c hc rw [mul_assoc] have hWeightedCombined : ∀ r : Regressor, ∑ u : Untreated, (L.vU u + weightedUntreated u) * P.qU u r = 0 := by intro r have hN := hNuisanceCoord r rw [hH0Aggregate r] at hN calc (∑ u : Untreated, (L.vU u + weightedUntreated u) * P.qU u r) = (∑ u : Untreated, L.vU u * P.qU u r) + ∑ u : Untreated, weightedUntreated u * P.qU u r := by rw [← Finset.sum_add_distrib] apply Finset.sum_congr rfl intro u hu rw [add_mul] _ = (∑ u : Untreated, weightedUntreated u * P.qU u r) + ∑ u : Untreated, L.vU u * P.qU u r := by rw [add_comm] _ = 0 := hN -- With no untreated cells the imputation representation is vacuous on the -- untreated coordinates; otherwise route the gap through the panel substrate. rcases isEmpty_or_nonempty Untreated with hEmpty | hNE · have hWitness : L.HasImputationRepresentation := { weights := H0 untreated_weight_representation := by intro u; exact (hEmpty.false u).elim } exact linear_unbiased_of_imputation_representation P L hUnbiasedForAllTau hWitness · have hgap : ∀ h ∈ P.columnSpan, (untreatedSupport Untreated).ip (fun u => L.vU u + ∑ c : Treated, P.a c * H0.weight c u) h = 0 := by rw [P.columnSpan_ip_orthogonal_iff] intro r exact hWeightedCombined r obtain ⟨H, hHsum⟩ := P.exists_imputationWeights_of_gap_orthogonal L.vU hc0 H0 hgap have hWitness : L.HasImputationRepresentation := { weights := H untreated_weight_representation := by intro u; rw [hHsum u]; ring } exact linear_unbiased_of_imputation_representation P L hUnbiasedForAllTau hWitness
    Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPanel.linear_unbiased_of_prediction_identified · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/PanelBridge.lean:257
Panel­Grounding 5 core · 8 supporting Builds a BJSPanel from an adoption path and two-way fixed effects, and proves the untreated-outcome model and fixed-effect hypotheses hold for it. ★ ofStaggeredTWFE_untreatedModel

BJS staggered-adoption grounding

Builds a BJSPanel from an adoption path and two-way fixed effects, and proves the untreated-outcome model and fixed-effect hypotheses hold for it. Treated cells are the cells whose treatment has switched on, untreated cells include never-treated cells and pre-adoption cells, and the canonical two-way fixed-effect design discharges the BJS hypotheses in a concrete panel. The main definitions are TreatedCell, UntreatedCell, feRow, and ofStaggeredTWFE; the main theorem bridges are ofStaggeredTWFE_untreatedModel and ofStaggeredTWFE_treatmentFixed.

def TreatedCell reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy

Cells whose treatment has switched on by period t (g i ≤ t).

Definition (Lean source)
def TreatedCell : Type _ := { c : I × Fin T // AdoptionPath.le (g c.1) c.2 }
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.TreatedCell · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/PanelGrounding.lean:48
def UntreatedCell reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy

Cells still untreated at period t (t < g i). Includes every cell of a never-treated unit and every pre-adoption cell of a treated unit.

Definition (Lean source)
def UntreatedCell : Type _ := { c : I × Fin T // AdoptionPath.lt (g c.1) c.2 }
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.UntreatedCell · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/PanelGrounding.lean:52
def feRow reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy

Two-way fixed-effect design row for cell (i,t): the unit-i indicator on the I block stacked with the time-t indicator on the Fin T block.

Definition (Lean source)
def feRow (c : I × Fin T) : (I ⊕ Fin T) → ℝ := elim (fun i' => if i' = c.1 then (1 : ℝ) else 0) (fun t' => if t' = c.2 then (1 : ℝ) else 0)
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.feRow · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/PanelGrounding.lean:87
def ofStaggeredTWFE reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy

Grounding constructor. From an adoption path g, unit effects α, time effects λ, target weights a, and treated-cell effects τ, build the BJSPanel whose treated/untreated cells are the staggered-adoption partition of I × Fin T and whose regressors are the two-way fixed effects. The untreated-outcome model E[Y(0)] = α_i + λ_t, no anticipation, and the fixed-effect equation all hold definitionally.

Definition (Lean source)
def ofStaggeredTWFE (α : I → ℝ) (lam : Fin T → ℝ) (a tau : TreatedCell g → ℝ) : BJSPanel (TreatedCell g) (UntreatedCell g) (I ⊕ Fin T) where qT := fun c => feRow c.val qU := fun u => feRow u.val a := a EY_T := fun c => (α c.val.1 + lam c.val.2) + tau c EY_U := fun u => α u.val.1 + lam u.val.2 EY0_T := fun c => α c.val.1 + lam c.val.2 EY0_U := fun u => α u.val.1 + lam u.val.2 beta0 := elim α lam tau := tau
theorem ofStaggeredTWFE_untreatedModel reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy

Untreated-outcome model holds by construction. For unit fixed effects α, period fixed effects lam, and target weights and treated-cell effects a, tau, the staggered-adoption grounded panel ofStaggeredTWFE g α lam a tau satisfies the BJS untreated-outcome model: treated and untreated cell means both equal the two-way fixed-effect model α_i + λ_t, and untreated cells exhibit no anticipation.

Formal statement
α :
I → ℝ
lam :
Fin T → ℝ
a tau :
TreatedCell g → ℝ
Proof (Lean source)
theorem ofStaggeredTWFE_untreatedModel (α : I → ℝ) (lam : Fin T → ℝ) (a tau : TreatedCell g → ℝ) : (ofStaggeredTWFE g α lam a tau).UntreatedOutcomeModel := by refine ⟨fun c => ?_, fun u => ?_, fun _ => rfl⟩ · change α c.val.1 + lam c.val.2 = dot (feRow c.val) (elim α lam) rw [dot_feRow] · change α u.val.1 + lam u.val.2 = dot (feRow u.val) (elim α lam) rw [dot_feRow]
8 supporting declarations (lemmas, instances)
Population­Bridge 4 core · 5 supporting This file constructs a finite BJSPanel from a probability space with treated and untreated potential outcomes, defining its mean fields as treated/untreated cell conditional means and deriving the untreated-consistency a ★ bjs_imputation_identification_population

Borusyak-Jaravel-Spiess imputation population bridge

This file constructs a finite BJSPanel from a probability space with treated and untreated potential outcomes, defining its mean fields as treated/untreated cell conditional means and deriving the untreated-consistency and fixed-effect restrictions from cell-level potential-outcome consistency.

structure BJSPopulation reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy

A population for the BJS imputation design: a probability space with a treated/untreated cell classifier and potential outcomes Y0 (untreated), Y1 (treated), and observed Yobs, related by cell-level consistency. The design rows qT, qU, target weights a, and nuisance vector beta0 are carried through to the induced panel unchanged.

Definition (Lean source)
Treated Untreated Regressor :
Type*
Fintype Treated
Fintype Untreated
Fintype Regressor
Unit sample space.
Ω :
Type*
Measurable-space structure on `Ω`.
measΩ :
Population measure.
μ :
`μ` is a probability measure.
probμ :
Treated/untreated cell classifier.
cellOf :
Ω → Treated ⊕ Untreated
Each cell is measurable.
cell_meas :
∀ i, MeasurableSet (cellOf ⁻¹' {i})
Each cell has positive mass.
cell_pos :
∀ i, 0 < (μ (cellOf ⁻¹' {i})).toReal
Untreated potential outcome.
Y0 :
Ω → ℝ
Treated potential outcome.
Y1 :
Ω → ℝ
Observed outcome.
Yobs :
Ω → ℝ
Consistency on treated cells: the observed outcome is the treated potential outcome.
hTreatedCons :
∀ (c : Treated) (ω : Ω)
if
cellOf ω = inl c
then
Yobs ω = Y1 ω
Consistency on untreated cells: the observed outcome is the untreated potential outcome.
hUntreatedCons :
∀ (u : Untreated) (ω : Ω)
if
cellOf ω = inr u
then
Yobs ω = Y0 ω
Regressor row for a treated cell.
qT :
Treated → Regressor → ℝ
Regressor row for an untreated cell.
qU :
Untreated → Regressor → ℝ
Target weight on treated cells.
a :
Treated → ℝ
Nuisance vector in the untreated outcome model.
beta0 :
Regressor → ℝ
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPopulation · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/PopulationBridge.lean:48
def cells reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPopulation

The treated/untreated cell partition induced by the classifier.

Definition (Lean source)
noncomputable def cells : CellPartition E.μ (Treated ⊕ Untreated) := cellPartitionOfClassifier E.μ E.cellOf E.cell_meas E.cell_pos
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPopulation.cells · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/PopulationBridge.lean:98 · uses BJSPopulation , CellPartition
def toPanel reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPopulation

The BJS panel induced by a population: every mean field is a treated/untreated cell conditional mean of the appropriate potential-outcome slice, and the treated effect tau c is the genuine population contrast E[Y(1) ∣ cell c] − E[Y(0) ∣ cell c].

Definition (Lean source)
noncomputable def toPanel : BJSPanel Treated Untreated Regressor where qT := E.qT qU := E.qU a := E.a beta0 := E.beta0 EY_T c := E.cells.mean E.Yobs (inl c) EY_U u := E.cells.mean E.Yobs (inr u) EY0_T c := E.cells.mean E.Y0 (inl c) EY0_U u := E.cells.mean E.Y0 (inr u) tau c := E.cells.mean E.Y1 (inl c) - E.cells.mean E.Y0 (inl c)
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPopulation.toPanel · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/PopulationBridge.lean:102 · uses BJSPanel , BJSPopulation
theorem bjs_imputation_identification_population reviewed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPopulation

Population BJS imputation identification (headline). For a population BJS design E, suppose the conditional mean of the untreated potential outcome on each treated cell equals a linear function q_T · β₀ of the treated-cell regressors and likewise, on each untreated cell, the conditional mean of the untreated potential outcome equals q_U · β₀ — jointly the additive untreated-outcome (parallel-trends) model — together with a target-relevant prediction-span witness for the induced panel. Then the observed-law imputation functional identifies the target ∑ a_c · (E[Y(1) ∣ cell c] − E[Y(0) ∣ cell c]): there is an imputation-weight witness for which the population imputation functional psiImp equals the target theta.

Formal statement
hLinT :
∀ c : Treated, E.cells.mean E.Y0 (inl c) = dot (E.qT c) E.beta0
hLinU :
∀ u : Untreated, E.cells.mean E.Y0 (inr u) = dot (E.qU u) E.beta0
hPred :
∃ h : (E.toPanel).ImputationWeights, (E.toPanel).psiImp h.weight = (E.toPanel).theta
Proof (Lean source)
theorem bjs_imputation_identification_population (hLinT : ∀ c : Treated, E.cells.mean E.Y0 (inl c) = dot (E.qT c) E.beta0) (hLinU : ∀ u : Untreated, E.cells.mean E.Y0 (inr u) = dot (E.qU u) E.beta0) (hPred : (E.toPanel).PredictionIdentified) : ∃ h : (E.toPanel).ImputationWeights, (E.toPanel).psiImp h.weight = (E.toPanel).theta := (E.toPanel).bjs_imputation_identification (E.toPanel_untreatedModel hLinT hLinU) hPred E.toPanel_treatmentEffectFixed
Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPopulation.bjs_imputation_identification_population · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/PopulationBridge.lean:167 · uses ImputationWeights , PredictionIdentified , psiImp , theta , BJSPopulation , cells , toPanel , dot , mean
5 supporting declarations (lemmas, instances)
  • toPanel_EY_T_eq_mean_Y1 theorem — On a treated cell the observed mean equals the treated potential-outcome mean.
    c :
    Treated
    (E.toPanel).EY_T c = E.cells.mean E.Y1 (inl c)
    Proof (Lean source)
    theorem toPanel_EY_T_eq_mean_Y1 (c : Treated) : (E.toPanel).EY_T c = E.cells.mean E.Y1 (inl c) := by refine (E.cells).mean_congr_on (inl c) ?_ intro ω hω have hcell : E.cellOf ω = inl c := by simpa [cells] using hω exact E.hTreatedCons c ω hcell
    Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPopulation.toPanel_EY_T_eq_mean_Y1 · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/PopulationBridge.lean:117
  • toPanel_EY_U_eq_mean_Y0 theorem — On an untreated cell the observed mean equals the untreated potential-outcome mean.
    u :
    Untreated
    (E.toPanel).EY_U u = E.cells.mean E.Y0 (inr u)
    Proof (Lean source)
    theorem toPanel_EY_U_eq_mean_Y0 (u : Untreated) : (E.toPanel).EY_U u = E.cells.mean E.Y0 (inr u) := by refine (E.cells).mean_congr_on (inr u) ?_ intro ω hω have hcell : E.cellOf ω = inr u := by simpa [cells] using hω exact E.hUntreatedCons u ω hcell
    Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPopulation.toPanel_EY_U_eq_mean_Y0 · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/PopulationBridge.lean:126
  • toPanel_tau_eq_po_contrast theorem — Causal-meaning certificate. In the induced panel, tau c is literally the population treatment-effect contrast E[Y(1) ∣ cell c] − E[Y(0) ∣ cell c], so the estimand carries genuine causal content.
    c :
    Treated
    (E.toPanel).tau c = E.cells.mean E.Y1 (inl c) - E.cells.mean E.Y0 (inl c)
    Proof (Lean source)
    theorem toPanel_tau_eq_po_contrast (c : Treated) : (E.toPanel).tau c = E.cells.mean E.Y1 (inl c) - E.cells.mean E.Y0 (inl c) := rfl
    Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPopulation.toPanel_tau_eq_po_contrast · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/PopulationBridge.lean:135
  • toPanel_treatmentEffectFixed theorem — Treatment-effect-fixed is derived. EY_T = EY0_T + tau holds because on treated cells the observed mean is the treated potential-outcome mean and tau is the treated-minus-untreated contrast.
    Proof (Lean source)
    theorem toPanel_treatmentEffectFixed : (E.toPanel).TreatmentEffectFixed := by intro c have h := E.toPanel_EY_T_eq_mean_Y1 c simp only [toPanel] at h ⊢ rw [h]; ring
    Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPopulation.toPanel_treatmentEffectFixed · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/PopulationBridge.lean:142
  • toPanel_untreatedModel theorem — Untreated-outcome model is derived from the linear untreated-mean hypotheses plus consistency. The two linear-model conjuncts E[Y(0) ∣ cell] = q · β₀ are the genuine modeling hypotheses hLinT/hLinU (additive fixed-effect / parallel-trends form); the observed-equals-untreated conjunct is derived from untreated-cell consistency.
    hLinT :
    ∀ c : Treated, E.cells.mean E.Y0 (inl c) = dot (E.qT c) E.beta0
    hLinU :
    ∀ u : Untreated, E.cells.mean E.Y0 (inr u) = dot (E.qU u) E.beta0
    Proof (Lean source)
    theorem toPanel_untreatedModel (hLinT : ∀ c : Treated, E.cells.mean E.Y0 (inl c) = dot (E.qT c) E.beta0) (hLinU : ∀ u : Untreated, E.cells.mean E.Y0 (inr u) = dot (E.qU u) E.beta0) : (E.toPanel).UntreatedOutcomeModel := by refine ⟨?_, ?_, ?_⟩ · intro c; simpa [toPanel] using hLinT c · intro u; simpa [toPanel] using hLinU u · intro u rw [E.toPanel_EY_U_eq_mean_Y0 u] simp [toPanel]
    Causalean.Panel.EstimandCharacterization.ImputationEventStudy.BJSPopulation.toPanel_untreatedModel · Causalean/Panel/EstimandCharacterization/ImputationEventStudy/PopulationBridge.lean:151