PO.ID.Partial.Balke­Pearl

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

Attainment 31 core · 33 supporting · 3 submodules Attainment of the Balke-Pearl bounds: the compatible distributions that realise each endpoint, which is what makes the bounds sharp rather than merely valid. Sharp 16 core · 35 supporting · 2 submodules The Balke–Pearl identified set for the average treatment effect is sharp on the model side: for a binary instrument, treatment and outcome, every latent response-type table that is feasible for the Balke–Pearl linear pro
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:39 · uses POSystem
def zVar reviewed
Causalean.PO.POBalkePearlSystem

For a potential-outcomes system and a binary Balke--Pearl system on it, the instrument variable is the system's instrument, packaged together with its binary measurement scale.

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

For a potential-outcomes system and a binary Balke--Pearl system on it, the treatment variable is the system's treatment, packaged together with its binary measurement scale.

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

For a potential-outcomes system and a binary Balke--Pearl system on it, the outcome variable is the system's outcome, packaged together with its binary measurement scale.

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

For a potential-outcomes system, a binary Balke--Pearl system on it, and an instrument value, the potential treatment function maps each unit to the treatment it would receive were the instrument set to that value.

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

For a potential-outcomes system, a binary Balke--Pearl system on it, and a treatment value, the potential outcome function maps each unit to the binary outcome it would have under that treatment value.

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

For a potential-outcomes system, a binary Balke--Pearl system on it, an instrument value, and a treatment value, the joint intervention regime sets the instrument to the specified instrument value and the treatment to the specified treatment value.

Definition (Lean source)
P :
shared
S :
shared
z d :
regimeZD S z d :
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

For a potential-outcomes system, a binary Balke--Pearl system on it, an instrument value, and a treatment value, the joint-intervention potential outcome function maps each unit to its outcome when the instrument and treatment are set jointly to those values.

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

For a potential-outcomes system and a binary Balke--Pearl system on it, the factual instrument function maps each unit to its observed binary instrument value.

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

For a potential-outcomes system and a binary Balke--Pearl system on it, the factual treatment function maps each unit to its observed binary treatment value.

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

For a potential-outcomes system and a binary Balke--Pearl system on it, the factual outcome function maps each unit to its observed binary outcome value.

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

The binary-to-real encoding maps every binary value to a real number: for true, its value is one, and for false, its value is zero.

Definition (Lean source)
boolToReal :
Bool → ℝ
clause 1
| true => 1
clause 2
| false => 0
Causalean.PO.POBalkePearlSystem.boolToReal · Causalean/PO/ID/Partial/BalkePearl/Setup.lean:105
def YofD_real reviewed
Causalean.PO.POBalkePearlSystem

For a potential-outcomes system, a binary Balke--Pearl system on it, and a treatment value, the real-valued potential outcome function maps each unit's binary potential outcome under that treatment to its zero--one real encoding.

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

For a potential-outcomes system, a binary Balke--Pearl system on it, and an instrument value, the instrument event is the set of units whose factual instrument equals that value.

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

For a potential-outcomes system, a binary Balke--Pearl system on it, and a treatment value, the treatment event is the set of units whose factual treatment equals that value.

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

For a potential-outcomes system, a binary Balke--Pearl system on it, and an outcome value, the outcome event is the set of units whose factual outcome equals that value.

Definition (Lean source)
P :
shared
S :
shared
y :
yEvent S y :
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
P :
shared
S :
shared
z :
Measurable (S.DofZ z)
Proof (Lean source)
@[fun_prop] 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:126 · uses POBalkePearlSystem , DofZ , POSystem
def ATE reviewed
Causalean.PO.POBalkePearlSystem

For a potential-outcomes system and a binary Balke--Pearl system on it, the average treatment effect is the expectation, under the system's probability measure, of the real-valued potential outcome under treatment minus that under control.

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

For a potential-outcomes system, a binary Balke--Pearl system on it, an outcome value, a treatment value, and an instrument value, the conditional cell probability is the probability that the factual outcome and treatment equal the specified values conditional on the factual instrument equaling the specified instrument value.

