Experimentation

Design-based experimentation under interference: finite randomization designs, exposure mappings, Horvitz-Thompson estimators, variance bounds, consistency, CLTs, and paper-specific Aronow-Samii, Hudgens-Halloran, and Savje-Aronow-Hudgens results.

Design­Based 119 core · 127 supporting · 30 submodules The shared, paper-agnostic substrate for design-based / randomization inference under interference: the finite-population, fixed-potential-outcome flavor of the potential-outcomes framework, where probability comes from Sequential 11 core · 2 supporting · 3 submodules The anytime-valid inference substrate for adaptive / sequential experiments, where the treatment-assignment rule evolves with the accumulating data. Exposure­Mapping­Interference 42 core · 7 supporting · 2 submodules Formalization of Aronow & Samii (2017, AOAS), "Estimating Average Causal Effects Under General Interference" (arXiv:1305.6156), built on the shared Experimentation.DesignBased substrate. Matched­Pair­Design 12 core · 4 supporting · 3 submodules Worked application of the design-based randomization substrate to the fixed-pair matched-pair design from Bai (2022), "Optimality of Matched-Pair Designs in Randomized Controlled Trials" (American Economic Review). Super­Population 15 core · 5 supporting · 5 submodules Super-population modules collect network-dependent sampling CLTs and HAC variance tools. Two­Stage­Interference 88 core · 39 supporting · 12 submodules Formalization of Hudgens & Halloran (2008), "Toward Causal Inference With Interference" (JASA), building on the paper-agnostic design-based substrate Experimentation.DesignBased. Unknown­Interference 45 core · 13 supporting · 7 submodules Formalization of the Bernoulli-design core of Sävje, Aronow & Hudgens (2021), "Average treatment effects in the presence of unknown interference," *Annals of Statistics* 49(2):673–701 (arXiv:1711.06399).
Betting­Mean 4 core · 3 supporting Worked application of the anytime-valid substrate to Waudby-Smith & Ramdas (2024), "Estimating means of bounded random variables by betting" (JRSS-B). ★ capital★ isTestSupermartingale_capital★ isConfidenceSequence_bettingCI★ isAnytimeValid_betting

Waudby-Smith & Ramdas (2024): confidence sequences by betting

Worked application of the anytime-valid substrate to Waudby-Smith & Ramdas (2024), "Estimating means of bounded random variables by betting" (JRSS-B). To test that the mean of a [0,1]-bounded data stream is m, a gambler bets a predictable fraction λₙ of current capital on each new observation, multiplying capital by 1 + λₙ(Xₙ − m). The resulting capital process Kₙ(m) = ∏ᵢ (1 + λᵢ(Xᵢ − m)) is, under the null that the conditional mean is m and with bets kept in the range that keeps capital nonnegative, a test supermartingale (IsTestSupermartingale): nonnegative, with K₀ = 1, and a fair bet cannot grow capital in expectation. Inverting it — keeping the values m whose capital has not yet reached 1/α — yields a confidence sequence for the mean with time-uniform coverage 1 − α, directly via Ville's inequality.

def capital reviewed
Causalean.Experimentation.BettingMean

The betting capital process for testing that the mean is m, with observations X and predictable betting fractions lam: K₀ = 1 and Kₙ₊₁ = Kₙ · (1 + lamₙ·(Xₙ − m)).

Definition (Lean source)
noncomputable def capital (X lam : ℕ → Ω → ℝ) (m : ℝ) : ℕ → Ω → ℝ | 0 => fun _ => 1 | (n + 1) => fun ω => capital X lam m n ω * (1 + lam n ω * (X n ω - m))
Causalean.Experimentation.BettingMean.capital · Causalean/Experimentation/BettingMean.lean:36
theorem isTestSupermartingale_capital reviewed
Causalean.Experimentation.BettingMean

The capital process is a test supermartingale (the Waudby-Smith–Ramdas construction). Consider a data stream X tested against a candidate mean m via betting fractions lam, all adapted to a filtration . If the capital process itself is adapted to , each bet lam n is measurable with respect to the time-n information, the capital process, the centered increment X n − m, and the bet-scaled increment lam n · (X n − m) are all integrable at every time n, every per-step return factor 1 + lam n (X n − m) stays nonnegative, and the conditional mean of X n − m given the time-n information is zero, i.e. the bet is conditionally fair, then the betting capital process is a nonnegative test supermartingale for under μ, with E[K₀] ≤ 1.

