Panel.Weighted

Weighted panel estimators: weighting schemes over cohorts/periods and the estimands they aggregate to.

Support 2 core · 3 supporting This file defines WeightedSupport, a finite observed support equipped with strictly positive weights that sum to one on the observed set and vanish off it. ★ sum_weight

Weighted finite supports

This file defines WeightedSupport, a finite observed support equipped with strictly positive weights that sum to one on the observed set and vanish off it. It also proves the basic normalization lemmas weight_nonneg, sum_weight_univ, sum_weight, and sum_weight_univ_eq_one.

The resulting object is the common finite weighted-index substrate for weighted inner products, weighted least squares, and Frisch-Waugh-Lovell decompositions.

structure WeightedSupport reviewed
Causalean.Panel.Weighted

A finite weighted index together with positive normalized weights: a nonempty observed subset of indices together with a weight function that is strictly positive on every observed index, vanishes off the observed set, and sums to one over the observed indices.

Definition (Lean source)
R :
The set of observed indices.
observed :
Witness that the observed set is nonempty.
observed_nonempty :
observed.Nonempty
The weight `ω : R → ℝ`, defined on the whole index type for notational convenience.
weight :
R → ℝ
`ω_r > 0` for every observed index `r`.
weight_pos :
∀ r ∈ observed, 0 < weight r
`ω_r = 0` for every index outside `observed`.
weight_zero_off :
∀ r
if
r ∉ observed
then
weight r = 0
Normalization `∑_{r ∈ observed} ω_r = 1`.
weight_sum_one :
∑ r ∈ observed, weight r = 1
Causalean.Panel.Weighted.WeightedSupport · Causalean/Panel/Weighted/Support.lean:53
lemma sum_weight reviewed
Causalean.Panel.Weighted.WeightedSupport

For a weighted-support system c, the weights sum to one over the observed index set (restated from the structure's normalization field for convenient reuse).

Formal statement
∑ r ∈ c.observed, c.weight r = 1
Proof (Lean source)
lemma sum_weight (c : WeightedSupport R) : ∑ r ∈ c.observed, c.weight r = 1 := c.weight_sum_one
Causalean.Panel.Weighted.WeightedSupport.sum_weight · Causalean/Panel/Weighted/Support.lean:102 · uses WeightedSupport
3 supporting declarations (lemmas, instances)
  • weight_nonneg lemma — The weight function ω is nonnegative everywhere on R.
    r :
    R
    0 ≤ c.weight r
    Proof (Lean source)
    lemma weight_nonneg (c : WeightedSupport R) (r : R) : 0 ≤ c.weight r := by by_cases h : r ∈ c.observed · exact (c.weight_pos r h).le · simp [c.weight_zero_off r h]
    Causalean.Panel.Weighted.WeightedSupport.weight_nonneg · Causalean/Panel/Weighted/Support.lean:87
  • sum_weight_univ lemma — Summing ω over the full type R equals summing over observed, because ω vanishes outside observed.
    ∑ r, c.weight r = ∑ r ∈ c.observed, c.weight r
    Proof (Lean source)
    lemma sum_weight_univ (c : WeightedSupport R) : ∑ r, c.weight r = ∑ r ∈ c.observed, c.weight r := by classical refine (Finset.sum_subset (Finset.subset_univ _) ?_).symm intro r _ hr exact c.weight_zero_off r hr
    Causalean.Panel.Weighted.WeightedSupport.sum_weight_univ · Causalean/Panel/Weighted/Support.lean:93
  • sum_weight_univ_eq_one lemma — Summing the weights over Finset.univ gives 1.
    ∑ r, c.weight r = 1
    Proof (Lean source)
    lemma sum_weight_univ_eq_one (c : WeightedSupport R) : ∑ r, c.weight r = 1 := by rw [c.sum_weight_univ, c.weight_sum_one]
    Causalean.Panel.Weighted.WeightedSupport.sum_weight_univ_eq_one · Causalean/Panel/Weighted/Support.lean:108
Inner­Product 3 core · 14 supporting This file defines the scalar weighted inner product over observed records and its matrix-valued lift to tuples of arrays. ★ ip_self_eq_zero_iff

Weighted inner products over a finite support

This file defines the scalar weighted inner product over observed records and its matrix-valued lift to tuples of arrays.

The inner product is the WLS pairing used by the weighted projection, WLS-optimality, and Frisch-Waugh-Lovell layers. It is bilinear, positive-semidefinite, definite on the observed support, and symmetric after matrix transposition.

def ip reviewed
Causalean.Panel.Weighted.WeightedSupport

The weighted inner product multiplies two arrays record by record and sums the products with the support weights over observed records.

Definition (Lean source)
def ip (c : WeightedSupport R) (A B : R → ℝ) : ℝ := ∑ r ∈ c.observed, c.weight r * A r * B r
Causalean.Panel.Weighted.WeightedSupport.ip · Causalean/Panel/Weighted/InnerProduct.lean:65 · uses WeightedSupport
lemma ip_self_eq_zero_iff reviewed
Causalean.Panel.Weighted.WeightedSupport

For a weighted-support system c, the weighted self inner product ⟨A, A⟩_ω of an array A vanishes if and only if A is zero at every index in the observed set. Arrays that differ only off c.observed are thus identified by this inner product.

Formal statement
A :
R → ℝ
c.ip A A = 0 ↔ ∀ r ∈ c.observed, A r = 0
Proof (Lean source)
lemma ip_self_eq_zero_iff (c : WeightedSupport R) (A : R → ℝ) : c.ip A A = 0 ↔ ∀ r ∈ c.observed, A r = 0 := by unfold ip rw [Finset.sum_eq_zero_iff_of_nonneg (c.ip_self_summand_nonneg A)] constructor · -- From `ω_r · A_r · A_r = 0` and `ω_r > 0`, deduce `A_r = 0`. intro h r hr have hwpos : 0 < c.weight r := c.weight_pos r hr have hsum : c.weight r * A r * A r = 0 := h r hr have hsum' : c.weight r * (A r * A r) = 0 := by rw [← mul_assoc]; exact hsum have hne : c.weight r ≠ 0 := ne_of_gt hwpos have hsq : A r * A r = 0 := (mul_eq_zero.mp hsum').resolve_left hne exact mul_self_eq_zero.mp hsq · -- `A_r = 0` ⇒ `ω_r · A_r · A_r = 0`. intro h r hr have hAr : A r = 0 := h r hr rw [hAr]; ring
Causalean.Panel.Weighted.WeightedSupport.ip_self_eq_zero_iff · Causalean/Panel/Weighted/InnerProduct.lean:126 · uses WeightedSupport , ip
def ipMat reviewed
Causalean.Panel.Weighted.WeightedSupport

The matrix-valued inner product takes the scalar weighted inner product between each pair of columns.

Definition (Lean source)
def ipMat (c : WeightedSupport R) (A B : J → R → ℝ) : Matrix J J ℝ := fun j k => c.ip (A j) (B k)
Causalean.Panel.Weighted.WeightedSupport.ipMat · Causalean/Panel/Weighted/InnerProduct.lean:157 · uses WeightedSupport
14 supporting declarations (lemmas, instances)
  • ip_def lemma — The weighted inner product unfolds to its finite weighted sum over observed records.
    A B :
    R → ℝ
    c.ip A B = ∑ r ∈ c.observed, c.weight r * A r * B r
    Proof (Lean source)
    @[simp] lemma ip_def (c : WeightedSupport R) (A B : R → ℝ) : c.ip A B = ∑ r ∈ c.observed, c.weight r * A r * B r := rfl
    Causalean.Panel.Weighted.WeightedSupport.ip_def · Causalean/Panel/Weighted/InnerProduct.lean:70
  • ip_symm lemma — Symmetry of the weighted inner product.
    A B :
    R → ℝ
    c.ip A B = c.ip B A
    Proof (Lean source)
    lemma ip_symm (c : WeightedSupport R) (A B : R → ℝ) : c.ip A B = c.ip B A := by unfold ip refine Finset.sum_congr rfl ?_ intro r _ ring
    Causalean.Panel.Weighted.WeightedSupport.ip_symm · Causalean/Panel/Weighted/InnerProduct.lean:75
  • ip_add_left lemma — Additivity in the left argument.
    A A' B :
    R → ℝ
    c.ip (A + A') B = c.ip A B + c.ip A' B
    Proof (Lean source)
    lemma ip_add_left (c : WeightedSupport R) (A A' B : R → ℝ) : c.ip (A + A') B = c.ip A B + c.ip A' B := by unfold ip rw [← Finset.sum_add_distrib] refine Finset.sum_congr rfl ?_ intro r _ simp [Pi.add_apply]; ring
    Causalean.Panel.Weighted.WeightedSupport.ip_add_left · Causalean/Panel/Weighted/InnerProduct.lean:83
  • ip_add_right lemma — Additivity in the right argument.
    A B B' :
    R → ℝ
    c.ip A (B + B') = c.ip A B + c.ip A B'
    Proof (Lean source)
    lemma ip_add_right (c : WeightedSupport R) (A B B' : R → ℝ) : c.ip A (B + B') = c.ip A B + c.ip A B' := by rw [ip_symm, ip_add_left, ip_symm c A B, ip_symm c A B']
    Causalean.Panel.Weighted.WeightedSupport.ip_add_right · Causalean/Panel/Weighted/InnerProduct.lean:92
  • ip_smul_left lemma — Scalar homogeneity in the left argument.
    s :
    A B :
    R → ℝ
    c.ip (s • A) B = s * c.ip A B
    Proof (Lean source)
    lemma ip_smul_left (c : WeightedSupport R) (s : ℝ) (A B : R → ℝ) : c.ip (s • A) B = s * c.ip A B := by unfold ip rw [Finset.mul_sum] refine Finset.sum_congr rfl ?_ intro r _ simp [Pi.smul_apply]; ring
    Causalean.Panel.Weighted.WeightedSupport.ip_smul_left · Causalean/Panel/Weighted/InnerProduct.lean:97
  • ip_smul_right lemma — Scalar homogeneity in the right argument.
    s :
    A B :
    R → ℝ
    c.ip A (s • B) = s * c.ip A B
    Proof (Lean source)
    lemma ip_smul_right (c : WeightedSupport R) (s : ℝ) (A B : R → ℝ) : c.ip A (s • B) = s * c.ip A B := by rw [ip_symm, ip_smul_left, ip_symm c A B]
    Causalean.Panel.Weighted.WeightedSupport.ip_smul_right · Causalean/Panel/Weighted/InnerProduct.lean:106
  • ip_self_summand_nonneg lemma — Each summand of ⟨A, A⟩_ω is nonnegative.
    A :
    R → ℝ
    ∀ r ∈ c.observed, 0 ≤ c.weight r * A r * A r
    Proof (Lean source)
    lemma ip_self_summand_nonneg (c : WeightedSupport R) (A : R → ℝ) : ∀ r ∈ c.observed, 0 ≤ c.weight r * A r * A r := by intro r hr have hw : 0 ≤ c.weight r := (c.weight_pos r hr).le have hsq : 0 ≤ A r * A r := mul_self_nonneg (A r) have : 0 ≤ c.weight r * (A r * A r) := mul_nonneg hw hsq simpa [mul_assoc] using this
    Causalean.Panel.Weighted.WeightedSupport.ip_self_summand_nonneg · Causalean/Panel/Weighted/InnerProduct.lean:111
  • ip_self_nonneg lemma — Positivity: ⟨A, A⟩_ω ≥ 0.
    A :
    R → ℝ
    0 ≤ c.ip A A
    Proof (Lean source)
    lemma ip_self_nonneg (c : WeightedSupport R) (A : R → ℝ) : 0 ≤ c.ip A A := by unfold ip exact sum_nonneg (c.ip_self_summand_nonneg A)
    Causalean.Panel.Weighted.WeightedSupport.ip_self_nonneg · Causalean/Panel/Weighted/InnerProduct.lean:120
  • ipMat_apply lemma — Each entry of the matrix-valued inner product is the scalar weighted inner product of the corresponding two columns.
    A B :
    J → R → ℝ
    j k :
    J
    c.ipMat A B j k = c.ip (A j) (B k)
    Proof (Lean source)
    @[simp] lemma ipMat_apply (c : WeightedSupport R) (A B : J → R → ℝ) (j k : J) : c.ipMat A B j k = c.ip (A j) (B k) := rfl
    Causalean.Panel.Weighted.WeightedSupport.ipMat_apply · Causalean/Panel/Weighted/InnerProduct.lean:163
  • ipMat_transpose lemma — The transpose of ⟨A, B⟩_ω is ⟨B, A⟩_ω.
    A B :
    J → R → ℝ
    (c.ipMat A B).transpose = c.ipMat B A
    Proof (Lean source)
    lemma ipMat_transpose (c : WeightedSupport R) (A B : J → R → ℝ) : (c.ipMat A B).transpose = c.ipMat B A := by ext j k rw [Matrix.transpose_apply, ipMat_apply, ipMat_apply, ip_symm]
    Causalean.Panel.Weighted.WeightedSupport.ipMat_transpose · Causalean/Panel/Weighted/InnerProduct.lean:169
  • ipMat_add_left lemma — Additivity in the left tuple argument (entrywise).
    A A' B :
    J → R → ℝ
    c.ipMat (A + A') B = c.ipMat A B + c.ipMat A' B
    Proof (Lean source)
    lemma ipMat_add_left (c : WeightedSupport R) (A A' B : J → R → ℝ) : c.ipMat (A + A') B = c.ipMat A B + c.ipMat A' B := by ext j k change c.ip ((A + A') j) (B k) = c.ipMat A B j k + c.ipMat A' B j k rw [Pi.add_apply, ip_add_left] simp [ipMat_apply]
    Causalean.Panel.Weighted.WeightedSupport.ipMat_add_left · Causalean/Panel/Weighted/InnerProduct.lean:175
  • ipMat_add_right lemma — Additivity in the right tuple argument (entrywise).
    A B B' :
    J → R → ℝ
    c.ipMat A (B + B') = c.ipMat A B + c.ipMat A B'
    Proof (Lean source)
    lemma ipMat_add_right (c : WeightedSupport R) (A B B' : J → R → ℝ) : c.ipMat A (B + B') = c.ipMat A B + c.ipMat A B' := by ext j k change c.ip (A j) ((B + B') k) = c.ipMat A B j k + c.ipMat A B' j k rw [Pi.add_apply, ip_add_right] simp [ipMat_apply]
    Causalean.Panel.Weighted.WeightedSupport.ipMat_add_right · Causalean/Panel/Weighted/InnerProduct.lean:183
  • ipMat_smul_left lemma — Scalar homogeneity in the left tuple argument (entrywise).
    s :
    A B :
    J → R → ℝ
    c.ipMat (s • A) B = s • c.ipMat A B
    Proof (Lean source)
    lemma ipMat_smul_left (c : WeightedSupport R) (s : ℝ) (A B : J → R → ℝ) : c.ipMat (s • A) B = s • c.ipMat A B := by ext j k change c.ip ((s • A) j) (B k) = s • (c.ipMat A B) j k rw [Pi.smul_apply, ip_smul_left] simp [ipMat_apply, smul_eq_mul]
    Causalean.Panel.Weighted.WeightedSupport.ipMat_smul_left · Causalean/Panel/Weighted/InnerProduct.lean:191
  • ipMat_smul_right lemma — Scalar homogeneity in the right tuple argument (entrywise).
    s :
    A B :
    J → R → ℝ
    c.ipMat A (s • B) = s • c.ipMat A B
    Proof (Lean source)
    lemma ipMat_smul_right (c : WeightedSupport R) (s : ℝ) (A B : J → R → ℝ) : c.ipMat A (s • B) = s • c.ipMat A B := by ext j k change c.ip (A j) ((s • B) k) = s • (c.ipMat A B) j k rw [Pi.smul_apply, ip_smul_right] simp [ipMat_apply, smul_eq_mul]
    Causalean.Panel.Weighted.WeightedSupport.ipMat_smul_right · Causalean/Panel/Weighted/InnerProduct.lean:199
