Mathlib.Analysis.Symmetric­Tensor­Pencil

Finite-dimensional symmetric-tensor-pencil recovery: contraction and conditioning bounds, generalized-eigenvalue perturbation, spectral matching, and a quantitative permutation-aligned local inverse.

Basic 16 core · 5 supporting This module fixes paper-independent array models for finite real tensors and factor matrices. ★ contractLast_frobeniusNorm_le

Finite tensors, contractions, and quantitative norms

This module fixes paper-independent array models for finite real tensors and factor matrices. It defines rank-one tensor powers, degree lifts, Frobenius norms, contraction against a family of probes, and the exact contracted factorization used by tensor-pencil arguments.

abbrev Vec reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

A finite real vector with p coordinates. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
p :
Vec p :
Type
Fin p → ℝ
Causalean.Mathlib.Analysis.SymmetricTensorPencil.Vec · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Basic.lean:17
abbrev FactorMatrix reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

A real matrix whose n columns are vectors with p coordinates. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
p n :
FactorMatrix p n :
Type
Matrix (Fin p) (Fin n) ℝ
Causalean.Mathlib.Analysis.SymmetricTensorPencil.FactorMatrix · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Basic.lean:20
abbrev Tensor reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

An order-r real tensor on a p-dimensional coordinate space, represented as an array. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
p r :
Tensor p r :
Type
(Fin r → Fin p) → ℝ
Causalean.Mathlib.Analysis.SymmetricTensorPencil.Tensor · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Basic.lean:23
abbrev LiftIndex reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

The ordered multi-index space used for a degree-d tensor-power lift. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
p d :
LiftIndex p d :
Type
Fin d → Fin p
Causalean.Mathlib.Analysis.SymmetricTensorPencil.LiftIndex · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Basic.lean:26
def finiteFrobeniusNorm reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

The Euclidean/Frobenius norm of a finite real array. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
ι :
Type*
x :
ι → ℝ
finiteFrobeniusNorm x :
sqrt (∑ i, (x i) ^ 2)
Causalean.Mathlib.Analysis.SymmetricTensorPencil.finiteFrobeniusNorm · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Basic.lean:29
def matrixFrobeniusNorm reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

The Frobenius norm of a finite real matrix. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
ι κ :
Type*
A :
Matrix ι κ ℝ
matrixFrobeniusNorm A :
finiteFrobeniusNorm (fun x : ι × κ => A x.1 x.2)
Causalean.Mathlib.Analysis.SymmetricTensorPencil.matrixFrobeniusNorm · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Basic.lean:33
def squareOperatorNorm reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

The Euclidean operator norm of a finite real square matrix. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
ι :
A :
Matrix ι ι ℝ
squareOperatorNorm A :
‖(Matrix.toEuclideanCLM (n := ι) (𝕜 := ℝ)) A‖
Causalean.Mathlib.Analysis.SymmetricTensorPencil.squareOperatorNorm · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Basic.lean:38
def leastColumnSingularValue reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

The last domain-indexed singular value of a finite real matrix, i.e. the singular value at index one less than the number of columns. For a matrix with no columns the index is zero by natural subtraction; the results using it assume a nonempty column index. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
ι κ :
A :
Matrix ι κ ℝ
leastColumnSingularValue A :
A.toEuclideanLin.singularValues (card κ - 1)
Causalean.Mathlib.Analysis.SymmetricTensorPencil.leastColumnSingularValue · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Basic.lean:43
def dot reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

The Euclidean dot product of two finite real vectors. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
p :
x y :
Vec p
dot x y :
∑ i, x i * y i
Causalean.Mathlib.Analysis.SymmetricTensorPencil.dot · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Basic.lean:50 · uses Vec
def rankOneTensor reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

The order-r rank-one tensor power of a vector. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
r :
p :
c :
Vec p
rankOneTensor r c :
Tensor p r
fun I => ∏ k, c (I k)
Causalean.Mathlib.Analysis.SymmetricTensorPencil.rankOneTensor · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Basic.lean:53 · uses Tensor , Vec
def decompositionTensor reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

The symmetric tensor represented by weighted rank-one tensor powers of the columns. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
p n :
r :
C :
lam :
Fin n → ℝ
decompositionTensor r C lam :
Tensor p r
fun I => ∑ j, lam j * rankOneTensor r (C.col j) I
Causalean.Mathlib.Analysis.SymmetricTensorPencil.decompositionTensor · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Basic.lean:57 · uses FactorMatrix , Tensor
def liftedDirections reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

The matrix whose columns are the ordered degree-d tensor powers of the factor columns. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
p n :
d :
C :
liftedDirections d C :
Matrix (LiftIndex p d) (Fin n) ℝ
fun I j => ∏ k, C (I k) j
Causalean.Mathlib.Analysis.SymmetricTensorPencil.liftedDirections · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Basic.lean:62 · uses FactorMatrix , LiftIndex
def blockIndex reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

Concatenate two degree-d indices and one degree-q index into an order-d+d+q index. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
p d q :
I J :
K :
Fin q → Fin p
blockIndex I J K :
Fin (d + d + q) → Fin p
Fin.addCases (Fin.addCases I J) K
Causalean.Mathlib.Analysis.SymmetricTensorPencil.blockIndex · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Basic.lean:67 · uses LiftIndex
def contractLast reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

Contract the final q modes of an order-d+d+q tensor against a family of q probes. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
p d q :
T :
Tensor p (d + d + q)
probes :
Fin q → Vec p
contractLast T probes :
Matrix (LiftIndex p d) (LiftIndex p d) ℝ
fun I J => ∑ K : Fin q → Fin p, T (blockIndex I J K) * ∏ a, probes a (K a)
Causalean.Mathlib.Analysis.SymmetricTensorPencil.contractLast · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Basic.lean:72 · uses LiftIndex , Tensor , Vec
def pencilProbes reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

The probe family containing q-1 copies of u followed by one copy of w, for positive q; for q = 0 it is the empty family. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
p q :
u w :
Vec p
pencilProbes u w :
Fin q → Vec p
fun a => if a.1 + 1 = q then w else u
Causalean.Mathlib.Analysis.SymmetricTensorPencil.pencilProbes · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Basic.lean:78 · uses Vec
theorem contractLast_frobeniusNorm_le reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

Contracting a finite tensor against probes of norm at most one cannot increase its Frobenius norm. Under the listed assumptions, the stated conclusion follows.

Formal statement
p d q :
T :
Tensor p (d + d + q)
probes :
Fin q → Vec p
hprobes :
∀ a, finiteFrobeniusNorm (probes a) ≤ 1
Proof (Lean source)
-- Proof route: identify each contraction as an inner product in the product probe index, -- apply finite Cauchy--Schwarz, and sum the squared bounds over the two free index blocks. theorem contractLast_frobeniusNorm_le {p d q : ℕ} (T : Tensor p (d + d + q)) (probes : Fin q → Vec p) (hprobes : ∀ a, finiteFrobeniusNorm (probes a) ≤ 1) : matrixFrobeniusNorm (contractLast T probes) ≤ finiteFrobeniusNorm T := by have hsingle (a : Fin q) : ∑ i, probes a i ^ 2 ≤ 1 := by have hsq := (sq_le_sq₀ (Real.sqrt_nonneg _) (by norm_num)).2 (hprobes a) simpa [finiteFrobeniusNorm, Real.sq_sqrt (sum_nonneg fun _ _ => sq_nonneg _)] using hsq have henergy : ∑ K : Fin q → Fin p, (∏ a, probes a (K a)) ^ 2 ≤ 1 := by calc _ = ∏ a, ∑ i, probes a i ^ 2 := by calc _ = ∑ K : Fin q → Fin p, ∏ a, probes a (K a) ^ 2 := by apply Finset.sum_congr rfl intro K _ rw [Finset.prod_pow] _ = _ := (Fintype.prod_sum (fun a : Fin q => fun i : Fin p => probes a i ^ 2)).symm _ ≤ 1 := Finset.prod_le_one (fun a _ => sum_nonneg fun _ _ => sq_nonneg _) (fun a _ => hsingle a) have hpoint (I J : LiftIndex p d) : (contractLast T probes I J) ^ 2 ≤ ∑ K : Fin q → Fin p, T (blockIndex I J K) ^ 2 := by have hcs := Finset.sum_mul_sq_le_sq_mul_sq (Finset.univ : Finset (Fin q → Fin p)) (fun K => T (blockIndex I J K)) (fun K => ∏ a, probes a (K a)) have hrow : 0 ≤ ∑ K : Fin q → Fin p, T (blockIndex I J K) ^ 2 := sum_nonneg fun _ _ => sq_nonneg _ calc _ ≤ (∑ K : Fin q → Fin p, T (blockIndex I J K) ^ 2) * (∑ K : Fin q → Fin p, (∏ a, probes a (K a)) ^ 2) := by simpa [contractLast] using hcs _ ≤ (∑ K : Fin q → Fin p, T (blockIndex I J K) ^ 2) * 1 := mul_le_mul_of_nonneg_left henergy hrow _ = _ := mul_one _ rw [matrixFrobeniusNorm, finiteFrobeniusNorm, finiteFrobeniusNorm] apply Real.sqrt_le_sqrt change (∑ x : LiftIndex p d × LiftIndex p d, (contractLast T probes x.1 x.2) ^ 2) ≤ ∑ L, T L ^ 2 rw [Fintype.sum_prod_type] calc _ ≤ ∑ I, ∑ J, ∑ K : Fin q → Fin p, T (blockIndex I J K) ^ 2 := by exact Finset.sum_le_sum fun I _ => Finset.sum_le_sum fun J _ => hpoint I J _ = ∑ x : (LiftIndex p d × LiftIndex p d) × (Fin q → Fin p), T (blockIndex x.1.1 x.1.2 x.2) ^ 2 := by rw [Fintype.sum_prod_type, Fintype.sum_prod_type] _ = _ := (blockIndexEquiv p d q).sum_comp (fun L => T L ^ 2)
5 supporting declarations (lemmas, instances)
Spectral­Matching 4 core · 2 supporting This module isolates the two ingredients that precede spectral-projector perturbation: a finite-dimensional Bauer--Fike localization theorem for explicitly diagonalized real matrices, and the finite matching argument tha ★ exists_permutation_matching_of_localization

Spectral localization and finite matching

This module isolates the two ingredients that precede spectral-projector perturbation: a finite-dimensional Bauer--Fike localization theorem for explicitly diagonalized real matrices, and the finite matching argument that turns one-sided localization into a permutation under a separation margin. It also records the elementary condition-number bound for coordinate projectors. The localization convention is the spectral-norm Bauer--Fike bound used in the robust simultaneous-diagonalization analysis of Goyal--Vempala--Xiao, arXiv:1306.5825, perturbation.tex, Theorem thm:bauer.

def PairwiseGap reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

A real scalar family, over an arbitrary index type, has pairwise gap at least gap. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
ι :
Type*
values :
ι → ℝ
gap :
i j :
i ≠ j
PairwiseGap values gap :
Prop
gap ≤ |values i - values j|
Causalean.Mathlib.Analysis.SymmetricTensorPencil.PairwiseGap · Causalean/Mathlib/Analysis/SymmetricTensorPencil/SpectralMatching.lean:19
def diagonalizableMatrix reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

The conjugation of the diagonal matrix of the prescribed real entries by S, that is S times the diagonal times the inverse of S. It is diagonalized by S with those entries when S is invertible; for singular S the inverse is zero by convention and the value is the zero matrix. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
n :
S :
Matrix (Fin n) (Fin n) ℝ
values :
Fin n → ℝ
diagonalizableMatrix S values :
Matrix (Fin n) (Fin n) ℝ
S * diagonal values * S⁻¹
Causalean.Mathlib.Analysis.SymmetricTensorPencil.diagonalizableMatrix · Causalean/Mathlib/Analysis/SymmetricTensorPencil/SpectralMatching.lean:23
def coordinateProjector reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

The coordinate projector selected by coordinate j of a diagonalizer S: S times the j-th standard diagonal unit matrix times the inverse of S. It is the rank-one spectral projector when S is invertible; for singular S the inverse is zero by convention and the value is the zero matrix. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
n :
S :
Matrix (Fin n) (Fin n) ℝ
j :
Fin n
coordinateProjector S j :
Matrix (Fin n) (Fin n) ℝ
S * diagonal (fun k => if k = j then 1 else 0) * S⁻¹
Causalean.Mathlib.Analysis.SymmetricTensorPencil.coordinateProjector · Causalean/Mathlib/Analysis/SymmetricTensorPencil/SpectralMatching.lean:30
theorem exists_permutation_matching_of_localization reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

One-sided localization between two equally sized finite scalar families becomes a permutation matching when the source family is separated by more than twice the localization radius. Under the listed assumptions, the stated conclusion follows.

