Komorebi Space · Lean source

SplitKernelPerturbation.lean

Declared contract recorded Coverage and evidence

The cited release explicitly reports completion of its registered formal contract, under its exact hypotheses.

This viewer reads the retained source; it does not run Lean or assign new claim mappings.

Local imports (1)

KomorebiSpace/SplitKernelPerturbation.lean247 lines

Original source pathlean/KomorebiSpace/SplitKernelPerturbation.lean
Skip declarations and read code

Skip source text

1 import KomorebiSpace.MovingKernelBounds
2 import Mathlib.Analysis.SpecificLimits.Normed
3 
4 set_option autoImplicit false
5 
6 /-!
7 # Small perturbations of a split-surjective defect
8 
9 A bounded right inverse of d is an explicit input. A Neumann inverse on the
10 residual space constructs a right inverse of e when a*epsilon<1. The perturbed
11 residual bound and kernel comparison are conclusions: no preservation of the
12 old kernel is assumed. The graph comparison is relative to the chosen splitting.
13 -/
14 universe u v
15 noncomputable section
16 namespace KomorebiSpace
17 namespace SplitKernel
18 open HilbertKernelProjection
19 variable {E : Type u} {R : Type v}
20 variable [NormedAddCommGroup E] [InnerProductSpace ℝ E] [CompleteSpace E]
21 variable [NormedAddCommGroup R] [NormedSpace ℝ R] [CompleteSpace R]
22 variable (d e : E →L[ℝ] R)
23 
24 structure Certificate where
25   sectionMap : R →L[ℝ] E
26   right_inverse : ∀ r, d (sectionMap r) = r
27   constant : ℝ
28   nonneg : 0 ≤ constant
29   section_bound : ∀ r, ‖sectionMap r‖ ≤ constant*‖r‖
30   epsilon : ℝ
31   epsilon_nonneg : 0 ≤ epsilon
32   operator_error : ‖d-e‖ ≤ epsilon
33   small : constant*epsilon < 1
34 
35 namespace Certificate
36 variable {d e} (T : Certificate d e)
37 
38 /-- Error in the old residual-coordinate section. -/
39 def residualError : R →L[ℝ] R := (d-e).comp T.sectionMap
40 
41 omit [CompleteSpace E] [CompleteSpace R] in
42 theorem residualError_bound : ‖T.residualError‖ ≤ T.constant*T.epsilon := by
43   apply ContinuousLinearMap.opNorm_le_bound _ (mul_nonneg T.nonneg T.epsilon_nonneg)
44   intro r
45   change ‖(d-e) (T.sectionMap r)‖ ≤ _
46   calc
47     _ ≤ ‖d-e‖*‖T.sectionMap r‖ := (d-e).le_opNorm _
48     _ ≤ T.epsilon*(T.constant*‖r‖) :=
49       mul_le_mul T.operator_error (T.section_bound r) (norm_nonneg _) T.epsilon_nonneg
50     _ = _ := by ring
51 
52 omit [CompleteSpace E] [CompleteSpace R] in
53 theorem residualError_small : ‖T.residualError‖ < 1 :=
54   T.residualError_bound.trans_lt T.small
55 
56 /-- A genuine invertible residual-coordinate map, constructed by a geometric series. -/
57 def residualEquiv : R ≃L[ℝ] R :=
58   ContinuousLinearEquiv.ofUnit (Units.oneSub T.residualError T.residualError_small)
59 
60 omit [CompleteSpace E] in
61 @[simp] theorem residualEquiv_apply (r : R) : T.residualEquiv r = e (T.sectionMap r) := by
62   change r-(d-e) (T.sectionMap r)=_
63   rw [sub_apply,T.right_inverse]
64   abel
65 
66 omit [CompleteSpace E] in
67 /-- The inverse norm is derived from the strict radius, not supplied separately. -/
68 theorem residual_inverse_bound (r : R) :
69     ‖T.residualEquiv.symm r‖ ≤ (1/(1-T.constant*T.epsilon))*‖r‖ := by
70   let z := T.residualEquiv.symm r
71   have hid : z = r+T.residualError z := by
72     have hi := T.residualEquiv.apply_symm_apply r
73     change z-T.residualError z = r at hi
74     exact (sub_eq_iff_eq_add).mp hi
75   have hz : ‖z‖ ≤ ‖r‖+(T.constant*T.epsilon)*‖z‖ := by
76     calc
77       ‖z‖ = ‖r+T.residualError z‖ := congrArg norm hid
78       _ ≤ ‖r‖+‖T.residualError z‖ := norm_add_le _ _
79       _ ≤ _ := add_le_add le_rfl ((T.residualError.le_opNorm z).trans
80         (mul_le_mul_of_nonneg_right T.residualError_bound (norm_nonneg z)))
81   have hp : 0 < 1-T.constant*T.epsilon := sub_pos.mpr T.small
82   have hh : (1-T.constant*T.epsilon)*‖z‖ ≤ ‖r‖ := by nlinarith
83   calc
84     ‖z‖ ≤ ‖r‖/(1-T.constant*T.epsilon) := (le_div_iff₀ hp).mpr (by nlinarith [hh])
85     _ = _ := by ring
86 
87 /-- The perturbed right inverse retains the old section range. -/
88 def perturbedSection : R →L[ℝ] E :=
89   T.sectionMap.comp T.residualEquiv.symm.toContinuousLinearMap
90 
91 omit [CompleteSpace E] in
92 @[simp] theorem perturbed_right_inverse (r : R) : e (T.perturbedSection r) = r := by
93   change e (T.sectionMap (T.residualEquiv.symm r)) = r
94   rw [← T.residualEquiv_apply]
95   exact T.residualEquiv.apply_symm_apply r
96 
97 omit [CompleteSpace E] in
98 theorem perturbed_section_bound (r : R) :
99     ‖T.perturbedSection r‖ ≤ (T.constant/(1-T.constant*T.epsilon))*‖r‖ := by
100   exact (T.section_bound _).trans (by
101     calc
102       T.constant*‖T.residualEquiv.symm r‖ ≤
103           T.constant*((1/(1-T.constant*T.epsilon))*‖r‖) :=
104         mul_le_mul_of_nonneg_left (T.residual_inverse_bound r) T.nonneg
105       _ = _ := by ring)
106 
107 include T in
108 omit [CompleteSpace E] in
109 theorem perturbed_surjective : Function.Surjective e :=
110   fun r => ⟨T.perturbedSection r, T.perturbed_right_inverse r⟩
111 
112 /-- A right inverse supplies an exact competitor, hence an orthogonal repair bound. -/
113 def referenceBound : ResidualRobustness.Bound d where
114   constant := T.constant
115   nonneg := T.nonneg
116   estimate x := by
117     have hx : d (x-T.sectionMap (d x))=0 := by rw [map_sub,T.right_inverse,sub_self]
118     have hb := projection_best d x (x-T.sectionMap (d x)) hx
119     have hid : x-(x-T.sectionMap (d x))=T.sectionMap (d x) := by abel
120     rw [hid] at hb
121     exact hb.trans (T.section_bound _)
122 
123 def perturbedBound : ResidualRobustness.Bound e where
124   constant := T.constant/(1-T.constant*T.epsilon)
125   nonneg := div_nonneg T.nonneg (le_of_lt (sub_pos.mpr T.small))
126   estimate x := by
127     have hx : e (x-T.perturbedSection (e x))=0 := by
128       rw [map_sub,T.perturbed_right_inverse,sub_self]
129     have hb := projection_best e x (x-T.perturbedSection (e x)) hx
130     have hid : x-(x-T.perturbedSection (e x))=T.perturbedSection (e x) := by abel
131     rw [hid] at hb
132     exact hb.trans (T.perturbed_section_bound _)
133 
134 include T in
135 theorem perturbed_range_closed : IsClosed (Set.range e) :=
136   closed_range_of_bound e T.perturbedBound.constant T.perturbedBound.nonneg
137     T.perturbedBound.estimate
138 
139 /-- A one-certificate motion bound; the new stability constant has been derived. -/
140 theorem projection_motion :
141     ‖projection d-projection e‖ ≤
142       (T.constant*T.epsilon)/(1-T.constant*T.epsilon) := by
143   have hp : 0 < 1-T.constant*T.epsilon := sub_pos.mpr T.small
144   have hc : T.constant ≤ T.constant/(1-T.constant*T.epsilon) := by
145     apply (le_div_iff₀ hp).mpr
146     nlinarith [mul_nonneg (mul_nonneg T.nonneg T.epsilon_nonneg) T.nonneg]
147   have hb := MovingKernel.projection_opNorm d e T.referenceBound T.perturbedBound T.operator_error
148   change ‖projection d-projection e‖ ≤ max T.constant
149     (T.constant/(1-T.constant*T.epsilon))*T.epsilon at hb
150   rw [max_eq_right hc] at hb
151   convert hb using 1
152   ring
153 
154 /-- A literal old-kernel-preservation assumption is absent from this estimate. -/
155 theorem perturbed_measured (x : E) (r : R) (η : ℝ) (hr : ‖e x-r‖ ≤ η) :
156     ‖x-projection e x‖ ≤ (T.constant/(1-T.constant*T.epsilon))*(‖r‖+η) :=
157   T.perturbedBound.measured x r η hr
158 
159 /-- The old splitting projection, not necessarily orthogonal. -/
160 def oldRetract : E →L[ℝ] E := ContinuousLinearMap.id ℝ E - T.sectionMap.comp d
161 
162 /-- The new splitting projection; its kernel complement is the old section range. -/
163 def newRetract : E →L[ℝ] E := ContinuousLinearMap.id ℝ E - T.perturbedSection.comp e
164 
165 omit [CompleteSpace E] [CompleteSpace R] in
166 @[simp] theorem oldRetract_apply (x : E) : T.oldRetract x = x-T.sectionMap (d x) := rfl
167 omit [CompleteSpace E] in
168 @[simp] theorem newRetract_apply (x : E) : T.newRetract x = x-T.perturbedSection (e x) := rfl
169 
170 omit [CompleteSpace E] [CompleteSpace R] in
171 @[simp] theorem oldRetract_exact (x : E) : d (T.oldRetract x)=0 := by
172   rw [T.oldRetract_apply,map_sub,T.right_inverse,sub_self]
173 
174 omit [CompleteSpace E] in
175 @[simp] theorem newRetract_exact (x : E) : e (T.newRetract x)=0 := by
176   rw [T.newRetract_apply,map_sub,T.perturbed_right_inverse,sub_self]
177 
178 omit [CompleteSpace E] in
179 @[simp] theorem section_cancel (r : R) : T.perturbedSection (e (T.sectionMap r))=T.sectionMap r := by
180   change T.sectionMap (T.residualEquiv.symm (e (T.sectionMap r)))=_
181   rw [← T.residualEquiv_apply,T.residualEquiv.symm_apply_apply]
182 
183 omit [CompleteSpace E] in
184 @[simp] theorem oldRetract_newSection (r : R) : T.oldRetract (T.perturbedSection r)=0 := by
185   change T.sectionMap (T.residualEquiv.symm r)-
186     T.sectionMap (d (T.sectionMap (T.residualEquiv.symm r)))=0
187   rw [T.right_inverse,sub_self]
188 
189 omit [CompleteSpace E] in
190 @[simp] theorem newRetract_oldSection (r : R) : T.newRetract (T.sectionMap r)=0 := by
191   rw [T.newRetract_apply,T.section_cancel,sub_self]
192 
193 def toNewKernel : d.ker →L[ℝ] e.ker :=
194   (T.newRetract.comp d.ker.subtypeL).codRestrict e.ker (fun x => T.newRetract_exact x)
195 
196 def toOldKernel : e.ker →L[ℝ] d.ker :=
197   (T.oldRetract.comp e.ker.subtypeL).codRestrict d.ker (fun x => T.oldRetract_exact x)
198 
199 omit [CompleteSpace E] in
200 theorem toOld_toNew (x : d.ker) : T.toOldKernel (T.toNewKernel x)=x := by
201   apply Subtype.ext
202   change T.oldRetract (T.newRetract x.val)=x.val
203   have hx : d x.val = 0 := x.property
204   rw [T.newRetract_apply,map_sub,T.oldRetract_newSection,sub_zero,
205     T.oldRetract_apply,hx,map_zero,sub_zero]
206 
207 omit [CompleteSpace E] in
208 theorem toNew_toOld (x : e.ker) : T.toNewKernel (T.toOldKernel x)=x := by
209   apply Subtype.ext
210   change T.newRetract (T.oldRetract x.val)=x.val
211   have hx : e x.val = 0 := x.property
212   rw [T.oldRetract_apply,map_sub,T.newRetract_oldSection,sub_zero,
213     T.newRetract_apply,hx,map_zero,sub_zero]
214 
215 /-- Actual continuously invertible transport between the moving exact spaces. -/
216 def kernelEquiv : d.ker ≃L[ℝ] e.ker where
217   toLinearEquiv :=
218     { T.toNewKernel.toLinearMap with
219       invFun := T.toOldKernel
220       left_inv := T.toOld_toNew
221       right_inv := T.toNew_toOld }
222   continuous_toFun := T.toNewKernel.continuous
223   continuous_invFun := T.toOldKernel.continuous
224 
225 /-- The new exact object is close to the old one in the declared ambient norm. -/
226 theorem kernel_transport_error (x : d.ker) :
227     ‖(T.kernelEquiv x).val-x.val‖ ≤
228       ((T.constant*T.epsilon)/(1-T.constant*T.epsilon))*‖x.val‖ := by
229   change ‖(x.val-T.perturbedSection (e x.val))-x.val‖ ≤ _
230   have hid : (x.val-T.perturbedSection (e x.val))-x.val = -T.perturbedSection (e x.val) := by abel
231   rw [hid,norm_neg]
232   have hd : ‖e x.val‖ ≤ T.epsilon*‖x.val‖ := by
233     have he := ((d-e).le_opNorm x.val).trans
234       (mul_le_mul_of_nonneg_right T.operator_error (norm_nonneg x.val))
235     have hx : d x.val = 0 := x.property
236     simpa only [sub_apply,hx,zero_sub,norm_neg] using he
237   exact (T.perturbed_section_bound _).trans (by
238     calc
239       (T.constant/(1-T.constant*T.epsilon))*‖e x.val‖ ≤
240           (T.constant/(1-T.constant*T.epsilon))*(T.epsilon*‖x.val‖) :=
241         mul_le_mul_of_nonneg_left hd T.perturbedBound.nonneg
242       _ = _ := by ring)
243 
244 end Certificate
245 end SplitKernel
246 end KomorebiSpace
247 end

Back to source controls

Original file and source record

This copy matches the recorded source file. Its publication here does not change the work’s review status.

SHA-256: 1e60514ffacf125c0c03302ae79694547ac016e50ccea15293796713c4f02723

Original source on GitHub

Back to Komorebi Space