Subspace 5 core · 11 supporting This file defines the weighted orthogonal projection onto a nuisance subspace and the corresponding residual maker. ★ residualize_in_orthogonal

Weighted projections and residual makers

This file defines the weighted orthogonal projection onto a nuisance subspace and the corresponding residual maker.

The projection exists for the semidefinite weighted inner product because only observed records matter. The resulting projection and residual maker are used by the WLS optimality and finite-cell Frisch-Waugh-Lovell layers.

def proj reviewed
Causalean.Panel.Weighted.WeightedSupport

The c.ip-orthogonal projection onto H, chosen via classical choice from weighted_orthogonal_projection_exists.

Definition (Lean source)
noncomputable def proj (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) : (R → ℝ) →ₗ[ℝ] (R → ℝ) := (c.weighted_orthogonal_projection_exists H).choose
Causalean.Panel.Weighted.WeightedSupport.proj · Causalean/Panel/Weighted/Subspace.lean:100 · uses WeightedSupport
def residualize reviewed
Causalean.Panel.Weighted.WeightedSupport

The residual maker M_H = id - P_H.

Definition (Lean source)
noncomputable def residualize (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) : (R → ℝ) →ₗ[ℝ] (R → ℝ) := LinearMap.id - c.proj H
Causalean.Panel.Weighted.WeightedSupport.residualize · Causalean/Panel/Weighted/Subspace.lean:172 · uses WeightedSupport
def tildeX reviewed
Causalean.Panel.Weighted.WeightedSupport

The residualized scalar array X̃ := M_H X.

Definition (Lean source)
noncomputable def tildeX (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) (X : R → ℝ) : R → ℝ := c.residualize H X
Causalean.Panel.Weighted.WeightedSupport.tildeX · Causalean/Panel/Weighted/Subspace.lean:184 · uses WeightedSupport
lemma residualize_in_orthogonal reviewed
Causalean.Panel.Weighted.WeightedSupport

Key orthogonality. For any array h lying in the nuisance subspace H, the residualized array X̃ = M_H X is orthogonal to h under the weighted inner product c.ip.

Formal statement
H :
Submodule ℝ (R → ℝ)
X :
R → ℝ
h :
R → ℝ
hH :
h ∈ H
c.ip (c.tildeX H X) h = 0
Proof (Lean source)
lemma residualize_in_orthogonal (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) (X : R → ℝ) {h : R → ℝ} (hH : h ∈ H) : c.ip (c.tildeX H X) h = 0 := by simp only [tildeX_eq] exact c.proj_orthogonal H X hH
Causalean.Panel.Weighted.WeightedSupport.residualize_in_orthogonal · Causalean/Panel/Weighted/Subspace.lean:196 · uses WeightedSupport , ip , tildeX
def tildeXVec reviewed
Causalean.Panel.Weighted.WeightedSupport

Column-by-column residualization for vector arrays X : J → (R → ℝ).

Definition (Lean source)
noncomputable def tildeXVec {J : Type*} (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) (X : J → R → ℝ) : J → R → ℝ := fun k => c.tildeX H (X k)
Causalean.Panel.Weighted.WeightedSupport.tildeXVec · Causalean/Panel/Weighted/Subspace.lean:248 · uses WeightedSupport
11 supporting declarations (lemmas, instances)
  • weighted_orthogonal_projection_exists lemma — Existence of a c.ip-orthogonal projection onto a subspace H.
    H :
    Submodule ℝ (R → ℝ)
    ∃ P : (R → ℝ) →ₗ[ℝ] (R → ℝ), (∀ X, P X ∈ H) ∧ (∀ X, ∀ h ∈ H, c.ip (X - P X) h = 0)
    Proof (Lean source)
    lemma weighted_orthogonal_projection_exists (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) : ∃ P : (R → ℝ) →ₗ[ℝ] (R → ℝ), (∀ X, P X ∈ H) ∧ (∀ X, ∀ h ∈ H, c.ip (X - P X) h = 0) := by classical let B : BilinForm ℝ (R → ℝ) := LinearMap.mk₂ ℝ (fun X Y => c.ip X Y) (by intro X Y Z exact c.ip_add_left X Y Z) (by intro a X Z exact c.ip_smul_left a X Z) (by intro X Y Z exact c.ip_add_right X Y Z) (by intro a X Z exact c.ip_smul_right a X Z) have hsymm : ∀ X Y : R → ℝ, B X Y = B Y X := by intro X Y exact c.ip_symm X Y have hpos : ∀ X : R → ℝ, 0 ≤ B X X := by intro X exact c.ip_self_nonneg X rcases exists_orthogonalProjection_of_posSemidef (B := B) hsymm hpos H with ⟨P, hmem, horth⟩ refine ⟨P, hmem, ?_⟩ intro X h hH change B (X - P X) h = 0 exact horth X h hH
    Causalean.Panel.Weighted.WeightedSupport.weighted_orthogonal_projection_exists · Causalean/Panel/Weighted/Subspace.lean:59
  • proj_mem lemma — The chosen weighted projection always lands in the nuisance subspace.
    H :
    Submodule ℝ (R → ℝ)
    X :
    R → ℝ
    c.proj H X ∈ H
    Proof (Lean source)
    lemma proj_mem (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) (X : R → ℝ) : c.proj H X ∈ H := (c.weighted_orthogonal_projection_exists H).choose_spec.1 X
    Causalean.Panel.Weighted.WeightedSupport.proj_mem · Causalean/Panel/Weighted/Subspace.lean:106
  • proj_orthogonal lemma — The residual from the chosen weighted projection is orthogonal to every element of the nuisance subspace.
    H :
    Submodule ℝ (R → ℝ)
    X :
    R → ℝ
    h :
    R → ℝ
    hH :
    h ∈ H
    c.ip (X - c.proj H X) h = 0
    Proof (Lean source)
    lemma proj_orthogonal (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) (X : R → ℝ) {h : R → ℝ} (hH : h ∈ H) : c.ip (X - c.proj H X) h = 0 := (c.weighted_orthogonal_projection_exists H).choose_spec.2 X h hH
    Causalean.Panel.Weighted.WeightedSupport.proj_orthogonal · Causalean/Panel/Weighted/Subspace.lean:111
  • proj_apply_of_mem lemma — If Y ∈ H then c.proj H Y agrees with Y on every observed index.
    H :
    Submodule ℝ (R → ℝ)
    Y :
    R → ℝ
    hY :
    Y ∈ H
    r :
    R
    hr :
    r ∈ c.observed
    c.proj H Y r = Y r
    Proof (Lean source)
    lemma proj_apply_of_mem (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) {Y : R → ℝ} (hY : Y ∈ H) (r : R) (hr : r ∈ c.observed) : c.proj H Y r = Y r := by have hdiff : Y - c.proj H Y ∈ H := H.sub_mem hY (c.proj_mem H Y) have hself : c.ip (Y - c.proj H Y) (Y - c.proj H Y) = 0 := c.proj_orthogonal H Y hdiff have hzero : ∀ s ∈ c.observed, (Y - c.proj H Y) s = 0 := (c.ip_self_eq_zero_iff (Y - c.proj H Y)).mp hself have h := hzero r hr have hh : Y r - c.proj H Y r = 0 := h exact (sub_eq_zero.mp hh).symm
    Causalean.Panel.Weighted.WeightedSupport.proj_apply_of_mem · Causalean/Panel/Weighted/Subspace.lean:120
  • proj_apply_eq_of_mem_orthogonal lemma — Projection uniqueness on observed indices.
    H :
    Submodule ℝ (R → ℝ)
    X :
    R → ℝ
    Y :
    R → ℝ
    hY :
    Y ∈ H
    horth :
    ∀ h ∈ H, c.ip (X - Y) h = 0
    r :
    R
    hr :
    r ∈ c.observed
    c.proj H X r = Y r
    Proof (Lean source)
    lemma proj_apply_eq_of_mem_orthogonal (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) (X : R → ℝ) {Y : R → ℝ} (hY : Y ∈ H) (horth : ∀ h ∈ H, c.ip (X - Y) h = 0) (r : R) (hr : r ∈ c.observed) : c.proj H X r = Y r := by let W : R → ℝ := Y - c.proj H X have hWmem : W ∈ H := H.sub_mem hY (c.proj_mem H X) have hproj : c.ip (X - c.proj H X) W = 0 := c.proj_orthogonal H X hWmem have hYorth : c.ip (X - Y) W = 0 := horth W hWmem have hdecomp : X - c.proj H X = (X - Y) + W := by ext s simp [W] have hsplit : c.ip (X - c.proj H X) W = c.ip (X - Y) W + c.ip W W := by rw [hdecomp, c.ip_add_left] have hself : c.ip W W = 0 := by rw [hproj, hYorth, zero_add] at hsplit exact hsplit.symm have hzero : ∀ s ∈ c.observed, W s = 0 := (c.ip_self_eq_zero_iff W).mp hself have hrzero : Y r - c.proj H X r = 0 := hzero r hr exact (sub_eq_zero.mp hrzero).symm
    Causalean.Panel.Weighted.WeightedSupport.proj_apply_eq_of_mem_orthogonal · Causalean/Panel/Weighted/Subspace.lean:133
  • proj_idem_apply lemma — Idempotence of the projection on the observed indices.
    H :
    Submodule ℝ (R → ℝ)
    X :
    R → ℝ
    r :
    R
    hr :
    r ∈ c.observed
    c.proj H (c.proj H X) r = c.proj H X r
    Proof (Lean source)
    lemma proj_idem_apply (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) (X : R → ℝ) (r : R) (hr : r ∈ c.observed) : c.proj H (c.proj H X) r = c.proj H X r := c.proj_apply_of_mem H (c.proj_mem H X) r hr
    Causalean.Panel.Weighted.WeightedSupport.proj_idem_apply · Causalean/Panel/Weighted/Subspace.lean:164
  • residualize_apply lemma — Applying the residual maker subtracts the weighted projection from the original array.
    H :
    Submodule ℝ (R → ℝ)
    X :
    R → ℝ
    c.residualize H X = X - c.proj H X
    Proof (Lean source)
    @[simp] lemma residualize_apply (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) (X : R → ℝ) : c.residualize H X = X - c.proj H X := by simp [residualize]
    Causalean.Panel.Weighted.WeightedSupport.residualize_apply · Causalean/Panel/Weighted/Subspace.lean:177
  • tildeX_eq lemma — The residualized scalar array is the original array minus its weighted projection onto the nuisance subspace.
    H :
    Submodule ℝ (R → ℝ)
    X :
    R → ℝ
    c.tildeX H X = X - c.proj H X
    Proof (Lean source)
    @[simp] lemma tildeX_eq (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) (X : R → ℝ) : c.tildeX H X = X - c.proj H X := by simp [tildeX]
    Causalean.Panel.Weighted.WeightedSupport.tildeX_eq · Causalean/Panel/Weighted/Subspace.lean:189
  • residualize_self_of_mem lemma — If X ∈ H then X̃ = M_H X vanishes on c.observed.
    H :
    Submodule ℝ (R → ℝ)
    X :
    R → ℝ
    hX :
    X ∈ H
    r :
    R
    hr :
    r ∈ c.observed
    c.tildeX H X r = 0
    Proof (Lean source)
    lemma residualize_self_of_mem (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) {X : R → ℝ} (hX : X ∈ H) (r : R) (hr : r ∈ c.observed) : c.tildeX H X r = 0 := by simp only [tildeX_eq, Pi.sub_apply] rw [c.proj_apply_of_mem H hX r hr] ring
    Causalean.Panel.Weighted.WeightedSupport.residualize_self_of_mem · Causalean/Panel/Weighted/Subspace.lean:205
  • residualize_idem_apply lemma — Idempotence of M_H on the observed indices: M_H (M_H X) = M_H X on c.observed.
    H :
    Submodule ℝ (R → ℝ)
    X :
    R → ℝ
    r :
    R
    hr :
    r ∈ c.observed
    c.residualize H (c.residualize H X) r = c.residualize H X r
    Proof (Lean source)
    lemma residualize_idem_apply (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) (X : R → ℝ) (r : R) (hr : r ∈ c.observed) : c.residualize H (c.residualize H X) r = c.residualize H X r := by simp only [residualize_apply, Pi.sub_apply] have hkey : c.proj H (X - c.proj H X) r = 0 := by set Z : R → ℝ := X - c.proj H X set W : R → ℝ := c.proj H Z have hWmem : W ∈ H := c.proj_mem H Z have h1 : c.ip Z W = 0 := c.proj_orthogonal H X hWmem have h2 : c.ip (Z - W) W = 0 := c.proj_orthogonal H Z hWmem have h3 : c.ip W W = 0 := by have hZ : Z = (Z - W) + W := (sub_add_cancel Z W).symm have hsplit : c.ip Z W = c.ip (Z - W) W + c.ip W W := by calc c.ip Z W = c.ip ((Z - W) + W) W := by rw [← hZ] _ = c.ip (Z - W) W + c.ip W W := c.ip_add_left _ _ _ have hsum : c.ip (Z - W) W + c.ip W W = 0 := hsplit ▸ h1 have : c.ip W W = 0 := by have := hsum rw [h2, zero_add] at this exact this exact this have hzero : ∀ s ∈ c.observed, W s = 0 := (c.ip_self_eq_zero_iff W).mp h3 exact hzero r hr change (X - c.proj H X) r - c.proj H (X - c.proj H X) r = (X - c.proj H X) r rw [hkey, sub_zero]
    Causalean.Panel.Weighted.WeightedSupport.residualize_idem_apply · Causalean/Panel/Weighted/Subspace.lean:214
  • tildeXVec_apply lemma — The residualized vector array applies scalar residualization to the chosen column.
    H :
    Submodule ℝ (R → ℝ)
    X :
    J → R → ℝ
    k :
    J
    c.tildeXVec H X k = c.tildeX H (X k)
    Proof (Lean source)
    @[simp] lemma tildeXVec_apply (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) (X : J → R → ℝ) (k : J) : c.tildeXVec H X k = c.tildeX H (X k) := rfl
    Causalean.Panel.Weighted.WeightedSupport.tildeXVec_apply · Causalean/Panel/Weighted/Subspace.lean:253
