Skip to content

Commit 22a6ad5

Browse files
ADedeckerCoolRmal
andcommitted
feat: define LinearMap.IsQuasiInverse (#39475)
If the name "QuasiInverse" is considered too vague, I am open to suggestions. This was written by @PatrickMassot and @CoolRmal at the May 2026 ICERM workshop as part of the project on Fredholm operators. Co-authored-by: Rmal <97214596+CoolRmal@users.noreply.github.com>
1 parent d64a465 commit 22a6ad5

1 file changed

Lines changed: 169 additions & 3 deletions

File tree

Mathlib/Algebra/Module/LinearMap/FiniteRange.lean

Lines changed: 169 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/-
22
Copyright (c) 2026 Patrick Massot. All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
4-
Authors: Patrick Massot, Anatole Dedecker
4+
Authors: Patrick Massot, Anatole Dedecker, Yongxi Lin
55
-/
66
module
77

@@ -32,6 +32,9 @@ In this file, we define:
3232
noetherian ring, in which case the two notions agree.
3333
This is an instance in the scope `LinearMap.FiniteRangeSetoid`,
3434
so opening this scope allows this relation to be denoted by `≈`.
35+
* `LinearMap.IsQuasiInverse`: two linear maps `u` and `v` are **quasi-inverses** if we have
36+
`u ∘ₗ v ≈ id` and `v ∘ₗ u ≈ id` modulo linear maps with noetherian ranges.
37+
3538
-/
3639

3740
@[expose] public section
@@ -50,10 +53,12 @@ variable [Semiring K]
5053
[AddCommMonoid V₃] [Module K V₃]
5154

5255
/-- A linear map **has Noetherian range** if its range is a Noetherian module. -/
53-
def HasNoetherianRange (f : V →ₗ[K] V₂) := IsNoetherian K f.range
56+
def HasNoetherianRange (f : V →ₗ[K] V₂) : Prop :=
57+
IsNoetherian K f.range
5458

5559
/-- A linear map **has finite range** if its range is finitely generated. -/
56-
def HasFiniteRange (f : V →ₗ[K] V₂) := f.range.FG
60+
def HasFiniteRange (f : V →ₗ[K] V₂) : Prop :=
61+
f.range.FG
5762

5863
lemma hasNoetherianRange_iff_range {f : V →ₗ[K] V₂} :
5964
f.HasNoetherianRange ↔ IsNoetherian K f.range :=
@@ -268,4 +273,165 @@ end FiniteRangeSetoid
268273

269274
end Setoid
270275

276+
section QuasiInverse
277+
278+
variable [CommRing K]
279+
[AddCommGroup V] [Module K V]
280+
[AddCommGroup V₂] [Module K V₂]
281+
[AddCommGroup V₃] [Module K V₃]
282+
283+
open scoped LinearMap.FiniteRangeSetoid
284+
285+
/-- `u` is a **left quasi-inverse** to `v` if `u ∘ₗ v ≈ id` modulo
286+
linear maps with noetherian ranges. Recall that if the scalar ring is noetherian
287+
(e.g a field), then "noetherian range" can be replaced by "finitely generated range". -/
288+
def IsLeftQuasiInverse (u : V →ₗ[K] V₂) (v : V₂ →ₗ[K] V) : Prop :=
289+
u ∘ₗ v ≈ .id
290+
291+
/-- `u` is a **right quasi-inverse** to `v` if `v ∘ₗ u ≈ id` modulo
292+
linear maps with noetherian ranges. Recall that if the scalar ring is noetherian
293+
(e.g a field), then "noetherian range" can be replaced by "finitely generated range". -/
294+
def IsRightQuasiInverse (u : V₃ →ₗ[K] V₂) (v : V₂ →ₗ[K] V₃) : Prop :=
295+
v ∘ₗ u ≈ .id
296+
297+
/-- `u` is a **quasi-inverse** to `v` if `u ∘ₗ v ≈ id` and `v ∘ₗ u ≈ id` modulo
298+
linear maps with noetherian ranges. Recall that if the scalar ring is noetherian
299+
(e.g a field), then "noetherian range" can be replaced by "finitely generated range". -/
300+
def IsQuasiInverse (u : V₃ →ₗ[K] V₂) (v : V₂ →ₗ[K] V₃) : Prop :=
301+
u.IsLeftQuasiInverse v ∧ u.IsRightQuasiInverse v
302+
303+
lemma isLeftQuasiInverse_iff_isRightQuasiInverse_swap {u : V₃ →ₗ[K] V₂} {v : V₂ →ₗ[K] V₃} :
304+
u.IsLeftQuasiInverse v ↔ v.IsRightQuasiInverse u := Iff.rfl
305+
306+
alias ⟨IsLeftQuasiInverse.isRightQuasiInverse, IsRightQuasiInverse.isLeftQuasiInverse⟩ :=
307+
isLeftQuasiInverse_iff_isRightQuasiInverse_swap
308+
309+
lemma IsLeftQuasiInverse.equiv {u : V₃ →ₗ[K] V₂} {v : V₂ →ₗ[K] V₃}
310+
(h : u.IsLeftQuasiInverse v) : u ∘ₗ v ≈ .id := h
311+
312+
lemma IsRightQuasiInverse.equiv {u : V₃ →ₗ[K] V₂} {v : V₂ →ₗ[K] V₃}
313+
(h : u.IsRightQuasiInverse v) : v ∘ₗ u ≈ .id := h
314+
315+
@[symm]
316+
lemma IsQuasiInverse.symm {u : V₃ →ₗ[K] V₂} {v : V₂ →ₗ[K] V₃}
317+
(h : u.IsQuasiInverse v) : v.IsQuasiInverse u :=
318+
And.symm h
319+
320+
@[gcongr]
321+
lemma IsLeftQuasiInverse.congr {u u' : V₃ →ₗ[K] V₂} {v v' : V₂ →ₗ[K] V₃}
322+
(h : u.IsLeftQuasiInverse v) (hu : u' ≈ u) (hv : v' ≈ v) :
323+
u'.IsLeftQuasiInverse v' := by
324+
unfold IsLeftQuasiInverse at *
325+
grw [hu, hv]
326+
assumption
327+
328+
@[gcongr]
329+
lemma isLeftQuasiInverse_congr {u u' : V₃ →ₗ[K] V₂} {v v' : V₂ →ₗ[K] V₃}
330+
(hu : u' ≈ u) (hv : v' ≈ v) :
331+
u.IsLeftQuasiInverse v ↔ u'.IsLeftQuasiInverse v' :=
332+
fun H ↦ H.congr hu hv, fun H ↦ H.congr (Setoid.symm hu) (Setoid.symm hv)⟩
333+
334+
@[gcongr]
335+
lemma IsRightQuasiInverse.congr {u u' : V₃ →ₗ[K] V₂} {v v' : V₂ →ₗ[K] V₃}
336+
(h : u.IsRightQuasiInverse v) (hu : u' ≈ u) (hv : v' ≈ v) :
337+
u'.IsRightQuasiInverse v' :=
338+
h.isLeftQuasiInverse.congr hv hu |>.isRightQuasiInverse
339+
340+
lemma isRightQuasiInverse_congr {u u' : V₃ →ₗ[K] V₂} {v v' : V₂ →ₗ[K] V₃}
341+
(hu : u' ≈ u) (hv : v' ≈ v) :
342+
u.IsRightQuasiInverse v ↔ u'.IsRightQuasiInverse v' :=
343+
fun H ↦ H.congr hu hv, fun H ↦ H.congr (Setoid.symm hu) (Setoid.symm hv)⟩
344+
345+
@[gcongr]
346+
lemma IsQuasiInverse.congr {u u' : V₃ →ₗ[K] V₂} {v v' : V₂ →ₗ[K] V₃}
347+
(h : u.IsQuasiInverse v) (hu : u' ≈ u) (hv : v' ≈ v) :
348+
u'.IsQuasiInverse v' :=
349+
⟨h.1.congr hu hv, h.2.congr hu hv⟩
350+
351+
lemma isQuasiInverse_congr {u u' : V₃ →ₗ[K] V₂} {v v' : V₂ →ₗ[K] V₃}
352+
(hu : u' ≈ u) (hv : v' ≈ v) :
353+
u.IsQuasiInverse v ↔ u'.IsQuasiInverse v' := by
354+
simp [IsQuasiInverse, isLeftQuasiInverse_congr hu hv, isRightQuasiInverse_congr hu hv]
355+
356+
lemma IsQuasiInverse.equiv_of_left {u u' : V₃ →ₗ[K] V₂} {v v' : V₂ →ₗ[K] V₃}
357+
(h : u.IsQuasiInverse v) (h' : u'.IsQuasiInverse v') (hu : u ≈ u') :
358+
v ≈ v' := by
359+
calc
360+
v = v ∘ₗ .id := by simp
361+
_ ≈ v ∘ₗ (u' ∘ₗ v') := by grw [h'.1.equiv]
362+
_ ≈ v ∘ₗ (u ∘ₗ v') := by grw [hu]
363+
_ = (v ∘ₗ u) ∘ₗ v' := by rw [comp_assoc]
364+
_ ≈ .id ∘ₗ v' := by grw [h.2.equiv]
365+
_ = v' := by simp
366+
367+
lemma IsQuasiInverse.equiv_of_right {u u' : V₃ →ₗ[K] V₂} {v v' : V₂ →ₗ[K] V₃}
368+
(h : u.IsQuasiInverse v) (h' : u'.IsQuasiInverse v') (hv : v ≈ v') :
369+
u ≈ u' :=
370+
h.symm.equiv_of_left h'.symm hv
371+
372+
/-- Left quasi-inverses compose in the opposite order. -/
373+
lemma IsLeftQuasiInverse.comp {u : V →ₗ[K] V₂} {v : V₂ →ₗ[K] V₃} {u' : V₂ →ₗ[K] V}
374+
{v' : V₃ →ₗ[K] V₂} (hu : u'.IsLeftQuasiInverse u) (hv : v'.IsLeftQuasiInverse v) :
375+
(u' ∘ₗ v').IsLeftQuasiInverse (v ∘ₗ u) :=
376+
calc
377+
_ = u' ∘ₗ (v' ∘ₗ v) ∘ₗ u := rfl
378+
_ ≈ u' ∘ₗ .id ∘ₗ u := by grw [hv.equiv]
379+
_ ≈ .id := hu.equiv
380+
381+
/-- Right quasi-inverses compose in the opposite order. -/
382+
lemma IsRightQuasiInverse.comp {u : V →ₗ[K] V₂} {v : V₂ →ₗ[K] V₃} {u' : V₂ →ₗ[K] V}
383+
{v' : V₃ →ₗ[K] V₂} (hu : u'.IsRightQuasiInverse u) (hv : v'.IsRightQuasiInverse v) :
384+
(u' ∘ₗ v').IsRightQuasiInverse (v ∘ₗ u) :=
385+
hv.isLeftQuasiInverse.comp hu.isLeftQuasiInverse |>.isRightQuasiInverse
386+
387+
/-- Quasi-inverses compose in the opposite order. -/
388+
lemma IsQuasiInverse.comp {u : V →ₗ[K] V₂} {v : V₂ →ₗ[K] V₃} {u' : V₂ →ₗ[K] V}
389+
{v' : V₃ →ₗ[K] V₂} (hu : u'.IsQuasiInverse u) (hv : v'.IsQuasiInverse v) :
390+
(u' ∘ₗ v').IsQuasiInverse (v ∘ₗ u) :=
391+
⟨hu.1.comp hv.1, hu.2.comp hv.2
392+
393+
/-- If `u'` is a right quasi-inverse of `u` and `w` is a left quasi-inverse of `v ∘ₗ u`,
394+
then `u ∘ₗ w` is a left quasi-inverse of `v`. -/
395+
lemma IsLeftQuasiInverse.of_comp_left {u : V →ₗ[K] V₂} {v : V₂ →ₗ[K] V₃}
396+
{u' : V₂ →ₗ[K] V} {w : V₃ →ₗ[K] V} (hu : u'.IsRightQuasiInverse u)
397+
(hw : w.IsLeftQuasiInverse (v ∘ₗ u)) :
398+
(u ∘ₗ w).IsLeftQuasiInverse v := by
399+
calc
400+
_ = ((u ∘ₗ w) ∘ₗ v) ∘ₗ .id := rfl
401+
_ ≈ ((u ∘ₗ w) ∘ₗ v) ∘ₗ (u ∘ₗ u') := by grw [hu.equiv]
402+
_ = u ∘ₗ (w ∘ₗ (v ∘ₗ u)) ∘ₗ u' := rfl
403+
_ ≈ u ∘ₗ .id ∘ₗ u' := by grw [hw.equiv]
404+
_ ≈ .id := hu.equiv
405+
406+
/-- If `u'` is a quasi-inverse of `u` and `w` is a quasi-inverse of `v ∘ₗ u`, then
407+
`u ∘ₗ w` is a quasi-inverse of `v`. -/
408+
lemma IsQuasiInverse.of_comp_left {u : V →ₗ[K] V₂} {v : V₂ →ₗ[K] V₃}
409+
{u' : V₂ →ₗ[K] V} {w : V₃ →ₗ[K] V} (hu : u'.IsQuasiInverse u)
410+
(hw : w.IsQuasiInverse (v ∘ₗ u)) :
411+
(u ∘ₗ w).IsQuasiInverse v :=
412+
⟨.of_comp_left hu.2 hw.1, hw.2
413+
414+
/-- If `v'` is a left quasi-inverse of `v` and `w` is a right quasi-inverse of `v ∘ₗ u`,
415+
then `w ∘ₗ v` is a right quasi-inverse of `u`. -/
416+
lemma IsRightQuasiInverse.of_comp_right {u : V →ₗ[K] V₂} {v : V₂ →ₗ[K] V₃}
417+
{v' : V₃ →ₗ[K] V₂} {w : V₃ →ₗ[K] V} (hv : v'.IsLeftQuasiInverse v)
418+
(hw : w.IsRightQuasiInverse (v ∘ₗ u)) :
419+
(w ∘ₗ v).IsRightQuasiInverse u := by
420+
calc
421+
_ = .id ∘ₗ (u ∘ₗ (w ∘ₗ v)) := rfl
422+
_ ≈ (v' ∘ₗ v) ∘ₗ (u ∘ₗ (w ∘ₗ v)) := by grw [hv.equiv]
423+
_ = v' ∘ₗ ((v ∘ₗ u) ∘ₗ w) ∘ₗ v := rfl
424+
_ ≈ v' ∘ₗ .id ∘ₗ v := by grw [hw.equiv]
425+
_ ≈ .id := hv.equiv
426+
427+
/-- If `v'` is a quasi-inverse of `v` and `w` is a quasi-inverse of `v ∘ₗ u`, then
428+
`w ∘ₗ v` is a quasi-inverse of `u`. -/
429+
lemma IsQuasiInverse.of_comp_right {u : V →ₗ[K] V₂} {v : V₂ →ₗ[K] V₃}
430+
{v' : V₃ →ₗ[K] V₂} {w : V₃ →ₗ[K] V} (hv : v'.IsQuasiInverse v)
431+
(hw : w.IsQuasiInverse (v ∘ₗ u)) :
432+
(w ∘ₗ v).IsQuasiInverse u :=
433+
⟨hw.1, IsRightQuasiInverse.of_comp_right hv.1 hw.2
434+
435+
end QuasiInverse
436+
271437
end LinearMap

0 commit comments

Comments
 (0)