Definition (Lean source)
P :
shared
S :
shared
y d z :
cellProb S y d z :
ℝ
(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

For a potential-outcome system and its Balke--Pearl observational system, and a binary instrument value, the treatment potential-outcome variable under that instrument value is the factual treatment variable evaluated in the intervention that fixes the instrument at that value.

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

For a potential-outcome system and its Balke--Pearl observational system, and a binary treatment value, the outcome potential-outcome variable under that treatment value is the factual outcome variable evaluated in the intervention that fixes treatment at that value.

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

For a potential-outcome system and its Balke--Pearl observational system, the counterfactual bundle collects, in order, treatment under instrument values zero and one and outcome under treatment values zero and one.

Definition (Lean source)
P :
shared
S :
shared
cfBundle S :
.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)
P :
shared
consistency_D :
∀ (z : Bool) {ω : P.Ω}
if
ω ∈ S.zEvent z
then
S.DofZ z ω = S.factualD ω

Treatment consistency on instrument cells: on {Z=z}, factual D equals D(z).

consistency_Y :
∀ (d : Bool) {ω : P.Ω}
if
ω ∈ S.dEvent d
then
S.YofD d ω = S.factualY ω

Outcome consistency on treatment cells: on {D=d}, factual Y equals Y(d).

exclusion :
∀ (z d : Bool), S.YofZD z d =ᵐ[P.μ] S.YofD d

Exclusion: Y(z,d) = Y(d) a.s. for all z d.

exogeneity :
P.IndepCF (.ofFactual S.zVar) S.cfBundle P.μ

Instrument exogeneity: Z ⊥ (D(0),D(1),Y(0),Y(1)).

posZ :
∀ z : Bool, 0 < P.μ (S.zVar.event z)

Both arms of Z have positive probability.

Causalean.PO.POBalkePearlSystem.BaseAssumptions · Causalean/PO/ID/Partial/BalkePearl/Assumptions.lean:63 · 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:94 · uses POBalkePearlSystem , BaseAssumptions , zVar , POSystem , event
2 supporting declarations (lemmas, instances)
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

For a binary instrument value and two binary treatment potential outcomes, respectively under instrument values zero and one, the selected treatment potential outcome is the first when the instrument value is zero and the second when it is one.

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

For a binary treatment value and two binary outcome potential outcomes, respectively under treatment values zero and one, the selected outcome potential outcome is the first when treatment is zero and the second when it is one.

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

For a potential-outcome system and its Balke--Pearl observational system and binary values for treatment under instrument zero and one and outcome under treatment zero and one, the latent-type event is the set of sample points at which all four corresponding potential outcomes equal those values.

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

For a potential-outcome system and its Balke--Pearl observational system and binary values for treatment under instrument zero and one and outcome under treatment zero and one, the latent-type probability is the real-valued probability of the corresponding latent-type event.

Definition (Lean source)
P :
shared
S :
shared
d0 d1 y0 y1 :
latentProb S d0 d1 y0 y1 :
ℝ
(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
P :
shared
S :
shared
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 × Bool → Set 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.
    P :
    shared
    S :
    shared
    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:71
  • latentProb_nonneg lemma — Latent type probabilities are nonnegative.
    P :
    shared
    S :
    shared
    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:84
  • latentProb_sum_eq_one lemma — The 16 latent sets partition Ω, so their probabilities sum to 1.
    P :
    shared
    S :
    shared
    ∑ 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 × Bool → Set 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:109
  • cellProb_eq_sum_latent theorem — Each observed conditional cell probability equals the sum of compatible latent type probabilities.
    P :
    shared
    S :
    shared
    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 × Bool → Set 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:287
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)
P :
shared
hA :
S.BaseAssumptions
π :
Bool → Bool → Bool → Bool → ℝ
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

For a table of real weights indexed by the four binary latent response values, the Balke--Pearl linear-program objective is the sum, over all latent response types, of that type's weight times its binary outcome response under treatment minus its binary outcome response under control.

Definition (Lean source)
π :
Bool → Bool → Bool → Bool → ℝ
BPObjective π :
ℝ
∑ 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:72
def BPIdentifiedInterval reviewed
Causalean.PO.POBalkePearlSystem