Additive­Span 4 core · 1 supporting This file defines AdditiveSpan, the linear subspace of finite arrays that decompose additively through two index maps. ★ const_mem

Additive Two-Axis Spans

This file defines AdditiveSpan, the linear subspace of finite arrays that decompose additively through two index maps. It provides the generic algebra behind two-way fixed-effect nuisance spaces, the product-index specialization twoAxisAdditiveSpan, and the unit/time membership predicate IsUnitTimeAdditive. The main public facts expose membership, constants in the span, and finite dimensionality over a finite support.

def AdditiveSpan reviewed
Causalean.Panel.Weighted

The additive span of two projections f₁ : R → A and f₂ : R → B: the subspace of R → ℝ consisting of arrays h r = a (f₁ r) + b (f₂ r) for some a : A → ℝ and b : B → ℝ.

Definition (Lean source)
def AdditiveSpan {R A B : Type*} (f₁ : R → A) (f₂ : R → B) : Submodule ℝ (R → ℝ) where carrier := { h | ∃ a : A → ℝ, ∃ b : B → ℝ, ∀ r : R, h r = a (f₁ r) + b (f₂ r) } zero_mem' := ⟨fun _ => 0, fun _ => 0, by intro r; simp⟩ add_mem' := by rintro h₁ h₂ ⟨a₁, b₁, hh₁⟩ ⟨a₂, b₂, hh₂⟩ refine ⟨a₁ + a₂, b₁ + b₂, ?_⟩ intro r simp [hh₁ r, hh₂ r, Pi.add_apply]; ring smul_mem' := by rintro s h ⟨a, b, hh⟩ refine ⟨s • a, s • b, ?_⟩ intro r simp [hh r, Pi.smul_apply, smul_eq_mul]; ring
Causalean.Panel.Weighted.AdditiveSpan · Causalean/Panel/Weighted/AdditiveSpan.lean:58
lemma const_mem reviewed
Causalean.Panel.Weighted.AdditiveSpan

The constant function equal to c₀ belongs to the additive span generated by two feature maps f₁ and f₂; it is witnessed by taking the f₁-component function constantly c₀ and the f₂-component function constantly 0.

Formal statement
f₁ :
R → A
f₂ :
R → B
c₀ :
(fun _ : R => c₀) ∈ AdditiveSpan f₁ f₂
Proof (Lean source)
lemma const_mem (f₁ : R → A) (f₂ : R → B) (c₀ : ℝ) : (fun _ : R => c₀) ∈ AdditiveSpan f₁ f₂ := by refine ⟨fun _ => c₀, fun _ => 0, ?_⟩ intro r; simp
Causalean.Panel.Weighted.AdditiveSpan.const_mem · Causalean/Panel/Weighted/AdditiveSpan.lean:86 · uses AdditiveSpan
def twoAxisAdditiveSpan reviewed
Causalean.Panel.Weighted

The two-axis additive span for the product index R = I × T: specializes AdditiveSpan to f₁ = Prod.fst, f₂ = Prod.snd.

Definition (Lean source)
def twoAxisAdditiveSpan (I T : Type*) : Submodule ℝ ((I × T) → ℝ) := AdditiveSpan (Prod.fst : I × T → I) (Prod.snd : I × T → T)
Causalean.Panel.Weighted.twoAxisAdditiveSpan · Causalean/Panel/Weighted/AdditiveSpan.lean:105
def IsUnitTimeAdditive reviewed
Causalean.Panel.Weighted

Predicate for the unit/time additive class h i t = a i + b t.

Definition (Lean source)
def IsUnitTimeAdditive {Unit Time : Type*} (h : Unit → Time → ℝ) : Prop := ∃ a : Unit → ℝ, ∃ b : Time → ℝ, ∀ i t, h i t = a i + b t
Causalean.Panel.Weighted.IsUnitTimeAdditive · Causalean/Panel/Weighted/AdditiveSpan.lean:110
1 supporting declaration (lemmas, instances)
  • mem_iff lemma — Membership unfolding for AdditiveSpan.
    h :
    R → ℝ
    h ∈ AdditiveSpan f₁ f₂ ↔ ∃ a : A → ℝ, ∃ b : B → ℝ, ∀ r : R, h r = a (f₁ r) + b (f₂ r)
    Proof (Lean source)
    lemma mem_iff {h : R → ℝ} : h ∈ AdditiveSpan f₁ f₂ ↔ ∃ a : A → ℝ, ∃ b : B → ℝ, ∀ r : R, h r = a (f₁ r) + b (f₂ r) := Iff.rfl
    Causalean.Panel.Weighted.AdditiveSpan.mem_iff · Causalean/Panel/Weighted/AdditiveSpan.lean:80
FWL 5 core · 6 supporting This file states and proves the finite weighted-support Frisch-Waugh-Lovell identity. ★ fwl_identity

Weighted Frisch-Waugh-Lovell Identity

This file states and proves the finite weighted-support Frisch-Waugh-Lovell identity. It constructs the residualized Gram matrix Q_XX, residualized score vector rhsVec, residualized coefficient thetaHat, and rank condition RankCondition. The lemma Q_XX_mulVec_thetaHat proves that thetaHat solves the residualized normal equations, and the theorem fwl_identity proves that any long weighted least-squares minimizer has coefficient thetaHat after residualizing against the nuisance space.

def Q_XX reviewed
Causalean.Panel.Weighted.WeightedSupport

Residualized regressor Gram matrix Q_XX = ⟨M_H X, M_H X⟩_ω.

Definition (Lean source)
noncomputable def Q_XX (c : WeightedSupport R) (X : Fin K → R → ℝ) (H : Submodule ℝ (R → ℝ)) : Matrix (Fin K) (Fin K) ℝ := c.ipMat (c.tildeXVec H X) (c.tildeXVec H X)
Causalean.Panel.Weighted.WeightedSupport.Q_XX · Causalean/Panel/Weighted/FWL.lean:66 · uses WeightedSupport
def rhsVec reviewed
Causalean.Panel.Weighted.WeightedSupport

Residualized FWL right-hand side ⟨M_H X, Y⟩_ω.

Definition (Lean source)
noncomputable def rhsVec (c : WeightedSupport R) (X : Fin K → R → ℝ) (H : Submodule ℝ (R → ℝ)) (Y : R → ℝ) : Fin K → ℝ := fun j => c.ip (c.tildeX H (X j)) Y
Causalean.Panel.Weighted.WeightedSupport.rhsVec · Causalean/Panel/Weighted/FWL.lean:78 · uses WeightedSupport
def thetaHat reviewed
Causalean.Panel.Weighted.WeightedSupport

Residualized weighted least-squares coefficient θ̂ = Q_XX⁻¹ ⟨M_H X, Y⟩_ω.

Definition (Lean source)
noncomputable def thetaHat (c : WeightedSupport R) (X : Fin K → R → ℝ) (H : Submodule ℝ (R → ℝ)) (Y : R → ℝ) : Fin K → ℝ := (Q_XX c X H)⁻¹.mulVec (rhsVec c X H Y)
Causalean.Panel.Weighted.WeightedSupport.thetaHat · Causalean/Panel/Weighted/FWL.lean:89 · uses WeightedSupport
def RankCondition reviewed
Causalean.Panel.Weighted.WeightedSupport

Rank condition for the residualized regressors: Q_XX is invertible.

Definition (Lean source)
def RankCondition (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) (X : Fin K → R → ℝ) : Prop := IsUnit (Q_XX c X H).det
Causalean.Panel.Weighted.WeightedSupport.RankCondition · Causalean/Panel/Weighted/FWL.lean:95 · uses WeightedSupport
theorem fwl_identity reviewed
Causalean.Panel.Weighted.WeightedSupport

Frisch–Waugh–Lovell at the WeightedSupport level. Assume the residualized-regressor Gram matrix Q_XX is invertible (the rank condition). Then whenever a coefficient vector β together with a nuisance term α ∈ H jointly minimizes the weighted least-squares objective c.ip (Y − ∑ₖ βₖ·Xₖ − α) (Y − ∑ₖ βₖ·Xₖ − α) over all coefficient/nuisance pairs, β must equal the short-regression residualized coefficient thetaHat c X H Y.

