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 :
Type u_1
shared
∑ 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 :
    Type u_1
    shared
    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 :
    Type u_1
    shared
    ∑ 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 :
    Type u_1
    shared
    ∑ 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

For a finite record set, a weighted support, and two real-valued arrays on the records, the weighted inner product is the sum, over observed records, of each support weight times the product of the two arrays at that record.

Definition (Lean source)
R :
Type u_1
shared
A B :
R → ℝ
ip c A B :
∑ 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
R :
Type u_1
shared
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:127 · uses WeightedSupport , ip
def ipMat reviewed
Causalean.Panel.Weighted.WeightedSupport

For a finite record set, an index set, a weighted support, and two families of real-valued arrays indexed by that set, the matrix-valued weighted inner product is the matrix whose (j,k)(j,k) entry is the weighted inner product of array jj in the first family and array kk in the second family.

Definition (Lean source)
R :
Type u_1
shared
J :
Type u_2
shared
A B :
J → R → ℝ
ipMat c A B :
Matrix J J ℝ
fun j k => c.ip (A j) (B k)
Causalean.Panel.Weighted.WeightedSupport.ipMat · Causalean/Panel/Weighted/InnerProduct.lean:158 · uses WeightedSupport
14 supporting declarations (lemmas, instances)
  • ip_def lemma — The weighted inner product unfolds to its finite weighted sum over observed records.
    R :
    Type u_1
    shared
    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:71
  • ip_symm lemma — Symmetry of the weighted inner product.
    R :
    Type u_1
    shared
    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:76
  • ip_add_left lemma — Additivity in the left argument.
    R :
    Type u_1
    shared
    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:84
  • ip_add_right lemma — Additivity in the right argument.
    R :
    Type u_1
    shared
    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:93
  • ip_smul_left lemma — Scalar homogeneity in the left argument.
    R :
    Type u_1
    shared
    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:98
  • ip_smul_right lemma — Scalar homogeneity in the right argument.
    R :
    Type u_1
    shared
    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:107
  • ip_self_summand_nonneg lemma — Each summand of ⟨A, A⟩_ω is nonnegative.
    R :
    Type u_1
    shared
    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:112
  • ip_self_nonneg lemma — Positivity: ⟨A, A⟩_ω ≥ 0.
    R :
    Type u_1
    shared
    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:121
  • ipMat_apply lemma — Each entry of the matrix-valued inner product is the scalar weighted inner product of the corresponding two columns.
    R :
    Type u_1
    shared
    J :
    Type u_2
    shared
    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:165
  • ipMat_transpose lemma — The transpose of ⟨A, B⟩_ω is ⟨B, A⟩_ω.
    R :
    Type u_1
    shared
    J :
    Type u_2
    shared
    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:171
  • ipMat_add_left lemma — Additivity in the left tuple argument (entrywise).
    R :
    Type u_1
    shared
    J :
    Type u_2
    shared
    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:177
  • ipMat_add_right lemma — Additivity in the right tuple argument (entrywise).
    R :
    Type u_1
    shared
    J :
    Type u_2
    shared
    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:185
  • ipMat_smul_left lemma — Scalar homogeneity in the left tuple argument (entrywise).
    R :
    Type u_1
    shared
    J :
    Type u_2
    shared
    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:193
  • ipMat_smul_right lemma — Scalar homogeneity in the right tuple argument (entrywise).
    R :
    Type u_1
    shared
    J :
    Type u_2
    shared
    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:201
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

For a finite record set, a weighted support, and a nuisance subspace of real-valued arrays, the weighted orthogonal projection onto that subspace maps every array to an array in the nuisance subspace whose residual is weighted-orthogonal to every array in that subspace.