Formal statement
X lam :
ℕ → Ω → ℝ
m :
hadapt :
Adapted ℱ (capital X lam m)
hlam :
∀ n, StronglyMeasurable[ℱ n] (lam n)
hint :
∀ n, Integrable (capital X lam m n) μ
hintX :
∀ n, Integrable (fun ω => X n ω - m) μ
hintInc :
∀ n, Integrable (fun ω => lam n ω * (X n ω - m)) μ
hbet :
∀ n ω, 0 ≤ 1 + lam n ω * (X n ω - m)
hfair :
∀ n, μ[fun ω => X n ω - m | ℱ n] =ᵐ[μ] 0
Proof (Lean source)
theorem isTestSupermartingale_capital [IsProbabilityMeasure μ] {X lam : ℕ → Ω → ℝ} {m : ℝ} (hadapt : Adapted ℱ (capital X lam m)) (hlam : ∀ n, StronglyMeasurable[ℱ n] (lam n)) (hint : ∀ n, Integrable (capital X lam m n) μ) (hintX : ∀ n, Integrable (fun ω => X n ω - m) μ) (hintInc : ∀ n, Integrable (fun ω => lam n ω * (X n ω - m)) μ) (hbet : ∀ n ω, 0 ≤ 1 + lam n ω * (X n ω - m)) (hfair : ∀ n, μ[fun ω => X n ω - m | ℱ n] =ᵐ[μ] 0) : IsTestSupermartingale (capital X lam m) ℱ μ := by refine ⟨?super, capital_nonneg hbet, ?init⟩ · refine (martingale_nat hadapt.stronglyAdapted hint ?_).supermartingale intro n -- `Kₙ₊₁ = Kₙ · (1 + lamₙ(Xₙ−m))`; pull the `ℱn`-measurable factors `Kₙ`, `lamₙ` out of the -- conditional expectation and use the fair-bet condition `μ[Xₙ−m | ℱn] = 0`. have hcap : StronglyMeasurable[ℱ n] (capital X lam m n) := hadapt.stronglyAdapted n have hgint : Integrable (fun ω => 1 + lam n ω * (X n ω - m)) μ := (integrable_const (1 : ℝ)).add (hintInc n) have hcapsucc : capital X lam m (n + 1) = capital X lam m n * (fun ω => 1 + lam n ω * (X n ω - m)) := by rw [capital_succ]; rfl have hfgint : Integrable (capital X lam m n * (fun ω => 1 + lam n ω * (X n ω - m))) μ := by rw [← hcapsucc]; exact hint (n + 1) have hpull : μ[capital X lam m (n + 1) | ℱ n] =ᵐ[μ] capital X lam m n * μ[(fun ω => 1 + lam n ω * (X n ω - m)) | ℱ n] := by rw [hcapsucc] exact condExp_mul_of_stronglyMeasurable_left hcap hfgint hgint have hinc : μ[(fun ω => 1 + lam n ω * (X n ω - m)) | ℱ n] =ᵐ[μ] (fun _ => (1 : ℝ)) := by have hsplit : (fun ω => 1 + lam n ω * (X n ω - m)) = (fun _ => (1 : ℝ)) + (fun ω => lam n ω * (X n ω - m)) := by funext ω; rfl rw [hsplit] refine (condExp_add (integrable_const (1 : ℝ)) (hintInc n) (ℱ n)).trans ?_ have hc1 : μ[(fun _ => (1 : ℝ)) | ℱ n] = (fun _ => (1 : ℝ)) := condExp_const (ℱ.le n) 1 have hlampull : μ[(fun ω => lam n ω * (X n ω - m)) | ℱ n] =ᵐ[μ] lam n * μ[(fun ω => X n ω - m) | ℱ n] := condExp_mul_of_stronglyMeasurable_left (hlam n) (hintInc n) (hintX n) rw [hc1] filter_upwards [hlampull, hfair n] with ω h1 h2 simp only [Pi.add_apply, Pi.mul_apply, h1, h2] simp refine (hpull.trans ?_).symm filter_upwards [hinc] with ω hω simp only [Pi.mul_apply, hω, mul_one] · rw [capital_zero] simp [integral_const]
Causalean.Experimentation.BettingMean.isTestSupermartingale_capital · Causalean/Experimentation/BettingMean.lean:65 · uses capital , IsTestSupermartingale
theorem isConfidenceSequence_bettingCI reviewed
Causalean.Experimentation.BettingMean

Betting confidence sequence (coverage). If the betting capital process built from the data stream X, betting fractions lam, and candidate mean m is a test supermartingale under μ and the target error level α is strictly positive, then the sequence of confidence sets that retains a candidate mean m only while its capital has not yet reached 1/α is a valid confidence sequence with time-uniform coverage 1 − α.