Formal statement
H :
Submodule ℝ (R → ℝ)
X :
Fin K → R → ℝ
Y :
R → ℝ
hRank :
c.RankCondition H X
∀ β : Fin K → ℝ,
∀ α : R → ℝ,
α ∈ H → (∀ β' : Fin K → ℝ, ∀ α' : R → ℝ, α' ∈ H → c.ip (Y - (∑ k, β k • X k) - α) (Y - (∑ k, β k • X k) - α) ≤ c.ip (Y - (∑ k, β' k • X k) - α') (Y - (∑ k, β' k • X k) - α')) → β
= thetaHat c X H Y
Proof (Lean source)
theorem fwl_identity (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) (X : Fin K → R → ℝ) (Y : R → ℝ) (hRank : c.RankCondition H X) : ∀ β : Fin K → ℝ, ∀ α : R → ℝ, α ∈ H → (∀ β' : Fin K → ℝ, ∀ α' : R → ℝ, α' ∈ H → c.ip (Y - (∑ k, β k • X k) - α) (Y - (∑ k, β k • X k) - α) ≤ c.ip (Y - (∑ k, β' k • X k) - α') (Y - (∑ k, β' k • X k) - α')) → β = thetaHat c X H Y := by intro β α hα hmin -- Step 1: Set up the residual `R₀ := Y - ∑ k β k • X k - α`. set R₀ : R → ℝ := Y - (∑ k, β k • X k) - α with hR₀_def -- Step 2: Derive joint orthogonality from joint minimality. -- -- (a) Varying α while fixing β: for any `g ∈ H`, the test point -- `(β, α + t • g) ∈ Fin K → ℝ × H` gives a one-parameter family. -- The residual at the test point is `R₀ - t • g`. -- Minimality gives `⟨R₀, g⟩_ω = 0` for all `g ∈ H`. have h_orth_H : ∀ g ∈ H, c.ip R₀ g = 0 := by intro g hg -- Apply the WLS first-order condition: `R₀ = Y - fitted β X - α`, -- treat as `(Y - fitted β X)` projected on `H` with candidate `α`. -- Specialize hmin to varying α only. have hmin_alpha : ∀ α' ∈ H, c.ip (Y - (∑ k, β k • X k) - α) (Y - (∑ k, β k • X k) - α) ≤ c.ip (Y - (∑ k, β k • X k) - α') (Y - (∑ k, β k • X k) - α') := by intro α' hα' exact hmin β α' hα' -- Use residualize_orth_iff_argmin with X := Y - fitted β X, p := α. have := (c.residualize_orth_iff_argmin H (Y - (∑ k, β k • X k)) α hα).mpr hmin_alpha exact this g hg -- (b) Varying β_j while fixing α: for any `j : Fin K` and `t : ℝ`, -- the test point `(β + t • e_j, α)` gives residual `R₀ - t • X j`. -- The minimality + perturbation argument forces `⟨R₀, X j⟩_ω = 0`. have h_orth_X : ∀ j : Fin K, c.ip R₀ (X j) = 0 := by intro j -- Build the perturbation: replace β by β + t • e_j. -- Specialize hmin to such perturbations. have hkey : ∀ t : ℝ, c.ip R₀ R₀ ≤ c.ip (R₀ - t • X j) (R₀ - t • X j) := by intro t -- β' := β + t • (Pi.single j 1). Then `∑ k β' k • X k = (∑ k β k • X k) + t • X j`. let δ : Fin K → ℝ := Pi.single j t let β' : Fin K → ℝ := β + δ have hsum_eq : (∑ k, β' k • X k) = (∑ k, β k • X k) + t • X j := by have hsplit : ∀ k, β' k • X k = β k • X k + δ k • X k := by intro k; simp only [β', Pi.add_apply, add_smul] rw [Finset.sum_congr rfl (fun k _ => hsplit k)] rw [Finset.sum_add_distrib] congr 1 rw [Finset.sum_eq_single j] · simp [δ, Pi.single_eq_same] · intro k _ hk simp [δ, Pi.single_eq_of_ne hk] · intro h; exact absurd (Finset.mem_univ j) h have hmin' := hmin β' α hα have heq : Y - (∑ k, β' k • X k) - α = R₀ - t • X j := by rw [hsum_eq, hR₀_def] ext s; simp; ring rw [heq] at hmin' exact hmin' -- Now apply the perturbation argument: quadratic-in-t inequality. have hquad : ∀ t : ℝ, 0 ≤ - (2 * t * c.ip R₀ (X j)) + t^2 * c.ip (X j) (X j) := by intro t have := hkey t have hexp := c.ip_sub_smul_expand R₀ 0 (X j) t -- ip_sub_smul_expand: `c.ip (X - p - t • h) ... = ⟨X-p,X-p⟩ - 2t⟨X-p,h⟩ + t²⟨h,h⟩`. -- Specialize at X := R₀, p := 0, h := X j. simp only [sub_zero] at hexp linarith -- Same case analysis as in WLS. by_cases hzero : c.ip (X j) (X j) = 0 · -- X j vanishes on observed, so `⟨R₀, X j⟩_ω = 0` directly. have hvan : ∀ r ∈ c.observed, X j r = 0 := (c.ip_self_eq_zero_iff (X j)).mp hzero exact c.ip_eq_zero_of_zero_on_observed R₀ (X j) hvan · have hpos : 0 < c.ip (X j) (X j) := lt_of_le_of_ne (c.ip_self_nonneg (X j)) (Ne.symm hzero) set a : ℝ := c.ip R₀ (X j) with ha set b : ℝ := c.ip (X j) (X j) with hb have htest := hquad (a / b) have hsimp : - (2 * (a / b) * a) + (a / b)^2 * b = - a^2 / b := by field_simp; ring rw [hsimp] at htest have ha2 : a^2 ≤ 0 := by have : - a^2 ≥ 0 := by have := (div_nonneg_iff.mp htest).resolve_right ?_ · exact this.1 · push_neg; intro _; exact hpos linarith have ha2nn : 0 ≤ a^2 := sq_nonneg a have ha2eq : a^2 = 0 := le_antisymm ha2 ha2nn exact sq_eq_zero_iff.mp ha2eq -- Step 3: Derive the normal equations `Q_XX β = rhsVec`. -- For each k: `⟨tildeX (X k), Y - ∑ j β j X j⟩_ω = 0` -- (since `tildeX (X k) ⊥ H` absorbs α, and `tildeX (X k) ⊥ ?`). have h_normal : ∀ k : Fin K, ∑ j, β j * c.ip (c.tildeX H (X j)) (c.tildeX H (X k)) = c.ip (c.tildeX H (X k)) Y := by intro k -- Use `ip_tildeX_eq_ip_tildeX_residual` to rewrite both sides into the -- tildeX-tildeX form, then apply orthogonality of residuals. -- Strategy: from h_orth_X applied to j-coordinate, we have -- c.ip R₀ (X j) = 0. -- Expand R₀ = Y - (∑ β j • X j) - α. -- So `c.ip Y (X k) - ∑ j β j • c.ip (X j) (X k) - c.ip α (X k) = 0`. -- But we want to work with tildeX. Use the lemma: residualizing one side -- of an inner product equals taking ⟨tildeX, tildeX⟩. -- -- Cleaner route: compute c.ip R₀ (tildeX H (X k)). -- Since tildeX H (X k) ⊥ H, c.ip α (tildeX H (X k)) = 0. -- Since tildeX H (X k) = X k - proj H (X k), and `c.ip R₀ g = 0` for g ∈ H: -- c.ip R₀ (tildeX H (X k)) = c.ip R₀ (X k) - c.ip R₀ (proj H (X k)) -- = 0 - 0 = 0. have hR₀_tilde : c.ip R₀ (c.tildeX H (X k)) = 0 := by -- tildeX H (X k) = X k + (- proj H (X k)) have hsplit : c.tildeX H (X k) = X k + (- c.proj H (X k)) := by simp [tildeX_eq, sub_eq_add_neg] rw [hsplit, c.ip_add_right] have h2 : c.ip R₀ (-c.proj H (X k)) = - c.ip R₀ (c.proj H (X k)) := by have heq : (-c.proj H (X k) : R → ℝ) = (-1 : ℝ) • c.proj H (X k) := by ext s; simp rw [heq, c.ip_smul_right]; ring rw [h_orth_X k, h2, h_orth_H (c.proj H (X k)) (c.proj_mem H (X k))]; ring -- Now expand c.ip R₀ (tildeX H (X k)) using bilinearity. have h_expand : c.ip R₀ (c.tildeX H (X k)) = c.ip Y (c.tildeX H (X k)) - ∑ j, β j * c.ip (X j) (c.tildeX H (X k)) - c.ip α (c.tildeX H (X k)) := by have hR₀_split : R₀ = Y - (∑ j, β j • X j) - α := hR₀_def have hsubeq : Y - (∑ j, β j • X j) - α = Y + (-(∑ j, β j • X j)) + (-α) := by ext s; simp [sub_eq_add_neg] rw [hR₀_split, hsubeq] rw [c.ip_add_left, c.ip_add_left] -- Term 1: c.ip Y (tildeX H (X k)) -- Term 2: c.ip (-(∑ j, β j • X j)) (tildeX H (X k)) -- = -c.ip (∑ j, β j • X j) (tildeX H (X k)) -- = -∑ j, β j * c.ip (X j) (tildeX H (X k)) -- Term 3: c.ip (-α) (tildeX H (X k)) = -c.ip α (tildeX H (X k)) have hneg_sum : c.ip (-(∑ j, β j • X j)) (c.tildeX H (X k)) = -∑ j, β j * c.ip (X j) (c.tildeX H (X k)) := by have heq : (-(∑ j, β j • X j) : R → ℝ) = (-1 : ℝ) • (∑ j, β j • X j) := by ext s; simp rw [heq, c.ip_smul_left, c.ip_sum_left] have hinner : ∀ j, c.ip (β j • X j) (c.tildeX H (X k)) = β j * c.ip (X j) (c.tildeX H (X k)) := by intro j; rw [c.ip_smul_left] rw [Finset.sum_congr rfl (fun j _ => hinner j)] ring have hneg_α : c.ip (-α) (c.tildeX H (X k)) = -c.ip α (c.tildeX H (X k)) := by have : (-α : R → ℝ) = (-1 : ℝ) • α := by ext s; simp rw [this, c.ip_smul_left]; ring rw [hneg_sum, hneg_α]; ring -- c.ip α (tildeX H (X k)) = 0 because tildeX ⊥ H and α ∈ H. have hα_tilde : c.ip α (c.tildeX H (X k)) = 0 := by rw [c.ip_symm] exact c.residualize_in_orthogonal H (X k) hα -- c.ip (X j) (tildeX H (X k)) = c.ip (tildeX H (X j)) (tildeX H (X k)). have hX_tilde : ∀ j, c.ip (X j) (c.tildeX H (X k)) = c.ip (c.tildeX H (X j)) (c.tildeX H (X k)) := by intro j rw [c.ip_symm (X j), c.ip_symm (c.tildeX H (X j))] exact c.ip_tildeX_eq_ip_tildeX_residual H X (X j) k -- c.ip Y (tildeX H (X k)) = c.ip (tildeX H (X k)) Y. have hY_symm : c.ip Y (c.tildeX H (X k)) = c.ip (c.tildeX H (X k)) Y := c.ip_symm _ _ -- Substitute everything into h_expand combined with hR₀_tilde = 0. rw [hα_tilde, sub_zero] at h_expand rw [hY_symm] at h_expand have : ∑ j, β j * c.ip (X j) (c.tildeX H (X k)) = ∑ j, β j * c.ip (c.tildeX H (X j)) (c.tildeX H (X k)) := by refine Finset.sum_congr rfl ?_ intro j _; rw [hX_tilde j] rw [this] at h_expand linarith [hR₀_tilde] -- Step 4: convert h_normal to `Q_XX.mulVec β = rhsVec`. have hmat : (Q_XX c X H).mulVec β = rhsVec c X H Y := by funext k simp only [mulVec, dotProduct, Q_XX_apply, rhsVec_apply] -- dotProduct: ∑ j, Q_XX k j * β j = ∑ j, c.ip (tildeX (X k)) (tildeX (X j)) * β j have hk := h_normal k -- h_normal: ∑ j, β j * c.ip (tildeX (X j)) (tildeX (X k)) = c.ip (tildeX (X k)) Y. -- Need: ∑ j, c.ip (tildeX (X k)) (tildeX (X j)) * β j = c.ip (tildeX (X k)) Y. -- These match by symmetry of c.ip and commutativity of multiplication. rw [← hk] refine Finset.sum_congr rfl ?_ intro j _ rw [c.ip_symm (c.tildeX H (X k)) (c.tildeX H (X j))] ring -- Step 5: β = Q_XX⁻¹ (Q_XX β) = Q_XX⁻¹ rhsVec = thetaHat. unfold thetaHat have : (Q_XX c X H)⁻¹.mulVec ((Q_XX c X H).mulVec β) = (Q_XX c X H)⁻¹.mulVec (rhsVec c X H Y) := by rw [hmat] rw [Matrix.mulVec_mulVec] at this rw [Matrix.nonsing_inv_mul _ hRank, Matrix.one_mulVec] at this exact this
Causalean.Panel.Weighted.WeightedSupport.fwl_identity · Causalean/Panel/Weighted/FWL.lean:154 · uses WeightedSupport , RankCondition , ip , thetaHat
6 supporting declarations (lemmas, instances)
  • Q_XX_apply lemma — Each entry of the residualized Gram matrix is the weighted inner product of the corresponding residualized regressors.
    X :
    Fin K → R → ℝ
    H :
    Submodule ℝ (R → ℝ)
    j k :
    Fin K
    Q_XX c X H j k = c.ip (c.tildeX H (X j)) (c.tildeX H (X k))
    Proof (Lean source)
    @[simp] lemma Q_XX_apply (c : WeightedSupport R) (X : Fin K → R → ℝ) (H : Submodule ℝ (R → ℝ)) (j k : Fin K) : Q_XX c X H j k = c.ip (c.tildeX H (X j)) (c.tildeX H (X k)) := rfl
    Causalean.Panel.Weighted.WeightedSupport.Q_XX_apply · Causalean/Panel/Weighted/FWL.lean:71
  • rhsVec_apply lemma — Each entry of the residualized right-hand side is the weighted inner product of a residualized regressor with the outcome.
    X :
    Fin K → R → ℝ
    H :
    Submodule ℝ (R → ℝ)
    Y :
    R → ℝ
    j :
    Fin K
    rhsVec c X H Y j = c.ip (c.tildeX H (X j)) Y
    Proof (Lean source)
    @[simp] lemma rhsVec_apply (c : WeightedSupport R) (X : Fin K → R → ℝ) (H : Submodule ℝ (R → ℝ)) (Y : R → ℝ) (j : Fin K) : rhsVec c X H Y j = c.ip (c.tildeX H (X j)) Y := rfl
    Causalean.Panel.Weighted.WeightedSupport.rhsVec_apply · Causalean/Panel/Weighted/FWL.lean:83
  • Q_XX_mulVec_thetaHat lemma — Under nonsingularity, thetaHat solves the residualized normal equations.
    X :
    Fin K → R → ℝ
    H :
    Submodule ℝ (R → ℝ)
    Y :
    R → ℝ
    hQ :
    IsUnit (Q_XX c X H).det
    (Q_XX c X H).mulVec (thetaHat c X H Y) = rhsVec c X H Y
    Proof (Lean source)
    lemma Q_XX_mulVec_thetaHat (c : WeightedSupport R) (X : Fin K → R → ℝ) (H : Submodule ℝ (R → ℝ)) (Y : R → ℝ) (hQ : IsUnit (Q_XX c X H).det) : (Q_XX c X H).mulVec (thetaHat c X H Y) = rhsVec c X H Y := by unfold thetaHat rw [Matrix.mulVec_mulVec, Matrix.mul_nonsing_inv _ hQ, Matrix.one_mulVec]
    Causalean.Panel.Weighted.WeightedSupport.Q_XX_mulVec_thetaHat · Causalean/Panel/Weighted/FWL.lean:100
  • ip_sum_left_finset lemma — For a weighted inner product, the inner product of a finite sum of functions with another function equals the corresponding finite sum of inner products.
    ι :
    Type*
    s :
    f :
    ι → R → ℝ
    B :
    R → ℝ
    c.ip (∑ i ∈ s, f i) B = ∑ i ∈ s, c.ip (f i) B
    Proof (Lean source)
    lemma ip_sum_left_finset (c : WeightedSupport R) {ι : Type*} (s : Finset ι) (f : ι → R → ℝ) (B : R → ℝ) : c.ip (∑ i ∈ s, f i) B = ∑ i ∈ s, c.ip (f i) B := by classical induction s using Finset.induction_on with | empty => simp [ip] | insert a s' hk ih => rw [Finset.sum_insert hk, Finset.sum_insert hk, c.ip_add_left, ih]
    Causalean.Panel.Weighted.WeightedSupport.ip_sum_left_finset · Causalean/Panel/Weighted/FWL.lean:114
  • ip_sum_right lemma — The weighted inner product of a function with a finite sum of functions equals the sum of its weighted inner products with the summands.
    A :
    R → ℝ
    f :
    Fin K → R → ℝ
    c.ip A (∑ k, f k) = ∑ k, c.ip A (f k)
    Proof (Lean source)
    lemma ip_sum_right (c : WeightedSupport R) (A : R → ℝ) (f : Fin K → R → ℝ) : c.ip A (∑ k, f k) = ∑ k, c.ip A (f k) := by rw [c.ip_symm, c.ip_sum_left] refine Finset.sum_congr rfl ?_ intro k _; exact c.ip_symm _ _
    Causalean.Panel.Weighted.WeightedSupport.ip_sum_right · Causalean/Panel/Weighted/FWL.lean:130
  • ip_tildeX_eq_ip_tildeX_residual lemma — A regressor residualized against a control space has the same weighted inner product with any function as with that function after residualizing it against the same control space.
    H :
    Submodule ℝ (R → ℝ)
    X :
    Fin K → R → ℝ
    A :
    R → ℝ
    k :
    Fin K
    c.ip (c.tildeX H (X k)) A = c.ip (c.tildeX H (X k)) (c.tildeX H A)
    Proof (Lean source)
    lemma ip_tildeX_eq_ip_tildeX_residual (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) (X : Fin K → R → ℝ) (A : R → ℝ) (k : Fin K) : c.ip (c.tildeX H (X k)) A = c.ip (c.tildeX H (X k)) (c.tildeX H A) := by have h1 : c.ip (c.tildeX H (X k)) (c.proj H A) = 0 := by have hsymm := c.ip_symm (c.tildeX H (X k)) (c.proj H A) rw [hsymm] rw [c.ip_symm] exact c.residualize_in_orthogonal H (X k) (c.proj_mem H A) have hAsplit : A = c.tildeX H A + c.proj H A := by simp [tildeX_eq] conv_lhs => rw [hAsplit] rw [c.ip_add_right, h1, add_zero]
    Causalean.Panel.Weighted.WeightedSupport.ip_tildeX_eq_ip_tildeX_residual · Causalean/Panel/Weighted/FWL.lean:139
Indicator­Span 7 core · 8 supporting This file provides finite-cell partition algebra over a weighted support. ★ cellMean_mul_cellMass

Indicator spans and partition-cell statistics

This file provides finite-cell partition algebra over a weighted support. It defines singleton cell indicators cellIndicator, one-axis spans indicatorSpan, two-axis spans twoAxisIndicatorSpan, and weighted partition-cell statistics WeightedSupport.cellMass, cellMean, and jointCellMass.

The declarations are the finite-support interface for nuisance spaces generated by classifier cells and for weighted averages over positive-mass partition cells.

def cellIndicator reviewed
Causalean.Panel.Weighted

The cell indicator is one on records classified into a given cell and zero elsewhere.

Definition (Lean source)
def cellIndicator {R 𝒢 : Type*} [DecidableEq 𝒢] (G : R → 𝒢) (g : 𝒢) : R → ℝ := fun r => if G r = g then (1 : ℝ) else 0
Causalean.Panel.Weighted.cellIndicator · Causalean/Panel/Weighted/IndicatorSpan.lean:52
def indicatorSpan reviewed
Causalean.Panel.Weighted

The one-axis indicator span contains exactly the finite linear combinations of singleton indicators for one classifier.

Definition (Lean source)
def indicatorSpan {R 𝒢 : Type*} [Fintype 𝒢] [DecidableEq 𝒢] (G : R → 𝒢) : Submodule ℝ (R → ℝ) where carrier := { f | ∃ c : 𝒢 → ℝ, ∀ r : R, f r = ∑ g, c g * cellIndicator G g r } zero_mem' := by refine ⟨fun _ => 0, ?_⟩ intro r; simp add_mem' := by rintro f₁ f₂ ⟨c₁, hc₁⟩ ⟨c₂, hc₂⟩ refine ⟨fun g => c₁ g + c₂ g, ?_⟩ intro r have : f₁ r + f₂ r = (∑ g, c₁ g * cellIndicator G g r) + ∑ g, c₂ g * cellIndicator G g r := by rw [hc₁ r, hc₂ r] calc (f₁ + f₂) r = f₁ r + f₂ r := rfl _ = (∑ g, c₁ g * cellIndicator G g r) + ∑ g, c₂ g * cellIndicator G g r := this _ = ∑ g, (c₁ g + c₂ g) * cellIndicator G g r := by rw [← Finset.sum_add_distrib] refine Finset.sum_congr rfl ?_ intro g _ ring smul_mem' := by rintro s f ⟨c, hc⟩ refine ⟨fun g => s * c g, ?_⟩ intro r have hsr : (s • f) r = s * f r := rfl rw [hsr, hc r] calc s * ∑ g, c g * cellIndicator G g r = ∑ g, s * (c g * cellIndicator G g r) := Finset.mul_sum _ _ _ _ = ∑ g, (s * c g) * cellIndicator G g r := by refine Finset.sum_congr rfl ?_ intro g _ ring
Causalean.Panel.Weighted.indicatorSpan · Causalean/Panel/Weighted/IndicatorSpan.lean:66
def twoAxisIndicatorSpan reviewed
Causalean.Panel.Weighted

The two-axis indicator span contains sums of one-axis indicator functions from two classifiers.

Definition (Lean source)
def twoAxisIndicatorSpan {R 𝒢 𝒯 : Type*} [Fintype 𝒢] [DecidableEq 𝒢] [Fintype 𝒯] [DecidableEq 𝒯] (G : R → 𝒢) (T : R → 𝒯) : Submodule ℝ (R → ℝ) := indicatorSpan G ⊔ indicatorSpan T
Causalean.Panel.Weighted.twoAxisIndicatorSpan · Causalean/Panel/Weighted/IndicatorSpan.lean:135
def cellMass reviewed
Causalean.Panel.Weighted.WeightedSupport

The cell mass is the total weight of observed records in one classifier cell.

Definition (Lean source)
def cellMass {𝒢 : Type*} [DecidableEq 𝒢] (c : WeightedSupport R) (G : R → 𝒢) (g : 𝒢) : ℝ := ∑ r ∈ c.observed, c.weight r * cellIndicator G g r
Causalean.Panel.Weighted.WeightedSupport.cellMass · Causalean/Panel/Weighted/IndicatorSpan.lean:162 · uses WeightedSupport
def cellMean reviewed
Causalean.Panel.Weighted.WeightedSupport

On a classifier cell with positive observed mass, the cell mean is the ordinary weighted average of the outcome over observed records in that cell.

Definition (Lean source)
noncomputable def cellMean {𝒢 : Type*} [DecidableEq 𝒢] (c : WeightedSupport R) (F : R → ℝ) (G : R → 𝒢) (g : 𝒢) (_hpos : 0 < c.cellMass G g) : ℝ := (∑ r ∈ c.observed, c.weight r * F r * cellIndicator G g r) / c.cellMass G g
Causalean.Panel.Weighted.WeightedSupport.cellMean · Causalean/Panel/Weighted/IndicatorSpan.lean:185 · uses WeightedSupport , cellMass
lemma cellMean_mul_cellMass reviewed
Causalean.Panel.Weighted.WeightedSupport

On a classifier cell g with strictly positive total weight, multiplying the cell mean of F by the cell's mass recovers the weighted sum of F over observed records in that cell.

Formal statement
𝒢 :
Type*
F :
R → ℝ
G :
R → 𝒢
g :
𝒢
hpos :
0 < c.cellMass G g
c.cellMean F G g hpos * c.cellMass G g
= ∑ r ∈ c.observed, c.weight r * F r * cellIndicator G g r
Proof (Lean source)
lemma cellMean_mul_cellMass {𝒢 : Type*} [DecidableEq 𝒢] (c : WeightedSupport R) (F : R → ℝ) (G : R → 𝒢) (g : 𝒢) (hpos : 0 < c.cellMass G g) : c.cellMean F G g hpos * c.cellMass G g = ∑ r ∈ c.observed, c.weight r * F r * cellIndicator G g r := by unfold cellMean exact div_mul_cancel₀ _ (ne_of_gt hpos)
Causalean.Panel.Weighted.WeightedSupport.cellMean_mul_cellMass · Causalean/Panel/Weighted/IndicatorSpan.lean:195 · uses WeightedSupport , cellMass , cellMean , cellIndicator
def jointCellMass reviewed
Causalean.Panel.Weighted.WeightedSupport

The joint cell mass is the total weight of observed records lying in a given pair of classifier cells.

Definition (Lean source)
def jointCellMass {𝒢 𝒯 : Type*} [DecidableEq 𝒢] [DecidableEq 𝒯] (c : WeightedSupport R) (G : R → 𝒢) (T : R → 𝒯) (g : 𝒢) (t : 𝒯) : ℝ := ∑ r ∈ c.observed, c.weight r * cellIndicator G g r * cellIndicator T t r
Causalean.Panel.Weighted.WeightedSupport.jointCellMass · Causalean/Panel/Weighted/IndicatorSpan.lean:206 · uses WeightedSupport
8 supporting declarations (lemmas, instances)
  • cellIndicator_apply lemma — The cell indicator evaluates by checking whether the record belongs to the chosen classifier cell.
    R 𝒢 :
    Type*
    G :
    R → 𝒢
    g :
    𝒢
    r :
    R
    cellIndicator G g r = if G r = g then (1 : ℝ) else 0
    Proof (Lean source)
    @[simp] lemma cellIndicator_apply {R 𝒢 : Type*} [DecidableEq 𝒢] (G : R → 𝒢) (g : 𝒢) (r : R) : cellIndicator G g r = if G r = g then (1 : ℝ) else 0 := rfl
    Causalean.Panel.Weighted.cellIndicator_apply · Causalean/Panel/Weighted/IndicatorSpan.lean:58
  • mem_indicatorSpan_iff lemma — Membership in the one-axis indicator span is equivalent to having coefficients on the classifier cells whose weighted sum reproduces the array.
    R 𝒢 :
    Type*
    Fintype 𝒢
    G :
    R → 𝒢
    f :
    R → ℝ
    f ∈ indicatorSpan G ↔ ∃ c : 𝒢 → ℝ, ∀ r : R, f r = ∑ g, c g * cellIndicator G g r
    Proof (Lean source)
    lemma mem_indicatorSpan_iff {R 𝒢 : Type*} [Fintype 𝒢] [DecidableEq 𝒢] (G : R → 𝒢) (f : R → ℝ) : f ∈ indicatorSpan G ↔ ∃ c : 𝒢 → ℝ, ∀ r : R, f r = ∑ g, c g * cellIndicator G g r := Iff.rfl
    Causalean.Panel.Weighted.mem_indicatorSpan_iff · Causalean/Panel/Weighted/IndicatorSpan.lean:103
  • cellIndicator_mem_indicatorSpan lemma — Each singleton cell indicator belongs to the span generated by all cells of the same classifier.
    R 𝒢 :
    Type*
    Fintype 𝒢
    G :
    R → 𝒢
    g :
    𝒢
    cellIndicator G g ∈ indicatorSpan G
    Proof (Lean source)
    lemma cellIndicator_mem_indicatorSpan {R 𝒢 : Type*} [Fintype 𝒢] [DecidableEq 𝒢] (G : R → 𝒢) (g : 𝒢) : cellIndicator G g ∈ indicatorSpan G := by classical refine ⟨fun g' => if g' = g then (1 : ℝ) else 0, ?_⟩ intro r -- exactly one summand survives (the one with `g' = g`); equals -- `cellIndicator G g r`. have hsum : (∑ g' ∈ (Finset.univ : Finset 𝒢), (if g' = g then (1 : ℝ) else 0) * cellIndicator G g' r) = (if g = g then (1 : ℝ) else 0) * cellIndicator G g r := by refine Finset.sum_eq_single g ?_ ?_ · intro b _ hbne simp [hbne] · intro hnot exact elim (hnot (Finset.mem_univ _)) rw [hsum] simp
    Causalean.Panel.Weighted.cellIndicator_mem_indicatorSpan · Causalean/Panel/Weighted/IndicatorSpan.lean:111
  • indicatorSpan_le_twoAxisIndicatorSpan lemma — The first classifier's indicator span is contained in the two-axis indicator span.
    R 𝒢 𝒯 :
    Type*
    Fintype 𝒢
    Fintype 𝒯
    G :
    R → 𝒢
    T :
    R → 𝒯
    indicatorSpan G ≤ twoAxisIndicatorSpan G T
    Proof (Lean source)
    lemma indicatorSpan_le_twoAxisIndicatorSpan {R 𝒢 𝒯 : Type*} [Fintype 𝒢] [DecidableEq 𝒢] [Fintype 𝒯] [DecidableEq 𝒯] (G : R → 𝒢) (T : R → 𝒯) : indicatorSpan G ≤ twoAxisIndicatorSpan G T := le_sup_left
    Causalean.Panel.Weighted.indicatorSpan_le_twoAxisIndicatorSpan · Causalean/Panel/Weighted/IndicatorSpan.lean:142
  • indicatorSpan_le_twoAxisIndicatorSpan_right lemma — The second classifier's indicator span is contained in the two-axis indicator span.
    R 𝒢 𝒯 :
    Type*
    Fintype 𝒢
    Fintype 𝒯
    G :
    R → 𝒢
    T :
    R → 𝒯
    indicatorSpan T ≤ twoAxisIndicatorSpan G T
    Proof (Lean source)
    lemma indicatorSpan_le_twoAxisIndicatorSpan_right {R 𝒢 𝒯 : Type*} [Fintype 𝒢] [DecidableEq 𝒢] [Fintype 𝒯] [DecidableEq 𝒯] (G : R → 𝒢) (T : R → 𝒯) : indicatorSpan T ≤ twoAxisIndicatorSpan G T := le_sup_right
    Causalean.Panel.Weighted.indicatorSpan_le_twoAxisIndicatorSpan_right · Causalean/Panel/Weighted/IndicatorSpan.lean:149
  • cellMass_def lemma — The cell mass unfolds to the weighted sum of the corresponding cell indicator over observed records.
    𝒢 :
    Type*
    G :
    R → 𝒢
    g :
    𝒢
    c.cellMass G g = ∑ r ∈ c.observed, c.weight r * cellIndicator G g r
    Proof (Lean source)
    @[simp] lemma cellMass_def {𝒢 : Type*} [DecidableEq 𝒢] (c : WeightedSupport R) (G : R → 𝒢) (g : 𝒢) : c.cellMass G g = ∑ r ∈ c.observed, c.weight r * cellIndicator G g r := rfl
    Causalean.Panel.Weighted.WeightedSupport.cellMass_def · Causalean/Panel/Weighted/IndicatorSpan.lean:168
  • cellMass_nonneg lemma — Every classifier cell has nonnegative total weight.
    𝒢 :
    Type*
    G :
    R → 𝒢
    g :
    𝒢
    0 ≤ c.cellMass G g
    Proof (Lean source)
    lemma cellMass_nonneg {𝒢 : Type*} [DecidableEq 𝒢] (c : WeightedSupport R) (G : R → 𝒢) (g : 𝒢) : 0 ≤ c.cellMass G g := by refine sum_nonneg ?_ intro r hr by_cases h : G r = g · have hw : 0 ≤ c.weight r := (c.weight_pos r hr).le simp [cellIndicator, h, hw] · simp [cellIndicator, h]
    Causalean.Panel.Weighted.WeightedSupport.cellMass_nonneg · Causalean/Panel/Weighted/IndicatorSpan.lean:174
  • jointCellMass_def lemma — The joint cell mass unfolds to the weighted sum of the two corresponding cell indicators over observed records.
    𝒢 𝒯 :
    Type*
    G :
    R → 𝒢
    T :
    R → 𝒯
    g :
    𝒢
    t :
    𝒯
    c.jointCellMass G T g t
    = ∑ r ∈ c.observed, c.weight r * cellIndicator G g r * cellIndicator T t r
    Proof (Lean source)
    @[simp] lemma jointCellMass_def {𝒢 𝒯 : Type*} [DecidableEq 𝒢] [DecidableEq 𝒯] (c : WeightedSupport R) (G : R → 𝒢) (T : R → 𝒯) (g : 𝒢) (t : 𝒯) : c.jointCellMass G T g t = ∑ r ∈ c.observed, c.weight r * cellIndicator G g r * cellIndicator T t r := rfl
    Causalean.Panel.Weighted.WeightedSupport.jointCellMass_def · Causalean/Panel/Weighted/IndicatorSpan.lean:213
