PO.ID.Partial.Balke­Pearl

Balke-Pearl linear-programming bounds for the ATE under an imperfect instrument.

Attainment 31 core · 33 supporting · 3 submodules This module collects the explicit latent tables witnessing that each of the sixteen Balke-Pearl closed-form expressions is achieved by an observationally equivalent model, on the region of observed distributions where th
Setup 19 core · 10 supporting This file defines the data layer for Balke-Pearl partial identification of the average treatment effect with a binary instrument, binary treatment, and binary outcome. ★ POBalkePearlSystem★ measurable_DofZ

Balke-Pearl Setup

This file defines the data layer for Balke-Pearl partial identification of the average treatment effect with a binary instrument, binary treatment, and binary outcome. The structure POBalkePearlSystem records the three binary system variables and their distinctness; its namespace supplies the factual variables factualZ, factualD, factualY, the counterfactuals DofZ, YofD, and YofZD, the real-valued Boolean embedding used for integration, the target estimand ATE, and the observable conditional cell probability cellProb.

structure POBalkePearlSystem reviewed
Causalean.PO

Binary-IV system for Balke–Pearl ATE bounds (def:po-iv-balke-pearl-system). Inside a potential-outcome system, this bundles a binary instrument node Z, a binary treatment node D, and a binary outcome node Y, subject to the instrument, treatment, and outcome being pairwise distinct system variables.

Definition (Lean source)
P :
Z :
P.V
D :
P.V
Y :
P.V
hZbool :
P.X Z ≃ᵐ Bool
hDbool :
P.X D ≃ᵐ Bool
hYbool :
P.X Y ≃ᵐ Bool
hZD :
Z ≠ D
hZY :
Z ≠ Y
hDY :
D ≠ Y
Causalean.PO.POBalkePearlSystem · Causalean/PO/ID/Partial/BalkePearl/Setup.lean:36 · uses POSystem
def zVar reviewed
Causalean.PO.POBalkePearlSystem

Instrument packaged as a POVar valued in Bool.

Definition (Lean source)
def zVar : POVar P Bool := ⟨S.Z, S.hZbool⟩
def dVar reviewed
Causalean.PO.POBalkePearlSystem

Treatment packaged as a POVar valued in Bool.

Definition (Lean source)
def dVar : POVar P Bool := ⟨S.D, S.hDbool⟩
def yVar reviewed
Causalean.PO.POBalkePearlSystem

Outcome packaged as a POVar valued in Bool.

Definition (Lean source)
def yVar : POVar P Bool := ⟨S.Y, S.hYbool⟩
def DofZ reviewed
Causalean.PO.POBalkePearlSystem

The treatment value that would be observed for a unit if the instrument were set to z.

Definition (Lean source)
noncomputable def DofZ (z : Bool) : P.Ω → Bool := S.dVar.cfUnder S.zVar z
def YofD reviewed
Causalean.PO.POBalkePearlSystem

Y(d) : P.Ω → Bool.

Definition (Lean source)
noncomputable def YofD (d : Bool) : P.Ω → Bool := S.yVar.cfUnder S.dVar d
def regimeZD reviewed
Causalean.PO.POBalkePearlSystem

Two-variable intervention regime r_{z,d} = ({Z,D}, (z,d)).

Definition (Lean source)
noncomputable def regimeZD (z d : Bool) : Regime P.V P.X := (Regime.single S.Z (S.hZbool.symm z)).sqcup (Regime.single S.D (S.hDbool.symm d)) (Regime.single_disjoint_single S.hZD _ _)
def YofZD reviewed
Causalean.PO.POBalkePearlSystem

Two-variable counterfactual Y(z,d) := yVar.cf (r_{z,d}).

Definition (Lean source)
noncomputable def YofZD (z d : Bool) : P.Ω → Bool := S.yVar.cf (S.regimeZD z d)
def factualZ reviewed
Causalean.PO.POBalkePearlSystem

Factual instrument.

Definition (Lean source)
noncomputable def factualZ : P.Ω → Bool := S.zVar.factual
def factualD reviewed
Causalean.PO.POBalkePearlSystem

Factual treatment.

Definition (Lean source)
noncomputable def factualD : P.Ω → Bool := S.dVar.factual
def factualY reviewed
Causalean.PO.POBalkePearlSystem

Factual outcome.

Definition (Lean source)
noncomputable def factualY : P.Ω → Bool := S.yVar.factual
def boolToReal reviewed
Causalean.PO.POBalkePearlSystem

Canonical embedding of Bool into : true ↦ 1, false ↦ 0.

Definition (Lean source)
@[simp] noncomputable def boolToReal : Bool → ℝ | true => 1 | false => 0
Causalean.PO.POBalkePearlSystem.boolToReal · Causalean/PO/ID/Partial/BalkePearl/Setup.lean:102
def YofD_real reviewed
Causalean.PO.POBalkePearlSystem

Y(d) lifted to for integration.

Definition (Lean source)
noncomputable def YofD_real (d : Bool) : P.Ω → ℝ := boolToReal ∘ S.YofD d
def zEvent reviewed
Causalean.PO.POBalkePearlSystem

The event {Z = z}.

Definition (Lean source)
def zEvent (z : Bool) : Set P.Ω := S.zVar.event z
def dEvent reviewed
Causalean.PO.POBalkePearlSystem

The event {D = d}.

Definition (Lean source)
def dEvent (d : Bool) : Set P.Ω := S.dVar.event d
def yEvent reviewed
Causalean.PO.POBalkePearlSystem

The event {Y = y}.

Definition (Lean source)
def yEvent (y : Bool) : Set P.Ω := S.yVar.event y
lemma measurable_DofZ reviewed
Causalean.PO.POBalkePearlSystem

For a fixed instrument value z, the potential treatment D(z) is measurable.

Formal statement
z :
Measurable (S.DofZ z)
Proof (Lean source)
lemma measurable_DofZ (z : Bool) : Measurable (S.DofZ z) := S.dVar.measurable_cfUnder S.zVar z
Causalean.PO.POBalkePearlSystem.measurable_DofZ · Causalean/PO/ID/Partial/BalkePearl/Setup.lean:123 · uses POBalkePearlSystem , DofZ , POSystem
def ATE reviewed
Causalean.PO.POBalkePearlSystem

Average treatment effect E[Y(1) - Y(0)] (as a difference of Bool-in-ℝ integrals).

Definition (Lean source)
noncomputable def ATE : ℝ := ∫ ω, S.YofD_real true ω - S.YofD_real false ω ∂P.μ
def cellProb reviewed
Causalean.PO.POBalkePearlSystem

Conditional cell probability P(Y = y, D = d | Z = z).

Definition (Lean source)
noncomputable def cellProb (y d z : Bool) : ℝ := (P.μ (S.zEvent z ∩ S.yEvent y ∩ S.dEvent d)).toReal / (P.μ (S.zEvent z)).toReal
10 supporting declarations (lemmas, instances)
Assumptions 5 core · 2 supporting This file collects the structural assumptions for Balke-Pearl partial identification with a binary instrument, including the IV-specific consistency equalities, exclusion, instrument exogeneity, and positive instrument p ★ posZ_toReal_pos

Balke-Pearl Assumptions

This file collects the structural assumptions for Balke-Pearl partial identification with a binary instrument, including the IV-specific consistency equalities, exclusion, instrument exogeneity, and positive instrument probabilities. It also packages the counterfactual variables used by the exogeneity condition.

def dUnderZ reviewed
Causalean.PO.POBalkePearlSystem

D(z) as a RegimedVar.

Definition (Lean source)
def dUnderZ (z : Bool) : RegimedVar P Bool := ⟨S.dVar, Regime.single S.Z (S.hZbool.symm z)⟩
def yUnderD reviewed
Causalean.PO.POBalkePearlSystem

Y(d) as a RegimedVar.

Definition (Lean source)
def yUnderD (d : Bool) : RegimedVar P Bool := ⟨S.yVar, Regime.single S.D (S.hDbool.symm d)⟩
def cfBundle reviewed
Causalean.PO.POBalkePearlSystem

Bundle (D(0), D(1), Y(0), Y(1)) for the exogeneity assumption Z ⊥ (D(0), D(1), Y(0), Y(1)).

Definition (Lean source)
def cfBundle : POCFBundle P := .cons (S.dUnderZ false) <| .cons (S.dUnderZ true) <| .cons (S.yUnderD false) <| .cons (S.yUnderD true) <| .nil P
structure BaseAssumptions reviewed
Causalean.PO.POBalkePearlSystem

Balke-Pearl IV assumptions — def:po-iv-balke-pearl-assumptions.

Definition (Lean source)
Treatment consistency on instrument cells: on `{Z=z}`, factual `D` equals `D(z)`.
consistency_D :
∀ (z : Bool) {ω : P.Ω}
if
ω ∈ S.zEvent z
then
S.DofZ z ω = S.factualD ω
Outcome consistency on treatment cells: on `{D=d}`, factual `Y` equals `Y(d)`.
consistency_Y :
∀ (d : Bool) {ω : P.Ω}
if
ω ∈ S.dEvent d
then
S.YofD d ω = S.factualY ω
Exclusion: Y(z,d) = Y(d) a.s. for all z d.
exclusion :
∀ (z d : Bool), S.YofZD z d =ᵐ[P.μ] S.YofD d
Instrument exogeneity: Z ⊥ (D(0),D(1),Y(0),Y(1)).
exogeneity :
P.IndepCF (.ofFactual S.zVar) S.cfBundle P.μ
Both arms of Z have positive probability.
posZ :
∀ z : Bool, 0 < P.μ (S.zVar.event z)
Causalean.PO.POBalkePearlSystem.BaseAssumptions · Causalean/PO/ID/Partial/BalkePearl/Assumptions.lean:55 · uses POBalkePearlSystem , POSystem
lemma posZ_toReal_pos reviewed
Causalean.PO.POBalkePearlSystem.BaseAssumptions

Under the Balke-Pearl IV base assumptions — IV-specific consistency of treatment and outcome on their respective cells, the exclusion restriction, instrument exogeneity, and positive instrument probability, the real-valued probability of each instrument cell z is strictly positive.

Formal statement
hA :
S.BaseAssumptions
z :
0 < (P.μ (S.zVar.event z)).toReal
Proof (Lean source)
lemma posZ_toReal_pos (hA : S.BaseAssumptions) (z : Bool) : 0 < (P.μ (S.zVar.event z)).toReal := ENNReal.toReal_pos (hA.posZ_ne_zero z) (hA.posZ_ne_top z)
Causalean.PO.POBalkePearlSystem.BaseAssumptions.posZ_toReal_pos · Causalean/PO/ID/Partial/BalkePearl/Assumptions.lean:86 · uses POBalkePearlSystem , BaseAssumptions , zVar , POSystem , event
2 supporting declarations (lemmas, instances)
  • posZ_ne_zero lemma — Positive instrument probabilities are nonzero.
    hA :
    S.BaseAssumptions
    z :
    P.μ (S.zVar.event z) ≠ 0
    Proof (Lean source)
    lemma posZ_ne_zero (hA : S.BaseAssumptions) (z : Bool) : P.μ (S.zVar.event z) ≠ 0 := ne_of_gt (hA.posZ z)
    Causalean.PO.POBalkePearlSystem.BaseAssumptions.posZ_ne_zero · Causalean/PO/ID/Partial/BalkePearl/Assumptions.lean:77
  • posZ_ne_top lemma — Instrument-cell probabilities are finite.
    _ :
    S.BaseAssumptions
    z :
    P.μ (S.zVar.event z) ≠ ⊤
    Proof (Lean source)
    lemma posZ_ne_top (_ : S.BaseAssumptions) (z : Bool) : P.μ (S.zVar.event z) ≠ ⊤ := ne_of_lt (lt_of_le_of_lt prob_le_one (by norm_num))
    Causalean.PO.POBalkePearlSystem.BaseAssumptions.posZ_ne_top · Causalean/PO/ID/Partial/BalkePearl/Assumptions.lean:81
Latent­Table 5 core · 4 supporting This file defines the 16-cell latent type table for Balke-Pearl bounds and relates it to the average treatment effect and observed conditional cell probabilities. ★ ATE_eq_sum_latent

Balke-Pearl Latent Table

This file defines the 16-cell latent type table for Balke-Pearl bounds and relates it to the average treatment effect and observed conditional cell probabilities. The latent cells partition the population by the two treatment potential outcomes and the two outcome potential outcomes.

def dArm reviewed
Causalean.PO.POBalkePearlSystem

The treatment arm under instrument value z: d₀ if z=false, d₁ if z=true.

Definition (Lean source)
def dArm (z d0 d1 : Bool) : Bool := if z then d1 else d0
Causalean.PO.POBalkePearlSystem.dArm · Causalean/PO/ID/Partial/BalkePearl/LatentTable.lean:38
def yArm reviewed
Causalean.PO.POBalkePearlSystem

The outcome arm under treatment d: y₀ if d=false, y₁ if d=true.