Formal statement
X lam :
ℕ → Ω → ℝ
m :
hM :
α :
:
0 < α
Proof (Lean source)
theorem isConfidenceSequence_bettingCI [IsFiniteMeasure μ] {X lam : ℕ → Ω → ℝ} {m : ℝ} (hM : IsTestSupermartingale (capital X lam m) ℱ μ) {α : ℝ} (hα : 0 < α) : IsConfidenceSequence (confSeqOfWealth (capital X lam m) α) μ α := isConfidenceSequence_confSeqOfWealth hM hα
Causalean.Experimentation.BettingMean.isConfidenceSequence_bettingCI · Causalean/Experimentation/BettingMean.lean:121 · uses capital , IsConfidenceSequence , IsTestSupermartingale , confSeqOfWealth
theorem isAnytimeValid_betting reviewed
Causalean.Experimentation.BettingMean

Anytime-valid test by betting. If the betting capital process built from the data stream X, betting fractions lam, and candidate mean m is a test supermartingale under μ and the target error level α is strictly positive, then the rejection region that declares significance once the capital ever reaches 1/α is an anytime-valid level-α test.

Formal statement
X lam :
ℕ → Ω → ℝ
m :
hM :
α :
:
0 < α
Proof (Lean source)
theorem isAnytimeValid_betting [IsFiniteMeasure μ] {X lam : ℕ → Ω → ℝ} {m : ℝ} (hM : IsTestSupermartingale (capital X lam m) ℱ μ) {α : ℝ} (hα : 0 < α) : IsAnytimeValid (rejectionRegion (capital X lam m) α) μ α := isAnytimeValid_rejectionRegion hM hα
3 supporting declarations (lemmas, instances)
  • capital_zero lemma — The betting capital starts at one before any observations are processed.
    X lam :
    ℕ → Ω → ℝ
    m :
    capital X lam m 0 = fun _ => 1
    Proof (Lean source)
    @[simp] lemma capital_zero (X lam : ℕ → Ω → ℝ) (m : ℝ) : capital X lam m 0 = fun _ => 1 := rfl
    Causalean.Experimentation.BettingMean.capital_zero · Causalean/Experimentation/BettingMean.lean:42
  • capital_succ lemma — One step of the betting capital multiplies current wealth by the return 1 + lam n · (X n − m).
    X lam :
    ℕ → Ω → ℝ
    m :
    n :
    capital X lam m (n + 1) = fun ω => capital X lam m n ω * (1 + lam n ω * (X n ω - m))
    Proof (Lean source)
    lemma capital_succ (X lam : ℕ → Ω → ℝ) (m : ℝ) (n : ℕ) : capital X lam m (n + 1) = fun ω => capital X lam m n ω * (1 + lam n ω * (X n ω - m)) := rfl
    Causalean.Experimentation.BettingMean.capital_succ · Causalean/Experimentation/BettingMean.lean:45
  • capital_nonneg lemma — The capital process stays nonnegative provided each bet keeps the per-step factor nonnegative (0 ≤ 1 + lamₙ(Xₙ − m)) — the admissibility constraint on the betting fractions.
    X lam :
    ℕ → Ω → ℝ
    m :
    hbet :
    ∀ n ω, 0 ≤ 1 + lam n ω * (X n ω - m)
    ∀ n, 0 ≤ capital X lam m n
    Proof (Lean source)
    lemma capital_nonneg {X lam : ℕ → Ω → ℝ} {m : ℝ} (hbet : ∀ n ω, 0 ≤ 1 + lam n ω * (X n ω - m)) : ∀ n, 0 ≤ capital X lam m n := by intro n induction n with | zero => rw [capital_zero] intro ω norm_num | succ n ih => rw [capital_succ] intro ω exact mul_nonneg (ih ω) (hbet n ω)
    Causalean.Experimentation.BettingMean.capital_nonneg · Causalean/Experimentation/BettingMean.lean:50
Cluster­Randomized­HT 6 core · 2 supporting This file formalizes the cluster-randomized Horvitz-Thompson identity behind Middleton and Aronow's average-treatment-effect result. ★ htClusterEffect★ totalEffect★ E_htClusterEffect

Middleton & Aronow (2015): cluster-randomized Horvitz-Thompson ATE

This file formalizes the cluster-randomized Horvitz-Thompson identity behind Middleton and Aronow's average-treatment-effect result. Treatment is assigned independently by cluster, each cluster has treated and control cluster-total potential outcomes, and inverse-probability weighting recovers the finite-population average treatment effect after normalization by the total number of units.

The file records the cluster Horvitz-Thompson treated/control totals, the unit-count denominator, the normalized effect estimator, the normalized finite-population ATE estimand, and the unbiasedness theorem (a direct consequence of the first-order cluster inclusion probability).