Normalized­Weights 2 core · 5 supporting This file develops paper-agnostic finite-sum algebra for normalized weights, weighted centered covariances, and weighted centered variances. ★ weighted_center_cov

Normalized finite weights and pairwise moment identities

This file develops paper-agnostic finite-sum algebra for normalized weights, weighted centered covariances, and weighted centered variances. It defines normalizedWeight, proves the basic nonnegativity and sum-to-one facts normalizedWeight_nonneg and sum_normalizedWeight_eq_one, and proves the pairwise formulas weighted_center_cov and weighted_center_var.

These identities are reusable in regression-weight decompositions where a coefficient is re-expressed as a finite weighted sum over cells or cohorts.

def normalizedWeight reviewed
Causalean.Panel.Weighted.NormalizedWeights

Generic normalized finite weight a_i / Σ_k a_k.

Definition (Lean source)
noncomputable def normalizedWeight {K : Type*} [Field K] (a : ι → K) (i : ι) : K := a i / ∑ k, a k
Causalean.Panel.Weighted.NormalizedWeights.normalizedWeight · Causalean/Panel/Weighted/NormalizedWeights.lean:57
lemma weighted_center_cov reviewed
Causalean.Panel.Weighted.NormalizedWeights

For weights p summing to one over a field where 2 is nonzero, the weighted centered covariance of x and y equals half the average, weighted by p ⊗ p, of the pairwise cross-products of their differences: Σᵢ pᵢ (xᵢ − x̄)(yᵢ − ȳ) = 1/2 Σᵢ Σⱼ pᵢpⱼ (xᵢ − xⱼ)(yᵢ − yⱼ).

