Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 105fa17

Browse files
committed
feat(linear_algebra/matrix): trace of an endomorphism independent of basis (#3125)
1 parent 068aaaf commit 105fa17

File tree

4 files changed

+211
-0
lines changed

4 files changed

+211
-0
lines changed

src/data/equiv/basic.lean

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,6 +1202,14 @@ noncomputable def of_bijective {α β} (f : α → β) (hf : bijective f) : α
12021202
@[simp] theorem coe_of_bijective {α β} {f : α → β} (hf : bijective f) :
12031203
(of_bijective f hf : α → β) = f := rfl
12041204

1205+
/-- If `f` is an injective function, then its domain is equivalent to its range. -/
1206+
noncomputable def of_injective {α β} (f : α → β) (hf : injective f) : α ≃ _root_.set.range f :=
1207+
of_bijective (λ x, ⟨f x, set.mem_range_self x⟩) ⟨λ x y hxy, hf $ by injections, λ ⟨_, x, rfl⟩, ⟨x, rfl⟩⟩
1208+
1209+
@[simp] lemma of_injective_apply {α β} (f : α → β) (hf : injective f) (x : α) :
1210+
of_injective f hf x = ⟨f x, set.mem_range_self x⟩ :=
1211+
rfl
1212+
12051213
def subtype_quotient_equiv_quotient_subtype (p₁ : α → Prop) [s₁ : setoid α]
12061214
[s₂ : setoid (subtype p₁)] (p₂ : quotient s₁ → Prop) (hp₂ : ∀ a, p₁ a ↔ p₂ ⟦a⟧)
12071215
(h : ∀ x y : subtype p₁, @setoid.r _ s₂ x y ↔ (x : α) ≈ y) :

src/linear_algebra/basic.lean

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,6 +1607,7 @@ def to_add_equiv : M ≃+ M₂ := { .. e }
16071607
(e₁.trans e₂) c = e₂ (e₁ c) := rfl
16081608
@[simp] theorem apply_symm_apply (c : M₂) : e (e.symm c) = c := e.6 c
16091609
@[simp] theorem symm_apply_apply (b : M) : e.symm (e b) = b := e.5 b
1610+
@[simp] lemma symm_trans_apply (c : M₃) : (e₁.trans e₂).symm c = e₁.symm (e₂.symm c) := rfl
16101611

16111612
@[simp] lemma trans_refl : e.trans (refl R M₂) = e := to_equiv_injective e.to_equiv.trans_refl
16121613
@[simp] lemma refl_trans : (refl R M).trans e = e := to_equiv_injective e.to_equiv.refl_trans
@@ -1829,6 +1830,13 @@ lemma arrow_congr_comp {N N₂ N₃ : Sort*}
18291830
arrow_congr e₁ e₃ (g.comp f) = (arrow_congr e₂ e₃ g).comp (arrow_congr e₁ e₂ f) :=
18301831
by { ext, simp only [symm_apply_apply, arrow_congr_apply, linear_map.comp_apply], }
18311832

1833+
lemma arrow_congr_trans {M₁ M₂ M₃ N₁ N₂ N₃ : Sort*}
1834+
[add_comm_group M₁] [module R M₁] [add_comm_group M₂] [module R M₂] [add_comm_group M₃] [module R M₃]
1835+
[add_comm_group N₁] [module R N₁] [add_comm_group N₂] [module R N₂] [add_comm_group N₃] [module R N₃]
1836+
(e₁ : M₁ ≃ₗ[R] M₂) (e₂ : N₁ ≃ₗ[R] N₂) (e₃ : M₂ ≃ₗ[R] M₃) (e₄ : N₂ ≃ₗ[R] N₃) :
1837+
(arrow_congr e₁ e₂).trans (arrow_congr e₃ e₄) = arrow_congr (e₁.trans e₃) (e₂.trans e₄) :=
1838+
rfl
1839+
18321840
/-- If `M₂` and `M₃` are linearly isomorphic then the two spaces of linear maps from `M` into `M₂`
18331841
and `M` into `M₃` are linearly isomorphic. -/
18341842
def congr_right (f : M₂ ≃ₗ[R] M₃) : (M →ₗ[R] M₂) ≃ₗ (M →ₗ M₃) := arrow_congr (linear_equiv.refl R M) f
@@ -2266,6 +2274,53 @@ end
22662274

22672275
end pi
22682276

2277+
section fun_left
2278+
variables (R M) [semiring R] [add_comm_monoid M] [semimodule R M]
2279+
variables {m n p : Type*}
2280+
2281+
/-- Given an `R`-module `M` and a function `m → n` between arbitrary types,
2282+
construct a linear map `(n → M) →ₗ[R] (m → M)` -/
2283+
def fun_left (f : m → n) : (n → M) →ₗ[R] (m → M) :=
2284+
mk (∘f) (λ _ _, rfl) (λ _ _, rfl)
2285+
2286+
@[simp] theorem fun_left_apply (f : m → n) (g : n → M) (i : m) : fun_left R M f g i = g (f i) :=
2287+
rfl
2288+
2289+
@[simp] theorem fun_left_id (g : n → M) : fun_left R M _root_.id g = g :=
2290+
rfl
2291+
2292+
theorem fun_left_comp (f₁ : n → p) (f₂ : m → n) :
2293+
fun_left R M (f₁ ∘ f₂) = (fun_left R M f₂).comp (fun_left R M f₁) :=
2294+
rfl
2295+
2296+
/-- Given an `R`-module `M` and an equivalence `m ≃ n` between arbitrary types,
2297+
construct a linear equivalence `(n → M) ≃ₗ[R] (m → M)` -/
2298+
def fun_congr_left (e : m ≃ n) : (n → M) ≃ₗ[R] (m → M) :=
2299+
linear_equiv.of_linear (fun_left R M e) (fun_left R M e.symm)
2300+
(ext $ λ x, funext $ λ i,
2301+
by rw [id_apply, ← fun_left_comp, equiv.symm_comp_self, fun_left_id])
2302+
(ext $ λ x, funext $ λ i,
2303+
by rw [id_apply, ← fun_left_comp, equiv.self_comp_symm, fun_left_id])
2304+
2305+
@[simp] theorem fun_congr_left_apply (e : m ≃ n) (x : n → M) :
2306+
fun_congr_left R M e x = fun_left R M e x :=
2307+
rfl
2308+
2309+
@[simp] theorem fun_congr_left_id :
2310+
fun_congr_left R M (equiv.refl n) = linear_equiv.refl R (n → M) :=
2311+
rfl
2312+
2313+
@[simp] theorem fun_congr_left_comp (e₁ : m ≃ n) (e₂ : n ≃ p) :
2314+
fun_congr_left R M (equiv.trans e₁ e₂) =
2315+
linear_equiv.trans (fun_congr_left R M e₂) (fun_congr_left R M e₁) :=
2316+
rfl
2317+
2318+
@[simp] lemma fun_congr_left_symm (e : m ≃ n) :
2319+
(fun_congr_left R M e).symm = fun_congr_left R M e.symm :=
2320+
rfl
2321+
2322+
end fun_left
2323+
22692324
universe i
22702325
variables [semiring R] [add_comm_monoid M] [semimodule R M]
22712326

src/linear_algebra/basis.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,9 @@ end
735735
lemma is_basis.injective (hv : is_basis R v) (zero_ne_one : (0 : R) ≠ 1) : injective v :=
736736
λ x y h, linear_independent.injective zero_ne_one hv.1 h
737737

738+
lemma is_basis.range (hv : is_basis R v) : is_basis R (λ x, x : range v → M) :=
739+
⟨hv.1.to_subtype_range, by { convert hv.2, ext i, exact ⟨λ ⟨p, hp⟩, hp ▸ p.2, λ hi, ⟨⟨i, hi⟩, rfl⟩⟩ }⟩
740+
738741
/-- Given a basis, any vector can be written as a linear combination of the basis vectors. They are
739742
given by this linear map. This is one direction of `module_equiv_finsupp`. -/
740743
def is_basis.repr : M →ₗ (ι →₀ R) :=

src/linear_algebra/matrix.lean

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,17 @@ end
6969
linear maps (n → R) →ₗ[R] (m → R). -/
7070
def to_lin : matrix m n R → (n → R) →ₗ[R] (m → R) := eval.to_fun
7171

72+
theorem to_lin_of_equiv {p q : Type*} [fintype p] [fintype q] (e₁ : m ≃ p) (e₂ : n ≃ q)
73+
(f : matrix p q R) : to_lin (λ i j, f (e₁ i) (e₂ j) : matrix m n R) =
74+
linear_equiv.arrow_congr
75+
(linear_map.fun_congr_left R R e₂)
76+
(linear_map.fun_congr_left R R e₁)
77+
(to_lin f) :=
78+
linear_map.ext $ λ v, funext $ λ i,
79+
calc ∑ j : n, f (e₁ i) (e₂ j) * v j
80+
= ∑ j : n, f (e₁ i) (e₂ j) * v (e₂.symm (e₂ j)) : by simp_rw e₂.symm_apply_apply
81+
... = ∑ k : q, f (e₁ i) k * v (e₂.symm k) : finset.sum_equiv e₂ (λ k, f (e₁ i) k * v (e₂.symm k))
82+
7283
lemma to_lin_add (M N : matrix m n R) : (M + N).to_lin = M.to_lin + N.to_lin :=
7384
matrix.eval.map_add M N
7485

@@ -113,6 +124,14 @@ def to_matrix [decidable_eq n] : ((n → R) →ₗ[R] (m → R)) → matrix m n
113124
(@linear_map.id _ (n → R) _ _ _).to_matrix = 1 :=
114125
by { ext, simp [to_matrix, to_matrixₗ, matrix.one_val, eq_comm] }
115126

127+
theorem to_matrix_of_equiv {p q : Type*} [fintype p] [fintype q] [decidable_eq n] [decidable_eq q]
128+
(e₁ : m ≃ p) (e₂ : n ≃ q) (f : (q → R) →ₗ[R] (p → R)) (i j) :
129+
to_matrix f (e₁ i) (e₂ j) = to_matrix (linear_equiv.arrow_congr
130+
(linear_map.fun_congr_left R R e₂)
131+
(linear_map.fun_congr_left R R e₁) f) i j :=
132+
show f (λ k : q, ite (e₂ j = k) 1 0) (e₁ i) = f (λ k : q, ite (j = e₂.symm k) 1 0) (e₁ i),
133+
by { congr' 1, ext, congr' 1, rw equiv.eq_symm_apply }
134+
116135
end linear_map
117136

118137
section linear_equiv_matrix
@@ -169,6 +188,9 @@ def linear_equiv_matrix' : ((n → R) →ₗ[R] (m → R)) ≃ₗ[R] matrix m n
169188
map_add' := to_matrixₗ.map_add,
170189
map_smul' := to_matrixₗ.map_smul }
171190

191+
@[simp] lemma linear_equiv_matrix'_apply (f : (n → R) →ₗ[R] (m → R)) :
192+
linear_equiv_matrix' f = to_matrix f := rfl
193+
172194
/-- Given a basis of two modules M₁ and M₂ over a commutative ring R, we get a linear equivalence
173195
between linear maps M₁ →ₗ M₂ and matrices over R indexed by the bases. -/
174196
def linear_equiv_matrix {ι κ M₁ M₂ : Type*}
@@ -179,6 +201,29 @@ def linear_equiv_matrix {ι κ M₁ M₂ : Type*}
179201
(M₁ →ₗ[R] M₂) ≃ₗ[R] matrix κ ι R :=
180202
linear_equiv.trans (linear_equiv.arrow_congr (equiv_fun_basis hv₁) (equiv_fun_basis hv₂)) linear_equiv_matrix'
181203

204+
open_locale classical
205+
206+
theorem linear_equiv_matrix_range {ι κ M₁ M₂ : Type*}
207+
[add_comm_group M₁] [module R M₁]
208+
[add_comm_group M₂] [module R M₂]
209+
[fintype ι] [fintype κ]
210+
{v₁ : ι → M₁} {v₂ : κ → M₂} (hv₁ : is_basis R v₁) (hv₂ : is_basis R v₂) (f : M₁ →ₗ[R] M₂) (k i) :
211+
linear_equiv_matrix hv₁.range hv₂.range f ⟨v₂ k, mem_range_self k⟩ ⟨v₁ i, mem_range_self i⟩ =
212+
linear_equiv_matrix hv₁ hv₂ f k i :=
213+
if H : (0 : R) = 1 then @subsingleton.elim _ (subsingleton_of_zero_eq_one R H) _ _ else
214+
begin
215+
simp_rw [linear_equiv_matrix, linear_equiv.trans_apply, linear_equiv_matrix'_apply,
216+
← equiv.of_injective_apply _ (hv₁.injective H), ← equiv.of_injective_apply _ (hv₂.injective H),
217+
to_matrix_of_equiv, ← linear_equiv.trans_apply, linear_equiv.arrow_congr_trans], congr' 3;
218+
refine function.left_inverse.injective linear_equiv.symm_symm _; ext x;
219+
simp_rw [linear_equiv.symm_trans_apply, equiv_fun_basis_symm_apply, fun_congr_left_symm,
220+
fun_congr_left_apply, fun_left_apply],
221+
convert (finset.sum_equiv (equiv.of_injective _ (hv₁.injective H)) _).symm,
222+
simp_rw [equiv.symm_apply_apply, equiv.of_injective_apply, subtype.coe_mk],
223+
convert (finset.sum_equiv (equiv.of_injective _ (hv₂.injective H)) _).symm,
224+
simp_rw [equiv.symm_apply_apply, equiv.of_injective_apply, subtype.coe_mk]
225+
end
226+
182227
end linear_equiv_matrix
183228

184229
namespace matrix
@@ -190,6 +235,25 @@ lemma comp_to_matrix_mul {R : Type v} [comm_ring R] [decidable_eq l] [decidable_
190235
suffices (f.comp g) = (f.to_matrix ⬝ g.to_matrix).to_lin, by rw [this, to_lin_to_matrix],
191236
by rw [mul_to_lin, to_matrix_to_lin, to_matrix_to_lin]
192237

238+
lemma linear_equiv_matrix_comp {R ι κ μ M₁ M₂ M₃ : Type*} [comm_ring R]
239+
[add_comm_group M₁] [module R M₁]
240+
[add_comm_group M₂] [module R M₂]
241+
[add_comm_group M₃] [module R M₃]
242+
[fintype ι] [decidable_eq ι] [fintype κ] [decidable_eq κ] [fintype μ]
243+
{v₁ : ι → M₁} {v₂ : κ → M₂} {v₃ : μ → M₃}
244+
(hv₁ : is_basis R v₁) (hv₂ : is_basis R v₂) (hv₃ : is_basis R v₃)
245+
(f : M₂ →ₗ[R] M₃) (g : M₁ →ₗ[R] M₂) :
246+
linear_equiv_matrix hv₁ hv₃ (f.comp g) =
247+
linear_equiv_matrix hv₂ hv₃ f ⬝ linear_equiv_matrix hv₁ hv₂ g :=
248+
by simp_rw [linear_equiv_matrix, linear_equiv.trans_apply, linear_equiv_matrix'_apply,
249+
linear_equiv.arrow_congr_comp _ (equiv_fun_basis hv₂), comp_to_matrix_mul]
250+
251+
lemma linear_equiv_matrix_mul {R M ι : Type*} [comm_ring R]
252+
[add_comm_group M] [module R M] [fintype ι] [decidable_eq ι]
253+
{b : ι → M} (hb : is_basis R b) (f g : M →ₗ[R] M) :
254+
linear_equiv_matrix hb hb (f * g) = linear_equiv_matrix hb hb f * linear_equiv_matrix hb hb g :=
255+
linear_equiv_matrix_comp hb hb hb f g
256+
193257
section trace
194258

195259
variables {R : Type v} {M : Type w} [ring R] [add_comm_group M] [module R M]
@@ -332,6 +396,87 @@ end finite_dimensional
332396

333397
end matrix
334398

399+
namespace linear_map
400+
401+
open_locale matrix
402+
403+
/-- The trace of an endomorphism given a basis. -/
404+
def trace_aux (R : Type u) [comm_ring R] {M : Type v} [add_comm_group M] [module R M]
405+
{ι : Type w} [fintype ι] [decidable_eq ι] {b : ι → M} (hb : is_basis R b) :
406+
(M →ₗ[R] M) →ₗ[R] R :=
407+
(matrix.trace ι R R).comp $ linear_equiv_matrix hb hb
408+
409+
@[simp] lemma trace_aux_def (R : Type u) [comm_ring R] {M : Type v} [add_comm_group M] [module R M]
410+
{ι : Type w} [fintype ι] [decidable_eq ι] {b : ι → M} (hb : is_basis R b) (f : M →ₗ[R] M) :
411+
trace_aux R hb f = matrix.trace ι R R (linear_equiv_matrix hb hb f) :=
412+
rfl
413+
414+
theorem trace_aux_eq' (R : Type u) [comm_ring R] {M : Type v} [add_comm_group M] [module R M]
415+
{ι : Type w} [fintype ι] [decidable_eq ι] {b : ι → M} (hb : is_basis R b)
416+
{κ : Type w} [fintype κ] [decidable_eq κ] {c : κ → M} (hc : is_basis R c) :
417+
trace_aux R hb = trace_aux R hc :=
418+
linear_map.ext $ λ f,
419+
calc matrix.trace ι R R (linear_equiv_matrix hb hb f)
420+
= matrix.trace ι R R (linear_equiv_matrix hb hb ((linear_map.id.comp f).comp linear_map.id)) :
421+
by rw [linear_map.id_comp, linear_map.comp_id]
422+
... = matrix.trace ι R R (linear_equiv_matrix hc hb linear_map.id ⬝
423+
linear_equiv_matrix hc hc f ⬝
424+
linear_equiv_matrix hb hc linear_map.id) :
425+
by rw [matrix.linear_equiv_matrix_comp _ hc, matrix.linear_equiv_matrix_comp _ hc]
426+
... = matrix.trace κ R R (linear_equiv_matrix hc hc f ⬝
427+
linear_equiv_matrix hb hc linear_map.id ⬝
428+
linear_equiv_matrix hc hb linear_map.id) :
429+
by rw [matrix.mul_assoc, matrix.trace_mul_comm]
430+
... = matrix.trace κ R R (linear_equiv_matrix hc hc ((f.comp linear_map.id).comp linear_map.id)) :
431+
by rw [matrix.linear_equiv_matrix_comp _ hb, matrix.linear_equiv_matrix_comp _ hc]
432+
... = matrix.trace κ R R (linear_equiv_matrix hc hc f) :
433+
by rw [linear_map.comp_id, linear_map.comp_id]
434+
435+
open_locale classical
436+
437+
theorem trace_aux_range (R : Type u) [comm_ring R] {M : Type v} [add_comm_group M] [module R M]
438+
{ι : Type w} [fintype ι] {b : ι → M} (hb : is_basis R b) :
439+
trace_aux R hb.range = trace_aux R hb :=
440+
linear_map.ext $ λ f, if H : 0 = 1 then @subsingleton.elim _ (subsingleton_of_zero_eq_one R H) _ _ else
441+
begin
442+
change ∑ i : set.range b, _ = ∑ i : ι, _, simp_rw [matrix.diag_apply], symmetry,
443+
convert finset.sum_equiv (equiv.of_injective _ $ hb.injective H) _, ext i,
444+
exact (linear_equiv_matrix_range hb hb f i i).symm
445+
end
446+
447+
/-- where `ι` and `κ` can reside in different universes -/
448+
theorem trace_aux_eq (R : Type u) [comm_ring R] {M : Type v} [add_comm_group M] [module R M]
449+
{ι : Type*} [fintype ι] [decidable_eq ι] {b : ι → M} (hb : is_basis R b)
450+
{κ : Type*} [fintype κ] [decidable_eq κ] {c : κ → M} (hc : is_basis R c) :
451+
trace_aux R hb = trace_aux R hc :=
452+
calc trace_aux R hb
453+
= trace_aux R hb.range : by { rw trace_aux_range R hb, congr }
454+
... = trace_aux R hc.range : trace_aux_eq' _ _ _
455+
... = trace_aux R hc : by { rw trace_aux_range R hc, congr }
456+
457+
/-- Trace of an endomorphism independent of basis. -/
458+
def trace (R : Type u) [comm_ring R] (M : Type v) [add_comm_group M] [module R M] :
459+
(M →ₗ[R] M) →ₗ[R] R :=
460+
if H : ∃ s : finset M, is_basis R (λ x, x : (↑s : set M) → M)
461+
then trace_aux R (classical.some_spec H)
462+
else 0
463+
464+
theorem trace_eq_matrix_trace (R : Type u) [comm_ring R] {M : Type v} [add_comm_group M] [module R M]
465+
{ι : Type w} [fintype ι] {b : ι → M} (hb : is_basis R b) (f : M →ₗ[R] M) :
466+
trace R M f = matrix.trace ι R R (linear_equiv_matrix hb hb f) :=
467+
have ∃ s : finset M, is_basis R (λ x, x : (↑s : set M) → M),
468+
from ⟨finset.univ.image b,
469+
by { rw [finset.coe_image, finset.coe_univ, set.image_univ], exact hb.range }⟩,
470+
by { rw [trace, dif_pos this, ← trace_aux_def], congr' 1, apply trace_aux_eq }
471+
472+
theorem trace_mul_comm (R : Type u) [comm_ring R] {M : Type v} [add_comm_group M] [module R M]
473+
(f g : M →ₗ[R] M) : trace R M (f * g) = trace R M (g * f) :=
474+
if H : ∃ s : finset M, is_basis R (λ x, x : (↑s : set M) → M) then let ⟨s, hb⟩ := H in
475+
by { simp_rw [trace_eq_matrix_trace R hb, matrix.linear_equiv_matrix_mul], apply matrix.trace_mul_comm }
476+
else by rw [trace, dif_neg H, linear_map.zero_apply, linear_map.zero_apply]
477+
478+
end linear_map
479+
335480
/-- The natural equivalence between linear endomorphisms of finite free modules and square matrices
336481
is compatible with the algebra structures. -/
337482
def alg_equiv_matrix' {R : Type v} [comm_ring R] [decidable_eq n] :

0 commit comments

Comments
 (0)