def htTreatedTotal reviewed
Causalean.Experimentation.ClusterRandomizedHT

The Horvitz–Thompson treated total: each treated cluster's total outcome y1 c, weighted by the inverse assignment probability 1 / p c.

Definition (Lean source)
noncomputable def htTreatedTotal (p y1 : C → ℝ) (z : C → Bool) : ℝ := ∑ c, (treatInd c z / p c) * y1 c
Causalean.Experimentation.ClusterRandomizedHT.htTreatedTotal · Causalean/Experimentation/ClusterRandomizedHT.lean:35
def htControlTotal reviewed
Causalean.Experimentation.ClusterRandomizedHT

The Horvitz–Thompson control total: each control cluster's total outcome y0 c, weighted by the inverse control probability 1 / (1 − p c).

Definition (Lean source)
noncomputable def htControlTotal (p y0 : C → ℝ) (z : C → Bool) : ℝ := ∑ c, ((1 - treatInd c z) / (1 - p c)) * y0 c
Causalean.Experimentation.ClusterRandomizedHT.htControlTotal · Causalean/Experimentation/ClusterRandomizedHT.lean:40
def totalUnits reviewed
Causalean.Experimentation.ClusterRandomizedHT

The total number of experimental units represented by the cluster counts n c.

Definition (Lean source)
noncomputable def totalUnits (n : C → ℕ) : ℝ := ∑ c, (n c : ℝ)
Causalean.Experimentation.ClusterRandomizedHT.totalUnits · Causalean/Experimentation/ClusterRandomizedHT.lean:45
def htClusterEffect reviewed
Causalean.Experimentation.ClusterRandomizedHT

The Middleton-Aronow Horvitz-Thompson ATE estimator divides the inverse-probability weighted treated-minus-control cluster-total estimator by the total number of units.

Definition (Lean source)
noncomputable def htClusterEffect (p : C → ℝ) (n : C → ℕ) (y1 y0 : C → ℝ) (z : C → Bool) : ℝ := (htTreatedTotal p y1 z - htControlTotal p y0 z) / totalUnits n
Causalean.Experimentation.ClusterRandomizedHT.htClusterEffect · Causalean/Experimentation/ClusterRandomizedHT.lean:48
def totalEffect reviewed
Causalean.Experimentation.ClusterRandomizedHT

The finite-population average treatment effect is the all-unit treated-minus-control potential-outcome total, aggregated through cluster totals, divided by the total number of units.

Definition (Lean source)
noncomputable def totalEffect (n : C → ℕ) (y1 y0 : C → ℝ) : ℝ := (∑ c, (y1 c - y0 c)) / totalUnits n
Causalean.Experimentation.ClusterRandomizedHT.totalEffect · Causalean/Experimentation/ClusterRandomizedHT.lean:54
theorem E_htClusterEffect reviewed
Causalean.Experimentation.ClusterRandomizedHT

Unbiasedness for the finite-population average treatment effect. Consider cluster randomization where each cluster c is assigned treatment with probability p c; suppose p c lies between 0 and 1 and, more sharply, p c lies strictly between 0 and 1, and the total number of units across clusters is positive. Then the Middleton–Aronow Horvitz–Thompson estimator of the effect — the inverse-probability-weighted treated-minus-control cluster-total contrast, normalized by the total unit count — is unbiased for the finite-population average treatment effect, the analogous unweighted contrast of the cluster-total potential outcomes normalized by the same unit count.