Formal statement
K :
Type*
p x y :
ι → K
hp :
∑ i, p i = 1
h2 :
(2 : K) ≠ 0
∑ i, p i * (x i - ∑ j, p j * x j) * (y i - ∑ j, p j * y j)
= (1 / 2) * ∑ i, ∑ j, p i * p j * (x i - x j) * (y i - y j)
Proof (Lean source)
lemma weighted_center_cov {K : Type*} [Field K] (p x y : ι → K) (hp : ∑ i, p i = 1) (h2 : (2 : K) ≠ 0) : ∑ i, p i * (x i - ∑ j, p j * x j) * (y i - ∑ j, p j * y j) = (1 / 2) * ∑ i, ∑ j, p i * p j * (x i - x j) * (y i - y j) := by rw [weighted_center_cov_left p x y hp, pairwise_cov_right p x y hp] simp [h2]
Causalean.Panel.Weighted.NormalizedWeights.weighted_center_cov · Causalean/Panel/Weighted/NormalizedWeights.lean:156
5 supporting declarations (lemmas, instances)
  • normalizedWeight_nonneg lemma — Nonnegativity of normalized weights from nonnegative raw weights and a positive normalizing sum.
    a :
    ι → K
    ha :
    ∀ i, 0 ≤ a i
    hsum :
    0 < ∑ i, a i
    i :
    ι
    0 ≤ normalizedWeight a i
    Proof (Lean source)
    lemma normalizedWeight_nonneg {K : Type*} [Field K] [LinearOrder K] [IsStrictOrderedRing K] (a : ι → K) (ha : ∀ i, 0 ≤ a i) (hsum : 0 < ∑ i, a i) (i : ι) : 0 ≤ normalizedWeight a i := by unfold normalizedWeight exact div_nonneg (ha i) (le_of_lt hsum)
    Causalean.Panel.Weighted.NormalizedWeights.normalizedWeight_nonneg · Causalean/Panel/Weighted/NormalizedWeights.lean:61
  • sum_normalizedWeight_eq_one lemma — Normalized finite weights sum to one when the normalizing sum is nonzero.
    K :
    Type*
    a :
    ι → K
    hsum :
    ∑ i, a i ≠ 0
    ∑ i, normalizedWeight a i = 1
    Proof (Lean source)
    lemma sum_normalizedWeight_eq_one {K : Type*} [Field K] (a : ι → K) (hsum : ∑ i, a i ≠ 0) : ∑ i, normalizedWeight a i = 1 := by unfold normalizedWeight rw [← Finset.sum_div] exact div_self hsum
    Causalean.Panel.Weighted.NormalizedWeights.sum_normalizedWeight_eq_one · Causalean/Panel/Weighted/NormalizedWeights.lean:70
  • weighted_center_cov_left lemma — When finite weights sum to one, the weighted covariance of two centered variables equals their weighted cross-moment minus the product of their weighted means.
    K :
    Type*
    p x y :
    ι → K
    hp :
    ∑ i, p i = 1
    ∑ i, p i * (x i - ∑ j, p j * x j) * (y i - ∑ j, p j * y j)
    = (∑ i, p i * x i * y i) - (∑ j, p j * x j) * (∑ j, p j * y j)
    Proof (Lean source)
    lemma weighted_center_cov_left {K : Type*} [CommRing K] (p x y : ι → K) (hp : ∑ i, p i = 1) : ∑ i, p i * (x i - ∑ j, p j * x j) * (y i - ∑ j, p j * y j) = (∑ i, p i * x i * y i) - (∑ j, p j * x j) * (∑ j, p j * y j) := by classical let mx := ∑ j, p j * x j let my := ∑ j, p j * y j have hpx : (∑ i, (p i * x i) * my) = mx * my := by dsimp [mx] rw [Finset.sum_mul] have hpy : (∑ i, (p i * y i) * mx) = my * mx := by dsimp [my] rw [Finset.sum_mul] have hpmy : (∑ i : ι, p i * mx * my) = mx * my := by calc (∑ i : ι, p i * mx * my) = ∑ i : ι, p i * (mx * my) := by refine Finset.sum_congr rfl ?_ intro i _hi ring _ = (∑ i : ι, p i) * (mx * my) := by exact (Finset.sum_mul (s := univ) (f := fun i : ι => p i) (a := mx * my)).symm _ = mx * my := by rw [hp] ring calc ∑ i, p i * (x i - ∑ j, p j * x j) * (y i - ∑ j, p j * y j) = ∑ i, (p i * x i * y i - (p i * x i) * my - (p i * y i) * mx + p i * mx * my) := by refine Finset.sum_congr rfl ?_ intro i _hi dsimp [mx, my] ring _ = (∑ i, p i * x i * y i) - (∑ i, (p i * x i) * my) - (∑ i, (p i * y i) * mx) + ∑ i, p i * mx * my := by simp only [Finset.sum_add_distrib, Finset.sum_sub_distrib] _ = (∑ i, p i * x i * y i) - mx * my := by rw [hpx, hpy, hpmy] ring _ = (∑ i, p i * x i * y i) - (∑ j, p j * x j) * (∑ j, p j * y j) := by rfl
    Causalean.Panel.Weighted.NormalizedWeights.weighted_center_cov_left · Causalean/Panel/Weighted/NormalizedWeights.lean:78
  • pairwise_cov_right lemma — When finite weights sum to one, the weighted sum of pairwise products of differences equals twice the weighted cross-moment minus twice the product of the weighted means.
    K :
    Type*
    p x y :
    ι → K
    hp :
    ∑ i, p i = 1
    (∑ i, ∑ j, p i * p j * (x i - x j) * (y i - y j))
    = 2 * ((∑ i, p i * x i * y i) - (∑ j, p j * x j) * (∑ j, p j * y j))
    Proof (Lean source)
    lemma pairwise_cov_right {K : Type*} [CommRing K] (p x y : ι → K) (hp : ∑ i, p i = 1) : (∑ i, ∑ j, p i * p j * (x i - x j) * (y i - y j)) = 2 * ((∑ i, p i * x i * y i) - (∑ j, p j * x j) * (∑ j, p j * y j)) := by classical calc (∑ i, ∑ j, p i * p j * (x i - x j) * (y i - y j)) = (∑ i, ∑ j, (((p i * x i * y i) * p j - (p i * x i) * (p j * y j)) - (p i * y i) * (p j * x j) + p i * (p j * x j * y j))) := by refine Finset.sum_congr rfl ?_ intro i _hi refine Finset.sum_congr rfl ?_ intro j _hj ring _ = ((∑ i, p i * x i * y i) * (∑ j, p j)) - ((∑ i, p i * x i) * (∑ j, p j * y j)) - ((∑ i, p i * y i) * (∑ j, p j * x j)) + ((∑ i, p i) * (∑ j, p j * x j * y j)) := by simp only [Finset.sum_add_distrib, Finset.sum_sub_distrib] rw [double_sum_mul (fun i => p i * x i * y i) (fun j => p j)] rw [double_sum_mul (fun i => p i * x i) (fun j => p j * y j)] rw [double_sum_mul (fun i => p i * y i) (fun j => p j * x j)] rw [double_sum_mul (fun i => p i) (fun j => p j * x j * y j)] _ = 2 * ((∑ i, p i * x i * y i) - (∑ j, p j * x j) * (∑ j, p j * y j)) := by rw [hp] ring
    Causalean.Panel.Weighted.NormalizedWeights.pairwise_cov_right · Causalean/Panel/Weighted/NormalizedWeights.lean:123
  • weighted_center_var lemma — Weighted centered variance as half the average pairwise squared gap.
    K :
    Type*
    p x :
    ι → K
    hp :
    ∑ i, p i = 1
    h2 :
    (2 : K) ≠ 0
    ∑ i, p i * (x i - ∑ j, p j * x j)^2 = (1 / 2) * ∑ i, ∑ j, p i * p j * (x i - x j)^2
    Proof (Lean source)
    lemma weighted_center_var {K : Type*} [Field K] (p x : ι → K) (hp : ∑ i, p i = 1) (h2 : (2 : K) ≠ 0) : ∑ i, p i * (x i - ∑ j, p j * x j)^2 = (1 / 2) * ∑ i, ∑ j, p i * p j * (x i - x j)^2 := by have h := weighted_center_cov p x x hp h2 calc ∑ i, p i * (x i - ∑ j, p j * x j)^2 = ∑ i, p i * (x i - ∑ j, p j * x j) * (x i - ∑ j, p j * x j) := by refine Finset.sum_congr rfl ?_ intro i _hi ring _ = (1 / 2) * ∑ i, ∑ j, p i * p j * (x i - x j) * (x i - x j) := h _ = (1 / 2) * ∑ i, ∑ j, p i * p j * (x i - x j)^2 := by congr 1 refine Finset.sum_congr rfl ?_ intro i _hi refine Finset.sum_congr rfl ?_ intro j _hj ring
    Causalean.Panel.Weighted.NormalizedWeights.weighted_center_var · Causalean/Panel/Weighted/NormalizedWeights.lean:168