Definition (Lean source)
def yArm (d y0 y1 : Bool) : Bool := if d then y1 else y0
Causalean.PO.POBalkePearlSystem.yArm · Causalean/PO/ID/Partial/BalkePearl/LatentTable.lean:41
def latentSet reviewed
Causalean.PO.POBalkePearlSystem

The event that unit ω has latent type (d0,d1,y0,y1).

Definition (Lean source)
def latentSet (d0 d1 y0 y1 : Bool) : Set P.Ω := {ω | S.DofZ false ω = d0 ∧ S.DofZ true ω = d1 ∧ S.YofD false ω = y0 ∧ S.YofD true ω = y1}
def latentProb reviewed
Causalean.PO.POBalkePearlSystem

Probability of the latent type (d0,d1,y0,y1).

Definition (Lean source)
noncomputable def latentProb (d0 d1 y0 y1 : Bool) : ℝ := (P.μ (S.latentSet d0 d1 y0 y1)).toReal
theorem ATE_eq_sum_latent reviewed
Causalean.PO.POBalkePearlSystem

The average treatment effect equals the probability-weighted sum, over the sixteen latent response types, of each type's treatment effect.

Formal statement
S.ATE
= ∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, (boolToReal y1 - boolToReal y0) * S.latentProb d0 d1 y0 y1
Proof (Lean source)
theorem ATE_eq_sum_latent : S.ATE = ∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, (boolToReal y1 - boolToReal y0) * S.latentProb d0 d1 y0 y1 := by unfold ATE set f : Bool × Bool × Bool × BoolSet P.Ω := fun i => S.latentSet i.1 i.2.1 i.2.2.1 i.2.2.2 have hmeas : ∀ i : Bool × Bool × Bool × Bool, MeasurableSet (f i) := fun ⟨d0, d1, y0, y1⟩ => S.measurableSet_latentSet d0 d1 y0 y1 have hdisj : Pairwise (onFun Disjoint f) := by intro ⟨d0, d1, y0, y1⟩ ⟨d0', d1', y0', y1'⟩ hne apply S.latentSet_disjoint intro h; exact absurd h hne have hcov : ⋃ i : Bool × Bool × Bool × Bool, f i = univ := S.latentSet_iUnion_prod_eq_univ have hint := S.integrable_YofD_real_sub -- Partition the integral over the 16 cells. have hsplit : ∫ ω, (S.YofD_real true ω - S.YofD_real false ω) ∂P.μ = ∑ i : Bool × Bool × Bool × Bool, ∫ ω in f i, (S.YofD_real true ω - S.YofD_real false ω) ∂P.μ := by rw [← setIntegral_univ, ← hcov, integral_iUnion_fintype hmeas hdisj (fun i => hint.integrableOn)] rw [hsplit] -- On each cell the integrand is constant = boolToReal y1 - boolToReal y0. have hconst : ∀ (d0 d1 y0 y1 : Bool) ω, ω ∈ S.latentSet d0 d1 y0 y1 → S.YofD_real true ω - S.YofD_real false ω = boolToReal y1 - boolToReal y0 := by intro d0 d1 y0 y1 ω ⟨_, _, hy0, hy1⟩ simp [YofD_real, hy0, hy1] -- Each set integral = constant * latentProb. have hcell : ∀ (d0 d1 y0 y1 : Bool), ∫ ω in S.latentSet d0 d1 y0 y1, (S.YofD_real true ω - S.YofD_real false ω) ∂P.μ = (boolToReal y1 - boolToReal y0) * S.latentProb d0 d1 y0 y1 := by intro d0 d1 y0 y1 rw [MeasureTheory.setIntegral_congr_fun (S.measurableSet_latentSet d0 d1 y0 y1) (fun ω hω => hconst d0 d1 y0 y1 ω hω), MeasureTheory.setIntegral_const] simp only [smul_eq_mul, latentProb, measureReal_def] ring -- Combine flat and nested sums. have hflat : ∀ i : Bool × Bool × Bool × Bool, ∫ ω in f i, (S.YofD_real true ω - S.YofD_real false ω) ∂P.μ = (boolToReal i.2.2.2 - boolToReal i.2.2.1) * S.latentProb i.1 i.2.1 i.2.2.1 i.2.2.2 := fun ⟨d0, d1, y0, y1⟩ => hcell d0 d1 y0 y1 simp_rw [hflat, Fintype.sum_prod_type]
4 supporting declarations (lemmas, instances)
  • measurableSet_latentSet lemma — Each latent type event is measurable.
    d0 d1 y0 y1 :
    MeasurableSet (S.latentSet d0 d1 y0 y1)
    Proof (Lean source)
    lemma measurableSet_latentSet (d0 d1 y0 y1 : Bool) : MeasurableSet (S.latentSet d0 d1 y0 y1) := by show MeasurableSet ({a | S.DofZ false a = d0} ∩ ({a | S.DofZ true a = d1} ∩ ({a | S.YofD false a = y0} ∩ {a | S.YofD true a = y1}))) refine MeasurableSet.inter ?_ (MeasurableSet.inter ?_ (MeasurableSet.inter ?_ ?_)) · exact S.measurable_DofZ false (measurableSet_singleton d0) · exact S.measurable_DofZ true (measurableSet_singleton d1) · exact S.measurable_YofD false (measurableSet_singleton y0) · exact S.measurable_YofD true (measurableSet_singleton y1)
    Causalean.PO.POBalkePearlSystem.measurableSet_latentSet · Causalean/PO/ID/Partial/BalkePearl/LatentTable.lean:57
  • latentProb_nonneg lemma — Latent type probabilities are nonnegative.
    d0 d1 y0 y1 :
    0 ≤ S.latentProb d0 d1 y0 y1
    Proof (Lean source)
    lemma latentProb_nonneg (d0 d1 y0 y1 : Bool) : 0 ≤ S.latentProb d0 d1 y0 y1 := ENNReal.toReal_nonneg
    Causalean.PO.POBalkePearlSystem.latentProb_nonneg · Causalean/PO/ID/Partial/BalkePearl/LatentTable.lean:70
  • latentProb_sum_eq_one lemma — The 16 latent sets partition Ω, so their probabilities sum to 1.
    ∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, S.latentProb d0 d1 y0 y1 = 1
    Proof (Lean source)
    lemma latentProb_sum_eq_one : ∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, S.latentProb d0 d1 y0 y1 = 1 := by -- Work with flat index type. set f : Bool × Bool × Bool × BoolSet P.Ω := fun i => S.latentSet i.1 i.2.1 i.2.2.1 i.2.2.2 have hmeas : ∀ i : Bool × Bool × Bool × Bool, MeasurableSet (f i) := fun ⟨d0, d1, y0, y1⟩ => S.measurableSet_latentSet d0 d1 y0 y1 have hdisj : Pairwise (onFun Disjoint f) := by intro ⟨d0, d1, y0, y1⟩ ⟨d0', d1', y0', y1'⟩ hne apply S.latentSet_disjoint intro h; exact absurd h hne have hcov : ⋃ i : Bool × Bool × Bool × Bool, f i = univ := S.latentSet_iUnion_prod_eq_univ -- Sum of ENNReal measures = 1. have hENNsum : ∑ i : Bool × Bool × Bool × Bool, P.μ (f i) = 1 := by have h1 := measure_iUnion (μ := P.μ) hdisj hmeas rw [hcov, measure_univ] at h1 rw [tsum_fintype] at h1 exact h1.symm -- Take .toReal of hENNsum using additivity. have hne_top : ∀ i : Bool × Bool × Bool × Bool, P.μ (f i) ≠ ⊤ := fun i => measure_ne_top _ _ have hreal : ∑ i : Bool × Bool × Bool × Bool, (P.μ (f i)).toReal = 1 := by have := congr_arg toReal hENNsum rw [ENNReal.toReal_sum (fun i _ => hne_top i)] at this simpa using this -- The nested sum equals the flat sum (latentProb = (P.μ (f ·)).toReal). have hflat : ∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, S.latentProb d0 d1 y0 y1 = ∑ i : Bool × Bool × Bool × Bool, (P.μ (f i)).toReal := by simp only [latentProb, f, ← Finset.sum_product', Finset.univ_product_univ] rw [hflat, hreal]
    Causalean.PO.POBalkePearlSystem.latentProb_sum_eq_one · Causalean/PO/ID/Partial/BalkePearl/LatentTable.lean:95
  • cellProb_eq_sum_latent theorem — Each observed conditional cell probability equals the sum of compatible latent type probabilities.
    hA :
    S.BaseAssumptions
    y d z :
    S.cellProb y d z
    = ∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, (if dArm z d0 d1 = d ∧ yArm d y0 y1 = y then 1 else 0) * S.latentProb d0 d1 y0 y1
    Proof (Lean source)
    theorem cellProb_eq_sum_latent (hA : S.BaseAssumptions) (y d z : Bool) : S.cellProb y d z = ∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, (if dArm z d0 d1 = d ∧ yArm d y0 y1 = y then 1 else 0) * S.latentProb d0 d1 y0 y1 := by -- Abbreviations. set E : Set P.Ω := S.cfCellEvent z d y with hE set T : Set (Bool × Bool × Bool × Bool) := {p | dArm z p.1 p.2.1 = d ∧ yArm d p.2.2.1 p.2.2.2 = y} with hT have hEpre : E = S.cfTuple ⁻¹' T := S.cfCellEvent_eq_preimage z d y have hT_meas : MeasurableSet T := (Set.toFinite T).measurableSet have hE_meas : MeasurableSet E := S.measurableSet_cfCellEvent z d y -- Step 1: consistency gives the set equality on numerator. have h1 : S.zEvent z ∩ S.yEvent y ∩ S.dEvent d = S.zEvent z ∩ E := S.zEvent_inter_cell_eq hA z d y -- Step 2: exogeneity factorization. have hindep : IndepFun S.factualZ S.cfTuple P.μ := S.indepFun_factualZ_cfTuple hA have hZeqEv : S.zEvent z = S.factualZ ⁻¹' {z} := rfl have h2 : P.μ (S.zEvent z ∩ E) = P.μ (S.zEvent z) * P.μ E := by rw [hEpre, hZeqEv] exact hindep.measure_inter_preimage_eq_mul {z} T (measurableSet_singleton _) hT_meas -- Step 3: decompose μ(E) over 16 latent cells. set fset : Bool × Bool × Bool × BoolSet P.Ω := fun i => S.latentSet i.1 i.2.1 i.2.2.1 i.2.2.2 with hfset have hmeas : ∀ i, MeasurableSet (fset i) := fun ⟨d0, d1, y0, y1⟩ => S.measurableSet_latentSet d0 d1 y0 y1 have hdisj : Pairwise (onFun Disjoint fset) := by intro ⟨d0, d1, y0, y1⟩ ⟨d0', d1', y0', y1'⟩ hne apply S.latentSet_disjoint; intro h; exact absurd h hne have hcov : ⋃ i, fset i = univ := S.latentSet_iUnion_prod_eq_univ -- Express μ(E) as a sum over latent cells. have hE_decomp : P.μ E = ∑ i : Bool × Bool × Bool × Bool, (if dArm z i.1 i.2.1 = d ∧ yArm d i.2.2.1 i.2.2.2 = y then 1 else 0) * P.μ (fset i) := by -- E = E ∩ univ = E ∩ ⋃ fset = ⋃ (E ∩ fset i), and disjoint. have hE_union : E = ⋃ i, E ∩ fset i := by rw [← Set.inter_iUnion, hcov, Set.inter_univ] have hdisj' : Pairwise (onFun Disjoint (fun i => E ∩ fset i)) := by intro i j hij exact (hdisj hij).inter_left' E |>.inter_right' E have hmeas' : ∀ i, MeasurableSet (E ∩ fset i) := fun i => hE_meas.inter (hmeas i) have hμsum : P.μ E = ∑ i, P.μ (E ∩ fset i) := by conv_lhs => rw [hE_union] rw [measure_iUnion hdisj' hmeas', tsum_fintype] -- For each i, E ∩ fset i = fset i if compatible, else ∅. have hcell : ∀ i, P.μ (E ∩ fset i) = (if dArm z i.1 i.2.1 = d ∧ yArm d i.2.2.1 i.2.2.2 = y then 1 else 0) * P.μ (fset i) := by rintro ⟨d0, d1, y0, y1⟩ by_cases hcompat : dArm z d0 d1 = d ∧ yArm d y0 y1 = y · -- E ⊇ fset (d0,d1,y0,y1): on latentSet, cfTuple = (d0,d1,y0,y1) and that point ∈ T. have hsub : fset (d0, d1, y0, y1) ⊆ E := by intro ω hω rw [hEpre] change S.cfTuple ω ∈ T rw [S.cfTuple_on_latentSet d0 d1 y0 y1 hω] exact hcompat rw [Set.inter_eq_right.mpr hsub] simp [hcompat] · -- Disjoint: cfTuple = (d0,d1,y0,y1) ∉ T on latentSet. have hdisjE : Disjoint E (fset (d0, d1, y0, y1)) := by rw [Set.disjoint_right] intro ω hω hωE rw [hEpre] at hωE have : S.cfTuple ω ∈ T := hωE rw [S.cfTuple_on_latentSet d0 d1 y0 y1 hω] at this exact hcompat this rw [Set.disjoint_iff_inter_eq_empty.mp hdisjE] simp [hcompat] rw [hμsum] exact Finset.sum_congr rfl (fun i _ => hcell i) -- Combine: numerator = μ(Z=z) * μ(E). have hnum : P.μ (S.zEvent z ∩ S.yEvent y ∩ S.dEvent d) = P.μ (S.zEvent z) * P.μ E := by rw [h1, h2] -- Now go to ℝ via .toReal. unfold cellProb rw [hnum, ENNReal.toReal_mul] rw [hE_decomp] -- Convert sum-toReal and divide. have hpZne : (P.μ (S.zEvent z)).toReal ≠ 0 := hA.posZ_toReal_pos z |>.ne' rw [mul_div_cancel_left₀ _ hpZne] -- Now show: (∑ i, indicator * μ(fset i)).toReal = ∑ ... * latentProb. have hne_top : ∀ i : Bool × Bool × Bool × Bool, (if dArm z i.1 i.2.1 = d ∧ yArm d i.2.2.1 i.2.2.2 = y then (1 : ENNReal) else 0) * P.μ (fset i) ≠ ⊤ := by intro i by_cases h : dArm z i.1 i.2.1 = d ∧ yArm d i.2.2.1 i.2.2.2 = y · simp [h, measure_ne_top] · simp [h] rw [ENNReal.toReal_sum (fun i _ => hne_top i)] -- Flatten Bool × Bool × Bool × Bool sum into nested Bool sums. simp_rw [Fintype.sum_prod_type] refine Finset.sum_congr rfl (fun d0 _ => ?_) refine Finset.sum_congr rfl (fun d1 _ => ?_) refine Finset.sum_congr rfl (fun y0 _ => ?_) refine Finset.sum_congr rfl (fun y1 _ => ?_) simp only [fset, latentProb] by_cases hcompat : dArm z d0 d1 = d ∧ yArm d y0 y1 = y · simp [hcompat] · simp [hcompat]
    Causalean.PO.POBalkePearlSystem.cellProb_eq_sum_latent · Causalean/PO/ID/Partial/BalkePearl/LatentTable.lean:273
Main 4 core · 2 supporting This file assembles the finite latent-type linear program for Balke-Pearl IV bounds. ★ ATE_mem_BPIdentifiedInterval

Balke-Pearl latent-table necessity theorem

This file assembles the finite latent-type linear program for Balke-Pearl IV bounds. It defines feasibility, the ATE objective, the identified objective range, proves that the realized latent table is feasible, and shows that the true ATE belongs to that range.

structure BPFeasible reviewed
Causalean.PO.POBalkePearlSystem

Balke–Pearl latent-table feasibility. A latent response-type table π — the joint distribution over the instrument's and treatment's potential values together with the outcome's potential values — is feasible for a Balke–Pearl IV system under a given assumption bundle when every table entry is nonnegative, the entries sum to one, and aggregating the table over the response types compatible with each observed instrument-treatment-outcome cell reproduces the observed conditional cell probability.

Definition (Lean source)
hA :
S.BaseAssumptions
π :
BoolBoolBoolBool → ℝ
nonneg :
∀ d0 d1 y0 y1, 0 ≤ π d0 d1 y0 y1
sum_one :
∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, π d0 d1 y0 y1 = 1
marginal :
∀ (y d z : Bool),
S.cellProb y d z
= ∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, (if dArm z d0 d1 = d ∧ yArm d y0 y1 = y then 1 else 0) * π d0 d1 y0 y1
def BPObjective reviewed
Causalean.PO.POBalkePearlSystem

The LP objective: ∑ (y1-y0) * π = ATE in the latent model.

Definition (Lean source)
noncomputable def BPObjective (π : BoolBoolBoolBool → ℝ) : ℝ := ∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, (boolToReal y1 - boolToReal y0) * π d0 d1 y0 y1
Causalean.PO.POBalkePearlSystem.BPObjective · Causalean/PO/ID/Partial/BalkePearl/Main.lean:67
def BPIdentifiedInterval reviewed
Causalean.PO.POBalkePearlSystem

The Balke-Pearl sharp identified interval for ATE.

Definition (Lean source)
noncomputable def BPIdentifiedInterval (S : POBalkePearlSystem P) (hA : S.BaseAssumptions) : Set ℝ := PartialID.IdentifiedInterval BPObjective (BPFeasible S hA)
Causalean.PO.POBalkePearlSystem.BPIdentifiedInterval · Causalean/PO/ID/Partial/BalkePearl/Main.lean:74 · uses POBalkePearlSystem , BaseAssumptions , POSystem
theorem ATE_mem_BPIdentifiedInterval reviewed
Causalean.PO.POBalkePearlSystem

Necessity. Under the Balke-Pearl IV base assumptions, the true average treatment effect lies in the Balke-Pearl identified interval.

Formal statement
hA :
S.BaseAssumptions
S.ATE ∈ S.BPIdentifiedInterval hA
Proof (Lean source)
theorem ATE_mem_BPIdentifiedInterval (hA : S.BaseAssumptions) : S.ATE ∈ S.BPIdentifiedInterval hA := by unfold BPIdentifiedInterval rw [S.ATE_eq_BPObjective hA] -- hA used here for type-checking only exact PartialID.mem_identifiedInterval (S.latentProb_feasible hA)
2 supporting declarations (lemmas, instances)
  • latentProb_feasible theorem — The actual latent type distribution latentProb is feasible.
    hA :
    S.BaseAssumptions
    BPFeasible S hA S.latentProb where nonneg
    Proof (Lean source)
    theorem latentProb_feasible (hA : S.BaseAssumptions) : BPFeasible S hA S.latentProb where nonneg := fun d0 d1 y0 y1 => S.latentProb_nonneg d0 d1 y0 y1 sum_one := S.latentProb_sum_eq_one marginal := fun y d z => S.cellProb_eq_sum_latent hA y d z
    Causalean.PO.POBalkePearlSystem.latentProb_feasible · Causalean/PO/ID/Partial/BalkePearl/Main.lean:81
  • ATE_eq_BPObjective theorem — ATE = BPObjective applied to the realized latent table.
    _hA :
    S.BaseAssumptions
    S.ATE = BPObjective S.latentProb
    Proof (Lean source)
    theorem ATE_eq_BPObjective (_hA : S.BaseAssumptions) : S.ATE = BPObjective S.latentProb := by unfold BPObjective exact S.ATE_eq_sum_latent
    Causalean.PO.POBalkePearlSystem.ATE_eq_BPObjective · Causalean/PO/ID/Partial/BalkePearl/Main.lean:90
Closed­Form 5 core · 5 supporting This file gives the explicit Balke-Pearl formulas for the endpoints of the identified interval for the average treatment effect under a binary instrument, as a maximum and a minimum of eight affine functions of the obser ★ ATE_mem_Icc_bpLower_bpUpper

Balke-Pearl bounds in closed form

This file gives the explicit Balke-Pearl formulas for the endpoints of the identified interval for the average treatment effect under a binary instrument, as a maximum and a minimum of eight affine functions of the observed cell probabilities, and proves that they bound the true effect.

def bpLowerTerm reviewed
Causalean.PO.POBalkePearlSystem

The i-th of the eight affine lower expressions in the Balke-Pearl closed form for the average treatment effect. Each is a valid lower bound on the effect, and their maximum is exactly the smallest effect compatible with the data.

Definition (Lean source)
noncomputable def bpLowerTerm (i : Fin 8) : ℝ := let p := S.cellProb match i with | 0 => p false false false + p true true false - 1 | 1 => p false false true + p true true true - 1 | 2 => p true true false + p false false true - 1 | 3 => p false false false + p true true true - 1 | 4 => p false false false + 2 * p true true false - p true false true - p true true true - 1 | 5 => 2 * p false false false + p true true false - p false false true - p false true true - 1 | 6 => -p false false false - p false true false + 2 * p false false true + p true true true - 1 | 7 => -p true false false - p true true false + p false false true + 2 * p true true true - 1
def bpUpperTerm reviewed
Causalean.PO.POBalkePearlSystem

The i-th of the eight affine upper expressions in the Balke-Pearl closed form for the average treatment effect. Each is a valid upper bound on the effect, and their minimum is exactly the largest effect compatible with the data.

Definition (Lean source)
noncomputable def bpUpperTerm (i : Fin 8) : ℝ := let p := S.cellProb match i with | 0 => 1 - p true false false - p false true false | 1 => 1 - p true false true - p false true true | 2 => 1 - p true false false - p false true true | 3 => 1 - p false true false - p true false true | 4 => 1 - p true false false - 2 * p false true false + p false false true + p false true true | 5 => 1 + p true false false + p true true false - 2 * p true false true - p false true true | 6 => 1 - 2 * p true false false - p false true false + p true false true + p true true true | 7 => 1 + p false false false + p false true false - p true false true - 2 * p false true true
def bpLower reviewed
Causalean.PO.POBalkePearlSystem

The Balke-Pearl closed-form lower endpoint: the largest of the eight lower expressions. This is the smallest average treatment effect compatible with the observed distribution under a valid binary instrument.

Definition (Lean source)
noncomputable def bpLower : ℝ := Finset.univ.sup' Finset.univ_nonempty S.bpLowerTerm
def bpUpper reviewed
Causalean.PO.POBalkePearlSystem

The Balke-Pearl closed-form upper endpoint: the smallest of the eight upper expressions. This is the largest average treatment effect compatible with the observed distribution under a valid binary instrument.

Definition (Lean source)
noncomputable def bpUpper : ℝ := Finset.univ.inf' Finset.univ_nonempty S.bpUpperTerm
theorem ATE_mem_Icc_bpLower_bpUpper reviewed
Causalean.PO.POBalkePearlSystem

The Balke-Pearl bound in closed form. Under the Balke-Pearl IV base assumptions, the true average treatment effect lies between the largest of eight closed-form lower expressions and the smallest of eight closed-form upper expressions, both computable directly from the observed cell probabilities.

Formal statement
hA :
S.BaseAssumptions
S.ATE ∈ Icc S.bpLower S.bpUpper
Proof (Lean source)
theorem ATE_mem_Icc_bpLower_bpUpper (hA : S.BaseAssumptions) : S.ATE ∈ Icc S.bpLower S.bpUpper := S.BPIdentifiedInterval_subset_Icc hA (S.ATE_mem_BPIdentifiedInterval hA)
5 supporting declarations (lemmas, instances)
Closed­Form­Attainment 3 core · 0 supporting Attainment of the Balke-Pearl closed-form endpoints ★ csInf_BPIdentifiedInterval_eq_bpLower★ csSup_BPIdentifiedInterval_eq_bpUpper★ bpLower_bpUpper_eq_csInf_csSup

Attainment of the Balke-Pearl closed-form endpoints

theorem csInf_BPIdentifiedInterval_eq_bpLower reviewed
Causalean.PO.POBalkePearlSystem

The closed-form lower endpoint is exactly the LP minimum. Under the Balke-Pearl IV base assumptions, the infimum of the Balke-Pearl identified interval equals the closed-form lower bound bpLower.

Formal statement
hA :
S.BaseAssumptions
sInf (S.BPIdentifiedInterval hA) = S.bpLower
Proof (Lean source)
theorem csInf_BPIdentifiedInterval_eq_bpLower (hA : S.BaseAssumptions) : sInf (S.BPIdentifiedInterval hA) = S.bpLower := by refine le_antisymm ?_ ?_ · exact csInf_le (S.bddBelow_BPIdentifiedInterval hA) (S.bpLower_mem_BPIdentifiedInterval hA) · refine le_csInf ⟨_, S.bpLower_mem_BPIdentifiedInterval hA⟩ ?_ rintro b ⟨x, rfl⟩ exact S.bpLower_le_BPObjective hA x.2
theorem csSup_BPIdentifiedInterval_eq_bpUpper reviewed
Causalean.PO.POBalkePearlSystem

The closed-form upper endpoint is exactly the LP maximum. Under the Balke-Pearl IV base assumptions, the supremum of the Balke-Pearl identified interval equals the closed-form upper bound bpUpper.

Formal statement
hA :
S.BaseAssumptions
sSup (S.BPIdentifiedInterval hA) = S.bpUpper
Proof (Lean source)
theorem csSup_BPIdentifiedInterval_eq_bpUpper (hA : S.BaseAssumptions) : sSup (S.BPIdentifiedInterval hA) = S.bpUpper := by refine le_antisymm ?_ ?_ · refine csSup_le ⟨_, S.bpUpper_mem_BPIdentifiedInterval hA⟩ ?_ rintro b ⟨x, rfl⟩ exact S.BPObjective_le_bpUpper hA x.2 · exact le_csSup (S.bddAbove_BPIdentifiedInterval hA) (S.bpUpper_mem_BPIdentifiedInterval hA)
theorem bpLower_bpUpper_eq_csInf_csSup reviewed
Causalean.PO.POBalkePearlSystem

The Balke-Pearl closed form is sharp. Under the Balke-Pearl IV base assumptions, the interval [bpLower, bpUpper], computed from the observed cell probabilities alone, has both endpoints attained by observationally-equivalent latent tables — equivalently, bpLower is the infimum and bpUpper is the supremum of the Balke-Pearl identified interval. So no smaller interval contains every average treatment effect compatible with the data: the bound cannot be improved without further assumptions.

Formal statement
hA :
S.BaseAssumptions
S.bpLower = sInf (S.BPIdentifiedInterval hA) ∧
S.bpUpper = sSup (S.BPIdentifiedInterval hA)
Proof (Lean source)
theorem bpLower_bpUpper_eq_csInf_csSup (hA : S.BaseAssumptions) : S.bpLower = sInf (S.BPIdentifiedInterval hA) ∧ S.bpUpper = sSup (S.BPIdentifiedInterval hA) := ⟨(S.csInf_BPIdentifiedInterval_eq_bpLower hA).symm, (S.csSup_BPIdentifiedInterval_eq_bpUpper hA).symm⟩
Interval­Form 1 core · 4 supporting This file restates the Balke-Pearl latent-table necessity result in the closed-interval vocabulary used by the partial-identification library. ★ ATE_mem_Icc_csInf_csSup

Balke-Pearl bounds in closed-interval form

This file restates the Balke-Pearl latent-table necessity result in the closed-interval vocabulary used by the partial-identification library. It proves boundedness of the linear-program objective and derives membership of the true ATE in the interval between the infimum and supremum of the feasible objective range.

theorem ATE_mem_Icc_csInf_csSup reviewed
Causalean.PO.POBalkePearlSystem

Necessity, closed-interval form. Under the Balke-Pearl IV base assumptions, the true average treatment effect lies between the infimum and supremum of the Balke-Pearl identified interval — the LP minimum and maximum. This is ATE_mem_BPIdentifiedInterval rephrased through the engine bridge Causalean.PartialID.mem_Icc_csInf_csSup.

Formal statement
hA :
S.BaseAssumptions
S.ATE ∈ Icc (sInf (S.BPIdentifiedInterval hA)) (sSup (S.BPIdentifiedInterval hA))
Proof (Lean source)
theorem ATE_mem_Icc_csInf_csSup (hA : S.BaseAssumptions) : S.ATE ∈ Icc (sInf (S.BPIdentifiedInterval hA)) (sSup (S.BPIdentifiedInterval hA)) := mem_Icc_csInf_csSup (S.bddBelow_BPIdentifiedInterval hA) (S.bddAbove_BPIdentifiedInterval hA) (S.ATE_mem_BPIdentifiedInterval hA)
4 supporting declarations (lemmas, instances)
  • BPObjective_le_one lemma — Upper bound on the objective. For a feasible (nonneg, sum-one) table π, the LP objective ∑ (y1 - y0) · π is at most 1, since every contrast is ≤ 1 and π is a probability vector.
    π :
    BoolBoolBoolBool → ℝ
    hnn :
    ∀ d0 d1 y0 y1, 0 ≤ π d0 d1 y0 y1
    hsum :
    ∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, π d0 d1 y0 y1 = 1
    BPObjective π ≤ 1
    Proof (Lean source)
    lemma BPObjective_le_one {π : BoolBoolBoolBool → ℝ} (hnn : ∀ d0 d1 y0 y1, 0 ≤ π d0 d1 y0 y1) (hsum : ∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, π d0 d1 y0 y1 = 1) : BPObjective π ≤ 1 := by unfold BPObjective refine le_of_le_of_eq (Finset.sum_le_sum fun d0 _ => Finset.sum_le_sum fun d1 _ => Finset.sum_le_sum fun y0 _ => Finset.sum_le_sum fun y1 _ => ?_) hsum exact (mul_le_mul_of_nonneg_right (boolToReal_diff_mem_Icc y0 y1).2 (hnn d0 d1 y0 y1)).trans_eq (one_mul _)
    Causalean.PO.POBalkePearlSystem.BPObjective_le_one · Causalean/PO/ID/Partial/BalkePearl/IntervalForm.lean:60
  • neg_one_le_BPObjective lemma — Lower bound on the objective. Symmetrically, -1 ≤ BPObjective π.
    π :
    BoolBoolBoolBool → ℝ
    hnn :
    ∀ d0 d1 y0 y1, 0 ≤ π d0 d1 y0 y1
    hsum :
    ∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, π d0 d1 y0 y1 = 1
    -1 ≤ BPObjective π
    Proof (Lean source)
    lemma neg_one_le_BPObjective {π : BoolBoolBoolBool → ℝ} (hnn : ∀ d0 d1 y0 y1, 0 ≤ π d0 d1 y0 y1) (hsum : ∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, π d0 d1 y0 y1 = 1) : -1 ≤ BPObjective π := by unfold BPObjective refine le_of_eq_of_le ?_ (Finset.sum_le_sum fun d0 _ => Finset.sum_le_sum fun d1 _ => Finset.sum_le_sum fun y0 _ => Finset.sum_le_sum fun y1 _ => (neg_one_mul (π d0 d1 y0 y1)).symm.trans_le (mul_le_mul_of_nonneg_right (boolToReal_diff_mem_Icc y0 y1).1 (hnn d0 d1 y0 y1))) -- Remaining goal: `-1 = ∑∑∑∑ (-(π …))`. Pull the negation out and use `hsum`. have hneg : (∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, -(π d0 d1 y0 y1)) = -(∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, π d0 d1 y0 y1) := by simp only [Finset.sum_neg_distrib] rw [hneg, hsum]
    Causalean.PO.POBalkePearlSystem.neg_one_le_BPObjective · Causalean/PO/ID/Partial/BalkePearl/IntervalForm.lean:74
  • bddBelow_BPIdentifiedInterval lemma — The Balke-Pearl identified interval is bounded below (by -1).
    hA :
    S.BaseAssumptions
    BddBelow (S.BPIdentifiedInterval hA)
    Proof (Lean source)
    lemma bddBelow_BPIdentifiedInterval (hA : S.BaseAssumptions) : BddBelow (S.BPIdentifiedInterval hA) := by refine ⟨-1, ?_⟩ rintro _ ⟨⟨π, hπ⟩, rfl⟩ exact neg_one_le_BPObjective hπ.nonneg hπ.sum_one
    Causalean.PO.POBalkePearlSystem.bddBelow_BPIdentifiedInterval · Causalean/PO/ID/Partial/BalkePearl/IntervalForm.lean:93
  • bddAbove_BPIdentifiedInterval lemma — The Balke-Pearl identified interval is bounded above (by 1).
    hA :
    S.BaseAssumptions
    BddAbove (S.BPIdentifiedInterval hA)
    Proof (Lean source)
    lemma bddAbove_BPIdentifiedInterval (hA : S.BaseAssumptions) : BddAbove (S.BPIdentifiedInterval hA) := by refine ⟨1, ?_⟩ rintro _ ⟨⟨π, hπ⟩, rfl⟩ exact BPObjective_le_one hπ.nonneg hπ.sum_one
    Causalean.PO.POBalkePearlSystem.bddAbove_BPIdentifiedInterval · Causalean/PO/ID/Partial/BalkePearl/IntervalForm.lean:100
Sharp 13 core · 32 supporting This file constructs the canonical binary-IV potential-outcome model that realizes any feasible latent table in the Balke-Pearl linear program. ★ balkePearl_sharp★ balkePearl_sharp_of_mem

Balke-Pearl Sharpness Construction

This file constructs the canonical binary-IV potential-outcome model that realizes any feasible latent table in the Balke-Pearl linear program. The model uses a binary instrument marginal from the original system and an independent four-type latent table, then verifies consistency, exclusion, exogeneity, matching observed cell probabilities, and realization of the linear-program objective as the average treatment effect. The main public results are balkePearl_sharp, which realizes any feasible table, and balkePearl_sharp_of_mem, which realizes every point of the Balke-Pearl identified interval.

abbrev SOmega reviewed
Causalean.PO.POBalkePearlSharp

The canonical sample space: a Z-value paired with the four latent arms (D(0), D(1), Y(0), Y(1)).

Definition (Lean source)
abbrev SOmega : Type := Bool × (Bool × Bool × Bool × Bool)
Causalean.PO.POBalkePearlSharp.SOmega · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:49
abbrev SV reviewed
Causalean.PO.POBalkePearlSharp

The canonical variable index type: 0 = Z, 1 = D, 2 = Y.

Definition (Lean source)
abbrev SV : Type := Fin 3
Causalean.PO.POBalkePearlSharp.SV · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:53
abbrev SX reviewed
Causalean.PO.POBalkePearlSharp

Canonical X assignment — every variable is Bool.

Definition (Lean source)
abbrev SX : SV → Type := fun _ => Bool
Causalean.PO.POBalkePearlSharp.SX · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:56 · uses SV
def dArmω reviewed
Causalean.PO.POBalkePearlSharp

The latent arm under intervention Z = z.

Definition (Lean source)
def dArmω (z : Bool) (ω : SOmega) : Bool := if z then ω.2.2.1 else ω.2.1
Causalean.PO.POBalkePearlSharp.dArmω · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:61 · uses SOmega
def yArmω reviewed
Causalean.PO.POBalkePearlSharp

The latent arm under intervention D = d.

Definition (Lean source)
def yArmω (d : Bool) (ω : SOmega) : Bool := if d then ω.2.2.2.2 else ω.2.2.2.1
Causalean.PO.POBalkePearlSharp.yArmω · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:65 · uses SOmega
def eval reviewed
Causalean.PO.POBalkePearlSharp

Canonical eval: cascade through Z → D → Y.

Definition (Lean source)
noncomputable def eval (r : Regime SV SX) (ω : SOmega) : ∀ v : SV, SX v := by classical intro v exact if hv : v ∈ r.target then r.assign v hv else match v with | ⟨0, _⟩ => ω.1 | ⟨1, _⟩ => let zEff : Bool := if h0 : (⟨0, by decide⟩ : SV) ∈ r.target then r.assign _ h0 else ω.1 dArmω zEff ω | ⟨2, _⟩ => let zEff : Bool := if h0 : (⟨0, by decide⟩ : SV) ∈ r.target then r.assign _ h0 else ω.1 let dEff : Bool := if h1 : (⟨1, by decide⟩ : SV) ∈ r.target then r.assign _ h1 else dArmω zEff ω yArmω dEff ω
def zMeasure reviewed
Causalean.PO.POBalkePearlSharp

The Z-marginal of S, viewed as a measure on Bool.

Definition (Lean source)
noncomputable def zMeasure : Measure Bool := ∑ z : Bool, P.μ (S.zEvent z) • Measure.dirac z
def piMeasure reviewed
Causalean.PO.POBalkePearlSharp

The discrete π-measure on Bool⁴ with weights π.

Definition (Lean source)
noncomputable def piMeasure (π : BoolBoolBoolBool → ℝ) : Measure (Bool × Bool × Bool × Bool) := ∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, ofReal (π d0 d1 y0 y1) • Measure.dirac (d0, d1, y0, y1)
Causalean.PO.POBalkePearlSharp.piMeasure · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:167
def canonicalMeasure reviewed
Causalean.PO.POBalkePearlSharp

Canonical product measure on SOmega.

Definition (Lean source)
noncomputable def canonicalMeasure (π : BoolBoolBoolBool → ℝ) : Measure SOmega := (zMeasure S).prod (piMeasure π)
Causalean.PO.POBalkePearlSharp.canonicalMeasure · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:173 · uses SOmega , POBalkePearlSystem , POSystem
def canonicalPOSystem reviewed
Causalean.PO.POBalkePearlSharp

The canonical PO system parametrised by S and a feasible π.

Definition (Lean source)
noncomputable def canonicalPOSystem (π : BoolBoolBoolBool → ℝ) (hπ_nn : ∀ d0 d1 y0 y1, 0 ≤ π d0 d1 y0 y1) (hπ_sum : ∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, π d0 d1 y0 y1 = 1) : POSystem := letI : IsProbabilityMeasure (piMeasure π) := instIsProbPiMeasure hπ_nn hπ_sum { V := SV X := SX Ω := SOmega μ := canonicalMeasure S π eval := eval measurable_eval := measurable_eval }
Causalean.PO.POBalkePearlSharp.canonicalPOSystem · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:271 · uses POBalkePearlSystem , POSystem
def canonicalBP reviewed
Causalean.PO.POBalkePearlSharp

The canonical Balke-Pearl system on the canonical PO system.

Definition (Lean source)
noncomputable def canonicalBP (π : BoolBoolBoolBool → ℝ) (hπ_nn : ∀ d0 d1 y0 y1, 0 ≤ π d0 d1 y0 y1) (hπ_sum : ∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, π d0 d1 y0 y1 = 1) : POBalkePearlSystem (canonicalPOSystem S π hπ_nn hπ_sum) where Z := ⟨0, by decide⟩ D := ⟨1, by decide⟩ Y := ⟨2, by decide⟩ hZbool := MeasurableEquiv.refl Bool hDbool := MeasurableEquiv.refl Bool hYbool := MeasurableEquiv.refl Bool hZD := by intro h; exact absurd (Fin.mk.inj_iff.mp h) (by decide) hZY := by intro h; exact absurd (Fin.mk.inj_iff.mp h) (by decide) hDY := by intro h; exact absurd (Fin.mk.inj_iff.mp h) (by decide)
theorem balkePearl_sharp reviewed
Causalean.PO.POBalkePearlSystem

Sharpness. Under the Balke-Pearl IV base assumptions, for a latent treatment-response table π that is feasible for the linear program — nonnegative, summing to one, and reproducing the observed cell probabilities as its marginals, there exists another potential-outcome system, satisfying the same base assumptions, whose observed cell probabilities agree with the original system's and whose average treatment effect equals the LP objective value of π: every feasible latent table is realised by some potential-outcome model.

Formal statement
hA :
S.BaseAssumptions
π :
BoolBoolBoolBool → ℝ
:
BPFeasible S hA π
∃ (P' : POSystem.{0,0,0}) (S' : POBalkePearlSystem P') (_hA' : S'.BaseAssumptions),
(∀ y d z, S'.cellProb y d z = S.cellProb y d z) ∧ S'.ATE = BPObjective π
Proof (Lean source)
theorem balkePearl_sharp (hA : S.BaseAssumptions) (π : BoolBoolBoolBool → ℝ) (hπ : BPFeasible S hA π) : ∃ (P' : POSystem.{0,0,0}) (S' : POBalkePearlSystem P') (_hA' : S'.BaseAssumptions), (∀ y d z, S'.cellProb y d z = S.cellProb y d z) ∧ S'.ATE = BPObjective π := by refine ⟨POBalkePearlSharp.canonicalPOSystem S π hπ.nonneg hπ.sum_one, POBalkePearlSharp.canonicalBP S π hπ.nonneg hπ.sum_one, POBalkePearlSharp.canonical_baseAssumptions S π hπ.nonneg hπ.sum_one hA, ?_, ?_⟩ · intros y d z exact POBalkePearlSharp.canonical_cellProb_eq S π hπ.nonneg hπ.sum_one hA hπ y d z · exact POBalkePearlSharp.canonical_ATE_eq S π hπ.nonneg hπ.sum_one hA
theorem balkePearl_sharp_of_mem reviewed
Causalean.PO.POBalkePearlSystem

Corollary of sharpness. Under the Balke-Pearl IV base assumptions, for a real number τ lying in the Balke-Pearl identified interval, there exists another potential-outcome system, satisfying the same base assumptions, whose observed cell probabilities agree with the original system's and whose average treatment effect equals τ: every value in the identified interval is the ATE of some BP-feasible model with matching observed cell probabilities.

Formal statement
hA :
S.BaseAssumptions
τ :
:
τ ∈ S.BPIdentifiedInterval hA
∃ (P' : POSystem.{0,0,0}) (S' : POBalkePearlSystem P') (_hA' : S'.BaseAssumptions),
(∀ y d z, S'.cellProb y d z = S.cellProb y d z) ∧ S'.ATE = τ
Proof (Lean source)
theorem balkePearl_sharp_of_mem (hA : S.BaseAssumptions) (τ : ℝ) (hτ : τ ∈ S.BPIdentifiedInterval hA) : ∃ (P' : POSystem.{0,0,0}) (S' : POBalkePearlSystem P') (_hA' : S'.BaseAssumptions), (∀ y d z, S'.cellProb y d z = S.cellProb y d z) ∧ S'.ATE = τ := by obtain ⟨⟨π, hπ⟩, hτπ⟩ := hτ obtain ⟨P', S', hA', hcell, hATE⟩ := S.balkePearl_sharp hA π hπ exact ⟨P', S', hA', hcell, by rw [hATE]; exact hτπ⟩
32 supporting declarations (lemmas, instances)
  • measurable_eval lemma — The canonical evaluator is measurable under every intervention regime.
    r :
    Measurable (eval r)
    Proof (Lean source)
    lemma measurable_eval (r : Regime SV SX) : Measurable (eval r) := by exact measurable_of_finite _
    Causalean.PO.POBalkePearlSharp.measurable_eval · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:92
  • eval_zero lemma — The Z-coordinate eval r ω 0: assignment if intervened on, else ω.1.
    r :
    ω :
    eval r ω ⟨0, by decide⟩
    = (if h : (⟨0, by decide⟩ : SV) ∈ r.target then r.assign _ h else ω.1)
    Proof (Lean source)
    lemma eval_zero (r : Regime SV SX) (ω : SOmega) : eval r ω ⟨0, by decide⟩ = (if h : (⟨0, by decide⟩ : SV) ∈ r.target then r.assign _ h else ω.1) := rfl
    Causalean.PO.POBalkePearlSharp.eval_zero · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:96
  • eval_one_raw lemma — The D-coordinate (raw).
    r :
    ω :
    eval r ω ⟨1, by decide⟩
    = (if h : (⟨1, by decide⟩ : SV) ∈ r.target then r.assign _ h else dArmω (if h0 : (⟨0, by decide⟩ : SV) ∈ r.target then r.assign _ h0 else ω.1) ω)
    Proof (Lean source)
    lemma eval_one_raw (r : Regime SV SX) (ω : SOmega) : eval r ω ⟨1, by decide⟩ = (if h : (⟨1, by decide⟩ : SV) ∈ r.target then r.assign _ h else dArmω (if h0 : (⟨0, by decide⟩ : SV) ∈ r.target then r.assign _ h0 else ω.1) ω) := rfl
    Causalean.PO.POBalkePearlSharp.eval_one_raw · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:101
  • eval_two_raw lemma — The Y-coordinate (raw).
    r :
    ω :
    eval r ω ⟨2, by decide⟩
    = (if h : (⟨2, by decide⟩ : SV) ∈ r.target then r.assign _ h else yArmω (if h1 : (⟨1, by decide⟩ : SV) ∈ r.target then r.assign _ h1 else dArmω (if h0 : (⟨0, by decide⟩ : SV) ∈ r.target then r.assign _ h0 else ω.1) ω) ω)
    Proof (Lean source)
    lemma eval_two_raw (r : Regime SV SX) (ω : SOmega) : eval r ω ⟨2, by decide⟩ = (if h : (⟨2, by decide⟩ : SV) ∈ r.target then r.assign _ h else yArmω (if h1 : (⟨1, by decide⟩ : SV) ∈ r.target then r.assign _ h1 else dArmω (if h0 : (⟨0, by decide⟩ : SV) ∈ r.target then r.assign _ h0 else ω.1) ω) ω) := rfl
    Causalean.PO.POBalkePearlSharp.eval_two_raw · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:108
  • eval_one lemma — The D-coordinate folded via eval_zero.
    r :
    ω :
    eval r ω ⟨1, by decide⟩
    = (if h : (⟨1, by decide⟩ : SV) ∈ r.target then r.assign _ h else dArmω (eval r ω ⟨0, by decide⟩) ω)
    Proof (Lean source)
    lemma eval_one (r : Regime SV SX) (ω : SOmega) : eval r ω ⟨1, by decide⟩ = (if h : (⟨1, by decide⟩ : SV) ∈ r.target then r.assign _ h else dArmω (eval r ω ⟨0, by decide⟩) ω) := by rw [eval_one_raw]; rfl
    Causalean.PO.POBalkePearlSharp.eval_one · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:118
  • eval_two lemma — The Y-coordinate folded via eval_one.
    r :
    ω :
    eval r ω ⟨2, by decide⟩
    = (if h : (⟨2, by decide⟩ : SV) ∈ r.target then r.assign _ h else yArmω (eval r ω ⟨1, by decide⟩) ω)
    Proof (Lean source)
    lemma eval_two (r : Regime SV SX) (ω : SOmega) : eval r ω ⟨2, by decide⟩ = (if h : (⟨2, by decide⟩ : SV) ∈ r.target then r.assign _ h else yArmω (eval r ω ⟨1, by decide⟩) ω) := by rw [eval_two_raw]; rfl
    Causalean.PO.POBalkePearlSharp.eval_two · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:125
  • zMeasure_univ lemma — zMeasure S has total mass 1.
    (zMeasure S) univ = 1
    Proof (Lean source)
    lemma zMeasure_univ : (zMeasure S) univ = 1 := by unfold zMeasure rw [Measure.coe_finset_sum] simp only [Finset.sum_apply, Measure.coe_smul, Pi.smul_apply, smul_eq_mul] simp only [Measure.dirac_apply' _ MeasurableSet.univ, Set.indicator_univ, Pi.one_apply, mul_one] have hpart : (S.zEvent false) ∪ (S.zEvent true) = univ := by ext ω refine ⟨fun _ => trivial, fun _ => ?_⟩ cases h : S.zVar.factual ω · exact Or.inl h · exact Or.inr h have hdisj : Disjoint (S.zEvent false) (S.zEvent true) := by rw [Set.disjoint_left]; intro ω h1 h2 have h1' : S.zVar.factual ω = false := h1 have h2' : S.zVar.factual ω = true := h2 rw [h1'] at h2'; exact Bool.false_ne_true h2' have hmeas_t : MeasurableSet (S.zEvent true) := S.measurableSet_zEvent _ have hadd : P.μ (S.zEvent false) + P.μ (S.zEvent true) = P.μ univ := by rw [← measure_union hdisj hmeas_t, hpart] rw [Fintype.sum_bool, add_comm, hadd, measure_univ]
    Causalean.PO.POBalkePearlSharp.zMeasure_univ · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:180
  • instIsProbZMeasure instance — The original instrument marginal is a probability measure.
    instance instIsProbZMeasure : IsProbabilityMeasure (zMeasure S) := ⟨zMeasure_univ S⟩
    Causalean.PO.POBalkePearlSharp.instIsProbZMeasure · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:203
  • piMeasure_univ_of_feasible lemma — piMeasure π has total mass 1 when π has nonneg entries summing to 1.
    π :
    BoolBoolBoolBool → ℝ
    hπ_nn :
    ∀ d0 d1 y0 y1, 0 ≤ π d0 d1 y0 y1
    hπ_sum :
    ∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, π d0 d1 y0 y1 = 1
    (piMeasure π) univ = 1
    Proof (Lean source)
    lemma piMeasure_univ_of_feasible {π : BoolBoolBoolBool → ℝ} (hπ_nn : ∀ d0 d1 y0 y1, 0 ≤ π d0 d1 y0 y1) (hπ_sum : ∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, π d0 d1 y0 y1 = 1) : (piMeasure π) univ = 1 := by unfold piMeasure -- Reduce iterated sum measure applied to univ to iterated sum of weights. simp only [Measure.coe_finset_sum, Finset.sum_apply, Measure.coe_smul, Pi.smul_apply, smul_eq_mul, Measure.dirac_apply' _ MeasurableSet.univ, Set.indicator_univ, Pi.one_apply, mul_one] -- Now goal: ∑ d0 ∑ d1 ∑ y0 ∑ y1, ofReal (π d0 d1 y0 y1) = 1 have h1 : ∀ d0 d1 y0, ∑ y1 : Bool, ofReal (π d0 d1 y0 y1) = ofReal (∑ y1 : Bool, π d0 d1 y0 y1) := by intros d0 d1 y0 rw [ENNReal.ofReal_sum_of_nonneg] intro y1 _; exact hπ_nn _ _ _ _ have h2 : ∀ d0 d1, ∑ y0 : Bool, ∑ y1 : Bool, ofReal (π d0 d1 y0 y1) = ofReal (∑ y0 : Bool, ∑ y1 : Bool, π d0 d1 y0 y1) := by intros d0 d1 simp_rw [h1] rw [ENNReal.ofReal_sum_of_nonneg] intro y0 _; exact sum_nonneg fun y1 _ => hπ_nn _ _ _ _ have h3 : ∀ d0, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, ofReal (π d0 d1 y0 y1) = ofReal (∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, π d0 d1 y0 y1) := by intros d0 simp_rw [h2] rw [ENNReal.ofReal_sum_of_nonneg] intro d1 _ exact sum_nonneg fun y0 _ => sum_nonneg fun y1 _ => hπ_nn _ _ _ _ have h4 : ∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, ofReal (π d0 d1 y0 y1) = ofReal (∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, π d0 d1 y0 y1) := by simp_rw [h3] rw [ENNReal.ofReal_sum_of_nonneg] intro d0 _ exact sum_nonneg fun d1 _ => sum_nonneg fun y0 _ => sum_nonneg fun y1 _ => hπ_nn _ _ _ _ rw [h4, hπ_sum] simp
    Causalean.PO.POBalkePearlSharp.piMeasure_univ_of_feasible · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:207
  • instIsProbPiMeasure lemma — A nonnegative latent table that sums to one induces a probability measure.
    π :
    BoolBoolBoolBool → ℝ
    hπ_nn :
    ∀ d0 d1 y0 y1, 0 ≤ π d0 d1 y0 y1
    hπ_sum :
    ∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, π d0 d1 y0 y1 = 1
    Proof (Lean source)
    lemma instIsProbPiMeasure {π : BoolBoolBoolBool → ℝ} (hπ_nn : ∀ d0 d1 y0 y1, 0 ≤ π d0 d1 y0 y1) (hπ_sum : ∑ d0 : Bool, ∑ d1 : Bool, ∑ y0 : Bool, ∑ y1 : Bool, π d0 d1 y0 y1 = 1) : IsProbabilityMeasure (piMeasure π) := ⟨piMeasure_univ_of_feasible hπ_nn hπ_sum⟩
    Causalean.PO.POBalkePearlSharp.instIsProbPiMeasure · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:254
  • instIsProbCanonicalMeasure instance — The product of the instrument marginal and latent-table measure is a probability measure.
    instance instIsProbCanonicalMeasure {π : BoolBoolBoolBool → ℝ} [IsProbabilityMeasure (piMeasure π)] : IsProbabilityMeasure (canonicalMeasure S π) := by unfold canonicalMeasure; infer_instance
    Causalean.PO.POBalkePearlSharp.instIsProbCanonicalMeasure · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:264
  • canonical_consistency lemma — Consistency for the canonical PO system.
    (P' S π hπ_nn hπ_sum).Consistency
    Proof (Lean source)
    lemma canonical_consistency : (P' S π hπ_nn hπ_sum).Consistency := by refine ⟨?_, ?_⟩ · -- Factual consistency. intro r Y hYr ω hFA funext v -- v : {x // x ∈ Y} have hv_notr : v.val ∉ r.target := fun hvr => Finset.disjoint_left.mp hYr v.property hvr -- Show eval r ω v = eval Regime.empty ω v. change eval r ω v.val = eval Regime.empty ω v.val -- Case-split on v.val : Fin 3. -- We'll use eval_zero/eval_one/eval_two and Regime.empty_target. rcases v with ⟨v, hvY⟩ -- v : Fin 3. Match on Fin 3 with three cases. have hne_empty0 : (⟨0, by decide⟩ : SV) ∉ (Regime.empty : Regime SV SX).target := by rw [Regime.empty_target]; exact Finset.notMem_empty _ have hne_empty1 : (⟨1, by decide⟩ : SV) ∉ (Regime.empty : Regime SV SX).target := by rw [Regime.empty_target]; exact Finset.notMem_empty _ have hne_empty2 : (⟨2, by decide⟩ : SV) ∉ (Regime.empty : Regime SV SX).target := by rw [Regime.empty_target]; exact Finset.notMem_empty _ fin_cases v · -- v = ⟨0, _⟩ have hv0_notr : (⟨0, by decide⟩ : SV) ∉ r.target := hv_notr rw [eval_zero_of_not_mem r ω hv0_notr, eval_zero_of_not_mem (Regime.empty : Regime SV SX) ω hne_empty0] · -- v = ⟨1, _⟩ have hv1_notr : (⟨1, by decide⟩ : SV) ∉ r.target := hv_notr rw [eval_one_of_not_mem r ω hv1_notr, eval_one_of_not_mem (Regime.empty : Regime SV SX) ω hne_empty1] have hzEq : eval r ω ⟨0, by decide⟩ = eval Regime.empty ω ⟨0, by decide⟩ := by by_cases h0 : (⟨0, by decide⟩ : SV) ∈ r.target · exact (eval_zero_of_mem r ω h0).trans (hFA _ h0).symm · rw [eval_zero_of_not_mem r ω h0, eval_zero_of_not_mem (Regime.empty : Regime SV SX) ω hne_empty0] exact congrArg (fun z => dArmω z ω) hzEq · -- v = ⟨2, _⟩ have hv2_notr : (⟨2, by decide⟩ : SV) ∉ r.target := hv_notr rw [eval_two_of_not_mem r ω hv2_notr, eval_two_of_not_mem (Regime.empty : Regime SV SX) ω hne_empty2] have hzEq : eval r ω ⟨0, by decide⟩ = eval Regime.empty ω ⟨0, by decide⟩ := by by_cases h0 : (⟨0, by decide⟩ : SV) ∈ r.target · exact (eval_zero_of_mem r ω h0).trans (hFA _ h0).symm · rw [eval_zero_of_not_mem r ω h0, eval_zero_of_not_mem (Regime.empty : Regime SV SX) ω hne_empty0] have hdEq : eval r ω ⟨1, by decide⟩ = eval Regime.empty ω ⟨1, by decide⟩ := by by_cases h1 : (⟨1, by decide⟩ : SV) ∈ r.target · exact (eval_one_of_mem r ω h1).trans (hFA _ h1).symm · rw [eval_one_of_not_mem r ω h1, eval_one_of_not_mem (Regime.empty : Regime SV SX) ω hne_empty1] exact congrArg (fun z => dArmω z ω) hzEq exact congrArg (fun d => yArmω d ω) hdEq · -- Composition. intro r₁ r₂ hd Y hY ω hIA -- Helper: agreement of `eval (r₁⊔r₂) ω` with `eval r₁ ω` at the Z-coord. have hzEq : eval (r₁.sqcup r₂ hd) ω ⟨0, by decide⟩ = eval r₁ ω ⟨0, by decide⟩ := by by_cases h01 : (⟨0, by decide⟩ : SV) ∈ r₁.target · have h0sq : (⟨0, by decide⟩ : SV) ∈ (r₁.sqcup r₂ hd).target := mem_union_left _ h01 exact (eval_zero_of_mem (r₁.sqcup r₂ hd) ω h0sq).trans ((sqcup_assign_left r₁ r₂ hd _ h01 h0sq).trans (eval_zero_of_mem r₁ ω h01).symm) · by_cases h02 : (⟨0, by decide⟩ : SV) ∈ r₂.target · have h0sq : (⟨0, by decide⟩ : SV) ∈ (r₁.sqcup r₂ hd).target := mem_union_right _ h02 exact (eval_zero_of_mem (r₁.sqcup r₂ hd) ω h0sq).trans ((sqcup_assign_right r₁ r₂ hd _ h01 h02 h0sq).trans (hIA _ h02).symm) · have h0sq : (⟨0, by decide⟩ : SV) ∉ (r₁.sqcup r₂ hd).target := by rw [Regime.sqcup_target]; intro h rcases Finset.mem_union.mp h with h | h · exact h01 h · exact h02 h rw [eval_zero_of_not_mem (r₁.sqcup r₂ hd) ω h0sq, eval_zero_of_not_mem r₁ ω h01] -- Helper: agreement at the D-coord. have hdEq : eval (r₁.sqcup r₂ hd) ω ⟨1, by decide⟩ = eval r₁ ω ⟨1, by decide⟩ := by by_cases h11 : (⟨1, by decide⟩ : SV) ∈ r₁.target · have h1sq : (⟨1, by decide⟩ : SV) ∈ (r₁.sqcup r₂ hd).target := mem_union_left _ h11 exact (eval_one_of_mem (r₁.sqcup r₂ hd) ω h1sq).trans ((sqcup_assign_left r₁ r₂ hd _ h11 h1sq).trans (eval_one_of_mem r₁ ω h11).symm) · by_cases h12 : (⟨1, by decide⟩ : SV) ∈ r₂.target · have h1sq : (⟨1, by decide⟩ : SV) ∈ (r₁.sqcup r₂ hd).target := mem_union_right _ h12 exact (eval_one_of_mem (r₁.sqcup r₂ hd) ω h1sq).trans ((sqcup_assign_right r₁ r₂ hd _ h11 h12 h1sq).trans (hIA _ h12).symm) · have h1sq : (⟨1, by decide⟩ : SV) ∉ (r₁.sqcup r₂ hd).target := by rw [Regime.sqcup_target]; intro h rcases Finset.mem_union.mp h with h | h · exact h11 h · exact h12 h rw [eval_one_of_not_mem (r₁.sqcup r₂ hd) ω h1sq, eval_one_of_not_mem r₁ ω h11] exact congrArg (fun z => dArmω z ω) hzEq funext v rcases v with ⟨v, hvY⟩ have hv_notr : v ∉ r₁.target ∪ r₂.target := Finset.disjoint_left.mp hY hvY have hv_notr1 : v ∉ r₁.target := fun h => hv_notr (mem_union_left _ h) have hv_not_sqcup : v ∉ (r₁.sqcup r₂ hd).target := by rw [Regime.sqcup_target]; exact hv_notr change eval (r₁.sqcup r₂ hd) ω v = eval r₁ ω v fin_cases v · exact hzEq · have hv1_not_sqcup : (⟨1, by decide⟩ : SV) ∉ (r₁.sqcup r₂ hd).target := hv_not_sqcup have hv1_notr1 : (⟨1, by decide⟩ : SV) ∉ r₁.target := hv_notr1 rw [eval_one_of_not_mem (r₁.sqcup r₂ hd) ω hv1_not_sqcup, eval_one_of_not_mem r₁ ω hv1_notr1] exact congrArg (fun z => dArmω z ω) hzEq · have hv2_not_sqcup : (⟨2, by decide⟩ : SV) ∉ (r₁.sqcup r₂ hd).target := hv_not_sqcup have hv2_notr1 : (⟨2, by decide⟩ : SV) ∉ r₁.target := hv_notr1 rw [eval_two_of_not_mem (r₁.sqcup r₂ hd) ω hv2_not_sqcup, eval_two_of_not_mem r₁ ω hv2_notr1] exact congrArg (fun d => yArmω d ω) hdEq
    Causalean.PO.POBalkePearlSharp.canonical_consistency · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:333
  • canonical_factualZ lemma — S'.factualZ ω = ω.1.
    ω :
    (S' S π hπ_nn hπ_sum).factualZ ω = ω.1
    Proof (Lean source)
    lemma canonical_factualZ (ω : SOmega) : (S' S π hπ_nn hπ_sum).factualZ ω = ω.1 := by change (eval Regime.empty ω ⟨0, by decide⟩) = ω.1 rw [eval_zero] have : (⟨0, by decide⟩ : SV) ∉ (Regime.empty : Regime SV SX).target := by rw [Regime.empty_target]; exact notMem_empty _ rw [dif_neg this]
    Causalean.PO.POBalkePearlSharp.canonical_factualZ · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:455
  • canonical_factualD lemma — S'.factualD ω = D(ω.1).
    ω :
    (S' S π hπ_nn hπ_sum).factualD ω = dArmω ω.1 ω
    Proof (Lean source)
    lemma canonical_factualD (ω : SOmega) : (S' S π hπ_nn hπ_sum).factualD ω = dArmω ω.1 ω := by change (eval Regime.empty ω ⟨1, by decide⟩) = dArmω ω.1 ω rw [eval_one] have h1nin : (⟨1, by decide⟩ : SV) ∉ (Regime.empty : Regime SV SX).target := by rw [Regime.empty_target]; exact notMem_empty _ rw [dif_neg h1nin] have h0nin : (⟨0, by decide⟩ : SV) ∉ (Regime.empty : Regime SV SX).target := by rw [Regime.empty_target]; exact notMem_empty _ rw [eval_zero, dif_neg h0nin]
    Causalean.PO.POBalkePearlSharp.canonical_factualD · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:464
  • canonical_factualY lemma — S'.factualY ω = Y(D(ω.1)).
    ω :
    (S' S π hπ_nn hπ_sum).factualY ω = yArmω (dArmω ω.1 ω) ω
    Proof (Lean source)
    lemma canonical_factualY (ω : SOmega) : (S' S π hπ_nn hπ_sum).factualY ω = yArmω (dArmω ω.1 ω) ω := by change (eval Regime.empty ω ⟨2, by decide⟩) = yArmω (dArmω ω.1 ω) ω rw [eval_two] have h2nin : (⟨2, by decide⟩ : SV) ∉ (Regime.empty : Regime SV SX).target := by rw [Regime.empty_target]; exact Finset.notMem_empty _ rw [dif_neg h2nin] have h0nin : (⟨0, by decide⟩ : SV) ∉ (Regime.empty : Regime SV SX).target := by rw [Regime.empty_target]; exact Finset.notMem_empty _ have h1nin : (⟨1, by decide⟩ : SV) ∉ (Regime.empty : Regime SV SX).target := by rw [Regime.empty_target]; exact Finset.notMem_empty _ rw [eval_one, dif_neg h1nin, eval_zero, dif_neg h0nin]
    Causalean.PO.POBalkePearlSharp.canonical_factualY · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:476
  • canonical_DofZ lemma — S'.DofZ z ω = (POBalkePearlSystem.dArm) z ω.2.1 ω.2.2.1.
    z :
    ω :
    (S' S π hπ_nn hπ_sum).DofZ z ω = POBalkePearlSystem.dArm z ω.2.1 ω.2.2.1
    Proof (Lean source)
    lemma canonical_DofZ (z : Bool) (ω : SOmega) : (S' S π hπ_nn hπ_sum).DofZ z ω = POBalkePearlSystem.dArm z ω.2.1 ω.2.2.1 := by change (eval (Regime.single (X := SX) ⟨0, by decide⟩ z) ω ⟨1, by decide⟩) = _ rw [eval_one] have h1nin : (⟨1, by decide⟩ : SV) ∉ (Regime.single (X := SX) (⟨0, by decide⟩ : SV) z).target := by rw [Regime.single_target]; intro h exact absurd (Finset.mem_singleton.mp h) (by decide) have h0in : (⟨0, by decide⟩ : SV) ∈ (Regime.single (X := SX) (⟨0, by decide⟩ : SV) z).target := by rw [Regime.single_target]; exact mem_singleton_self _ rw [dif_neg h1nin, eval_zero, dif_pos h0in, Regime.single_assign_self] unfold dArmω POBalkePearlSystem.dArm cases z <;> rfl
    Causalean.PO.POBalkePearlSharp.canonical_DofZ · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:490
  • canonical_YofD lemma — S'.YofD d ω = (POBalkePearlSystem.yArm) d ω.2.2.2.1 ω.2.2.2.2.
    d :
    ω :
    (S' S π hπ_nn hπ_sum).YofD d ω = POBalkePearlSystem.yArm d ω.2.2.2.1 ω.2.2.2.2
    Proof (Lean source)
    lemma canonical_YofD (d : Bool) (ω : SOmega) : (S' S π hπ_nn hπ_sum).YofD d ω = POBalkePearlSystem.yArm d ω.2.2.2.1 ω.2.2.2.2 := by change (eval (Regime.single (X := SX) ⟨1, by decide⟩ d) ω ⟨2, by decide⟩) = _ rw [eval_two] have h2nin : (⟨2, by decide⟩ : SV) ∉ (Regime.single (X := SX) (⟨1, by decide⟩ : SV) d).target := by rw [Regime.single_target]; intro h exact absurd (Finset.mem_singleton.mp h) (by decide) have h1in : (⟨1, by decide⟩ : SV) ∈ (Regime.single (X := SX) (⟨1, by decide⟩ : SV) d).target := by rw [Regime.single_target]; exact mem_singleton_self _ rw [dif_neg h2nin, eval_one, dif_pos h1in, Regime.single_assign_self] unfold yArmω POBalkePearlSystem.yArm cases d <;> rfl
    Causalean.PO.POBalkePearlSharp.canonical_YofD · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:507
  • canonical_YofZD lemma — S'.YofZD z d ω = (POBalkePearlSystem.yArm) d ω.2.2.2.1 ω.2.2.2.2.
    z d :
    ω :
    (S' S π hπ_nn hπ_sum).YofZD z d ω = POBalkePearlSystem.yArm d ω.2.2.2.1 ω.2.2.2.2
    Proof (Lean source)
    lemma canonical_YofZD (z d : Bool) (ω : SOmega) : (S' S π hπ_nn hπ_sum).YofZD z d ω = POBalkePearlSystem.yArm d ω.2.2.2.1 ω.2.2.2.2 := by -- Unfold YofZD to show eval at the regimeZD. have hZ_eq : (S' S π hπ_nn hπ_sum).Z = (⟨0, by decide⟩ : SV) := rfl have hD_eq : (S' S π hπ_nn hπ_sum).D = (⟨1, by decide⟩ : SV) := rfl have h2nin : (⟨2, by decide⟩ : SV) ∉ ((S' S π hπ_nn hπ_sum).regimeZD z d).target := by unfold POBalkePearlSystem.regimeZD rw [Regime.sqcup_target, Regime.single_target, Regime.single_target, hZ_eq, hD_eq] intro h rcases Finset.mem_union.mp h with h | h · exact absurd (Finset.mem_singleton.mp h) (by decide) · exact absurd (Finset.mem_singleton.mp h) (by decide) have h1in : (⟨1, by decide⟩ : SV) ∈ ((S' S π hπ_nn hπ_sum).regimeZD z d).target := by unfold POBalkePearlSystem.regimeZD rw [Regime.sqcup_target] refine mem_union_right _ ?_ rw [Regime.single_target, hD_eq] exact Finset.mem_singleton_self _ -- The assign for D is `d`. have h11 : (⟨1, by decide⟩ : SV) ∉ (Regime.single (X := SX) (⟨0, by decide⟩ : SV) z).target := by rw [Regime.single_target]; intro h exact absurd (Finset.mem_singleton.mp h) (by decide) have h12 : (⟨1, by decide⟩ : SV) ∈ (Regime.single (X := SX) (⟨1, by decide⟩ : SV) d).target := Finset.mem_singleton_self _ have hAssignD : ((S' S π hπ_nn hπ_sum).regimeZD z d).assign ⟨1, by decide⟩ h1in = d := by change ((Regime.single (X := SX) (⟨0, by decide⟩ : SV) z).sqcup (Regime.single (X := SX) (⟨1, by decide⟩ : SV) d) _).assign _ h1in = d rw [sqcup_assign_right _ _ _ _ h11 h12 h1in, Regime.single_assign_self] change (eval ((S' S π hπ_nn hπ_sum).regimeZD z d) ω ⟨2, by decide⟩) = _ rw [eval_two_of_not_mem _ _ h2nin, eval_one_of_mem _ _ h1in, hAssignD] unfold yArmω POBalkePearlSystem.yArm cases d <;> rfl
    Causalean.PO.POBalkePearlSharp.canonical_YofZD · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:524
  • canonical_exclusion lemma — Exclusion: Y(z,d) = Y(d) pointwise (and so a.e.).
    z d :
    (S' S π hπ_nn hπ_sum).YofZD z d = (S' S π hπ_nn hπ_sum).YofD d
    Proof (Lean source)
    lemma canonical_exclusion (z d : Bool) : (S' S π hπ_nn hπ_sum).YofZD z d = (S' S π hπ_nn hπ_sum).YofD d := by funext ω exact (canonical_YofZD S π hπ_nn hπ_sum z d ω).trans (canonical_YofD S π hπ_nn hπ_sum d ω).symm
    Causalean.PO.POBalkePearlSharp.canonical_exclusion · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:563
  • canonical_zEvent lemma — The Z-event in the canonical model is {ω | ω.1 = z}.
    z :
    (S' S π hπ_nn hπ_sum).zEvent z = {ω : SOmega | ω.1 = z}
    Proof (Lean source)
    lemma canonical_zEvent (z : Bool) : (S' S π hπ_nn hπ_sum).zEvent z = {ω : SOmega | ω.1 = z} := by ext ω change (S' S π hπ_nn hπ_sum).factualZ ω = z ↔ ω.1 = z exact of_eq (congrArg (fun t => t = z) (canonical_factualZ S π hπ_nn hπ_sum ω))
    Causalean.PO.POBalkePearlSharp.canonical_zEvent · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:571
  • canonical_zEvent_measure lemma — μ' (S'.zEvent z) = P.μ (S.zEvent z).
    z :
    (P' S π hπ_nn hπ_sum).μ ((S' S π hπ_nn hπ_sum).zEvent z) = P.μ (S.zEvent z)
    Proof (Lean source)
    lemma canonical_zEvent_measure (z : Bool) : (P' S π hπ_nn hπ_sum).μ ((S' S π hπ_nn hπ_sum).zEvent z) = P.μ (S.zEvent z) := by rw [canonical_zEvent] change (canonicalMeasure S π) {ω : SOmega | ω.1 = z} = P.μ (S.zEvent z) unfold canonicalMeasure -- Use Measure.prod_apply for {ω | ω.1 = z} = {z} ×ˢ Set.univ. have hsetEq : {ω : SOmega | ω.1 = z} = {z} ×ˢ (Set.univ : Set (Bool × Bool × Bool × Bool)) := by ext ω; simp [Set.mem_prod, Set.mem_singleton_iff] letI : IsProbabilityMeasure (piMeasure π) := instIsProbPiMeasure hπ_nn hπ_sum rw [hsetEq, Measure.prod_prod] -- piMeasure univ = 1 rw [piMeasure_univ_of_feasible hπ_nn hπ_sum, mul_one] -- zMeasure {z} = P.μ (S.zEvent z) unfold zMeasure rw [Measure.coe_finset_sum] simp only [Finset.sum_apply, Measure.coe_smul, Pi.smul_apply, smul_eq_mul] -- ∑ z' : Bool, P.μ (S.zEvent z') * Measure.dirac z' {z} rw [Fintype.sum_bool] -- Cases on z. cases z · simp [Measure.dirac_apply' _ (MeasurableSet.singleton false)] · simp [Measure.dirac_apply' _ (MeasurableSet.singleton true)]
    Causalean.PO.POBalkePearlSharp.canonical_zEvent_measure · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:579
  • canonical_posZ lemma — Positive Z probability.
    hA :
    S.BaseAssumptions
    z :
    0 < (P' S π hπ_nn hπ_sum).μ ((S' S π hπ_nn hπ_sum).zVar.event z)
    Proof (Lean source)
    lemma canonical_posZ (hA : S.BaseAssumptions) (z : Bool) : 0 < (P' S π hπ_nn hπ_sum).μ ((S' S π hπ_nn hπ_sum).zVar.event z) := by change 0 < (P' S π hπ_nn hπ_sum).μ ((S' S π hπ_nn hπ_sum).zEvent z) rw [canonical_zEvent_measure] exact hA.posZ z
    Causalean.PO.POBalkePearlSharp.canonical_posZ · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:604
  • canonical_factualZ_eq_fst lemma — The factualZ on the canonical model factors through Prod.fst.
    (S' S π hπ_nn hπ_sum).factualZ = fun ω : SOmega => ω.1
    Proof (Lean source)
    lemma canonical_factualZ_eq_fst : (S' S π hπ_nn hπ_sum).factualZ = fun ω : SOmega => ω.1 := by funext ω; exact canonical_factualZ S π hπ_nn hπ_sum ω
    Causalean.PO.POBalkePearlSharp.canonical_factualZ_eq_fst · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:613
  • canonical_cfBundle_factors_through_snd lemma — The cfBundle's jointValue factors through Prod.snd: it depends only on the latent factor.
    ∃ g : (Bool × Bool × Bool × Bool) → (∀ i : Fin (S' S π hπ_nn hπ_sum).cfBundle.n, (S' S π hπ_nn hπ_sum).cfBundle.type i),
    Measurable g ∧ (S' S π hπ_nn hπ_sum).cfBundle.jointValue = (fun ω : SOmega => g ω.2)
    Proof (Lean source)
    lemma canonical_cfBundle_factors_through_snd : ∃ g : (Bool × Bool × Bool × Bool) → (∀ i : Fin (S' S π hπ_nn hπ_sum).cfBundle.n, (S' S π hπ_nn hπ_sum).cfBundle.type i), Measurable g ∧ (S' S π hπ_nn hπ_sum).cfBundle.jointValue = (fun ω : SOmega => g ω.2) := by refine ⟨fun p i => ?_, ?_, ?_⟩ · -- The bundle has 4 components: (D(false), D(true), Y(false), Y(true)). -- D(z) ω = dArm z ω.2.1 ω.2.2.1; Y(d) ω = yArm d ω.2.2.2.1 ω.2.2.2.2. -- We can express the value purely from p = ω.2. refine i.cases (motive := fun i => (S' S π hπ_nn hπ_sum).cfBundle.type i) (POBalkePearlSystem.dArm false p.1 p.2.1) ?_ intro j refine j.cases (motive := fun j => (S' S π hπ_nn hπ_sum).cfBundle.type j.succ) (POBalkePearlSystem.dArm true p.1 p.2.1) ?_ intro k refine k.cases (motive := fun k => (S' S π hπ_nn hπ_sum).cfBundle.type k.succ.succ) (POBalkePearlSystem.yArm false p.2.2.1 p.2.2.2) ?_ intro l refine l.cases (motive := fun l => (S' S π hπ_nn hπ_sum).cfBundle.type l.succ.succ.succ) (POBalkePearlSystem.yArm true p.2.2.1 p.2.2.2) ?_ exact fun m => Fin.elim0 m · exact measurable_of_finite _ · funext ω i change (S' S π hπ_nn hπ_sum).cfBundle.jointValue ω i = _ -- Case split on i : Fin 4. fin_cases i · -- D(false) ω = dArm false ω.2.1 ω.2.2.1 exact (canonical_DofZ S π hπ_nn hπ_sum false ω).trans rfl · -- D(true) ω = dArm true ω.2.1 ω.2.2.1 exact (canonical_DofZ S π hπ_nn hπ_sum true ω).trans rfl · -- Y(false) ω = yArm false ω.2.2.2.1 ω.2.2.2.2 exact (canonical_YofD S π hπ_nn hπ_sum false ω).trans rfl · -- Y(true) ω = yArm true ω.2.2.2.1 ω.2.2.2.2 exact (canonical_YofD S π hπ_nn hπ_sum true ω).trans rfl
    Causalean.PO.POBalkePearlSharp.canonical_cfBundle_factors_through_snd · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:618
  • canonical_exogeneity lemma — Exogeneity: Z ⊥ cfBundle under the canonical product measure.
    (P' S π hπ_nn hπ_sum).IndepCF (.ofFactual (S' S π hπ_nn hπ_sum).zVar) (S' S π hπ_nn hπ_sum).cfBundle (P' S π hπ_nn hπ_sum).μ
    Proof (Lean source)
    lemma canonical_exogeneity : (P' S π hπ_nn hπ_sum).IndepCF (.ofFactual (S' S π hπ_nn hπ_sum).zVar) (S' S π hπ_nn hπ_sum).cfBundle (P' S π hπ_nn hπ_sum).μ := by -- Unfold IndepCF to IndepFun. unfold POSystem.IndepCF -- Pick X = id : BoolBool, Y = g (above). obtain ⟨g, hg_meas, hg⟩ := canonical_cfBundle_factors_through_snd S π hπ_nn hπ_sum -- factualZ = ω.1, cfBundle.jointValue = g ∘ ω.2. have hZeq : (RegimedVar.ofFactual (S' S π hπ_nn hπ_sum).zVar).value = fun ω : SOmega => ω.1 := by funext ω change (S' S π hπ_nn hπ_sum).zVar.factual ω = ω.1 exact canonical_factualZ S π hπ_nn hπ_sum ω rw [hZeq, hg] -- The product measure independence theorem. letI : IsProbabilityMeasure (piMeasure π) := instIsProbPiMeasure hπ_nn hπ_sum change IndepFun (fun ω : SOmega => ω.1) (fun ω : SOmega => g ω.2) ((zMeasure S).prod (piMeasure π)) exact ProbabilityTheory.indepFun_prod measurable_id hg_meas
    Causalean.PO.POBalkePearlSharp.canonical_exogeneity · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:665
  • canonical_baseAssumptions lemma — Bundle the canonical model's BaseAssumptions.
    hA :
    S.BaseAssumptions
    (S' S π hπ_nn hπ_sum).BaseAssumptions where consistency_D
    Proof (Lean source)
    lemma canonical_baseAssumptions (hA : S.BaseAssumptions) : (S' S π hπ_nn hπ_sum).BaseAssumptions where consistency_D := by intro z ω hω rw [canonical_DofZ S π hπ_nn hπ_sum z ω, canonical_factualD S π hπ_nn hπ_sum ω] have hz : ω.1 = z := by have hset := canonical_zEvent S π hπ_nn hπ_sum z change ω ∈ (S' S π hπ_nn hπ_sum).zEvent z at hω rw [hset] at hω exact hω rw [hz] unfold dArmω POBalkePearlSystem.dArm rfl consistency_Y := by intro d ω hω rw [canonical_YofD S π hπ_nn hπ_sum d ω, canonical_factualY S π hπ_nn hπ_sum ω] have hd : dArmω ω.1 ω = d := by change (S' S π hπ_nn hπ_sum).factualD ω = d at hω rw [canonical_factualD S π hπ_nn hπ_sum ω] at hω exact hω rw [hd] unfold yArmω POBalkePearlSystem.yArm rfl exclusion := fun z d => by rw [canonical_exclusion] exogeneity := canonical_exogeneity S π hπ_nn hπ_sum posZ := canonical_posZ S π hπ_nn hπ_sum hA
    Causalean.PO.POBalkePearlSharp.canonical_baseAssumptions · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:689
  • piMeasure_singleton lemma — piMeasure π {(d0, d1, y0, y1)} = ENNReal.ofReal (π d0 d1 y0 y1).
    d0 d1 y0 y1 :
    piMeasure π {(d0, d1, y0, y1)} = ofReal (π d0 d1 y0 y1)
    Proof (Lean source)
    lemma piMeasure_singleton (d0 d1 y0 y1 : Bool) : piMeasure π {(d0, d1, y0, y1)} = ofReal (π d0 d1 y0 y1) := by unfold piMeasure simp only [Measure.coe_finset_sum, Finset.sum_apply] have hSing : MeasurableSet ({(d0, d1, y0, y1)} : Set (Bool × Bool × Bool × Bool)) := MeasurableSet.singleton _ -- Compute each summand: it's the dirac measure scaled by π. -- The summand at (d0', d1', y0', y1') = ofReal(π d0' d1' y0' y1') if matches, else 0. have hsummand : ∀ (d0' d1' y0' y1' : Bool), ((ofReal (π d0' d1' y0' y1') • Measure.dirac (d0', d1', y0', y1') : Measure (Bool × Bool × Bool × Bool)) {(d0, d1, y0, y1)}) = if (d0', d1', y0', y1') = (d0, d1, y0, y1) then ofReal (π d0' d1' y0' y1') else 0 := by intros d0' d1' y0' y1' rw [Measure.smul_apply, Measure.dirac_apply' _ hSing, smul_eq_mul] by_cases h : (d0', d1', y0', y1') = (d0, d1, y0, y1) · rw [Set.indicator_of_mem (Set.mem_singleton_iff.mpr h), if_pos h, Pi.one_apply, mul_one] · rw [Set.indicator_of_notMem (by rw [Set.mem_singleton_iff]; exact h), if_neg h, mul_zero] simp_rw [hsummand] -- Now isolate the unique nonzero term. rw [Finset.sum_eq_single d0 (fun d0' _ hne => ?_) (fun h => absurd (Finset.mem_univ _) h)] · rw [Finset.sum_eq_single d1 (fun d1' _ hne => ?_) (fun h => absurd (Finset.mem_univ _) h)] · rw [Finset.sum_eq_single y0 (fun y0' _ hne => ?_) (fun h => absurd (Finset.mem_univ _) h)] · rw [Finset.sum_eq_single y1 (fun y1' _ hne => ?_) (fun h => absurd (Finset.mem_univ _) h)] · simp · simp [hne] · refine Finset.sum_eq_zero (fun y1' _ => ?_) simp [hne] · refine Finset.sum_eq_zero (fun y0' _ => ?_) refine Finset.sum_eq_zero (fun y1' _ => ?_) simp [hne] · refine Finset.sum_eq_zero (fun d1' _ => ?_) refine Finset.sum_eq_zero (fun y0' _ => ?_) refine Finset.sum_eq_zero (fun y1' _ => ?_) simp [hne]
    Causalean.PO.POBalkePearlSharp.piMeasure_singleton · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:720
  • canonical_latentSet lemma — The canonical latent set is Set.univ ×ˢ {(d0, d1, y0, y1)}.
    d0 d1 y0 y1 :
    (S' S π hπ_nn hπ_sum).latentSet d0 d1 y0 y1
    = (univ ×ˢ {(d0, d1, y0, y1)} : Set SOmega)
    Proof (Lean source)
    lemma canonical_latentSet (d0 d1 y0 y1 : Bool) : (S' S π hπ_nn hπ_sum).latentSet d0 d1 y0 y1 = (univ ×ˢ {(d0, d1, y0, y1)} : Set SOmega) := by ext ω rcases ω with ⟨z, d0', d1', y0', y1'⟩ change ((S' S π hπ_nn hπ_sum).DofZ false (z, d0', d1', y0', y1') = d0 ∧ (S' S π hπ_nn hπ_sum).DofZ true (z, d0', d1', y0', y1') = d1 ∧ (S' S π hπ_nn hπ_sum).YofD false (z, d0', d1', y0', y1') = y0 ∧ (S' S π hπ_nn hπ_sum).YofD true (z, d0', d1', y0', y1') = y1) ↔ _ rw [canonical_DofZ, canonical_DofZ, canonical_YofD, canonical_YofD] change ((POBalkePearlSystem.dArm false d0' d1' = d0) ∧ (POBalkePearlSystem.dArm true d0' d1' = d1) ∧ (POBalkePearlSystem.yArm false y0' y1' = y0) ∧ (POBalkePearlSystem.yArm true y0' y1' = y1)) ↔ (z, d0', d1', y0', y1') ∈ (univ ×ˢ {(d0, d1, y0, y1)} : Set SOmega) unfold POBalkePearlSystem.dArm POBalkePearlSystem.yArm simp only [Bool.false_eq_true, if_false, if_true] refine ⟨?_, ?_⟩ · rintro ⟨rfl, rfl, rfl, rfl⟩ exact Set.mk_mem_prod (Set.mem_univ _) rfl · rintro ⟨_, h2⟩ rw [Set.mem_singleton_iff] at h2 -- h2 : (z, d0', d1', y0', y1').2 = (d0, d1, y0, y1) -- Need: conjunction of equalities. simp only [Prod.mk.injEq] at h2 exact h2
    Causalean.PO.POBalkePearlSharp.canonical_latentSet · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:764
  • canonical_latentSet_measure lemma — μ'(latentSet) = ENNReal.ofReal (π d0 d1 y0 y1).
    d0 d1 y0 y1 :
    (P' S π hπ_nn hπ_sum).μ ((S' S π hπ_nn hπ_sum).latentSet d0 d1 y0 y1)
    = ofReal (π d0 d1 y0 y1)
    Proof (Lean source)
    lemma canonical_latentSet_measure (d0 d1 y0 y1 : Bool) : (P' S π hπ_nn hπ_sum).μ ((S' S π hπ_nn hπ_sum).latentSet d0 d1 y0 y1) = ofReal (π d0 d1 y0 y1) := by rw [canonical_latentSet] change (canonicalMeasure S π) (univ ×ˢ {(d0, d1, y0, y1)}) = _ unfold canonicalMeasure letI : IsProbabilityMeasure (piMeasure π) := instIsProbPiMeasure hπ_nn hπ_sum rw [Measure.prod_prod, zMeasure_univ, one_mul, piMeasure_singleton]
    Causalean.PO.POBalkePearlSharp.canonical_latentSet_measure · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:793
  • canonical_latentProb_eq lemma — S'.latentProb = π.
    d0 d1 y0 y1 :
    (S' S π hπ_nn hπ_sum).latentProb d0 d1 y0 y1 = π d0 d1 y0 y1
    Proof (Lean source)
    lemma canonical_latentProb_eq (d0 d1 y0 y1 : Bool) : (S' S π hπ_nn hπ_sum).latentProb d0 d1 y0 y1 = π d0 d1 y0 y1 := by unfold POBalkePearlSystem.latentProb rw [canonical_latentSet_measure] exact ENNReal.toReal_ofReal (hπ_nn _ _ _ _)
    Causalean.PO.POBalkePearlSharp.canonical_latentProb_eq · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:804
  • canonical_cellProb_eq lemma — S'.cellProb y d z = S.cellProb y d z for any feasible π.
    hA :
    S.BaseAssumptions
    :
    POBalkePearlSystem.BPFeasible S hA π
    y d z :
    (S' S π hπ_nn hπ_sum).cellProb y d z = S.cellProb y d z
    Proof (Lean source)
    lemma canonical_cellProb_eq (hA : S.BaseAssumptions) (hπ : POBalkePearlSystem.BPFeasible S hA π) (y d z : Bool) : (S' S π hπ_nn hπ_sum).cellProb y d z = S.cellProb y d z := by rw [(S' S π hπ_nn hπ_sum).cellProb_eq_sum_latent (canonical_baseAssumptions S π hπ_nn hπ_sum hA) y d z, hπ.marginal y d z] refine Finset.sum_congr rfl (fun d0 _ => ?_) refine Finset.sum_congr rfl (fun d1 _ => ?_) refine Finset.sum_congr rfl (fun y0 _ => ?_) refine Finset.sum_congr rfl (fun y1 _ => ?_) rw [canonical_latentProb_eq]
    Causalean.PO.POBalkePearlSharp.canonical_cellProb_eq · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:811
  • canonical_ATE_eq lemma — S'.ATE = BPObjective π.
    hA :
    S.BaseAssumptions
    (S' S π hπ_nn hπ_sum).ATE = POBalkePearlSystem.BPObjective π
    Proof (Lean source)
    lemma canonical_ATE_eq (hA : S.BaseAssumptions) : (S' S π hπ_nn hπ_sum).ATE = POBalkePearlSystem.BPObjective π := by rw [(S' S π hπ_nn hπ_sum).ATE_eq_BPObjective (canonical_baseAssumptions S π hπ_nn hπ_sum hA)] unfold POBalkePearlSystem.BPObjective refine Finset.sum_congr rfl (fun d0 _ => ?_) refine Finset.sum_congr rfl (fun d1 _ => ?_) refine Finset.sum_congr rfl (fun y0 _ => ?_) refine Finset.sum_congr rfl (fun y1 _ => ?_) rw [canonical_latentProb_eq]
    Causalean.PO.POBalkePearlSharp.canonical_ATE_eq · Causalean/PO/ID/Partial/BalkePearl/Sharp.lean:823