Definition (Lean source)
R :
Type u_1
shared
H :
Submodule ℝ (R → ℝ)
proj c H :
(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

For a finite record set, a weighted support, and a nuisance subspace of real-valued arrays, the residual-maker linear map subtracts the weighted orthogonal projection onto the nuisance subspace from each array.

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

For a finite record set, a weighted support, a nuisance subspace of real-valued arrays, and a real-valued array, the residualized array is the result of applying the residual maker associated with that nuisance subspace to the array.

Definition (Lean source)
R :
Type u_1
shared
H :
Submodule ℝ (R → ℝ)
X :
R → ℝ
tildeX c H X :
R → ℝ
c.residualize H X
Causalean.Panel.Weighted.WeightedSupport.tildeX · Causalean/Panel/Weighted/Subspace.lean:187 · 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
R :
Type u_1
shared
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:201 · uses WeightedSupport , ip , tildeX
def tildeXVec reviewed
Causalean.Panel.Weighted.WeightedSupport

For a finite record set, an index set, a weighted support, a nuisance subspace of real-valued arrays, and a family of real-valued arrays, the residualized array family assigns to each member of the family its residual after projection onto the nuisance subspace.

Definition (Lean source)
R :
Type u_1
shared
J :
Type*
H :
Submodule ℝ (R → ℝ)
X :
J → R → ℝ
tildeXVec c H X :
J → R → ℝ
fun k => c.tildeX H (X k)
Causalean.Panel.Weighted.WeightedSupport.tildeXVec · Causalean/Panel/Weighted/Subspace.lean:253 · uses WeightedSupport
11 supporting declarations (lemmas, instances)
  • weighted_orthogonal_projection_exists lemma — Existence of a c.ip-orthogonal projection onto a subspace H.
    R :
    Type u_1
    shared
    H :
    Submodule ℝ (R → ℝ)
    ∃ P : (R → ℝ) →ₗ[ℝ] (R → ℝ),
    conclusion 1
    X :
    P X ∈ H
    conclusion 2
    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.
    R :
    Type u_1
    shared
    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:107
  • proj_orthogonal lemma — The residual from the chosen weighted projection is orthogonal to every element of the nuisance subspace.
    R :
    Type u_1
    shared
    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:112
  • proj_apply_of_mem lemma — If Y ∈ H then c.proj H Y agrees with Y on every observed index.
    R :
    Type u_1
    shared
    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:121
  • proj_apply_eq_of_mem_orthogonal lemma — Projection uniqueness on observed indices.
    R :
    Type u_1
    shared
    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:134
  • proj_idem_apply lemma — Idempotence of the projection on the observed indices.
    R :
    Type u_1
    shared
    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:165
  • residualize_apply lemma — Applying the residual maker subtracts the weighted projection from the original array.
    R :
    Type u_1
    shared
    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:180
  • tildeX_eq lemma — The residualized scalar array is the original array minus its weighted projection onto the nuisance subspace.
    R :
    Type u_1
    shared
    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:194
  • residualize_self_of_mem lemma — If X ∈ H then X̃ = M_H X vanishes on c.observed.
    R :
    Type u_1
    shared
    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:210
  • residualize_idem_apply lemma — Idempotence of M_H on the observed indices: M_H (M_H X) = M_H X on c.observed.
    R :
    Type u_1
    shared
    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:219
  • tildeXVec_apply lemma — The residualized vector array applies scalar residualization to the chosen column.
    R :
    Type u_1
    shared
    J :
    Type u_2
    shared
    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:260
Additive­Span 4 core · 2 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

Given an index set, two feature sets, and two maps from the index set to those feature sets, the additive span is the real linear subspace of real-valued arrays on the index set consisting exactly of arrays that can be written as the sum of a real-valued function of the first feature and a real-valued function of the second feature.

Definition (Lean source)
R A B :
Type*
f₁ :
R → A
f₂ :
R → B
AdditiveSpan f₁ f₂ :
Submodule ℝ (R → ℝ)
clause 1
carrier := { h | ∃ a : A → ℝ, ∃ b : B → ℝ, ∀ r : R, h r = a (f₁ r) + b (f₂ r) }
clause 2
zero_mem' := ⟨fun _ => 0, fun _ => 0, by intro r; simp⟩
clause 3
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
clause 4
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
R :
Type u_1
shared
A :
Type u_2
shared
B :
Type u_3
shared
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:87 · uses AdditiveSpan
def twoAxisAdditiveSpan reviewed
Causalean.Panel.Weighted

Given a set of units and a set of periods, the two-axis additive span is the real linear subspace of unit-period arrays that can be written as the sum of a unit-specific real-valued function and a period-specific real-valued function.

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

Given a set of units, a set of periods, and a real-valued unit-period array, the unit-time additive condition holds precisely when there exist a real-valued unit function and a real-valued period function whose sum equals the array at every unit-period pair.

Definition (Lean source)
Unit Time :
Type*
h :
Unit → Time → ℝ
IsUnitTimeAdditive h :
Prop
∃ a : Unit → ℝ, ∃ b : Time → ℝ, ∀ i t, h i t = a i + b t
Causalean.Panel.Weighted.IsUnitTimeAdditive · Causalean/Panel/Weighted/AdditiveSpan.lean:112
2 supporting declarations (lemmas, instances)
  • mem_iff lemma — Membership unfolding for AdditiveSpan.
    R :
    Type u_1
    shared
    A :
    Type u_2
    shared
    B :
    Type u_3
    shared
    f₁ :
    R → A
    shared
    f₂ :
    R → B
    shared
    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:81
  • finiteDimensional instance — Under [Finite R] the additive span sits inside the finite-dimensional ambient space R → ℝ, hence is finite-dimensional.
    R :
    Type u_1
    shared
    A :
    Type u_2
    shared
    B :
    Type u_3
    shared
    f₁ :
    R → A
    shared
    f₂ :
    R → B
    shared
    Finite R
    finiteDimensional :
    Finite ℝ (AdditiveSpan f₁ f₂)
    by haveI : Fintype R := Fintype.ofFinite R haveI : Finite ℝ (R → ℝ) := by infer_instance exact Module.Finite.of_injective (AdditiveSpan f₁ f₂).subtype (val_injective)
    Causalean.Panel.Weighted.AdditiveSpan.finiteDimensional · Causalean/Panel/Weighted/AdditiveSpan.lean:95
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

For a finite record set and a nonnegative integer KK, a weighted support, a family of KK regressors, and a nuisance subspace of real-valued arrays determine the residualized regressor Gram matrix, whose (j,k)(j,k) entry is the weighted inner product of regressor jj and regressor kk after both are residualized against the nuisance subspace.

Definition (Lean source)
R :
Type u_1
shared
K :
shared
X :
Fin K → R → ℝ
H :
Submodule ℝ (R → ℝ)
Q_XX c X H :
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

For a finite record set and a nonnegative integer KK, a weighted support, a family of KK regressors, a nuisance subspace of real-valued arrays, and an outcome array determine the residualized right-hand-side vector, whose coordinate jj is the weighted inner product of regressor jj residualized against the nuisance subspace with the outcome.

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

For a finite record set and a nonnegative integer KK, a weighted support, a family of KK regressors, a nuisance subspace of real-valued arrays, and an outcome array determine the residualized weighted least-squares coefficient vector, obtained by multiplying the inverse of the residualized regressor Gram matrix by the residualized right-hand-side vector.

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

For a finite record set and a nonnegative integer KK, a weighted support, a nuisance subspace of real-valued arrays, and a family of KK regressors satisfy the residualized-regressor rank condition exactly when the determinant of their residualized weighted Gram matrix is nonzero.

Definition (Lean source)
R :
Type u_1
shared
K :
shared
H :
Submodule ℝ (R → ℝ)
X :
Fin K → R → ℝ
RankCondition c H X :
Prop
IsUnit (Q_XX c X H).det
Causalean.Panel.Weighted.WeightedSupport.RankCondition · Causalean/Panel/Weighted/FWL.lean:100 · 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
R :
Type u_1
shared
K :
shared
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:161 · 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.
    R :
    Type u_1
    shared
    K :
    shared
    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:73
  • rhsVec_apply lemma — Each entry of the residualized right-hand side is the weighted inner product of a residualized regressor with the outcome.
    R :
    Type u_1
    shared
    K :
    shared
    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:87
  • Q_XX_mulVec_thetaHat lemma — Under nonsingularity, thetaHat solves the residualized normal equations.
    R :
    Type u_1
    shared
    K :
    shared
    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:107
  • 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.
    R :
    Type u_1
    shared
    ι :
    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:121
  • 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.
    R :
    Type u_1
    shared
    K :
    shared
    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:137
  • 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.
    R :
    Type u_1
    shared
    K :
    shared
    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:146
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

For a classifier from records to cells and a chosen cell, the cell-indicator array assigns one to each record in the chosen cell and zero to every other record.

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

For a finite collection of distinguishable cells and a classifier from records to those cells, the one-axis indicator span is the real vector space of arrays that are weighted sums of the classifier's singleton cell indicators, with one real coefficient for each cell.

Definition (Lean source)
R 𝒢 :
Type*
Fintype 𝒢
G :
R → 𝒢
indicatorSpan G :
Submodule ℝ (R → ℝ)
clause 1
carrier := { f | ∃ c : 𝒢 → ℝ, ∀ r : R, f r = ∑ g, c g * cellIndicator G g r }
clause 2
zero_mem' := by refine ⟨fun _ => 0, ?_⟩ intro r; simp
clause 3
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
clause 4
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:69
def twoAxisIndicatorSpan reviewed
Causalean.Panel.Weighted

For two finite collections of distinguishable cells, a first classifier and a second classifier from records to their respective cells, the two-axis indicator span is the real vector space generated jointly by the singleton indicators of both classifiers.

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

For a finite record set, a weighted support, a classifier from records to distinguishable cells, and a chosen cell, the cell mass is the sum of the support weights of all observed records classified into that cell.

Definition (Lean source)
R :
Type u_1
shared
𝒢 :
Type*
G :
R → 𝒢
g :
𝒢
cellMass c G g :
∑ r ∈ c.observed, c.weight r * cellIndicator G g r
Causalean.Panel.Weighted.WeightedSupport.cellMass · Causalean/Panel/Weighted/IndicatorSpan.lean:167 · uses WeightedSupport
def cellMean reviewed
Causalean.Panel.Weighted.WeightedSupport

For a finite record set, a weighted support, an outcome array, a classifier from records to distinguishable cells, a chosen cell, and the condition that this cell has strictly positive mass, the cell mean is the weighted average of the outcome over observed records in that cell.

Definition (Lean source)
R :
Type u_1
shared
𝒢 :
Type*
F :
R → ℝ
G :
R → 𝒢
g :
𝒢
_hpos :
0 < c.cellMass G g
cellMean c F G g _hpos :
(∑ 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:191 · 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
R :
Type u_1
shared
𝒢 :
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:202 · uses WeightedSupport , cellMass , cellMean , cellIndicator
def jointCellMass reviewed
Causalean.Panel.Weighted.WeightedSupport

For a finite record set, a weighted support, a first classifier into distinguishable cells, a second classifier into distinguishable cells, a chosen cell of the first classifier, and a chosen cell of the second classifier, the joint cell mass is the sum of the support weights of observed records lying in both chosen cells.

Definition (Lean source)
R :
Type u_1
shared
𝒢 𝒯 :
Type*
G :
R → 𝒢
T :
R → 𝒯
g :
𝒢
t :
𝒯
jointCellMass c G T 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:213 · 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, causal_defs_simps] 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:60
  • 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:107
  • 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:115
  • 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:147
  • 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:154
  • cellMass_def lemma — The cell mass unfolds to the weighted sum of the corresponding cell indicator over observed records.
    R :
    Type u_1
    shared
    𝒢 :
    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:174
  • cellMass_nonneg lemma — Every classifier cell has nonnegative total weight.
    R :
    Type u_1
    shared
    𝒢 :
    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:180
  • jointCellMass_def lemma — The joint cell mass unfolds to the weighted sum of the two corresponding cell indicators over observed records.
    R :
    Type u_1
    shared
    𝒢 𝒯 :
    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:221
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

For a finite index set, a field of scalars, a scalar-valued raw weight function, and an index, the normalized finite weight is that index's raw weight divided by the sum of all raw weights.

Definition (Lean source)
ι :
Type u_3
shared
K :
Type*
a :
ι → K
i :
ι
normalizedWeight a 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
ι :
Type u_3
shared
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:158
5 supporting declarations (lemmas, instances)
  • normalizedWeight_nonneg lemma — Nonnegativity of normalized weights from nonnegative raw weights and a positive normalizing sum.
    ι :
    Type u_3
    shared
    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:63
  • sum_normalizedWeight_eq_one lemma — Normalized finite weights sum to one when the normalizing sum is nonzero.
    ι :
    Type u_3
    shared
    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:72
  • 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.
    ι :
    Type u_3
    shared
    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:80
  • 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.
    ι :
    Type u_3
    shared
    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:125
  • weighted_center_var lemma — Weighted centered variance as half the average pairwise squared gap.
    ι :
    Type u_3
    shared
    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:170
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

For a finite measurable record space in which every singleton is measurable and a probability measure, the weighted support induced by that probability measure has as observed records exactly those with strictly positive point mass and assigns each record its point mass as weight.

Definition (Lean source)
R :
Type u_1
shared
ofProbabilityMeasure μ :
clause 1
observed := Finset.univ.filter (fun r => 0 < (μ {r}).toReal)
clause 2
observed_nonempty := by classical by_contra h rw [Finset.not_nonempty_iff_eq_empty] at h 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
clause 3
weight := fun r => (μ {r}).toReal
clause 4
weight_pos := by intro r hr exact (Finset.mem_filter.mp hr).2
clause 5
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⟩)
clause 6
weight_sum_one := by classical 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
R :
Type u_1
shared
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
R :
Type u_1
shared
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.
    R :
    Type u_1
    shared
    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
R :
Type u_1
shared
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
R :
Type u_1
shared
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.
    R :
    Type u_1
    shared
    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.
    R :
    Type u_1
    shared
    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⟩_ω.
    R :
    Type u_1
    shared
    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