Of­Probability­Measure 2 core · 1 supporting This file connects the finite weighted-support algebra to probability measures on finite measurable spaces. ★ ip_eq_integral

Weighted supports from probability measures

This file connects the finite weighted-support algebra to probability measures on finite measurable spaces. The construction ofProbabilityMeasure turns point masses into a WeightedSupport whose observed set is the positive-mass support, and ofProbabilityMeasure_weight exposes the resulting atom weights.

The main bridge theorem, ip_eq_integral, identifies the finite weighted inner product with the corresponding L²(μ) integral pairing. This lets measure-theoretic cell bridges and finite weighted-support Frisch-Waugh-Lovell arguments be used interchangeably on a finite probability space.

def ofProbabilityMeasure reviewed
Causalean.Panel.Weighted.WeightedSupport

A probability measure on a finite measurable space induces a weighted support whose weights are point masses and whose observed records have positive mass.

Definition (Lean source)
noncomputable def ofProbabilityMeasure (μ : Measure R) [IsProbabilityMeasure μ] : WeightedSupport R where observed := Finset.univ.filter (fun r => 0 < (μ {r}).toReal) observed_nonempty := by classical by_contra h rw [Finset.not_nonempty_iff_eq_empty] at h -- If no atom is positive, every atom has zero real mass, so the total -- real mass is 0, contradicting `μ.real univ = 1`. have hzero : ∀ r : R, (μ {r}).toReal = 0 := by intro r by_contra hr have hpos : 0 < (μ {r}).toReal := lt_of_le_of_ne ENNReal.toReal_nonneg (Ne.symm hr) have : r ∈ Finset.univ.filter (fun r => 0 < (μ {r}).toReal) := Finset.mem_filter.mpr ⟨Finset.mem_univ r, hpos⟩ rw [h] at this exact absurd this (notMem_empty r) have hsum : ∑ r : R, (μ {r}).toReal = 1 := by have := (MeasureTheory.sum_measureReal_preimage_singleton (μ := μ) (s := (Finset.univ : Finset R)) (f := id) (hf := by intro r _; exact measurableSet_singleton r) (h := by intro r _; exact measure_ne_top μ {r})) simpa [Measure.real, Set.preimage_id, MeasurableSet.univ, measure_univ] using this rw [Finset.sum_congr rfl (fun r _ => hzero r)] at hsum simp at hsum weight := fun r => (μ {r}).toReal weight_pos := by intro r hr exact (Finset.mem_filter.mp hr).2 weight_zero_off := by intro r hr by_contra hne have hpos : 0 < (μ {r}).toReal := lt_of_le_of_ne ENNReal.toReal_nonneg (Ne.symm hne) exact hr (Finset.mem_filter.mpr ⟨Finset.mem_univ r, hpos⟩) weight_sum_one := by classical -- The filtered sum equals the full sum because off-support terms vanish. have hfull : ∑ r : R, (μ {r}).toReal = 1 := by have := (MeasureTheory.sum_measureReal_preimage_singleton (μ := μ) (s := (Finset.univ : Finset R)) (f := id) (hf := by intro r _; exact measurableSet_singleton r) (h := by intro r _; exact measure_ne_top μ {r})) simpa [Measure.real, Set.preimage_id, MeasurableSet.univ, measure_univ] using this rw [← hfull] refine (Finset.sum_filter_of_ne ?_) intro r _ hne exact lt_of_le_of_ne ENNReal.toReal_nonneg (Ne.symm hne)
Causalean.Panel.Weighted.WeightedSupport.ofProbabilityMeasure · Causalean/Panel/Weighted/OfProbabilityMeasure.lean:49 · uses WeightedSupport
theorem ip_eq_integral reviewed
Causalean.Panel.Weighted.WeightedSupport

For a finite probability measure μ, the weighted inner product induced by μ on any two functions A and B equals the L²(μ) integral pairing ∫ A·B dμ.

Formal statement
A B :
R → ℝ
(ofProbabilityMeasure μ).ip A B = ∫ r, A r * B r ∂μ
Proof (Lean source)
theorem ip_eq_integral (μ : Measure R) [IsProbabilityMeasure μ] (A B : R → ℝ) : (ofProbabilityMeasure μ).ip A B = ∫ r, A r * B r ∂μ := by classical -- The integral over a finite measurable space is the atom-weighted sum. rw [MeasureTheory.integral_fintype (Integrable.of_finite)] -- `ip` sums over `observed`; extend to all of `R` since off-support weights -- are zero. unfold ip rw [Finset.sum_subset (Finset.subset_univ _)] · refine Finset.sum_congr rfl ?_ intro r _ simp only [ofProbabilityMeasure_weight, Measure.real, smul_eq_mul] ring · intro r _ hr have hzero : (μ {r}).toReal = 0 := by by_contra hne have hpos : 0 < (μ {r}).toReal := lt_of_le_of_ne ENNReal.toReal_nonneg (Ne.symm hne) exact hr (Finset.mem_filter.mpr ⟨Finset.mem_univ r, hpos⟩) simp [ofProbabilityMeasure_weight, hzero]
Causalean.Panel.Weighted.WeightedSupport.ip_eq_integral · Causalean/Panel/Weighted/OfProbabilityMeasure.lean:111 · uses ip , ofProbabilityMeasure
1 supporting declaration (lemmas, instances)
Scalar­FWL 1 core · 1 supporting This file proves the single-regressor finite weighted-support Frisch-Waugh-Lovell formula from weighted normal equations. ★ scalar_fwl_of_normalEqs

Scalar Frisch-Waugh-Lovell from normal equations

This file proves the single-regressor finite weighted-support Frisch-Waugh-Lovell formula from weighted normal equations. The supporting lemma ip_tildeX_self identifies the residualized regressor's inner product with the original regressor and with itself. The main theorem scalar_fwl_of_normalEqs states that any scalar coefficient satisfying the regressor and nuisance normal equations equals the residualized coefficient ratio.

The result supplies the normal-equation form needed by downstream estimand-characterization arguments without requiring them to restate a joint least-squares minimization problem.

theorem scalar_fwl_of_normalEqs reviewed
Causalean.Panel.Weighted.WeightedSupport

Scalar FWL from the normal equations. Suppose the nuisance term α lies in H, the H-residualized regressor has nonzero weighted self-inner-product, and the coefficient β with nuisance term α satisfies the weighted normal equation against the raw regressor X and the weighted normal equation against every element of the nuisance space H. Then β equals the residualized coefficient ratio ⟨X̃, Y⟩_ω / ⟨X̃, X̃⟩_ω.

Formal statement
H :
Submodule ℝ (R → ℝ)
X Y :
R → ℝ
β :
α :
R → ℝ
:
α ∈ H
hden :
c.ip (c.tildeX H X) (c.tildeX H X) ≠ 0
h_normal_X :
c.ip (Y - β • X - α) X = 0
h_normal_H :
∀ h ∈ H, c.ip (Y - β • X - α) h = 0
β = c.ip (c.tildeX H X) Y / c.ip (c.tildeX H X) (c.tildeX H X)
Proof (Lean source)
theorem scalar_fwl_of_normalEqs (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) (X Y : R → ℝ) (β : ℝ) (α : R → ℝ) (hα : α ∈ H) (hden : c.ip (c.tildeX H X) (c.tildeX H X) ≠ 0) (h_normal_X : c.ip (Y - β • X - α) X = 0) (h_normal_H : ∀ h ∈ H, c.ip (Y - β • X - α) h = 0) : β = c.ip (c.tildeX H X) Y / c.ip (c.tildeX H X) (c.tildeX H X) := by set Xt : R → ℝ := c.tildeX H X with hXt set R₀ : R → ℝ := Y - β • X - α with hR₀ -- The residualized regressor is orthogonal to the regression residual. have hXt_R₀ : c.ip Xt R₀ = 0 := by have hsplit : Xt = X + (-1 : ℝ) • c.proj H X := by rw [hXt, tildeX_eq]; ext r; simp [sub_eq_add_neg] rw [hsplit, c.ip_add_left] -- ⟨X, R₀⟩ = ⟨R₀, X⟩ = 0 have h1 : c.ip X R₀ = 0 := by rw [c.ip_symm]; exact h_normal_X -- ⟨(-1)•proj X, R₀⟩ = (-1) * ⟨R₀, proj X⟩ = 0 have h2 : c.ip ((-1 : ℝ) • c.proj H X) R₀ = 0 := by rw [c.ip_smul_left, c.ip_symm] rw [h_normal_H (c.proj H X) (c.proj_mem H X)] ring rw [h1, h2, add_zero] -- Expand ⟨Xt, R₀⟩ = ⟨Xt, Y⟩ − β⟨Xt, X⟩ − ⟨Xt, α⟩, and kill ⟨Xt, α⟩. have hα_zero : c.ip Xt α = 0 := c.residualize_in_orthogonal H X hα have hXt_X : c.ip Xt X = c.ip Xt Xt := ip_tildeX_self c H X have hexpand : c.ip Xt R₀ = c.ip Xt Y - β * c.ip Xt Xt := by have hrw : R₀ = Y - β • X - α := hR₀ rw [hrw] -- Y - β•X - α = Y + (-(β•X)) + (-α) have hsub : Y - β • X - α = Y + (-(β • X)) + (-α) := by ext r; simp [sub_eq_add_neg] rw [hsub, c.ip_add_right, c.ip_add_right] have hneg_smul : c.ip Xt (-(β • X)) = - (β * c.ip Xt X) := by have : (-(β • X) : R → ℝ) = (-β) • X := by ext r; simp rw [this, c.ip_smul_right]; ring have hneg_α : c.ip Xt (-α) = - c.ip Xt α := by have : (-α : R → ℝ) = (-1 : ℝ) • α := by ext r; simp rw [this, c.ip_smul_right]; ring rw [hneg_smul, hneg_α, hα_zero, hXt_X]; ring -- Combine: 0 = ⟨Xt, Y⟩ − β⟨Xt, Xt⟩. rw [hexpand] at hXt_R₀ have hne : c.ip Xt Xt ≠ 0 := by simpa [hXt] using hden field_simp at hXt_R₀ ⊢ linarith [hXt_R₀]
Causalean.Panel.Weighted.WeightedSupport.scalar_fwl_of_normalEqs · Causalean/Panel/Weighted/ScalarFWL.lean:69 · uses WeightedSupport , ip , tildeX
1 supporting declaration (lemmas, instances)
  • ip_tildeX_self lemma — ⟨X̃, X⟩_ω = ⟨X̃, X̃⟩_ω: the residualized regressor sees X and its residual identically, because the projection part lies in H and is orthogonal to the residual.
    H :
    Submodule ℝ (R → ℝ)
    X :
    R → ℝ
    c.ip (c.tildeX H X) X = c.ip (c.tildeX H X) (c.tildeX H X)
    Proof (Lean source)
    lemma ip_tildeX_self (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) (X : R → ℝ) : c.ip (c.tildeX H X) X = c.ip (c.tildeX H X) (c.tildeX H X) := by -- Write `X = tildeX + proj X` only in the *right* slot. have hsplit : X = c.tildeX H X + c.proj H X := by rw [tildeX_eq]; ext r; simp calc c.ip (c.tildeX H X) X = c.ip (c.tildeX H X) (c.tildeX H X + c.proj H X) := by rw [← hsplit] _ = c.ip (c.tildeX H X) (c.tildeX H X) + c.ip (c.tildeX H X) (c.proj H X) := c.ip_add_right _ _ _ _ = c.ip (c.tildeX H X) (c.tildeX H X) := by rw [c.residualize_in_orthogonal H X (c.proj_mem H X), add_zero]
    Causalean.Panel.Weighted.WeightedSupport.ip_tildeX_self · Causalean/Panel/Weighted/ScalarFWL.lean:53