Formal statement
p :
C → ℝ
n :
C → ℕ
y1 y0 :
C → ℝ
hp0 :
∀ c, 0 ≤ p c
hp1 :
∀ c, p c ≤ 1
hppos :
∀ c, 0 < p c
hp1' :
∀ c, p c < 1
hNpos :
(clusterDesign p hp0 hp1).E (htClusterEffect p n y1 y0) = totalEffect n y1 y0
Proof (Lean source)
theorem E_htClusterEffect (p : C → ℝ) (n : C → ℕ) (y1 y0 : C → ℝ) (hp0 : ∀ c, 0 ≤ p c) (hp1 : ∀ c, p c ≤ 1) (hppos : ∀ c, 0 < p c) (hp1' : ∀ c, p c < 1) (hNpos : 0 < totalUnits n) : (clusterDesign p hp0 hp1).E (htClusterEffect p n y1 y0) = totalEffect n y1 y0 := by unfold htClusterEffect totalEffect have hNne : totalUnits n ≠ 0 := ne_of_gt hNpos rw [show (fun z => (htTreatedTotal p y1 z - htControlTotal p y0 z) / totalUnits n) = (fun z => (htTreatedTotal p y1 z - htControlTotal p y0 z) * (totalUnits n)⁻¹) from funext (fun z => by rw [div_eq_mul_inv])] rw [FiniteDesign.E_mul_const, FiniteDesign.E_sub, E_htTreatedTotal p y1 hp0 hp1 hppos, E_htControlTotal p y0 hp0 hp1 hp1', ← Finset.sum_sub_distrib, div_eq_mul_inv]
Causalean.Experimentation.ClusterRandomizedHT.E_htClusterEffect · Causalean/Experimentation/ClusterRandomizedHT.lean:111 · uses htClusterEffect , totalEffect , totalUnits , E , clusterDesign
2 supporting declarations (lemmas, instances)
  • E_htTreatedTotal theorem — The HT treated total is unbiased for the treated-arm population total ∑ y1 c: each cluster is treated with probability p c, which the inverse weight 1 / p c exactly undoes.
    p y1 :
    C → ℝ
    hp0 :
    ∀ c, 0 ≤ p c
    hp1 :
    ∀ c, p c ≤ 1
    hppos :
    ∀ c, 0 < p c
    (clusterDesign p hp0 hp1).E (htTreatedTotal p y1) = ∑ c, y1 c
    Proof (Lean source)
    theorem E_htTreatedTotal (p y1 : C → ℝ) (hp0 : ∀ c, 0 ≤ p c) (hp1 : ∀ c, p c ≤ 1) (hppos : ∀ c, 0 < p c) : (clusterDesign p hp0 hp1).E (htTreatedTotal p y1) = ∑ c, y1 c := by change (bernoulliDesign p hp0 hp1).E (fun z => ∑ c, treatInd c z / p c * y1 c) = ∑ c, y1 c rw [show (fun z => ∑ c, treatInd c z / p c * y1 c) = (fun z => ∑ c, y1 c / p c * treatInd c z) from funext (fun z => Finset.sum_congr rfl (fun c _ => by ring))] rw [FiniteDesign.E_sum] refine Finset.sum_congr rfl (fun c _ => ?_) rw [FiniteDesign.E_const_mul _ (y1 c / p c) (treatInd c)] have hE : (bernoulliDesign p hp0 hp1).E (treatInd c) = p c := by -- `simp` no longer eta-expands the partially applied `treatInd c`, so state the -- goal in the applied form (defeq) and rewrite there. show (bernoulliDesign p hp0 hp1).E (fun z => (fun b => if b then (1 : ℝ) else 0) (z c)) = p c rw [bernoulliDesign_E_treatInd p hp0 hp1 c (fun b => if b then (1 : ℝ) else 0)] norm_num rw [hE] exact div_mul_cancel₀ (y1 c) (hppos c).ne'
    Causalean.Experimentation.ClusterRandomizedHT.E_htTreatedTotal · Causalean/Experimentation/ClusterRandomizedHT.lean:59
  • E_htControlTotal theorem — The HT control total is unbiased for the control-arm population total ∑ y0 c: each cluster is a control with probability 1 − p c, undone by the weight 1 / (1 − p c).
    p y0 :
    C → ℝ
    hp0 :
    ∀ c, 0 ≤ p c
    hp1 :
    ∀ c, p c ≤ 1
    hp1' :
    ∀ c, p c < 1
    (clusterDesign p hp0 hp1).E (htControlTotal p y0) = ∑ c, y0 c
    Proof (Lean source)
    theorem E_htControlTotal (p y0 : C → ℝ) (hp0 : ∀ c, 0 ≤ p c) (hp1 : ∀ c, p c ≤ 1) (hp1' : ∀ c, p c < 1) : (clusterDesign p hp0 hp1).E (htControlTotal p y0) = ∑ c, y0 c := by have hone : ∀ c, (bernoulliDesign p hp0 hp1).E (fun z => 1 - treatInd c z) = 1 - p c := by intro c rw [show (fun z => (1 : ℝ) - treatInd c z) = (fun z => (fun _ => (1 : ℝ)) z - treatInd c z) from rfl, FiniteDesign.E_sub, FiniteDesign.E_const] have hE : (bernoulliDesign p hp0 hp1).E (treatInd c) = p c := by -- `simp` no longer eta-expands the partially applied `treatInd c`, so state the -- goal in the applied form (defeq) and rewrite there. show (bernoulliDesign p hp0 hp1).E (fun z => (fun b => if b then (1 : ℝ) else 0) (z c)) = p c rw [bernoulliDesign_E_treatInd p hp0 hp1 c (fun b => if b then (1 : ℝ) else 0)] norm_num rw [hE] change (bernoulliDesign p hp0 hp1).E (fun z => ∑ c, (1 - treatInd c z) / (1 - p c) * y0 c) = ∑ c, y0 c rw [show (fun z => ∑ c, (1 - treatInd c z) / (1 - p c) * y0 c) = (fun z => ∑ c, y0 c / (1 - p c) * (1 - treatInd c z)) from funext (fun z => Finset.sum_congr rfl (fun c _ => by ring))] rw [FiniteDesign.E_sum] refine Finset.sum_congr rfl (fun c _ => ?_) rw [FiniteDesign.E_const_mul _ (y0 c / (1 - p c)) (fun z => 1 - treatInd c z), hone c] exact div_mul_cancel₀ (y0 c) (sub_ne_zero.mpr (hp1' c).ne')
    Causalean.Experimentation.ClusterRandomizedHT.E_htControlTotal · Causalean/Experimentation/ClusterRandomizedHT.lean:82