For a potential-outcomes system, a binary Balke--Pearl system on it, and proof that the system satisfies the Balke--Pearl base assumptions, the sharp identified interval for the average treatment effect is the set of values of the Balke--Pearl linear-program objective over all feasible latent response-type tables.

Definition (Lean source)
P :
shared
hA :
S.BaseAssumptions
BPIdentifiedInterval S hA :
Set ℝ
Causalean.PO.POBalkePearlSystem.BPIdentifiedInterval · Causalean/PO/ID/Partial/BalkePearl/Main.lean:79 · 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
P :
shared
S :
shared
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] exact PartialID.mem_identifiedSet (S.latentProb_feasible hA)
2 supporting declarations (lemmas, instances)
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

For a potential-outcome system and its Balke--Pearl observational system, and one of the eight indices, the corresponding affine lower-bound expression is calculated from the observed outcome--treatment cell probabilities by naming those probabilities and applying the appropriate first, second, third, fourth, fifth, sixth, seventh, or eighth displayed formula.

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

For a potential-outcome system and its Balke--Pearl observational system, and one of the eight indices, the corresponding affine upper-bound expression is calculated from the observed outcome--treatment cell probabilities by naming those probabilities and applying the appropriate first, second, third, fourth, fifth, sixth, seventh, or eighth displayed formula.

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

For a potential-outcome system and its Balke--Pearl observational system, the closed-form lower endpoint is the largest of its eight affine lower-bound expressions.

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

For a potential-outcome system and its Balke--Pearl observational system, the closed-form upper endpoint is the smallest of its eight affine upper-bound expressions.

Definition (Lean source)
P :
shared
S :
shared
bpUpper S :
ℝ
Finset.univ.inf' 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
P :
shared
S :
shared
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 The Balke–Pearl closed-form bounds on the average treatment effect with a binary instrument, treatment and outcome are exact: the largest of the eight lower expressions equals the infimum, and the smallest of the eight u ★ csInf_BPIdentifiedInterval_eq_bpLower★ csSup_BPIdentifiedInterval_eq_bpUpper★ bpLower_bpUpper_eq_csInf_csSup

Attainment of the Balke–Pearl closed-form endpoints

The Balke–Pearl closed-form bounds on the average treatment effect with a binary instrument, treatment and outcome are exact: the largest of the eight lower expressions equals the infimum, and the smallest of the eight upper expressions equals the supremum, of the linear-program objective over all latent response-type tables compatible with the observed cell probabilities. The proof combines validity of the closed form (every feasible table has objective between the two endpoints) with explicit feasible tables attaining each endpoint. This is a statement about the linear program; that every feasible table comes from an actual potential-outcome model is the separate sharpness theorem balkePearl_sharp.

Main results

  • csInf_BPIdentifiedInterval_eq_bpLower — the infimum of the identified set is bpLower.
  • csSup_BPIdentifiedInterval_eq_bpUpper — the supremum of the identified set is bpUpper.
  • bpLower_bpUpper_eq_csInf_csSup — both equalities together, under the base assumptions.
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
P :
shared
S :
shared
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
P :
shared
S :
shared
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
P :
shared
S :
shared
hA :
S.BaseAssumptions
conclusion 1
S.bpLower = sInf (S.BPIdentifiedInterval hA)
conclusion 2
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
P :
shared
S :
shared
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.
    π :
    Bool → Bool → Bool → Bool → ℝ
    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 {π : Bool → Bool → Bool → Bool → ℝ} (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:63
  • neg_one_le_BPObjective lemma — Lower bound on the objective. Symmetrically, -1 ≤ BPObjective π.
    π :
    Bool → Bool → Bool → Bool → ℝ
    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 {π : Bool → Bool → Bool → Bool → ℝ} (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:77
  • bddBelow_BPIdentifiedInterval lemma — The Balke-Pearl identified interval is bounded below (by -1).
    P :
    shared
    S :
    shared
    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:96
  • bddAbove_BPIdentifiedInterval lemma — The Balke-Pearl identified interval is bounded above (by 1).
    P :
    shared
    S :
    shared
    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:103