WLS 2 core · 3 supporting This file proves that the semidefinite weighted projection from Causalean.Panel.Weighted.Subspace has the expected least-squares characterization. ★ proj_eq_argmin★ residualize_orth_iff_argmin

Weighted least-squares optimality

This file proves that the semidefinite weighted projection from Causalean.Panel.Weighted.Subspace has the expected least-squares characterization. The lemma ip_self_sub_le_of_orth gives the forward orthogonality-to-optimality implication, and proj_eq_argmin specializes it to the chosen weighted projection c.proj H X.

The reverse perturbation argument is packaged in residualize_orth_iff_argmin: for any candidate p ∈ H, residual orthogonality to every direction in H is equivalent to weighted least-squares optimality. The helper lemmas ip_eq_zero_of_zero_on_observed and ip_sub_smul_expand handle the semidefinite zero-energy case and the quadratic expansion used in that proof.

theorem proj_eq_argmin reviewed
Causalean.Panel.Weighted.WeightedSupport

The weighted orthogonal projection minimizes the WLS objective over H. Given a weighted support on a finite index set and a submodule H of candidate real-valued functions, for any competitor h lying in H, the weighted sum of squared residuals of the projection of a target function onto H is at most the weighted sum of squared residuals of h.

Formal statement
H :
Submodule ℝ (R → ℝ)
X h :
R → ℝ
hH :
h ∈ H
c.ip (X - c.proj H X) (X - c.proj H X) ≤ c.ip (X - h) (X - h)
Proof (Lean source)
theorem proj_eq_argmin (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) (X h : R → ℝ) (hH : h ∈ H) : c.ip (X - c.proj H X) (X - c.proj H X) ≤ c.ip (X - h) (X - h) := by refine c.ip_self_sub_le_of_orth H X (c.proj H X) (c.proj_mem H X) ?_ hH intro g hg exact c.proj_orthogonal H X hg
Causalean.Panel.Weighted.WeightedSupport.proj_eq_argmin · Causalean/Panel/Weighted/WLS.lean:91 · uses WeightedSupport , ip , proj
theorem residualize_orth_iff_argmin reviewed
Causalean.Panel.Weighted.WeightedSupport

First-order WLS optimality. For a weighted support and a submodule H of candidate functions, fix a candidate function p belonging to H; then the residual X - p being weighted-orthogonal to every element of H is equivalent to p attaining the minimal weighted sum of squared residuals over H.

Formal statement
H :
Submodule ℝ (R → ℝ)
X p :
R → ℝ
hp :
p ∈ H
(∀ h ∈ H, c.ip (X - p) h = 0) ↔ (∀ h ∈ H, c.ip (X - p) (X - p) ≤ c.ip (X - h) (X - h))
Proof (Lean source)
theorem residualize_orth_iff_argmin (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) (X p : R → ℝ) (hp : p ∈ H) : (∀ h ∈ H, c.ip (X - p) h = 0) ↔ (∀ h ∈ H, c.ip (X - p) (X - p) ≤ c.ip (X - h) (X - h)) := by constructor · -- Forward direction: standard expansion. intro horth h hh exact c.ip_self_sub_le_of_orth H X p hp horth hh · -- Reverse direction: perturbation argument. intro hmin h hh -- For any `t : ℝ`, `p + t • h ∈ H`. -- Note: `X - (p + t • h) = X - p - t • h`. have hkey : ∀ t : ℝ, c.ip (X - p) (X - p) ≤ c.ip (X - p - t • h) (X - p - t • h) := by intro t have hpth : p + t • h ∈ H := H.add_mem hp (H.smul_mem t hh) have := hmin (p + t • h) hpth have heq : X - (p + t • h) = X - p - t • h := by ext s; simp; ring rw [heq] at this exact this -- Combined with the quadratic expansion, this gives -- 0 ≤ -2 t · ⟨X-p, h⟩_ω + t² · ⟨h, h⟩_ω for all `t : ℝ`. have hquad : ∀ t : ℝ, 0 ≤ - (2 * t * c.ip (X - p) h) + t^2 * c.ip h h := by intro t have := hkey t have hexp := c.ip_sub_smul_expand X p h t linarith -- Case split on whether `⟨h, h⟩_ω > 0`. by_cases hzero : c.ip h h = 0 · -- `h` vanishes on observed, so `⟨X - p, h⟩_ω = 0` directly. have hvan : ∀ r ∈ c.observed, h r = 0 := (c.ip_self_eq_zero_iff h).mp hzero exact c.ip_eq_zero_of_zero_on_observed (X - p) h hvan · -- `⟨h, h⟩_ω > 0`. Plug `t = ⟨X-p, h⟩_ω / ⟨h, h⟩_ω`. have hpos : 0 < c.ip h h := lt_of_le_of_ne (c.ip_self_nonneg h) (Ne.symm hzero) set a : ℝ := c.ip (X - p) h with ha set b : ℝ := c.ip h h with hb -- The minimum of `t ↦ -2 a t + b t²` over `t : ℝ` is `-a² / b` at -- `t = a / b`. have htest := hquad (a / b) -- `- (2 * (a/b) * a) + (a/b)² * b = -2 a² / b + a² / b = -a² / b`. have hsimp : - (2 * (a / b) * a) + (a / b)^2 * b = - a^2 / b := by field_simp ring rw [hsimp] at htest -- So `-a²/b ≥ 0`. Combined with `b > 0`, this forces `a² ≤ 0`, -- hence `a = 0`. have hineq : - a^2 / b ≥ 0 := htest have ha2 : a^2 ≤ 0 := by have : - a^2 ≥ 0 := by have := (div_nonneg_iff.mp hineq).resolve_right ?_ · exact this.1 · push_neg intro _ exact hpos linarith have ha2nn : 0 ≤ a^2 := sq_nonneg a have ha2eq : a^2 = 0 := le_antisymm ha2 ha2nn have : a = 0 := by have := sq_eq_zero_iff.mp ha2eq exact this exact this
Causalean.Panel.Weighted.WeightedSupport.residualize_orth_iff_argmin · Causalean/Panel/Weighted/WLS.lean:146 · uses WeightedSupport , ip
3 supporting declarations (lemmas, instances)
  • ip_self_sub_le_of_orth lemma — If p ∈ H and the residual X - p is c.ip-orthogonal to all of H, then p minimizes the WLS objective over H.
    H :
    Submodule ℝ (R → ℝ)
    X p :
    R → ℝ
    hp :
    p ∈ H
    horth :
    ∀ h ∈ H, c.ip (X - p) h = 0
    h :
    R → ℝ
    hh :
    h ∈ H
    c.ip (X - p) (X - p) ≤ c.ip (X - h) (X - h)
    Proof (Lean source)
    lemma ip_self_sub_le_of_orth (c : WeightedSupport R) (H : Submodule ℝ (R → ℝ)) (X p : R → ℝ) (hp : p ∈ H) (horth : ∀ h ∈ H, c.ip (X - p) h = 0) {h : R → ℝ} (hh : h ∈ H) : c.ip (X - p) (X - p) ≤ c.ip (X - h) (X - h) := by -- `X - h = (X - p) + (p - h)`. have hph : p - h ∈ H := H.sub_mem hp hh have hdecomp : X - h = (X - p) + (p - h) := by ext s; simp [sub_eq_add_neg] -- Expand the inner product via bilinearity. have hcross : c.ip (X - p) (p - h) = 0 := horth (p - h) hph have hexpand : c.ip (X - h) (X - h) = c.ip (X - p) (X - p) + c.ip (p - h) (p - h) := by -- `⟨(X-p)+(p-h), (X-p)+(p-h)⟩ -- = ⟨X-p, X-p⟩ + ⟨X-p, p-h⟩ + ⟨p-h, X-p⟩ + ⟨p-h, p-h⟩`. rw [hdecomp, c.ip_add_left, c.ip_add_right, c.ip_add_right] have hsymm : c.ip (p - h) (X - p) = c.ip (X - p) (p - h) := c.ip_symm _ _ rw [hsymm, hcross]; ring -- `⟨p - h, p - h⟩ ≥ 0`. have hpos : 0 ≤ c.ip (p - h) (p - h) := c.ip_self_nonneg (p - h) linarith
    Causalean.Panel.Weighted.WeightedSupport.ip_self_sub_le_of_orth · Causalean/Panel/Weighted/WLS.lean:65
  • ip_eq_zero_of_zero_on_observed lemma — If h vanishes on every observed index, then c.ip A h = 0 for any A.
    A h :
    R → ℝ
    hh :
    ∀ r ∈ c.observed, h r = 0
    c.ip A h = 0
    Proof (Lean source)
    lemma ip_eq_zero_of_zero_on_observed (c : WeightedSupport R) (A h : R → ℝ) (hh : ∀ r ∈ c.observed, h r = 0) : c.ip A h = 0 := by unfold ip refine Finset.sum_eq_zero ?_ intro r hr rw [hh r hr]; ring
    Causalean.Panel.Weighted.WeightedSupport.ip_eq_zero_of_zero_on_observed · Causalean/Panel/Weighted/WLS.lean:117
  • ip_sub_smul_expand lemma — Quadratic-in-t expansion used in the perturbation argument: ⟨X - p - t • h, X - p - t • h⟩_ω = ⟨X-p, X-p⟩_ω - 2 t · ⟨X-p, h⟩_ω + t² · ⟨h, h⟩_ω.
    X p h :
    R → ℝ
    t :
    c.ip (X - p - t • h) (X - p - t • h)
    = c.ip (X - p) (X - p) - 2 * t * c.ip (X - p) h + t^2 * c.ip h h
    Proof (Lean source)
    lemma ip_sub_smul_expand (c : WeightedSupport R) (X p h : R → ℝ) (t : ℝ) : c.ip (X - p - t • h) (X - p - t • h) = c.ip (X - p) (X - p) - 2 * t * c.ip (X - p) h + t^2 * c.ip h h := by have hsub : X - p - t • h = (X - p) + (- (t • h)) := by ext s; simp [sub_eq_add_neg] rw [hsub] rw [c.ip_add_left, c.ip_add_right, c.ip_add_right] have hneg : -(t • h) = (-t) • h := by ext s; simp have h1 : c.ip (X - p) (-(t • h)) = - (t * c.ip (X - p) h) := by rw [hneg, c.ip_smul_right]; ring have h2 : c.ip (-(t • h)) (X - p) = - (t * c.ip (X - p) h) := by rw [c.ip_symm]; exact h1 have h3 : c.ip (-(t • h)) (-(t • h)) = t^2 * c.ip h h := by rw [hneg, c.ip_smul_left, c.ip_smul_right]; ring rw [h1, h2, h3]; ring
    Causalean.Panel.Weighted.WeightedSupport.ip_sub_smul_expand · Causalean/Panel/Weighted/WLS.lean:126