Finite­Population­Moments 6 core · 0 supporting Worked application of the complete-randomization design to Li & Ding (2017), "General Forms of Finite Population Central Limit Theorems with Applications to Causal Inference" (JASA). ★ sampleMean★ E_sampleMean★ Var_sampleMean

Li & Ding (2017): finite-population moments of the simple-random-sampling mean

Worked application of the complete-randomization design to Li & Ding (2017), "General Forms of Finite Population Central Limit Theorems with Applications to Causal Inference" (JASA). Their foundational object (Theorem 1, after Hájek 1960) is the average ȳ_S = (1/n) ∑_{i∈S} y_i of a simple random sample S of size n drawn from a fixed finite population Π_N = {y_1,…,y_N} — which is exactly the completeRandomization design on size-n subsets. This file proves the two exact finite-sample moments that the Hájek central limit theorem is stated about:

* the sample mean is unbiased for the population mean, E[ȳ_S] = ȳ_N; and * its randomization variance is the classical sampling-without-replacement (Cochran) formula Var(ȳ_S) = (1/n − 1/N)·v_N, where v_N = (1/(N−1)) ∑ (y_i − ȳ_N)² is the finite-population variance.

The Hájek CLT itself — (ȳ_S − ȳ_N)/√Var(ȳ_S) ⇝ N(0,1) under the Lindeberg-type condition m_N/(v_N·min(n,N−n)) → 0, where m_N = maxᵢ (y_i − ȳ_N)² — is the asymptotic result built on these moments. This module formalizes the finite-population moments and the maximal-deviation quantity popMaxSqDev; it does not formalize the sequence-level convergence-in-distribution statement.

def popMean reviewed
Causalean.Experimentation.FinitePopulationMoments

The finite-population mean ȳ_N = (1/N) ∑ y_i.

Definition (Lean source)
noncomputable def popMean (y : U → ℝ) : ℝ := (∑ i, y i) / (Fintype.card U : ℝ)
Causalean.Experimentation.FinitePopulationMoments.popMean · Causalean/Experimentation/FinitePopulationMoments.lean:44
def popVar reviewed
Causalean.Experimentation.FinitePopulationMoments

The finite-population variance v_N = (1/(N−1)) ∑ (y_i − ȳ_N)².

Definition (Lean source)
noncomputable def popVar (y : U → ℝ) : ℝ := (∑ i, (y i - popMean y) ^ 2) / ((Fintype.card U : ℝ) - 1)
Causalean.Experimentation.FinitePopulationMoments.popVar · Causalean/Experimentation/FinitePopulationMoments.lean:47
def popMaxSqDev reviewed
Causalean.Experimentation.FinitePopulationMoments

The maximum squared deviation m_N = maxᵢ (y_i − ȳ_N)² driving the Hájek CLT condition.

Definition (Lean source)
noncomputable def popMaxSqDev [Nonempty U] (y : U → ℝ) : ℝ := Finset.univ.sup' Finset.univ_nonempty (fun i => (y i - popMean y) ^ 2)
Causalean.Experimentation.FinitePopulationMoments.popMaxSqDev · Causalean/Experimentation/FinitePopulationMoments.lean:51
def sampleMean reviewed
Causalean.Experimentation.FinitePopulationMoments

The simple-random-sample mean ȳ_S = (1/n) ∑_{i∈S} y_i of a size-n sample S.