Formal statement
n :
values values' :
Fin n → ℝ
gap radius :
hradius :
0 ≤ radius
hgap' :
PairwiseGap values' gap
hlocal :
∀ j', ∃ j, |values' j' - values j| ≤ radius
hsmall :
2 * radius < gap
∃ pi : Perm (Fin n), ∀ j, |values' (pi j) - values j| ≤ radius
Proof (Lean source)
-- Proof route: choose for every primed index one nearby unprimed index. Two primed indices -- with the same choice would violate separation by the triangle inequality, so the choice map -- is injective, hence bijective on the finite type; its inverse is the required permutation. theorem exists_permutation_matching_of_localization {n : ℕ} (values values' : Fin n → ℝ) {gap radius : ℝ} (hradius : 0 ≤ radius) (hgap' : PairwiseGap values' gap) (hlocal : ∀ j', ∃ j, |values' j' - values j| ≤ radius) (hsmall : 2 * radius < gap) : ∃ pi : Perm (Fin n), ∀ j, |values' (pi j) - values j| ≤ radius := by classical choose f hf using hlocal have hinj : Injective f := by intro a b hab by_contra hne have hgapab : gap ≤ |values' a - values' b| := hgap' a b hne have hdist : |values' a - values' b| ≤ 2 * radius := by calc |values' a - values' b| = |(values' a - values (f a)) + (values (f b) - values' b)| := by rw [hab] congr 1 ring _ ≤ |values' a - values (f a)| + |values (f b) - values' b| := abs_add_le _ _ _ = |values' a - values (f a)| + |values' b - values (f b)| := by rw [abs_sub_comm (values (f b)) (values' b)] _ ≤ radius + radius := add_le_add (hf a) (hf b) _ = 2 * radius := by ring exact (not_lt_of_ge (hgapab.trans hdist)) hsmall have hbij : Bijective f := hinj.bijective_of_finite let e : Perm (Fin n) := Equiv.ofBijective f hbij refine ⟨e.symm, ?_⟩ intro j change |values' ((Equiv.ofBijective f hbij).symm j) - values j| ≤ radius have hfj : f ((Equiv.ofBijective f hbij).symm j) = j := Equiv.ofBijective_apply_symm_apply f hbij j simpa [hfj] using hf ((Equiv.ofBijective f hbij).symm j)
Causalean.Mathlib.Analysis.SymmetricTensorPencil.exists_permutation_matching_of_localization · Causalean/Mathlib/Analysis/SymmetricTensorPencil/SpectralMatching.lean:198 · uses PairwiseGap
2 supporting declarations (lemmas, instances)
  • coordinateProjector_operatorNorm_le theorem — Every coordinate projector of a diagonalizer has Euclidean operator norm at most the declared condition-number envelope. Under the listed assumptions, the stated conclusion follows.
    n :
    S :
    Matrix (Fin n) (Fin n) ℝ
    j :
    Fin n
    chi :
    hS :
    IsUnit S.det
    hcondition :
    Proof (Lean source)
    -- Proof route: use submultiplicativity twice, the fact that the one-coordinate diagonal -- projector has operator norm one, and the supplied bound on `‖S‖₂ ‖S⁻¹‖₂`. theorem coordinateProjector_operatorNorm_le {n : ℕ} (S : Matrix (Fin n) (Fin n) ℝ) (j : Fin n) {chi : ℝ} (hS : IsUnit S.det) (hcondition : squareOperatorNorm S * squareOperatorNorm S⁻¹ ≤ chi) : squareOperatorNorm (coordinateProjector S j) ≤ chi := by let _ : Nonempty (Fin n) := ⟨j⟩ unfold coordinateProjector squareOperatorNorm rw [Matrix.l2_opNorm_toEuclideanCLM] calc ‖S * diagonal (fun k => if k = j then (1 : ℝ) else 0) * S⁻¹‖ ≤ ‖S * diagonal (fun k => if k = j then (1 : ℝ) else 0)‖ * ‖S⁻¹‖ := Matrix.l2_opNorm_mul _ _ _ ≤ (‖S‖ * ‖Matrix.diagonal (fun k => if k = j then (1 : ℝ) else 0)‖) * ‖S⁻¹‖ := by gcongr exact Matrix.l2_opNorm_mul _ _ _ = ‖S‖ * ‖S⁻¹‖ := by rw [Matrix.l2_opNorm_diagonal] have hnorm : ‖(fun k : Fin n => if k = j then (1 : ℝ) else 0)‖ = 1 := by apply le_antisymm · apply (pi_norm_le_iff_of_nonempty _).2 intro k split <;> norm_num · simpa using norm_le_pi_norm (fun k : Fin n => if k = j then (1 : ℝ) else 0) j rw [hnorm, mul_one] _ ≤ chi := hcondition
    Causalean.Mathlib.Analysis.SymmetricTensorPencil.coordinateProjector_operatorNorm_le · Causalean/Mathlib/Analysis/SymmetricTensorPencil/SpectralMatching.lean:38
  • diagonalizableMatrix_eigenvalue_localization theorem — Every prescribed eigenvalue of a nearby explicitly diagonalized matrix lies within chi * delta of some eigenvalue of the reference diagonalization. Under the listed assumptions, the stated conclusion follows.
    n :
    S S' :
    Matrix (Fin n) (Fin n) ℝ
    values values' :
    Fin n → ℝ
    chi delta :
    hS :
    IsUnit S.det
    hS' :
    IsUnit S'.det
    hcondition :
    hclose :
    j' :
    ∃ j, |values' j' - values j| ≤ chi * delta
    Proof (Lean source)
    -- Proof route: take the corresponding nonzero column of `S'` as an eigenvector of the -- perturbed matrix, conjugate its residual by `S⁻¹`, choose a largest coordinate, and compare -- that coordinate against the Euclidean norm. This is the finite-dimensional Bauer--Fike -- argument and uses no normality assumption. theorem diagonalizableMatrix_eigenvalue_localization {n : ℕ} [NeZero n] (S S' : Matrix (Fin n) (Fin n) ℝ) (values values' : Fin n → ℝ) {chi delta : ℝ} (hS : IsUnit S.det) (hS' : IsUnit S'.det) (hcondition : squareOperatorNorm S * squareOperatorNorm S⁻¹ ≤ chi) (hclose : squareOperatorNorm (diagonalizableMatrix S' values' - diagonalizableMatrix S values) ≤ delta) : ∀ j', ∃ j, |values' j' - values j| ≤ chi * delta := by classical intro j' obtain ⟨j, _, hj⟩ := Finset.exists_min_image univ (fun k => |values' j' - values k|) Finset.univ_nonempty refine ⟨j, ?_⟩ let v : Fin n → ℝ := S'.col j' let x : Fin n → ℝ := (S⁻¹).mulVec v have hv_ne : v ≠ 0 := by intro hv apply hS'.ne_zero apply Matrix.det_eq_zero_of_column_eq_zero j' intro i exact congrFun hv i have hv_recover : S.mulVec x = v := by simp [x, Matrix.mulVec_mulVec, Matrix.mul_nonsing_inv S hS] have hx_ne : x ≠ 0 := by intro hx apply hv_ne rw [← hv_recover, hx, Matrix.mulVec_zero] have hinvcol : (S'⁻¹).mulVec v = single j' 1 := by rw [show v = S'.mulVec (single j' 1) by simp [v]] rw [Matrix.mulVec_mulVec, Matrix.nonsing_inv_mul S' hS', Matrix.one_mulVec] have heigen : (diagonalizableMatrix S' values').mulVec v = values' j' • v := by calc _ = S'.mulVec ((diagonal values').mulVec ((S'⁻¹).mulVec v)) := by rw [diagonalizableMatrix, Matrix.mulVec_mulVec, Matrix.mulVec_mulVec] _ = S'.mulVec ((diagonal values').mulVec (single j' 1)) := by rw [hinvcol] _ = S'.mulVec (values' j' • single j' 1) := by congr 1 ext k by_cases hk : k = j' · subst k simp [Matrix.mulVec_diagonal] · simp [Matrix.mulVec_diagonal, hk] _ = values' j' • S'.mulVec (single j' 1) := Matrix.mulVec_smul S' (values' j') (single j' (1 : ℝ)) _ = values' j' • v := by rw [Matrix.mulVec_single_one] have hreference : (diagonalizableMatrix S values).mulVec v = S.mulVec ((diagonal values).mulVec x) := by rw [diagonalizableMatrix, Matrix.mulVec_mulVec, Matrix.mulVec_mulVec] let E := diagonalizableMatrix S' values' - diagonalizableMatrix S values let d : Fin n → ℝ := fun k => values' j' - values k have hcancel (z : Fin n → ℝ) : (S⁻¹).mulVec (S.mulVec z) = z := by rw [Matrix.mulVec_mulVec, Matrix.nonsing_inv_mul S hS, Matrix.one_mulVec] have hres : (diagonal d).mulVec x = (S⁻¹).mulVec (E.mulVec v) := by rw [show E = diagonalizableMatrix S' values' - diagonalizableMatrix S values by rfl] rw [Matrix.sub_mulVec, heigen, hreference, Matrix.mulVec_sub, Matrix.mulVec_smul] change (diagonal d).mulVec x = values' j' • x - (S⁻¹).mulVec (S.mulVec ((diagonal values).mulVec x)) rw [hcancel] ext k simp [d, Matrix.mulVec_diagonal] ring have hlower : |values' j' - values j| * ‖WithLp.toLp 2 x‖ ≤ ‖WithLp.toLp 2 ((diagonal d).mulVec x)‖ := by apply min_abs_mul_euclidean_norm_le_diagonal_mulVec_norm d x j intro k exact hj k (Finset.mem_univ k) have hu1 : ‖WithLp.toLp 2 ((diagonal d).mulVec x)‖ ≤ ‖S⁻¹‖ * ‖WithLp.toLp 2 (E.mulVec v)‖ := by rw [hres] exact Matrix.l2_opNorm_mulVec S⁻¹ (toLp 2 (E.mulVec v)) have hu2 : ‖WithLp.toLp 2 (E.mulVec v)‖ ≤ ‖E‖ * ‖WithLp.toLp 2 v‖ := Matrix.l2_opNorm_mulVec E (toLp 2 v) have hvnorm : ‖WithLp.toLp 2 v‖ ≤ ‖S‖ * ‖WithLp.toLp 2 x‖ := by rw [← hv_recover] exact Matrix.l2_opNorm_mulVec S (toLp 2 x) have hxnorm_pos : 0 < ‖WithLp.toLp 2 x‖ := norm_pos_iff.mpr (by exact fun hx => hx_ne (WithLp.toLp_injective 2 hx)) have hE : ‖E‖ ≤ delta := by rw [← Matrix.l2_opNorm_toEuclideanCLM] simpa [E, squareOperatorNorm] using hclose have hdelta : 0 ≤ delta := (norm_nonneg E).trans hE have hcond : ‖S‖ * ‖S⁻¹‖ ≤ chi := by simpa only [squareOperatorNorm, Matrix.l2_opNorm_toEuclideanCLM] using hcondition have hupper : ‖WithLp.toLp 2 ((diagonal d).mulVec x)‖ ≤ (chi * delta) * ‖WithLp.toLp 2 x‖ := by calc _ ≤ ‖S⁻¹‖ * ‖WithLp.toLp 2 (E.mulVec v)‖ := hu1 _ ≤ ‖S⁻¹‖ * (‖E‖ * ‖WithLp.toLp 2 v‖) := mul_le_mul_of_nonneg_left hu2 (norm_nonneg _) _ ≤ ‖S⁻¹‖ * (delta * ‖WithLp.toLp 2 v‖) := by gcongr _ ≤ ‖S⁻¹‖ * (delta * (‖S‖ * ‖WithLp.toLp 2 x‖)) := by gcongr _ = ((‖S‖ * ‖S⁻¹‖) * delta) * ‖WithLp.toLp 2 x‖ := by ring _ ≤ (chi * delta) * ‖WithLp.toLp 2 x‖ := by gcongr exact le_of_mul_le_mul_right (hlower.trans hupper) hxnorm_pos
    Causalean.Mathlib.Analysis.SymmetricTensorPencil.diagonalizableMatrix_eigenvalue_localization · Causalean/Mathlib/Analysis/SymmetricTensorPencil/SpectralMatching.lean:85
Pencil 3 core · 3 supporting This module packages the finite-dimensional inverse perturbation estimates needed after tensor contractions are compressed to the lifted signal space. ★ rightPencil_perturbation_bound

Inverse and tensor-pencil perturbation bounds

This module packages the finite-dimensional inverse perturbation estimates needed after tensor contractions are compressed to the lifted signal space. The constants are exposed separately so applications can assemble a local radius without unfolding proofs.

def rightPencil reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

The right generalized-eigenvalue pencil formed from a numerator and denominator matrix. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
n :
Aw Au :
Matrix (Fin n) (Fin n) ℝ
rightPencil Aw Au :
Matrix (Fin n) (Fin n) ℝ
Aw * Au⁻¹
Causalean.Mathlib.Analysis.SymmetricTensorPencil.rightPencil · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Pencil.lean:15
def pencilPerturbationConstant reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

The explicit Lipschitz coefficient for a right pencil whose denominator has lower singular value eta and whose numerator norm is at most n * Lambda. The formula is unguarded: it is a Lipschitz coefficient only for positive eta, and eta = 0 gives zero by the division-by-zero convention. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
n :
eta Lambda :
pencilPerturbationConstant n eta Lambda :
2 / eta + 2 * n * Lambda / eta ^ 2
Causalean.Mathlib.Analysis.SymmetricTensorPencil.pencilPerturbationConstant · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Pencil.lean:20
theorem rightPencil_perturbation_bound reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

Given reference and perturbed numerator and denominator contractions, a positive denominator margin, nonnegative numerator and error bounds, a denominator singular-value bound, a numerator norm bound, numerator and denominator perturbation bounds, and a small-error condition, both denominator matrices are invertible and the two right generalized-eigenvalue pencils differ by the explicit Lipschitz bound. Under the listed assumptions, the stated conclusion follows.

Formal statement
n :
Aw Au Aw' Au' :
Matrix (Fin n) (Fin n) ℝ
eta Lambda e :
heta :
0 < eta
hLambda :
0 ≤ Lambda
he :
0 ≤ e
hsv :
hnumer :
squareOperatorNorm Aw ≤ n * Lambda
hnumPert :
squareOperatorNorm (Aw' - Aw) ≤ e
hdenPert :
squareOperatorNorm (Au' - Au) ≤ e
hsmall :
e < eta / 2
conclusion 1
IsUnit Au.det
conclusion 2
IsUnit Au'.det
conclusion 3
Proof (Lean source)
-- Proof route: add and subtract `Aw * Au'⁻¹`, then combine the numerator perturbation with the -- inverse-difference bound and `‖Aw‖ ≤ n Lambda`; use `Matrix.l2_opNorm_mul` throughout. theorem rightPencil_perturbation_bound {n : ℕ} [NeZero n] (Aw Au Aw' Au' : Matrix (Fin n) (Fin n) ℝ) {eta Lambda e : ℝ} (heta : 0 < eta) (hLambda : 0 ≤ Lambda) (he : 0 ≤ e) (hsv : eta ≤ leastColumnSingularValue Au) (hnumer : squareOperatorNorm Aw ≤ n * Lambda) (hnumPert : squareOperatorNorm (Aw' - Aw) ≤ e) (hdenPert : squareOperatorNorm (Au' - Au) ≤ e) (hsmall : e < eta / 2) : IsUnit Au.det ∧ IsUnit Au'.det ∧ squareOperatorNorm (rightPencil Aw' Au' - rightPencil Aw Au) ≤ pencilPerturbationConstant n eta Lambda * e := by obtain ⟨hdetAu, _⟩ := inverse_operatorNorm_le_reciprocal Au heta hsv obtain ⟨hdetAu', hinvAu', hdiffInv⟩ := inverse_perturbation_bound Au Au' heta he hsv hdenPert hsmall change ‖Aw‖ ≤ n * Lambda at hnumer change ‖Aw' - Aw‖ ≤ e at hnumPert change ‖Au'⁻¹‖ ≤ 2 / eta at hinvAu' change ‖Au'⁻¹ - Au⁻¹‖ ≤ 2 * e / eta ^ 2 at hdiffInv refine ⟨hdetAu, hdetAu', ?_⟩ change ‖Aw' * Au'⁻¹ - Aw * Au⁻¹‖ ≤ (2 / eta + 2 * n * Lambda / eta ^ 2) * e have hsplit : Aw' * Au'⁻¹ - Aw * Au⁻¹ = (Aw' - Aw) * Au'⁻¹ + Aw * (Au'⁻¹ - Au⁻¹) := by noncomm_ring rw [hsplit] calc ‖(Aw' - Aw) * Au'⁻¹ + Aw * (Au'⁻¹ - Au⁻¹)‖ ≤ ‖(Aw' - Aw) * Au'⁻¹‖ + ‖Aw * (Au'⁻¹ - Au⁻¹)‖ := norm_add_le _ _ _ ≤ ‖Aw' - Aw‖ * ‖Au'⁻¹‖ + ‖Aw‖ * ‖Au'⁻¹ - Au⁻¹‖ := add_le_add (Matrix.l2_opNorm_mul _ _) (Matrix.l2_opNorm_mul _ _) _ ≤ e * (2 / eta) + (n * Lambda) * (2 * e / eta ^ 2) := by apply add_le_add · exact mul_le_mul hnumPert hinvAu' (norm_nonneg _) he · exact mul_le_mul hnumer hdiffInv (norm_nonneg _) (mul_nonneg (Nat.cast_nonneg n) hLambda) _ = (2 / eta + 2 * n * Lambda / eta ^ 2) * e := by ring
3 supporting declarations (lemmas, instances)
  • inverse_operatorNorm_le_reciprocal theorem — A positive lower bound on the least singular value of a real square matrix makes its determinant a unit and bounds the operator norm of its inverse by the reciprocal margin. Under the listed assumptions, the stated conclusion follows.
    n :
    A :
    Matrix (Fin n) (Fin n) ℝ
    eta :
    heta :
    0 < eta
    hsv :
    conclusion 1
    IsUnit A.det
    conclusion 2
    squareOperatorNorm A⁻¹ ≤ eta⁻¹
    Proof (Lean source)
    -- Proof route: diagonalize `A†A`; positivity of its last eigenvalue eliminates the kernel and -- gives the inverse bound after applying the least-singular-value expansion inequality. The -- preceding module already contains the required ingredients: -- `injective_of_pos_le_leastColumnSingularValue`, `Matrix.mulVec_injective_iff_isUnit`, and the -- proof pattern of `squareInverse_operatorNorm_le_reciprocal`. theorem inverse_operatorNorm_le_reciprocal {n : ℕ} [NeZero n] (A : Matrix (Fin n) (Fin n) ℝ) {eta : ℝ} (heta : 0 < eta) (hsv : eta ≤ leastColumnSingularValue A) : IsUnit A.det ∧ squareOperatorNorm A⁻¹ ≤ eta⁻¹ := by have hinj := injective_of_pos_le_leastColumnSingularValue A heta hsv have hmulVec : Injective A.mulVec := by intro x y hxy have hlp : A.toEuclideanLin (toLp 2 x) = A.toEuclideanLin (toLp 2 y) := by simpa [Matrix.toEuclideanLin_apply] using congrArg (toLp 2) hxy have := hinj hlp simpa using congrArg WithLp.ofLp this have hunitA : IsUnit A := Matrix.mulVec_injective_iff_isUnit.mp hmulVec have hdet : IsUnit A.det := (Matrix.isUnit_iff_isUnit_det A).mp hunitA refine ⟨hdet, ?_⟩ rw [squareOperatorNorm] apply ContinuousLinearMap.opNorm_le_bound _ (inv_nonneg.mpr heta.le) intro x let E := (Matrix.toEuclideanCLM (n := Fin n) (𝕜 := ℝ)) have hcancel : E A (E A⁻¹ x) = x := by rw [← ContinuousLinearMap.mul_apply, ← map_mul, Matrix.mul_nonsing_inv A hdet, map_one, ContinuousLinearMap.one_apply] have hleast := least_singularValue_mul_norm_le A.toEuclideanLin hinj (E A⁻¹ x) have heta_mul : eta * ‖E A⁻¹ x‖ ≤ ‖x‖ := by calc eta * ‖E A⁻¹ x‖ ≤ leastColumnSingularValue A * ‖E A⁻¹ x‖ := mul_le_mul_of_nonneg_right hsv (norm_nonneg _) _ ≤ ‖A.toEuclideanLin (E A⁻¹ x)‖ := by simpa [leastColumnSingularValue, finrank_euclideanSpace] using hleast _ = ‖x‖ := by change ‖E A (E A⁻¹ x)‖ = ‖x‖ rw [hcancel] rw [inv_mul_eq_div] exact (le_div_iff₀ heta).2 (by simpa [mul_comm] using heta_mul)
    Causalean.Mathlib.Analysis.SymmetricTensorPencil.inverse_operatorNorm_le_reciprocal · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Pencil.lean:27
  • inverse_perturbation_bound theorem — If a square matrix with least singular value at least eta is perturbed by at most e < eta / 2, the perturbed matrix stays invertible and its inverse norm is at most 2 / eta. Under the listed assumptions, the stated conclusion follows.
    n :
    A A' :
    Matrix (Fin n) (Fin n) ℝ
    eta e :
    heta :
    0 < eta
    he :
    0 ≤ e
    hsv :
    hpert :
    squareOperatorNorm (A' - A) ≤ e
    hsmall :
    e < eta / 2
    conclusion 1
    IsUnit A'.det
    conclusion 2
    squareOperatorNorm A'⁻¹ ≤ 2 / eta
    conclusion 3
    squareOperatorNorm (A'⁻¹ - A⁻¹) ≤ 2 * e / eta ^ 2
    Proof (Lean source)
    -- Proof route: turn the determinant-unit witness for `A` into a matrix unit and use -- `Units.ofNearby`/`Units.val_ofNearby` after proving -- `‖A' - A‖ < ‖A⁻¹‖⁻¹`. Bound the new inverse by factoring through the inverse of -- `1 + A⁻¹(A'-A)` (or its geometric series), then use `Matrix.inv_sub_inv` for -- `A'⁻¹-A⁻¹ = A'⁻¹(A-A')A⁻¹`. theorem inverse_perturbation_bound {n : ℕ} [NeZero n] (A A' : Matrix (Fin n) (Fin n) ℝ) {eta e : ℝ} (heta : 0 < eta) (he : 0 ≤ e) (hsv : eta ≤ leastColumnSingularValue A) (hpert : squareOperatorNorm (A' - A) ≤ e) (hsmall : e < eta / 2) : IsUnit A'.det ∧ squareOperatorNorm A'⁻¹ ≤ 2 / eta ∧ squareOperatorNorm (A'⁻¹ - A⁻¹) ≤ 2 * e / eta ^ 2 := by obtain ⟨hdetA, hinvA⟩ := inverse_operatorNorm_le_reciprocal A heta hsv change ‖A⁻¹‖ ≤ eta⁻¹ at hinvA change ‖A' - A‖ ≤ e at hpert let D := A' - A let Q := A⁻¹ * D have hQ : ‖Q‖ < 1 / 2 := by calc ‖Q‖ ≤ ‖A⁻¹‖ * ‖D‖ := Matrix.l2_opNorm_mul _ _ _ ≤ eta⁻¹ * e := mul_le_mul hinvA hpert (norm_nonneg _) (inv_nonneg.mpr heta.le) _ < 1 / 2 := by rw [inv_mul_eq_div, div_lt_iff₀ heta] simpa [div_eq_mul_inv, mul_comm, mul_left_comm, mul_assoc] using hsmall have hnegQ : ‖-Q‖ < 1 := by simpa using hQ.trans (by norm_num) let B : Matrix (Fin n) (Fin n) ℝ := 1 + Q have hdetB : IsUnit B.det := by apply (Matrix.isUnit_iff_isUnit_det B).mp have hu := (Units.oneSub (-Q) hnegQ).isUnit simpa [B] using hu have hfactor : A' = A * B := by calc A' = A + D := by simp [D] _ = A * (1 + Q) := by simp only [Matrix.mul_add, Matrix.mul_one, Q, D] rw [← Matrix.mul_assoc, Matrix.mul_nonsing_inv A hdetA, Matrix.one_mul] _ = A * B := rfl have hdetA' : IsUnit A'.det := by rw [hfactor, Matrix.det_mul] exact hdetA.mul hdetB have hinvB : ‖B⁻¹‖ ≤ 2 := by rw [Matrix.nonsing_inv_eq_ringInverse] rw [show B = 1 - (-Q) by simp [B], NormedRing.inverse_one_sub (-Q) hnegQ] change ‖∑' k : ℕ, (-Q) ^ k‖ ≤ 2 have hgeom := tsum_geometric_le_of_norm_lt_one (-Q) hnegQ have hden : (1 - ‖-Q‖)⁻¹ ≤ 2 := by have : ‖-Q‖ < 1 / 2 := by simpa using hQ exact inv_le_of_inv_le₀ (by norm_num) (by norm_num; linarith) have hgeom' : ‖∑' k : ℕ, (-Q) ^ k‖ ≤ (1 - ‖-Q‖)⁻¹ := by simpa only [norm_one, sub_self, zero_add] using hgeom exact hgeom'.trans hden have hinvA' : ‖A'⁻¹‖ ≤ 2 / eta := by rw [hfactor, Matrix.mul_inv_rev] calc ‖B⁻¹ * A⁻¹‖ ≤ ‖B⁻¹‖ * ‖A⁻¹‖ := Matrix.l2_opNorm_mul _ _ _ ≤ 2 * eta⁻¹ := mul_le_mul hinvB hinvA (norm_nonneg _) (by norm_num) _ = 2 / eta := by rw [div_eq_mul_inv] refine ⟨hdetA', hinvA', ?_⟩ change ‖A'⁻¹ - A⁻¹‖ ≤ 2 * e / eta ^ 2 have hunitA' : IsUnit A' := (Matrix.isUnit_iff_isUnit_det A').2 hdetA' have hunitA : IsUnit A := (Matrix.isUnit_iff_isUnit_det A).2 hdetA rw [Matrix.inv_sub_inv ⟨fun _ => hunitA, fun _ => hunitA'⟩] calc ‖A'⁻¹ * (A - A') * A⁻¹‖ ≤ ‖A'⁻¹ * (A - A')‖ * ‖A⁻¹‖ := Matrix.l2_opNorm_mul _ _ _ ≤ (‖A'⁻¹‖ * ‖A - A'‖) * ‖A⁻¹‖ := by gcongr exact Matrix.l2_opNorm_mul _ _ _ ≤ ((2 / eta) * e) * eta⁻¹ := by have hdiff : ‖A - A'‖ ≤ e := by simpa [norm_sub_rev] using hpert have hleft : ‖A'⁻¹‖ * ‖A - A'‖ ≤ (2 / eta) * e := mul_le_mul hinvA' hdiff (norm_nonneg _) (div_nonneg (by norm_num) heta.le) exact mul_le_mul hleft hinvA (norm_nonneg _) (mul_nonneg (div_nonneg (by norm_num) heta.le) he) _ = 2 * e / eta ^ 2 := by field_simp [heta.ne']
    Causalean.Mathlib.Analysis.SymmetricTensorPencil.inverse_perturbation_bound · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Pencil.lean:70
  • rightPencil_eq_diagonalization theorem — Exact contracted factorizations produce a simultaneous diagonalization of every right pencil, with diagonal entries equal to probe-loading ratios. Under the listed assumptions, the stated conclusion follows.
    n :
    S :
    Matrix (Fin n) (Fin n) ℝ
    lam den num :
    Fin n → ℝ
    hS :
    IsUnit S.det
    hload :
    ∀ j, lam j * den j ≠ 0
    rightPencil (S * diagonal (fun j => lam j * num j) * S.transpose) (S * diagonal (fun j => lam j * den j) * S.transpose)
    = S * diagonal (fun j => num j / den j) * S⁻¹
    Proof (Lean source)
    -- Proof route: use determinant-unit closure for `S`, `S.transpose`, and the nonzero diagonal -- core, expand the nonsingular inverse of a product, cancel `S.transpose`, and check the -- remaining diagonal identity entrywise with `Matrix.diagonal_mul_diagonal`. theorem rightPencil_eq_diagonalization {n : ℕ} (S : Matrix (Fin n) (Fin n) ℝ) (lam den num : Fin n → ℝ) (hS : IsUnit S.det) (hload : ∀ j, lam j * den j ≠ 0) : rightPencil (S * diagonal (fun j => lam j * num j) * S.transpose) (S * diagonal (fun j => lam j * den j) * S.transpose) = S * diagonal (fun j => num j / den j) * S⁻¹ := by let Dnum := diagonal (fun j => lam j * num j) let Dden := diagonal (fun j => lam j * den j) let Drat := diagonal (fun j => num j / den j) have hSt : IsUnit S.transpose.det := Matrix.isUnit_det_transpose S hS have hdiag : Dnum * Dden⁻¹ = Drat := by let f : Fin n → ℝ := fun j => lam j * den j have hf : IsUnit f := Pi.isUnit_iff.mpr fun j => isUnit_iff_ne_zero.mpr (hload j) obtain ⟨u, hu⟩ := hf have hinvf : Ring.inverse f = ↑u⁻¹ := by rw [← hu, Ring.inverse_unit] rw [Matrix.inv_diagonal, Matrix.diagonal_mul_diagonal] congr 1 funext j have hlam : lam j ≠ 0 := left_ne_zero_of_mul (hload j) have hden : den j ≠ 0 := right_ne_zero_of_mul (hload j) have hcancel : f j * Ring.inverse f j = 1 := by rw [hinvf, ← hu] exact congrFun u.val_inv j have hinv_entry : Ring.inverse f j = (f j)⁻¹ := by apply mul_left_cancel₀ (hload j) rw [hcancel, mul_inv_cancel₀ (hload j)] change lam j * num j * Ring.inverse f j = num j / den j rw [hinv_entry] dsimp only [f] field_simp [hlam, hden] change (S * Dnum * S.transpose) * (S * Dden * S.transpose)⁻¹ = S * Drat * S⁻¹ rw [Matrix.mul_inv_rev, Matrix.mul_inv_rev] simp only [Matrix.mul_assoc] rw [← Matrix.mul_assoc S.transpose S.transpose⁻¹, Matrix.mul_nonsing_inv S.transpose hSt, Matrix.one_mul] rw [← Matrix.mul_assoc Dnum Dden⁻¹, hdiag]
    Causalean.Mathlib.Analysis.SymmetricTensorPencil.rightPencil_eq_diagonalization · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Pencil.lean:194
Recovery 7 core · 6 supporting This module turns matched spectral projectors into quantitative direction information. ★ traceCoordinates_perturbation_bound

Recovery and normalization of directions

This module turns matched spectral projectors into quantitative direction information. It includes both direct recovery of a rank-one lifted line from a nearby projector and the trace-coordinate construction that removes the degree-lift ambiguity by using coordinate probes.

def standardBasis reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

The standard coordinate vector in a finite real coordinate space. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
p :
i :
Fin p
standardBasis p i :
Vec p
fun k => if k = i then 1 else 0
Causalean.Mathlib.Analysis.SymmetricTensorPencil.standardBasis · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Recovery.lean:13 · uses Vec
def normalizeFinite reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

Normalize a finite real array by its Euclidean norm, with the conventional zero value when the input is zero. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
ι :
Type*
z :
ι → ℝ
normalizeFinite z :
ι → ℝ
(finiteFrobeniusNorm z)⁻¹ • z
Causalean.Mathlib.Analysis.SymmetricTensorPencil.normalizeFinite · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Recovery.lean:17
def normalizeVec reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

Normalize a finite coordinate vector by its Euclidean norm, with the conventional zero value when the input is zero. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
p :
z :
Vec p
normalizeVec z :
Vec p
Causalean.Mathlib.Analysis.SymmetricTensorPencil.normalizeVec · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Recovery.lean:22 · uses Vec
def recoverRankOneLift reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

Apply a candidate projector to a degree-d rank-one lift and normalize the resulting lifted direction. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
p d :
P :
Matrix (LiftIndex p d) (LiftIndex p d) ℝ
c :
Vec p
recoverRankOneLift P c :
LiftIndex p d → ℝ
normalizeFinite (P.mulVec (fun I => ∏ k, c (I k)))
Causalean.Mathlib.Analysis.SymmetricTensorPencil.recoverRankOneLift · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Recovery.lean:129 · uses LiftIndex , Vec
def traceCoordinates reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

Trace coordinates evaluate each coordinate pencil against the j-th matrix of a supplied matrix family, by the trace of their product. No condition is imposed on the family; in the recovery argument it is a family of rank-one spectral projectors. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
p n :
G :
Vec p → Matrix (Fin n) (Fin n) ℝ
P :
Fin n → Matrix (Fin n) (Fin n) ℝ
j :
Fin n
traceCoordinates G P j :
Vec p
fun i => trace (G (standardBasis p i) * P j)
Causalean.Mathlib.Analysis.SymmetricTensorPencil.traceCoordinates · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Recovery.lean:203 · uses Vec
theorem traceCoordinates_perturbation_bound reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

Given reference and perturbed coordinate pencils, reference and perturbed matrix families (arbitrary matrices; projectors in the intended use), coordinate-pencil error bounds, projector error bounds, perturbed-projector norm bounds, and reference-pencil norm bounds, every trace coordinate obeys the explicit product error bound. Under the listed assumptions, the stated conclusion follows.

Formal statement
p n :
G G' :
Vec p → Matrix (Fin n) (Fin n) ℝ
P P' :
Fin n → Matrix (Fin n) (Fin n) ℝ
pencilError projectorError projectorNorm pencilNorm :
hpencil :
∀ i, squareOperatorNorm (G' (standardBasis p i) - G (standardBasis p i)) ≤ pencilError
hprojector :
∀ j, squareOperatorNorm (P' j - P j) ≤ projectorError
hprojectorNorm :
∀ j, squareOperatorNorm (P' j) ≤ projectorNorm
hpencilNorm :
∀ i, squareOperatorNorm (G (standardBasis p i)) ≤ pencilNorm
i j :
|traceCoordinates G' P' j i - traceCoordinates G P j i|
≤ n * (pencilError * projectorNorm + pencilNorm * projectorError)
Proof (Lean source)
-- Proof route: write `G'P'-GP = (G'-G)P' + G(P'-P)`, use submultiplicativity, and finish with -- `abs_trace_le_card_mul_operatorNorm`. theorem traceCoordinates_perturbation_bound {p n : ℕ} (G G' : Vec p → Matrix (Fin n) (Fin n) ℝ) (P P' : Fin n → Matrix (Fin n) (Fin n) ℝ) {pencilError projectorError projectorNorm pencilNorm : ℝ} (hpencil : ∀ i, squareOperatorNorm (G' (standardBasis p i) - G (standardBasis p i)) ≤ pencilError) (hprojector : ∀ j, squareOperatorNorm (P' j - P j) ≤ projectorError) (hprojectorNorm : ∀ j, squareOperatorNorm (P' j) ≤ projectorNorm) (hpencilNorm : ∀ i, squareOperatorNorm (G (standardBasis p i)) ≤ pencilNorm) : ∀ i j, |traceCoordinates G' P' j i - traceCoordinates G P j i| ≤ n * (pencilError * projectorNorm + pencilNorm * projectorError) := by classical intro i j let e := standardBasis p i have hpencilError : 0 ≤ pencilError := (show 0 ≤ squareOperatorNorm (G' e - G e) by exact norm_nonneg _).trans (hpencil i) have hprojectorError : 0 ≤ projectorError := (show 0 ≤ squareOperatorNorm (P' j - P j) by exact norm_nonneg _).trans (hprojector j) have hprojectorNorm₀ : 0 ≤ projectorNorm := (show 0 ≤ squareOperatorNorm (P' j) by exact norm_nonneg _).trans (hprojectorNorm j) have hpencilNorm₀ : 0 ≤ pencilNorm := (show 0 ≤ squareOperatorNorm (G e) by exact norm_nonneg _).trans (hpencilNorm i) have hdecomp : G' e * P' j - G e * P j = (G' e - G e) * P' j + G e * (P' j - P j) := by noncomm_ring have hop : squareOperatorNorm (G' e * P' j - G e * P j) ≤ pencilError * projectorNorm + pencilNorm * projectorError := by rw [hdecomp] calc squareOperatorNorm ((G' e - G e) * P' j + G e * (P' j - P j)) ≤ squareOperatorNorm ((G' e - G e) * P' j) + squareOperatorNorm (G e * (P' j - P j)) := squareOperatorNorm_add_le _ _ _ ≤ squareOperatorNorm (G' e - G e) * squareOperatorNorm (P' j) + squareOperatorNorm (G e) * squareOperatorNorm (P' j - P j) := add_le_add (squareOperatorNorm_mul_le _ _) (squareOperatorNorm_mul_le _ _) _ ≤ pencilError * projectorNorm + pencilNorm * projectorError := by apply add_le_add · exact mul_le_mul (hpencil i) (hprojectorNorm j) (show 0 ≤ squareOperatorNorm (P' j) by exact norm_nonneg _) hpencilError · exact mul_le_mul (hpencilNorm i) (hprojector j) (show 0 ≤ squareOperatorNorm (P' j - P j) by exact norm_nonneg _) hpencilNorm₀ change |trace (G' e * P' j) - trace (G e * P j)| ≤ _ rw [← Matrix.trace_sub] exact (abs_trace_le_card_mul_operatorNorm (G' e * P' j - G e * P j)).trans (mul_le_mul_of_nonneg_left hop (Nat.cast_nonneg n))
Causalean.Mathlib.Analysis.SymmetricTensorPencil.traceCoordinates_perturbation_bound · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Recovery.lean:255 · uses Vec , squareOperatorNorm , standardBasis , traceCoordinates
def permuteColumns reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

Permute the columns of a finite factor matrix. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
p n :
C :
pi :
Perm (Fin n)
permuteColumns C pi :
fun i j => C i (pi j)
Causalean.Mathlib.Analysis.SymmetricTensorPencil.permuteColumns · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Recovery.lean:385 · uses FactorMatrix
6 supporting declarations (lemmas, instances)
Conditioning 3 core · 8 supporting This module records how an orthonormal basis of the lifted column space preserves the signal singular values. ★ compressedDenominator_leastSingularValue

Conditioning of compressed lifted factors

This module records how an orthonormal basis of the lifted column space preserves the signal singular values. It then derives explicit lower and upper bounds for the contracted matrices which form the denominator and numerators of a tensor pencil.

def OrthonormalColumns reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

A finite matrix has orthonormal columns when its transpose times itself is the identity. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
ι κ :
U :
Matrix ι κ ℝ
OrthonormalColumns U :
Prop
U.transpose * U = 1
Causalean.Mathlib.Analysis.SymmetricTensorPencil.OrthonormalColumns · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Conditioning.lean:15
def SameColumnSpace reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

Two finite matrices have the same column space when their associated Euclidean linear maps have equal ranges. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
ι κ :
U V :
Matrix ι κ ℝ
SameColumnSpace U V :
Prop
U.toEuclideanLin.range = V.toEuclideanLin.range
Causalean.Mathlib.Analysis.SymmetricTensorPencil.SameColumnSpace · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Conditioning.lean:20
theorem compressedDenominator_leastSingularValue reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

Given a factor matrix, its coefficients, a denominator probe, orthonormal lifted coordinates, positive degree and margins, a lifted singular-value margin, coefficient lower bounds, and probe-loading lower bounds, the compressed denominator contraction has least singular value at least the assembled margin. Under the listed assumptions, the stated conclusion follows.

Formal statement
p n d q :
C :
lam :
Fin n → ℝ
u :
Vec p
U :
Matrix (LiftIndex p d) (Fin n) ℝ
sigma kappa :
hq :
0 < q
hsigma :
0 < sigma
hkappa :
0 < kappa
horth :
hlift :
hlam :
∀ j, kappa ≤ |lam j|
hprobe :
∀ j, sigma ≤ dot u (C.col j)
kappa * sigma ^ (q + 2)
leastColumnSingularValue ((U.transpose * liftedDirections d C) * diagonal (fun j => lam j * dot u (C.col j) ^ q) * (U.transpose * liftedDirections d C).transpose)
Proof (Lean source)
-- Proof route: use `Matrix.singularValues_mul_mul_transpose_lower_bound`; the diagonal core -- expands by `kappa * sigma^q`, while each compressed lifted factor expands by `sigma`. theorem compressedDenominator_leastSingularValue {p n d q : ℕ} [NeZero n] (C : FactorMatrix p n) (lam : Fin n → ℝ) (u : Vec p) (U : Matrix (LiftIndex p d) (Fin n) ℝ) {sigma kappa : ℝ} (hq : 0 < q) (hsigma : 0 < sigma) (hkappa : 0 < kappa) (horth : OrthonormalColumns U) (hspace : SameColumnSpace U (liftedDirections d C)) (hlift : sigma ≤ leastColumnSingularValue (liftedDirections d C)) (hlam : ∀ j, kappa ≤ |lam j|) (hprobe : ∀ j, sigma ≤ dot u (C.col j)) : kappa * sigma ^ (q + 2) ≤ leastColumnSingularValue ((U.transpose * liftedDirections d C) * diagonal (fun j => lam j * dot u (C.col j) ^ q) * (U.transpose * liftedDirections d C).transpose) := by let S := U.transpose * liftedDirections d C let D := diagonal (fun j => lam j * dot u (C.col j) ^ q) have hSsv : sigma ≤ leastColumnSingularValue S := compressedLift_leastSingularValue C U hsigma hlift horth hspace have hSinj : Injective S.toEuclideanLin := injective_of_pos_le_leastColumnSingularValue S hsigma hSsv have hload (j : Fin n) : kappa * sigma ^ q ≤ |lam j * dot u (C.col j) ^ q| := by have huj : 0 < dot u (C.col j) := hsigma.trans_le (hprobe j) rw [abs_mul, abs_pow, abs_of_pos huj] exact mul_le_mul (hlam j) (pow_le_pow_left₀ hsigma.le (hprobe j) q) (pow_nonneg hsigma.le q) (abs_nonneg _) have hDinj : Injective D.toEuclideanLin := by intro x y hxy apply PiLp.ext intro j have hj := congrArg (fun z : EuclideanSpace ℝ (Fin n) => ofLp z j) hxy simp only [D, Matrix.toEuclideanLin_apply, WithLp.ofLp_toLp, Matrix.mulVec_diagonal] at hj have hne : lam j * dot u (C.col j) ^ q ≠ 0 := by intro hz have := hload j rw [hz, abs_zero] at this have hcpos : 0 < kappa * sigma ^ q := mul_pos hkappa (pow_pos hsigma q) linarith exact mul_left_cancel₀ hne hj have hDsv : kappa * sigma ^ q ≤ leastColumnSingularValue D := by apply le_singularValues_of_subspace D.toEuclideanLin ⊤ · exact mul_nonneg hkappa.le (pow_nonneg hsigma.le q) · simp only [finrank_euclideanSpace, finrank_top] exact sub_lt (Fintype.card_pos) (by omega) · intro x _hx apply (sq_le_sq₀ (mul_nonneg (mul_nonneg hkappa.le (pow_nonneg hsigma.le q)) (norm_nonneg x)) (norm_nonneg (D.toEuclideanLin x))).mp rw [mul_pow, EuclideanSpace.norm_sq_eq, EuclideanSpace.norm_sq_eq, Finset.mul_sum] apply Finset.sum_le_sum intro j _ simp only [D, Matrix.toEuclideanLin_apply, WithLp.ofLp_toLp, Matrix.mulVec_diagonal, Real.norm_eq_abs, PiLp.inner_apply, RCLike.inner_apply, conj_trivial, mul_pow] rw [abs_mul, mul_pow] convert mul_le_mul_of_nonneg_right ((sq_le_sq₀ (mul_nonneg hkappa.le (pow_nonneg hsigma.le q)) (abs_nonneg _)).2 (hload j)) (sq_nonneg (ofLp x j)) using 1 <;> simp only [sq_abs] <;> ring have hprod := singularValues_mul_mul_transpose_lower_bound S D S hSinj hDinj hSinj have hS0 := S.toEuclideanLin.singularValues_nonneg (card (Fin n) - 1) have hD0 := D.toEuclideanLin.singularValues_nonneg (card (Fin n) - 1) calc kappa * sigma ^ (q + 2) = sigma * (kappa * sigma ^ q) * sigma := by rw [pow_add] ring _ ≤ leastColumnSingularValue S * leastColumnSingularValue D * leastColumnSingularValue S := by exact mul_le_mul (mul_le_mul hSsv hDsv (mul_nonneg hkappa.le (pow_nonneg hsigma.le q)) hS0) hSsv hsigma.le (mul_nonneg hS0 hD0) _ ≤ leastColumnSingularValue (S * D * S.transpose) := by simpa [leastColumnSingularValue] using hprod
8 supporting declarations (lemmas, instances)
Main 6 core · 1 supporting This module assembles contraction, lifted conditioning, pencil perturbation, spectral-projector matching, trace-coordinate recovery, and normalization into a permutation-aligned local inverse for finite symmetric rank-on ★ exists_permutation_factorMatrix_frobeniusNorm_le

Quantitative local inverse for symmetric tensor pencils

This module assembles contraction, lifted conditioning, pencil perturbation, spectral-projector matching, trace-coordinate recovery, and normalization into a permutation-aligned local inverse for finite symmetric rank-one tensor decompositions.

def contractedMargin reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

The contracted denominator singular-value margin assembled from coefficient, probe, and lifted-factor margins. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
q :
sigma kappa :
contractedMargin q sigma kappa :
kappa * sigma ^ (q + 2)
Causalean.Mathlib.Analysis.SymmetricTensorPencil.contractedMargin · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Main.lean:15
def liftedConditionEnvelope reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

The condition-number envelope for a lifted matrix with n unit columns and least singular value at least sigma, namely the square root of n divided by sigma. The formula is unguarded: it is a condition-number envelope only for positive sigma, and a zero margin gives zero by the division-by-zero convention. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
n :
sigma :
liftedConditionEnvelope n sigma :
sqrt n / sigma
Causalean.Mathlib.Analysis.SymmetricTensorPencil.liftedConditionEnvelope · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Main.lean:20
def localInverseRadius reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

The admissible tensor perturbation radius for the quantitative tensor-pencil inverse. The formula is unguarded: it is an admissible radius only in the positive-margin regime assumed by the inverse theorem, and degenerate margins give zero by the division-by-zero convention. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
n q :
sigma kappa Lambda :
localInverseRadius n q sigma kappa Lambda :
eta :
contractedMargin q sigma kappa
chi :
h :
min (eta / 2) (sigma / (6 * chi * h))
Causalean.Mathlib.Analysis.SymmetricTensorPencil.localInverseRadius · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Main.lean:27
def traceRecoveryConstant reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

The coordinatewise trace-recovery Lipschitz factor for the quantitative tensor-pencil inverse. The formula is unguarded: it is a valid Lipschitz factor only in the positive-margin regime assumed by the recovery theorems, and degenerate margins give zero by the division-by-zero convention. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
n q :
sigma kappa Lambda :
traceRecoveryConstant n q sigma kappa Lambda :
eta :
contractedMargin q sigma kappa
chi :
h :
n * h * (2 * chi + 6 * n * Lambda * chi ^ 2 / (eta * sigma))
Causalean.Mathlib.Analysis.SymmetricTensorPencil.traceRecoveryConstant · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Main.lean:36
def factorRecoveryConstant reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

The final factor-matrix Frobenius Lipschitz factor for the quantitative tensor-pencil inverse. It is a fixed multiple of the trace-recovery factor and inherits its unguarded conventions: it is a valid Lipschitz factor only in the positive-margin regime of the recovery theorems. With its explicit inputs, the defined object is given by the displayed formula.

Definition (Lean source)
p n q :
sigma kappa Lambda :
factorRecoveryConstant p n q sigma kappa Lambda :
2 * sqrt (n * p) * traceRecoveryConstant n q sigma kappa Lambda
Causalean.Mathlib.Analysis.SymmetricTensorPencil.factorRecoveryConstant · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Main.lean:46
theorem exists_permutation_factorMatrix_frobeniusNorm_le reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

Quantitative symmetric-tensor-pencil local inverse. Given two finite factor matrices, their coefficient vectors, two probes, the gap and coefficient margins, positive ambient dimensions and degrees, an admissible singular-value margin, positive and compatible coefficient bounds, unit probes, unit factor columns, two-sided coefficient bounds, positive denominator loadings, well-conditioned lifted directions, separated pencil ratios, and a tensor perturbation below the explicit local radius, one column permutation makes the factor-matrix Frobenius error at most the stated Lipschitz factor times the tensor Frobenius error. Under the listed assumptions, the stated conclusion follows.

Formal statement
p n d q :
C C' :
lam lam' :
Fin n → ℝ
u v :
Vec p
sigma kappa Lambda :
hp :
0 < p
hn :
0 < n
hd :
0 < d
hq :
0 < q
hsigma :
0 < sigma ∧ sigma ≤ 1
hkappa :
0 < kappa
hkappaLambda :
kappa ≤ Lambda
hu :
hv :
hunit :
(∀ j, finiteFrobeniusNorm (C.col j) = 1) ∧ ∀ j, finiteFrobeniusNorm (C'.col j) = 1
hlam :
(∀ j, kappa ≤ |lam j| ∧ |lam j| ≤ Lambda) ∧ ∀ j, kappa ≤ |lam' j| ∧ |lam' j| ≤ Lambda
hprobe :
(∀ j, sigma ≤ dot u (C.col j)) ∧ ∀ j, sigma ≤ dot u (C'.col j)
hgap :
PairwiseGap (fun j => dot v (C.col j) / dot u (C.col j)) sigma ∧
PairwiseGap (fun j => dot v (C'.col j) / dot u (C'.col j)) sigma
hclose :
finiteFrobeniusNorm (decompositionTensor (d + d + q) C' lam' - decompositionTensor (d + d + q) C lam) < localInverseRadius n q sigma kappa Lambda
∃ pi : Perm (Fin n),
factorRecoveryConstant p n q sigma kappa Lambda * finiteFrobeniusNorm (decompositionTensor (d + d + q) C' lam' - decompositionTensor (d + d + q) C lam)
Proof (Lean source)
-- Proof route: contract and compress using one orthonormal basis for the unprimed lifted range; -- the denominator margin is `eta`, every coordinate pencil moves by at most `h*e`, and the -- Riesz-projector theorem supplies one common permutation. Trace coordinates then move by -- `Lz*e`; positive probe orientation makes their normalization equal the original columns. -- -- A convenient detailed assembly is as follows. -- 1. Put `V = liftedDirections d C`, choose an orthonormal basis of `V.toEuclideanLin.range` -- (use `stdOrthonormalBasis` on the range subtype and reindex using the finrank equality from -- injectivity), and write its ambient coordinate columns as `U`. Prove `OrthonormalColumns U` -- and `SameColumnSpace U V`; put `S = U.transpose * V` and similarly `S'` for `C'`. -- 2. Compress the `u` denominator contractions and coordinate numerator contractions by `U`. -- The exact contraction identity identifies them with `S * diagonal * S.transpose` (and the -- primed analogue). Contraction plus `squareOperatorNorm_compress_le` bounds every difference -- by the tensor error `e`. The denominator theorem gives least singular value `eta`; inverse -- perturbation makes the primed denominator invertible, and determinant multiplicativity then -- makes `S'` invertible. -- 3. Define the right pencils `G w` and `G' w`. `rightPencil_eq_diagonalization` identifies them -- with the loading-ratio diagonalizations. For every standard basis probe, -- `rightPencil_perturbation_bound` gives error `h*e`; the unprimed pencil norm is at most -- `n*Lambda/eta` by numerator and inverse bounds. -- 4. From `e < min (eta/2) (sigma/(6*chi*h))`, derive both smallness inequalities and apply -- `exists_permutation_projector_matching` once. Feed that common permutation and its -- projector bounds into `traceCoordinates_perturbation_bound`; after -- `finiteFrobeniusNorm_sub_le_sqrt_mul`, each trace vector has error at most -- `sqrt p * traceRecoveryConstant ... * e`. -- 5. Exact trace diagonalization says those vectors are the positively rescaled columns. -- Cauchy--Schwarz and the unit hypotheses make their norms at least one. Apply -- `normalizeVec_sub_normalizeVec_le`, rewrite both normalizations with -- `normalizeVec_inv_smul_eq`, and combine the column estimates using -- `matrixFrobeniusNorm_le_sqrt_mul_of_columns`. Finish with -- `Real.sqrt_mul` on the nonnegative natural casts and the definition of -- `factorRecoveryConstant`. theorem exists_permutation_factorMatrix_frobeniusNorm_le {p n d q : ℕ} (C C' : FactorMatrix p n) (lam lam' : Fin n → ℝ) (u v : Vec p) (sigma kappa Lambda : ℝ) (hp : 0 < p) (hn : 0 < n) (hd : 0 < d) (hq : 0 < q) (hsigma : 0 < sigma ∧ sigma ≤ 1) (hkappa : 0 < kappa) (hkappaLambda : kappa ≤ Lambda) (hu : finiteFrobeniusNorm u = 1) (hv : finiteFrobeniusNorm v = 1) (hunit : (∀ j, finiteFrobeniusNorm (C.col j) = 1) ∧ ∀ j, finiteFrobeniusNorm (C'.col j) = 1) (hlam : (∀ j, kappa ≤ |lam j| ∧ |lam j| ≤ Lambda) ∧ ∀ j, kappa ≤ |lam' j| ∧ |lam' j| ≤ Lambda) (hprobe : (∀ j, sigma ≤ dot u (C.col j)) ∧ ∀ j, sigma ≤ dot u (C'.col j)) (hlift : sigma ≤ leastColumnSingularValue (liftedDirections d C) ∧ sigma ≤ leastColumnSingularValue (liftedDirections d C')) (hgap : PairwiseGap (fun j => dot v (C.col j) / dot u (C.col j)) sigma ∧ PairwiseGap (fun j => dot v (C'.col j) / dot u (C'.col j)) sigma) (hclose : finiteFrobeniusNorm (decompositionTensor (d + d + q) C' lam' - decompositionTensor (d + d + q) C lam) < localInverseRadius n q sigma kappa Lambda) : ∃ pi : Perm (Fin n), matrixFrobeniusNorm (permuteColumns C' pi - C) ≤ factorRecoveryConstant p n q sigma kappa Lambda * finiteFrobeniusNorm (decompositionTensor (d + d + q) C' lam' - decompositionTensor (d + d + q) C lam) := by classical letI : NeZero n := ⟨Nat.ne_of_gt hn⟩ let T := decompositionTensor (d + d + q) C lam let T' := decompositionTensor (d + d + q) C' lam' let e := finiteFrobeniusNorm (T' - T) let eta := contractedMargin q sigma kappa let chi := liftedConditionEnvelope n sigma let h := pencilPerturbationConstant n eta Lambda let Lz := traceRecoveryConstant n q sigma kappa Lambda have hLambda : 0 < Lambda := lt_of_lt_of_le hkappa hkappaLambda obtain ⟨heta, hchi, hh, hradius, hLz, _hfactor⟩ := localInverse_constants_pos hp hn hq hsigma.1 hkappa hkappaLambda change 0 < eta at heta change 0 < chi at hchi change 0 < h at hh change 0 < Lz at hLz have he : 0 ≤ e := Real.sqrt_nonneg _ have heRadius : e < localInverseRadius n q sigma kappa Lambda := hclose have heSmall : e < eta / 2 := by exact heRadius.trans_le (min_le_left _ _) have heProjector : 6 * chi * (h * e) < sigma := by have heSecond : e < sigma / (6 * chi * h) := heRadius.trans_le (min_le_right _ _) have hden : 0 < 6 * chi * h := mul_pos (mul_pos (by norm_num) hchi) hh apply (lt_div_iff₀ hden).mp at heSecond nlinarith let V := liftedDirections d C let V' := liftedDirections d C' have hinjV : Injective V.toEuclideanLin := injective_of_pos_le_leastColumnSingularValue V hsigma.1 hlift.1 obtain ⟨U, hUorth, hUspace⟩ := exists_orthonormalColumns_sameColumnSpace V hinjV let S := U.transpose * V let S' := U.transpose * V' let Au := U.transpose * contractLast T (pencilProbes u u) * U let Au' := U.transpose * contractLast T' (pencilProbes u u) * U let Aw : Vec p → Matrix (Fin n) (Fin n) ℝ := fun w => U.transpose * contractLast T (pencilProbes u w) * U let Aw' : Vec p → Matrix (Fin n) (Fin n) ℝ := fun w => U.transpose * contractLast T' (pencilProbes u w) * U have hpencilProbes (w : Vec p) (hw : finiteFrobeniusNorm w = 1) : ∀ a : Fin q, finiteFrobeniusNorm (pencilProbes u w a) ≤ 1 := by intro a simp only [pencilProbes] split <;> simp_all have hcompressedPert (w : Vec p) (hw : finiteFrobeniusNorm w = 1) : squareOperatorNorm (Aw' w - Aw w) ≤ e := by have hcontract : contractLast T' (pencilProbes u w) - contractLast T (pencilProbes u w) = contractLast (T' - T) (pencilProbes u w) := by ext i j simp only [contractLast, Matrix.sub_apply, Pi.sub_apply] rw [← Finset.sum_sub_distrib] apply Finset.sum_congr rfl intro K _ ring have hmatrix : Aw' w - Aw w = U.transpose * contractLast (T' - T) (pencilProbes u w) * U := by dsimp only [Aw, Aw'] rw [← Matrix.sub_mul, ← Matrix.mul_sub, hcontract] rw [hmatrix] exact (squareOperatorNorm_compress_le U (contractLast (T' - T) (pencilProbes u w)) hUorth).trans (contractLast_operatorNorm_le (T' - T) (pencilProbes u w) (hpencilProbes w hw)) have hAuPert : squareOperatorNorm (Au' - Au) ≤ e := by simpa only [Au, Au', Aw, Aw'] using hcompressedPert u hu have hAuFactor : Au = S * diagonal (fun j => lam j * dot u (C.col j) ^ q) * S.transpose := by dsimp only [Au, T] rw [contractLast_decompositionTensor hq] have hdiag : diagonal (fun j => lam j * dot u (C.col j) ^ (q - 1) * dot u (C.col j)) = diagonal (fun j => lam j * dot u (C.col j) ^ q) := by congr 1 funext j rw [mul_assoc, pow_sub_one_mul (Nat.ne_of_gt hq)] rw [hdiag] simp only [S, V, Matrix.transpose_mul, Matrix.transpose_transpose, Matrix.mul_assoc] have hAuFactor' : Au' = S' * diagonal (fun j => lam' j * dot u (C'.col j) ^ q) * S'.transpose := by dsimp only [Au', T'] rw [contractLast_decompositionTensor hq] have hdiag : diagonal (fun j => lam' j * dot u (C'.col j) ^ (q - 1) * dot u (C'.col j)) = diagonal (fun j => lam' j * dot u (C'.col j) ^ q) := by congr 1 funext j rw [mul_assoc, pow_sub_one_mul (Nat.ne_of_gt hq)] rw [hdiag] simp only [S', V', Matrix.transpose_mul, Matrix.transpose_transpose, Matrix.mul_assoc] have hAuSv : eta ≤ leastColumnSingularValue Au := by rw [hAuFactor] exact compressedDenominator_leastSingularValue C lam u U hq hsigma.1 hkappa hUorth hUspace hlift.1 (fun j => hlam.1 j |>.1) hprobe.1 obtain ⟨hAuUnit, hAuInv⟩ := inverse_operatorNorm_le_reciprocal Au heta hAuSv obtain ⟨hAuUnit', hAuInv', hAuInvPert⟩ := inverse_perturbation_bound Au Au' heta he hAuSv hAuPert heSmall have hSsv : sigma ≤ leastColumnSingularValue S := compressedLift_leastSingularValue C U hsigma.1 hlift.1 hUorth hUspace obtain ⟨hS, _hSinv⟩ := inverse_operatorNorm_le_reciprocal S hsigma.1 hSsv have hS' : IsUnit S'.det := by apply isUnit_iff_ne_zero.mpr intro hzero have hdetzero : Au'.det = 0 := by rw [hAuFactor', Matrix.det_mul, Matrix.det_mul, hzero] simp exact (isUnit_iff_ne_zero.mp hAuUnit') hdetzero have hcondition : squareOperatorNorm S * squareOperatorNorm S⁻¹ ≤ chi := by exact compressedLift_condition_le C U hd hsigma.1 hunit.1 hlift.1 hUorth hUspace have hstandard (i : Fin p) : finiteFrobeniusNorm (standardBasis p i) = 1 := by unfold finiteFrobeniusNorm standardBasis simp have hAwNorm (i : Fin p) : squareOperatorNorm (Aw (standardBasis p i)) ≤ n * Lambda := by exact compressedNumerator_operatorNorm_le C lam u (standardBasis p i) U hd hq hLambda.le hUorth hunit.1 hu (hstandard i) (fun j => hlam.1 j |>.2) let G : Vec p → Matrix (Fin n) (Fin n) ℝ := fun w => rightPencil (Aw w) Au let G' : Vec p → Matrix (Fin n) (Fin n) ℝ := fun w => rightPencil (Aw' w) Au' let values : Fin n → ℝ := fun j => dot v (C.col j) / dot u (C.col j) let values' : Fin n → ℝ := fun j => dot v (C'.col j) / dot u (C'.col j) have hprobePos (j : Fin n) : 0 < dot u (C.col j) := hsigma.1.trans_le (hprobe.1 j) have hprobePos' (j : Fin n) : 0 < dot u (C'.col j) := hsigma.1.trans_le (hprobe.2 j) have hload (j : Fin n) : lam j * dot u (C.col j) ^ q ≠ 0 := mul_ne_zero (abs_pos.mp (lt_of_lt_of_le hkappa (hlam.1 j).1)) (pow_ne_zero _ (hprobePos j).ne') have hload' (j : Fin n) : lam' j * dot u (C'.col j) ^ q ≠ 0 := mul_ne_zero (abs_pos.mp (lt_of_lt_of_le hkappa (hlam.2 j).1)) (pow_ne_zero _ (hprobePos' j).ne') have hAwFactor (w : Vec p) : Aw w = S * diagonal (fun j => lam j * (dot u (C.col j) ^ (q - 1) * dot w (C.col j))) * S.transpose := by dsimp only [Aw, T] rw [contractLast_decompositionTensor hq] have hdiag : diagonal (fun j => lam j * dot u (C.col j) ^ (q - 1) * dot w (C.col j)) = diagonal (fun j => lam j * (dot u (C.col j) ^ (q - 1) * dot w (C.col j))) := by congr 1 funext j ring rw [hdiag] simp only [S, V, Matrix.transpose_mul, Matrix.transpose_transpose, Matrix.mul_assoc] have hAwFactor' (w : Vec p) : Aw' w = S' * diagonal (fun j => lam' j * (dot u (C'.col j) ^ (q - 1) * dot w (C'.col j))) * S'.transpose := by dsimp only [Aw', T'] rw [contractLast_decompositionTensor hq] have hdiag : diagonal (fun j => lam' j * dot u (C'.col j) ^ (q - 1) * dot w (C'.col j)) = diagonal (fun j => lam' j * (dot u (C'.col j) ^ (q - 1) * dot w (C'.col j))) := by congr 1 funext j ring rw [hdiag] simp only [S', V', Matrix.transpose_mul, Matrix.transpose_transpose, Matrix.mul_assoc] have hGdiag (w : Vec p) : G w = diagonalizableMatrix S (fun j => dot w (C.col j) / dot u (C.col j)) := by dsimp only [G] rw [hAwFactor, hAuFactor] rw [rightPencil_eq_diagonalization S lam (fun j => dot u (C.col j) ^ q) (fun j => dot u (C.col j) ^ (q - 1) * dot w (C.col j)) hS hload] have hratio : (fun j => dot u (C.col j) ^ (q - 1) * dot w (C.col j) / dot u (C.col j) ^ q) = (fun j => dot w (C.col j) / dot u (C.col j)) := by funext j field_simp [(hprobePos j).ne'] calc _ = (dot u (C.col j) ^ (q - 1) * dot u (C.col j)) * dot w (C.col j) := by ring _ = dot u (C.col j) ^ q * dot w (C.col j) := by rw [pow_sub_one_mul (Nat.ne_of_gt hq)] _ = _ := by ring rw [hratio] rfl have hGdiag' (w : Vec p) : G' w = diagonalizableMatrix S' (fun j => dot w (C'.col j) / dot u (C'.col j)) := by dsimp only [G'] rw [hAwFactor', hAuFactor'] rw [rightPencil_eq_diagonalization S' lam' (fun j => dot u (C'.col j) ^ q) -- … truncated; follow the source link for the rest …
1 supporting declaration (lemmas, instances)
  • localInverse_constants_pos theorem — For positive dimensions and admissible positive margins, the contracted margin, lifted condition envelope, pencil constant, local radius, trace constant, and factor constant are all strictly positive. Under the listed assumptions, the stated conclusion follows.
    p n q :
    hp :
    0 < p
    hn :
    0 < n
    hq :
    0 < q
    sigma kappa Lambda :
    hsigma :
    0 < sigma
    hkappa :
    0 < kappa
    hkappaLambda :
    kappa ≤ Lambda
    conclusion 1
    0 < contractedMargin q sigma kappa
    conclusion 2
    conclusion 3
    0 < pencilPerturbationConstant n (contractedMargin q sigma kappa) Lambda
    conclusion 4
    0 < localInverseRadius n q sigma kappa Lambda
    conclusion 5
    0 < traceRecoveryConstant n q sigma kappa Lambda
    conclusion 6
    0 < factorRecoveryConstant p n q sigma kappa Lambda
    Proof (Lean source)
    -- Proof route: unfold the six constants in dependency order. `Real.sqrt_pos.2` handles the -- two dimension square roots; `pow_pos`, division positivity, and `min_pos` handle the remaining -- arithmetic. Derive `0 < Lambda` from `hkappa` and `hkappaLambda` before proving positivity of -- `pencilPerturbationConstant`. theorem localInverse_constants_pos {p n q : ℕ} (hp : 0 < p) (hn : 0 < n) (hq : 0 < q) {sigma kappa Lambda : ℝ} (hsigma : 0 < sigma) (hkappa : 0 < kappa) (hkappaLambda : kappa ≤ Lambda) : 0 < contractedMargin q sigma kappa ∧ 0 < liftedConditionEnvelope n sigma ∧ 0 < pencilPerturbationConstant n (contractedMargin q sigma kappa) Lambda ∧ 0 < localInverseRadius n q sigma kappa Lambda ∧ 0 < traceRecoveryConstant n q sigma kappa Lambda ∧ 0 < factorRecoveryConstant p n q sigma kappa Lambda := by have hLambda : 0 < Lambda := lt_of_lt_of_le hkappa hkappaLambda have heta : 0 < contractedMargin q sigma kappa := by unfold contractedMargin exact mul_pos hkappa (pow_pos hsigma _) have hsqrtn : 0 < sqrt n := Real.sqrt_pos.2 (Nat.cast_pos.2 hn) have hchi : 0 < liftedConditionEnvelope n sigma := by unfold liftedConditionEnvelope exact div_pos hsqrtn hsigma have hh : 0 < pencilPerturbationConstant n (contractedMargin q sigma kappa) Lambda := by unfold pencilPerturbationConstant positivity have hradius : 0 < localInverseRadius n q sigma kappa Lambda := by unfold localInverseRadius exact lt_min (div_pos heta (by norm_num)) (div_pos hsigma (mul_pos (mul_pos (by norm_num) hchi) hh)) have htrace : 0 < traceRecoveryConstant n q sigma kappa Lambda := by unfold traceRecoveryConstant positivity have hfactor : 0 < factorRecoveryConstant p n q sigma kappa Lambda := by unfold factorRecoveryConstant have hsqrtnp : 0 < sqrt (n * p) := Real.sqrt_pos.2 (mul_pos (Nat.cast_pos.2 hn) (Nat.cast_pos.2 hp)) positivity exact ⟨heta, hchi, hh, hradius, htrace, hfactor⟩
    Causalean.Mathlib.Analysis.SymmetricTensorPencil.localInverse_constants_pos · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Main.lean:122
Projectors 1 core · 2 supporting This module states a quantitative finite-dimensional matching theorem for two real matrices with simple, separated, real spectra. ★ exists_permutation_projector_matching

Gap-based matching of spectral projectors

This module states a quantitative finite-dimensional matching theorem for two real matrices with simple, separated, real spectra. Projectors are represented algebraically through the respective diagonalizers, while the proof route is the usual complex Riesz-contour argument. Mathlib's circle-integral Cauchy formulas supply the scalar residue calculation; the resolvent bounds themselves use the explicitly supplied reference diagonalizer and a Neumann argument.

theorem exists_permutation_projector_matching reviewed
Causalean.Mathlib.Analysis.SymmetricTensorPencil

Given two diagonalizers, their simple spectra, invertibility, positive separation, conditioning, and error margins, separation of both spectra, a diagonalizer condition bound, a pencil perturbation bound, and the required small-error condition, one permutation matches the simple spectral projectors with explicit eigenvalue and operator-norm bounds. Under the listed assumptions, the stated conclusion follows.

Formal statement
n :
S S' :
Matrix (Fin n) (Fin n) ℝ
values values' :
Fin n → ℝ
sigma chi delta :
hS :
IsUnit S.det
hS' :
IsUnit S'.det
hsigma :
0 < sigma
hchi :
0 < chi
hdelta :
0 ≤ delta
hgap :
PairwiseGap values sigma
hgap' :
PairwiseGap values' sigma
hcondition :
hclose :
hsmall :
6 * chi * delta < sigma
∃ pi : Perm (Fin n),
∀ j,
|values' (pi j) - values j| < sigma / 3 ∧
≤ 6 * chi ^ 2 * delta / sigma ∧
squareOperatorNorm (coordinateProjector S' (pi j)) ≤ 2 * chi
Proof (Lean source)
-- Proof route: apply `diagonalizableMatrix_eigenvalue_localization`, turn the resulting -- one-sided localization into a permutation with `exists_permutation_matching_of_localization`, -- and apply `coordinateProjector_perturbation_of_matched_eigenvalue` along that permutation. theorem exists_permutation_projector_matching {n : ℕ} [NeZero n] (S S' : Matrix (Fin n) (Fin n) ℝ) (values values' : Fin n → ℝ) {sigma chi delta : ℝ} (hS : IsUnit S.det) (hS' : IsUnit S'.det) (hsigma : 0 < sigma) (hchi : 0 < chi) (hdelta : 0 ≤ delta) (hgap : PairwiseGap values sigma) (hgap' : PairwiseGap values' sigma) (hcondition : squareOperatorNorm S * squareOperatorNorm S⁻¹ ≤ chi) (hclose : squareOperatorNorm (diagonalizableMatrix S' values' - diagonalizableMatrix S values) ≤ delta) (hsmall : 6 * chi * delta < sigma) : ∃ pi : Perm (Fin n), ∀ j, |values' (pi j) - values j| < sigma / 3 ∧ squareOperatorNorm (coordinateProjector S' (pi j) - coordinateProjector S j) ≤ 6 * chi ^ 2 * delta / sigma ∧ squareOperatorNorm (coordinateProjector S j) ≤ chi ∧ squareOperatorNorm (coordinateProjector S' (pi j)) ≤ 2 * chi := by have hlocal := diagonalizableMatrix_eigenvalue_localization S S' values values' hS hS' hcondition hclose have hradius : 0 ≤ chi * delta := mul_nonneg hchi.le hdelta have htwosmall : 2 * (chi * delta) < sigma := by linarith obtain ⟨pi, hpi⟩ := exists_permutation_matching_of_localization values values' hradius hgap' hlocal htwosmall refine ⟨pi, fun j => ?_⟩ have hmatch := hpi j have hthird : |values' (pi j) - values j| < sigma / 3 := by linarith exact ⟨hthird, coordinateProjector_perturbation_of_matched_eigenvalue S S' values values' j (pi j) hS hS' hsigma hchi hdelta hgap hgap' hcondition hclose hmatch hsmall⟩
Causalean.Mathlib.Analysis.SymmetricTensorPencil.exists_permutation_projector_matching · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Projectors.lean:678 · uses PairwiseGap , coordinateProjector , diagonalizableMatrix , squareOperatorNorm
2 supporting declarations (lemmas, instances)
  • abs_trace_le_card_mul_operatorNorm theorem — The trace of a real square matrix is at most the dimension times its Euclidean operator norm in absolute value. The stated conclusion follows.
    n :
    A :
    Matrix (Fin n) (Fin n) ℝ
    Proof (Lean source)
    theorem abs_trace_le_card_mul_operatorNorm {n : ℕ} (A : Matrix (Fin n) (Fin n) ℝ) : |trace A| ≤ n * squareOperatorNorm A := by classical have hentry (i : Fin n) : |A i i| ≤ squareOperatorNorm A := by let e : EuclideanSpace ℝ (Fin n) := toLp 2 (single i 1) have he : ‖e‖ = 1 := by simp [e] have hcoord : |((EuclideanSpace.equiv (Fin n) ℝ).symm (mulVec A e)) i| ≤ ‖(EuclideanSpace.equiv (Fin n) ℝ).symm (mulVec A e)‖ := by simpa only [Real.norm_eq_abs] using PiLp.norm_apply_le ((EuclideanSpace.equiv (Fin n) ℝ).symm (mulVec A e)) i calc |A i i| = |((EuclideanSpace.equiv (Fin n) ℝ).symm (mulVec A e)) i| := by simp [e] _ ≤ ‖(EuclideanSpace.equiv (Fin n) ℝ).symm (mulVec A e)‖ := hcoord _ ≤ ‖A‖ * ‖e‖ := Matrix.l2_opNorm_mulVec A e _ = ‖A‖ := by rw [he, mul_one] _ = ‖(Matrix.toEuclideanCLM (n := Fin n) (𝕜 := ℝ)) A‖ := (Matrix.l2_opNorm_toEuclideanCLM A).symm _ = squareOperatorNorm A := rfl calc |trace A| = |∑ i, A i i| := rfl _ ≤ ∑ i, |A i i| := Finset.abs_sum_le_sum_abs _ _ _ ≤ ∑ _ : Fin n, squareOperatorNorm A := Finset.sum_le_sum fun i _ => hentry i _ = n * squareOperatorNorm A := by simp
    Causalean.Mathlib.Analysis.SymmetricTensorPencil.abs_trace_le_card_mul_operatorNorm · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Projectors.lean:18
  • coordinateProjector_perturbation_of_matched_eigenvalue theorem — Matched simple eigenvalues of two nearby diagonalizable matrices have close coordinate projectors, and the perturbed projector remains controlled by twice the reference condition envelope. Under the listed assumptions, the stated conclusion follows.
    n :
    S S' :
    Matrix (Fin n) (Fin n) ℝ
    values values' :
    Fin n → ℝ
    j j' :
    Fin n
    sigma chi delta :
    hS :
    IsUnit S.det
    hS' :
    IsUnit S'.det
    hsigma :
    0 < sigma
    hchi :
    0 < chi
    hdelta :
    0 ≤ delta
    hgap :
    PairwiseGap values sigma
    hgap' :
    PairwiseGap values' sigma
    hcondition :
    hclose :
    hmatch :
    |values' j' - values j| ≤ chi * delta
    hsmall :
    6 * chi * delta < sigma
    conclusion 1
    ≤ 6 * chi ^ 2 * delta / sigma
    conclusion 2
    conclusion 3
    Proof (Lean source)
    -- Proof route: complexify and use the circle of radius `sigma / 3` about `values j`. -- Bauer--Fike localization and `hsmall` keep the Neumann resolvent along that circle invertible; -- the resolvent identity bounds the contour-integral difference. Algebraic identification of -- those Riesz integrals with the two coordinate projectors gives the three stated estimates. theorem coordinateProjector_perturbation_of_matched_eigenvalue {n : ℕ} [NeZero n] (S S' : Matrix (Fin n) (Fin n) ℝ) (values values' : Fin n → ℝ) (j j' : Fin n) {sigma chi delta : ℝ} (hS : IsUnit S.det) (hS' : IsUnit S'.det) (hsigma : 0 < sigma) (hchi : 0 < chi) (hdelta : 0 ≤ delta) (hgap : PairwiseGap values sigma) (hgap' : PairwiseGap values' sigma) (hcondition : squareOperatorNorm S * squareOperatorNorm S⁻¹ ≤ chi) (hclose : squareOperatorNorm (diagonalizableMatrix S' values' - diagonalizableMatrix S values) ≤ delta) (hmatch : |values' j' - values j| ≤ chi * delta) (hsmall : 6 * chi * delta < sigma) : squareOperatorNorm (coordinateProjector S' j' - coordinateProjector S j) ≤ 6 * chi ^ 2 * delta / sigma ∧ squareOperatorNorm (coordinateProjector S j) ≤ chi ∧ squareOperatorNorm (coordinateProjector S' j') ≤ 2 * chi := by let c : ℂ := (values j : ℂ) let R : ℝ := sigma / 3 let E := diagonalizableMatrix S' values' - diagonalizableMatrix S values have hR : 0 < R := by dsimp [R]; positivity have hchidelta : chi * delta < sigma / 6 := by linarith have hcircle_norm {z : ℂ} (hz : z ∈ sphere c R) : ‖z - c‖ = R := by rw [← dist_eq_norm] exact Metric.mem_sphere.mp hz have href_dist {z : ℂ} (hz : z ∈ sphere c R) : ∀ k, sigma / 3 ≤ ‖z - (values k : ℂ)‖ := by intro k by_cases hkj : k = j · subst k simpa [c, R] using (hcircle_norm hz).ge · have hgapkj : sigma ≤ ‖(values k : ℂ) - c‖ := by calc sigma ≤ |values k - values j| := by simpa [abs_sub_comm] using hgap k j hkj _ = ‖((values k - values j : ℝ) : ℂ)‖ := by rw [Complex.norm_real, Real.norm_eq_abs] _ = ‖(values k : ℂ) - (values j : ℂ)‖ := by norm_cast _ = ‖(values k : ℂ) - c‖ := by rw [show c = (values j : ℂ) by rfl] have htri := norm_sub_le_norm_sub_add_norm_sub (values k : ℂ) z c have hzc := hcircle_norm hz rw [norm_sub_rev (values k : ℂ) z] at htri dsimp [R] at hzc linarith have hprime_in : ‖(values' j' : ℂ) - c‖ < R := by have hm : ‖(values' j' : ℂ) - c‖ ≤ chi * delta := by calc _ = ‖((values' j' - values j : ℝ) : ℂ)‖ := by rw [show c = (values j : ℂ) by rfl] norm_cast _ = |values' j' - values j| := by rw [Complex.norm_real, Real.norm_eq_abs] _ ≤ _ := hmatch dsimp [R] linarith have hprime_out : ∀ k, k ≠ j' → R < ‖(values' k : ℂ) - c‖ := by intro k hkj' have hgapkj : sigma ≤ ‖(values' k : ℂ) - (values' j' : ℂ)‖ := by calc sigma ≤ |values' k - values' j'| := by simpa [abs_sub_comm] using hgap' k j' hkj' _ = ‖((values' k - values' j' : ℝ) : ℂ)‖ := by rw [Complex.norm_real, Real.norm_eq_abs] _ = _ := by norm_cast have htri := norm_sub_le_norm_sub_add_norm_sub (values' k : ℂ) c (values' j' : ℂ) have hm : ‖c - (values' j' : ℂ)‖ ≤ chi * delta := by rw [norm_sub_rev] calc _ = ‖((values' j' - values j : ℝ) : ℂ)‖ := by rw [show c = (values j : ℂ) by rfl] norm_cast _ = |values' j' - values j| := by rw [Complex.norm_real, Real.norm_eq_abs] _ ≤ _ := hmatch dsimp [R] linarith have href_out : ∀ k, k ≠ j → R < ‖(values k : ℂ) - c‖ := by intro k hkj have hg : sigma ≤ ‖(values k : ℂ) - c‖ := by calc sigma ≤ |values k - values j| := by simpa [abs_sub_comm] using hgap k j hkj _ = ‖((values k - values j : ℝ) : ℂ)‖ := by rw [Complex.norm_real, Real.norm_eq_abs] _ = ‖(values k : ℂ) - (values j : ℂ)‖ := by norm_cast _ = _ := by rw [show c = (values j : ℂ) by rfl] dsimp [R] linarith have href_ne {z : ℂ} (hz : z ∈ sphere c R) : ∀ k, z ≠ (values k : ℂ) := by intro k hzk subst z have := href_dist hz k simp only [sub_self, norm_zero] at this linarith have hprime_ne {z : ℂ} (hz : z ∈ sphere c R) : ∀ k, z ≠ (values' k : ℂ) := by intro k hzk subst z by_cases hkj : k = j' · subst k have heq := hcircle_norm hz linarith · have hout := hprime_out k hkj have heq := hcircle_norm hz linarith have hE : ‖complexMatrix E‖ ≤ delta := by rw [complexMatrix_norm_eq] simpa only [E, squareOperatorNorm, Matrix.l2_opNorm_toEuclideanCLM] using hclose let r : ℝ := 3 * chi / sigma have hrpos : 0 < r := by dsimp [r]; positivity have href_norm {z : ℂ} (hz : z ∈ sphere c R) : ‖complexResolvent S values z‖ ≤ r := by dsimp [r] exact complexResolvent_norm_le S values z hsigma hcondition (href_dist hz) have hdelta_r : delta * r < 1 / 2 := by dsimp [r] rw [show delta * (3 * chi / sigma) = (3 * chi * delta) / sigma by ring] apply (div_lt_iff₀ hsigma).2 nlinarith [hsmall] have hprime_norm {z : ℂ} (hz : z ∈ sphere c R) : ‖complexResolvent S' values' z‖ ≤ 2 * r := by have hid := complex_resolvent_identity S S' values values' z hS hS' (href_ne hz) (hprime_ne hz) have hdiff : ‖complexResolvent S' values' z - complexResolvent S values z‖ ≤ (‖complexResolvent S' values' z‖ * delta) * r := by rw [hid] calc ‖complexResolvent S' values' z * complexMatrix E * complexResolvent S values z‖ ≤ ‖complexResolvent S' values' z * complexMatrix E‖ * ‖complexResolvent S values z‖ := Matrix.l2_opNorm_mul _ _ _ ≤ (‖complexResolvent S' values' z‖ * ‖complexMatrix E‖) * ‖complexResolvent S values z‖ := by gcongr exact Matrix.l2_opNorm_mul _ _ _ ≤ (‖complexResolvent S' values' z‖ * delta) * ‖complexResolvent S values z‖ := by exact mul_le_mul_of_nonneg_right (mul_le_mul_of_nonneg_left hE (norm_nonneg _)) (norm_nonneg _) _ ≤ (‖complexResolvent S' values' z‖ * delta) * r := by exact mul_le_mul_of_nonneg_left (href_norm hz) (mul_nonneg (norm_nonneg _) hdelta) have hsum : ‖complexResolvent S' values' z‖ ≤ ‖complexResolvent S' values' z - complexResolvent S values z‖ + ‖complexResolvent S values z‖ := by calc ‖complexResolvent S' values' z‖ = ‖(complexResolvent S' values' z - complexResolvent S values z) + complexResolvent S values z‖ := by congr 1; abel _ ≤ _ := norm_add_le _ _ nlinarith [href_norm hz, norm_nonneg (complexResolvent S' values' z)] have hint_bound {z : ℂ} (hz : z ∈ sphere c R) : ‖complexResolvent S' values' z - complexResolvent S values z‖ ≤ 18 * chi ^ 2 * delta / sigma ^ 2 := by rw [complex_resolvent_identity S S' values values' z hS hS' (href_ne hz) (hprime_ne hz)] calc ‖complexResolvent S' values' z * complexMatrix E * complexResolvent S values z‖ ≤ ‖complexResolvent S' values' z * complexMatrix E‖ * ‖complexResolvent S values z‖ := Matrix.l2_opNorm_mul _ _ _ ≤ (‖complexResolvent S' values' z‖ * ‖complexMatrix E‖) * ‖complexResolvent S values z‖ := by gcongr exact Matrix.l2_opNorm_mul _ _ _ ≤ (‖complexResolvent S' values' z‖ * delta) * ‖complexResolvent S values z‖ := by exact mul_le_mul_of_nonneg_right (mul_le_mul_of_nonneg_left hE (norm_nonneg _)) (norm_nonneg _) _ ≤ ((2 * r) * delta) * ‖complexResolvent S values z‖ := by exact mul_le_mul_of_nonneg_right (mul_le_mul_of_nonneg_right (hprime_norm hz) hdelta) (norm_nonneg _) _ ≤ ((2 * r) * delta) * r := by exact mul_le_mul_of_nonneg_left (href_norm hz) (mul_nonneg (mul_nonneg (by positivity) hrpos.le) hdelta) _ = 18 * chi ^ 2 * delta / sigma ^ 2 := by dsimp [r] field_simp ring have hcontour : ‖(2 * pi * Complex.I : ℂ)⁻¹ • (∮ z in C(c, R), (complexResolvent S' values' z - complexResolvent S values z))‖ ≤ 6 * chi ^ 2 * delta / sigma := by calc _ ≤ R * (18 * chi ^ 2 * delta / sigma ^ 2) := circleIntegral.norm_two_pi_i_inv_smul_integral_le_of_norm_le_const hR.le (fun z hz => hint_bound hz) _ = 6 * chi ^ 2 * delta / sigma := by dsimp [R] field_simp ring have href_int := complexResolvent_integral_eq_projector S values j c hR (by simp [c, R, hR]) href_out have hprime_int := complexResolvent_integral_eq_projector S' values' j' c hR hprime_in hprime_out have hintS : CircleIntegrable (fun z => complexResolvent S values z) c R := by apply complexResolvent_circleIntegrable S values c hR.le intro k hk exact href_ne hk k rfl have hintS' : CircleIntegrable (fun z => complexResolvent S' values' z) c R := by apply complexResolvent_circleIntegrable S' values' c hR.le intro k hk exact hprime_ne hk k rfl have hprojector_diff : complexMatrix (coordinateProjector S' j' - coordinateProjector S j) = (2 * pi * Complex.I : ℂ)⁻¹ • (∮ z in C(c, R), (complexResolvent S' values' z - complexResolvent S values z)) := by rw [complexMatrix_sub, circleIntegral.integral_sub hintS' hintS, smul_sub, hprime_int, href_int] have hdiff_real : squareOperatorNorm (coordinateProjector S' j' - coordinateProjector S j) ≤ 6 * chi ^ 2 * delta / sigma := by rw [squareOperatorNorm] rw [Matrix.l2_opNorm_toEuclideanCLM (coordinateProjector S' j' - coordinateProjector S j)] rw [← complexMatrix_norm_eq] rw [hprojector_diff] exact hcontour have hP := coordinateProjector_operatorNorm_le S j hS hcondition have hP' : squareOperatorNorm (coordinateProjector S' j') ≤ 2 * chi := by calc squareOperatorNorm (coordinateProjector S' j') = squareOperatorNorm ((coordinateProjector S' j' - coordinateProjector S j) + coordinateProjector S j) := by congr 2; abel _ ≤ squareOperatorNorm (coordinateProjector S' j' - coordinateProjector S j) + squareOperatorNorm (coordinateProjector S j) := by unfold squareOperatorNorm rw [map_add] exact norm_add_le _ _ _ ≤ 6 * chi ^ 2 * delta / sigma + chi := add_le_add hdiff_real hP _ ≤ 2 * chi := by have herr_lt : 6 * chi ^ 2 * delta / sigma < chi := by apply (div_lt_iff₀ hsigma).2 nlinarith [hsmall] linarith exact ⟨hdiff_real, hP, hP'⟩
    Causalean.Mathlib.Analysis.SymmetricTensorPencil.coordinateProjector_perturbation_of_matched_eigenvalue · Causalean/Mathlib/Analysis/SymmetricTensorPencil/Projectors.lean:437