Definition (Lean source)
noncomputable def sampleMean (n : ℕ) (y : U → ℝ) (S : {S : Finset U // S.card = n}) : ℝ := (∑ i, (if i ∈ S.val then y i else 0)) / (n : ℝ)
Causalean.Experimentation.FinitePopulationMoments.sampleMean · Causalean/Experimentation/FinitePopulationMoments.lean:55
theorem E_sampleMean reviewed
Causalean.Experimentation.FinitePopulationMoments

Unbiasedness of the sample mean (Li & Ding 2017, Thm 1 moments). For a sample size that is positive and at most the population size, the mean of a simple random sample of that size, drawn without replacement from the finite population of outcomes y, is unbiased for the population mean: each unit is sampled with probability n/N, which the 1/n weight averages to 1/N.

Formal statement
n :
hn :
n ≤ card U
hn0 :
0 < n
y :
U → ℝ
(completeRandomization n hn).E (sampleMean n y) = popMean y
Proof (Lean source)
theorem E_sampleMean (n : ℕ) (hn : n ≤ card U) (hn0 : 0 < n) (y : U → ℝ) : (completeRandomization n hn).E (sampleMean n y) = popMean y := -- `sampleMean n y` is definitionally the treated-arm mean of `y`, already proved unbiased. E_treatedMean n hn hn0 y
Causalean.Experimentation.FinitePopulationMoments.E_sampleMean · Causalean/Experimentation/FinitePopulationMoments.lean:59 · uses E , completeRandomization , popMean , sampleMean
theorem Var_sampleMean reviewed
Causalean.Experimentation.FinitePopulationMoments

Variance of the sample mean (Li & Ding 2017, Thm 1 / Cochran). For a sample size that is positive and at most the population size, when the population contains at least two units, the randomization variance of the simple-random-sample mean equals (1/n − 1/N)·v_N, the sampling-without-replacement variance.

Formal statement
n :
hn :
n ≤ Fintype.card U
hn0 :
0 < n
hN :
2 ≤ Fintype.card U
y :
U → ℝ
(completeRandomization n hn).Var (sampleMean n y)
= (1 / (n : ℝ) - 1 / (Fintype.card U : ℝ)) * popVar y
Proof (Lean source)
theorem Var_sampleMean (n : ℕ) (hn : n ≤ Fintype.card U) (hn0 : 0 < n) (hN : 2 ≤ Fintype.card U) (y : U → ℝ) : (completeRandomization n hn).Var (sampleMean n y) = (1 / (n : ℝ) - 1 / (Fintype.card U : ℝ)) * popVar y := by classical set D := completeRandomization n hn with hDdef -- the per-unit sampling indicator `1(i ∈ S)` set I : U → ({S : Finset U // S.card = n}) → ℝ := fun i => FiniteDesign.ind (fun S => i ∈ S.val) with hIdef have hNnat : 0 < Fintype.card U := lt_of_lt_of_le (by norm_num) hN have hNR : (Fintype.card U : ℝ) ≠ 0 := by exact_mod_cast hNnat.ne' have hnR : (n : ℝ) ≠ 0 := by exact_mod_cast hn0.ne' have hN1R : (Fintype.card U : ℝ) - 1 ≠ 0 := by have h1 : (1 : ℝ) < Fintype.card U := by exact_mod_cast hN exact sub_ne_zero.mpr h1.ne' -- first-order and second-order inclusion probabilities have hπ : ∀ i, D.Pr (fun S => i ∈ S.val) = (n : ℝ) / Fintype.card U := fun i => completeRandomization_incl n hn i -- diagonal covariance: `Var(1ᵢ) = π(1−π)` have hdiag : ∀ i, D.Cov (I i) (I i) = (n : ℝ) / Fintype.card U * (1 - (n : ℝ) / Fintype.card U) := by intro i; rw [hIdef, FiniteDesign.Cov_self, FiniteDesign.Var_ind, hπ i] -- off-diagonal covariance: `Cov(1ᵢ,1ⱼ) = π_ij − π²` (i ≠ j) have hoff : ∀ i j, i ≠ j → D.Cov (I i) (I j) = (n : ℝ) * ((n : ℝ) - 1) / (Fintype.card U * ((Fintype.card U : ℝ) - 1)) - (n : ℝ) / Fintype.card U * ((n : ℝ) / Fintype.card U) := by intro i j hij rw [hIdef, FiniteDesign.Cov_eq] have hprod : (fun S : {S : Finset U // S.card = n} => FiniteDesign.ind (fun S => i ∈ S.val) S * FiniteDesign.ind (fun S => j ∈ S.val) S) = FiniteDesign.ind (fun S : {S : Finset U // S.card = n} => i ∈ S.val ∧ j ∈ S.val) := by funext S; simp only [FiniteDesign.ind] by_cases hi : i ∈ S.val <;> by_cases hj : j ∈ S.val <;> simp [hi, hj] rw [hprod, FiniteDesign.E_ind, FiniteDesign.E_ind, FiniteDesign.E_ind, completeRandomization_incl_pair n hn hij, hπ i, hπ j] -- `sampleMean = (1/n) · ∑ᵢ yᵢ · 1ᵢ` have hsm : sampleMean n y = fun S => (1 / (n : ℝ)) * ∑ i, y i * I i S := by funext S have hterm : (∑ i, if i ∈ S.val then y i else 0) = ∑ i, y i * I i S := by refine Finset.sum_congr rfl fun i _ => ?_ rw [hIdef]; simp only [FiniteDesign.ind]; by_cases h : i ∈ S.val <;> simp [h] change (∑ i, if i ∈ S.val then y i else 0) / (n : ℝ) = (1 / (n : ℝ)) * ∑ i, y i * I i S rw [hterm]; ring rw [hsm] rw [show (D.Var (fun S => 1 / (n : ℝ) * ∑ i, y i * I i S)) = (1 / (n : ℝ)) ^ 2 * D.Var (fun S => ∑ i, y i * I i S) from D.Var_const_mul (1 / (n : ℝ)) (fun S => ∑ i, y i * I i S)] rw [D.Var_linear_comb univ y I] -- collapse the double sum using `Cov(1ᵢ,1ⱼ) = off + 1{i=j}(diag − off)` set off : ℝ := (n : ℝ) * ((n : ℝ) - 1) / (Fintype.card U * ((Fintype.card U : ℝ) - 1)) - (n : ℝ) / Fintype.card U * ((n : ℝ) / Fintype.card U) with hoffdef set diag : ℝ := (n : ℝ) / Fintype.card U * (1 - (n : ℝ) / Fintype.card U) with hdiagdef have hcov : ∀ i j, y i * y j * D.Cov (I i) (I j) = y i * y j * off + (if i = j then y i * y j * (diag - off) else 0) := by intro i j by_cases hij : i = j · subst hij; rw [hdiag i, if_pos rfl]; ring · rw [hoff i j hij, if_neg hij]; ring simp_rw [hcov] -- collapse the double sum: `off·(∑y)² + (diag−off)·∑y²` have hsumsq : (∑ i, ∑ j, y i * y j) = (∑ i, y i) ^ 2 := by rw [sq, Finset.sum_mul_sum] have hsplit : (∑ i, ∑ j, (y i * y j * off + if i = j then y i * y j * (diag - off) else 0)) = off * (∑ i, y i) ^ 2 + (diag - off) * ∑ i, (y i) ^ 2 := by rw [show (∑ i, ∑ j, (y i * y j * off + if i = j then y i * y j * (diag - off) else 0)) = (∑ i, ∑ j, y i * y j * off) + (∑ i, ∑ j, (if i = j then y i * y j * (diag - off) else 0)) from by rw [← Finset.sum_add_distrib] exact Finset.sum_congr rfl fun i _ => Finset.sum_add_distrib] have hA : (∑ i, ∑ j, y i * y j * off) = off * (∑ i, y i) ^ 2 := by rw [← hsumsq, Finset.mul_sum] exact Finset.sum_congr rfl fun i _ => by rw [Finset.mul_sum]; exact Finset.sum_congr rfl fun j _ => by ring have hB : (∑ i, ∑ j, (if i = j then y i * y j * (diag - off) else 0)) = (diag - off) * ∑ i, (y i) ^ 2 := by rw [Finset.mul_sum] refine Finset.sum_congr rfl fun i _ => ?_ rw [Finset.sum_ite_eq univ i (fun j => y i * y j * (diag - off))] simp only [Finset.mem_univ, if_true]; ring rw [hA, hB] rw [hsplit, hoffdef, hdiagdef, popVar, popMean] -- computational variance formula `∑(yᵢ−ȳ)² = ∑yᵢ² − (∑y)²/N` have hexp : (∑ i, (y i - (∑ k, y k) / (Fintype.card U : ℝ)) ^ 2) = (∑ i, (y i) ^ 2) - (∑ i, y i) ^ 2 / (Fintype.card U : ℝ) := by have hpt : ∀ i, (y i - (∑ k, y k) / (Fintype.card U : ℝ)) ^ 2 = (y i) ^ 2 - 2 * ((∑ k, y k) / (Fintype.card U : ℝ)) * y i + ((∑ k, y k) / (Fintype.card U : ℝ)) ^ 2 := fun i => by ring simp_rw [hpt] rw [Finset.sum_add_distrib, Finset.sum_sub_distrib, ← Finset.mul_sum, Finset.sum_const, Finset.card_univ, nsmul_eq_mul] field_simp ring rw [hexp] field_simp ring
Causalean.Experimentation.FinitePopulationMoments.Var_sampleMean · Causalean/Experimentation/FinitePopulationMoments.lean:69 · uses Var , completeRandomization , popVar , sampleMean