-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Expand file tree
/
Copy pathSl2.lean
More file actions
278 lines (238 loc) · 11.1 KB
/
Copy pathSl2.lean
File metadata and controls
278 lines (238 loc) · 11.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
/-
Copyright (c) 2024 Oliver Nash. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Oliver Nash
-/
module
public import Mathlib.Algebra.Lie.OfAssociative
public import Mathlib.LinearAlgebra.Eigenspace.Basic
public import Mathlib.LinearAlgebra.FreeModule.StrongRankCondition
public import Mathlib.Algebra.Lie.Weights.Basic
/-!
# The Lie algebra `sl₂` and its representations
The Lie algebra `sl₂` is the unique simple Lie algebra of minimal rank, 1, and as such occupies a
distinguished position in the general theory. This file provides some basic definitions and results
about `sl₂`.
## Main definitions:
* `IsSl2Triple`: a structure representing a triple of elements in a Lie algebra which satisfy the
standard relations for `sl₂`.
* `IsSl2Triple.HasPrimitiveVectorWith`: a structure representing a primitive vector in a
representation of a Lie algebra relative to a distinguished `sl₂` triple.
* `IsSl2Triple.HasPrimitiveVectorWith.exists_nat`: the eigenvalue of a primitive vector must be a
natural number if the representation is finite-dimensional.
-/
@[expose] public section
variable (R L M : Type*) [CommRing R] [LieRing L] [LieAlgebra R L]
[AddCommGroup M] [Module R M] [LieRingModule L M] [LieModule R L M]
open LieModule Module Set
variable {L} in
/-- An `sl₂` triple within a Lie ring `L` is a triple of elements `h`, `e`, `f` obeying relations
which ensure that the Lie subalgebra they generate is equivalent to `sl₂`. -/
structure IsSl2Triple (h e f : L) : Prop where
h_ne_zero : h ≠ 0
lie_e_f : ⁅e, f⁆ = h
lie_h_e_nsmul : ⁅h, e⁆ = 2 • e
lie_h_f_nsmul : ⁅h, f⁆ = -(2 • f)
namespace IsSl2Triple
variable {L M}
variable {h e f : L}
lemma symm (ht : IsSl2Triple h e f) : IsSl2Triple (-h) f e where
h_ne_zero := by simpa using ht.h_ne_zero
lie_e_f := by rw [← neg_eq_iff_eq_neg, lie_skew, ht.lie_e_f]
lie_h_e_nsmul := by rw [neg_lie, neg_eq_iff_eq_neg, ht.lie_h_f_nsmul]
lie_h_f_nsmul := by rw [neg_lie, neg_inj, ht.lie_h_e_nsmul]
@[simp] lemma symm_iff : IsSl2Triple (-h) f e ↔ IsSl2Triple h e f :=
⟨fun t ↦ neg_neg h ▸ t.symm, symm⟩
lemma lie_h_e_smul (t : IsSl2Triple h e f) : ⁅h, e⁆ = (2 : R) • e := by
simp [t.lie_h_e_nsmul, two_smul]
lemma lie_lie_smul_f (t : IsSl2Triple h e f) : ⁅h, f⁆ = -((2 : R) • f) := by
simp [t.lie_h_f_nsmul, two_smul]
lemma e_ne_zero (t : IsSl2Triple h e f) : e ≠ 0 := by
have := t.h_ne_zero
contrapose this
simpa [this] using t.lie_e_f.symm
lemma f_ne_zero (t : IsSl2Triple h e f) : f ≠ 0 := by
have := t.h_ne_zero
contrapose this
simpa [this] using t.lie_e_f.symm
variable {R}
/-- Given a representation of a Lie algebra with distinguished `sl₂` triple, a vector is said to be
primitive if it is a simultaneous eigenvector for the action of both `h` and `e`, and the eigenvalue
for `e` is zero. -/
structure HasPrimitiveVectorWith (t : IsSl2Triple h e f) (m : M) (μ : R) : Prop where
ne_zero : m ≠ 0
lie_h : ⁅h, m⁆ = μ • m
lie_e : ⁅e, m⁆ = 0
/-- Given a representation of a Lie algebra with distinguished `sl₂` triple, a simultaneous
eigenvector for the action of both `h` and `e` necessarily has eigenvalue zero for `e`. -/
lemma HasPrimitiveVectorWith.mk' [IsAddTorsionFree M] (t : IsSl2Triple h e f) (m : M) (μ ρ : R)
(hm : m ≠ 0) (hm' : ⁅h, m⁆ = μ • m) (he : ⁅e, m⁆ = ρ • m) :
HasPrimitiveVectorWith t m μ where
ne_zero := hm
lie_h := hm'
lie_e := by
suffices 2 • ⁅e, m⁆ = 0 by simpa using this
rw [← nsmul_lie, ← t.lie_h_e_nsmul, lie_lie, hm', lie_smul, he, lie_smul, hm',
smul_smul, smul_smul, mul_comm ρ μ, sub_self]
variable (R) in
open Submodule in
/-- The subalgebra associated to an `sl₂` triple. -/
def toLieSubalgebra (t : IsSl2Triple h e f) :
LieSubalgebra R L where
__ := span R {e, f, h}
lie_mem' {x y} hx hy := by
simp only [carrier_eq_coe, SetLike.mem_coe] at hx hy ⊢
induction hx using span_induction with
| zero => simp
| add u v hu hv hu' hv' => simpa only [add_lie] using add_mem hu' hv'
| smul t u hu hu' => simpa only [smul_lie] using smul_mem _ t hu'
| mem u hu =>
induction hy using span_induction with
| zero => simp
| add u v hu hv hu' hv' => simpa only [lie_add] using add_mem hu' hv'
| smul t u hv hv' => simpa only [lie_smul] using smul_mem _ t hv'
| mem v hv =>
push _ ∈ _ at hu hv
rcases hu with rfl | rfl | rfl <;>
rcases hv with rfl | rfl | rfl <;> (try simp only [lie_self, zero_mem])
· rw [t.lie_e_f]
apply subset_span
simp
· rw [← lie_skew, t.lie_h_e_nsmul, neg_mem_iff]
apply nsmul_mem <| subset_span _
simp
· rw [← lie_skew, t.lie_e_f, neg_mem_iff]
apply subset_span
simp
· rw [← lie_skew, t.lie_h_f_nsmul, neg_neg]
apply nsmul_mem <| subset_span _
simp
· rw [t.lie_h_e_nsmul]
apply nsmul_mem <| subset_span _
simp
· rw [t.lie_h_f_nsmul, neg_mem_iff]
apply nsmul_mem <| subset_span _
simp
lemma mem_toLieSubalgebra_iff {x : L} {t : IsSl2Triple h e f} :
x ∈ t.toLieSubalgebra R ↔ ∃ c₁ c₂ c₃ : R, x = c₁ • e + c₂ • f + c₃ • ⁅e, f⁆ := by
simp_rw [t.lie_e_f, toLieSubalgebra, ← LieSubalgebra.mem_toSubmodule, Submodule.mem_span_triple,
eq_comm]
namespace HasPrimitiveVectorWith
variable {m : M} {μ : R} {t : IsSl2Triple h e f}
local notation "ψ " n => ((toEnd R L M f) ^ n) m
-- Although this is true by definition, we include this lemma (and the assumption) to mirror the API
-- for `lie_h_pow_toEnd_f` and `lie_e_pow_succ_toEnd_f`.
set_option linter.unusedVariables false in
@[nolint unusedArguments]
lemma lie_f_pow_toEnd_f (P : HasPrimitiveVectorWith t m μ) (n : ℕ) :
⁅f, ψ n⁆ = ψ (n + 1) := by
simp [pow_succ']
variable (P : HasPrimitiveVectorWith t m μ)
include P
lemma lie_h_pow_toEnd_f (n : ℕ) :
⁅h, ψ n⁆ = (μ - 2 * n) • ψ n := by
induction n with
| zero => simpa using P.lie_h
| succ n ih =>
rw [pow_succ', Module.End.mul_apply, toEnd_apply_apply, Nat.cast_add, Nat.cast_one,
leibniz_lie h, t.lie_lie_smul_f R, ← neg_smul, ih, lie_smul, smul_lie, ← add_smul]
congr
ring
lemma lie_e_pow_succ_toEnd_f (n : ℕ) :
⁅e, ψ (n + 1)⁆ = ((n + 1) * (μ - n)) • ψ n := by
induction n with
| zero =>
simp only [zero_add, pow_one, toEnd_apply_apply, Nat.cast_zero, sub_zero, one_mul,
pow_zero, Module.End.one_apply, leibniz_lie e, t.lie_e_f, P.lie_e, P.lie_h, lie_zero,
add_zero]
| succ n ih =>
rw [pow_succ', Module.End.mul_apply, toEnd_apply_apply, leibniz_lie e, t.lie_e_f,
lie_h_pow_toEnd_f P, ih, lie_smul, lie_f_pow_toEnd_f P, ← add_smul,
Nat.cast_add, Nat.cast_one]
congr
ring
/-- The eigenvalue of a primitive vector must be a natural number if the representation is
finite-dimensional. -/
lemma exists_nat [IsNoetherian R M] [IsTorsionFree R M] [IsDomain R] [CharZero R] :
∃ n : ℕ, μ = n := by
suffices ∃ n : ℕ, (ψ n) = 0 by
obtain ⟨n, hn₁, hn₂⟩ := Nat.exists_not_and_succ_of_not_zero_of_exists P.ne_zero this
refine ⟨n, ?_⟩
have := lie_e_pow_succ_toEnd_f P n
rw [hn₂, lie_zero, eq_comm, smul_eq_zero_iff_left hn₁, mul_eq_zero, sub_eq_zero] at this
exact this.resolve_left <| Nat.cast_add_one_ne_zero n
have hs : (range <| fun (n : ℕ) ↦ μ - 2 * n).Infinite := by
rw [infinite_range_iff (fun n m ↦ by simp)]; infer_instance
by_contra! contra
exact hs ((toEnd R L M h).eigenvectors_linearIndependent
{μ - 2 * n | n : ℕ}
(fun ⟨s, hs⟩ ↦ ψ Classical.choose hs)
(fun ⟨r, hr⟩ ↦ by simp [lie_h_pow_toEnd_f P, Classical.choose_spec hr, contra,
Module.End.hasEigenvector_iff])).finite
lemma pow_toEnd_f_ne_zero_of_eq_nat [CharZero R] [IsDomain R] [IsTorsionFree R M]
{n : ℕ} (hn : μ = n) {i} (hi : i ≤ n) : (ψ i) ≠ 0 := by
intro H
induction i
· exact P.ne_zero (by simpa using H)
· next i IH =>
have : ((i + 1) * (n - i) : ℤ) • (toEnd R L M f ^ i) m = 0 := by
have := congr_arg (⁅e, ·⁆) H
simpa [← Int.cast_smul_eq_zsmul R, P.lie_e_pow_succ_toEnd_f, hn] using this
rw [← Int.cast_smul_eq_zsmul R, smul_eq_zero, Int.cast_eq_zero, mul_eq_zero, sub_eq_zero,
Nat.cast_inj, ← @Nat.cast_one ℤ, ← Nat.cast_add, Nat.cast_eq_zero] at this
simp only [add_eq_zero, one_ne_zero, and_false, false_or] at this
exact (hi.trans_eq (this.resolve_right (IH (i.le_succ.trans hi)))).not_gt i.lt_succ_self
lemma pow_toEnd_f_eq_zero_of_eq_nat [IsDomain R] [CharZero R] [IsNoetherian R M] [IsTorsionFree R M]
{n : ℕ} (hn : μ = n) : (ψ (n + 1)) = 0 := by
by_contra h
have : t.HasPrimitiveVectorWith (ψ (n + 1)) (n - 2 * (n + 1) : R) :=
{ ne_zero := h
lie_h := (P.lie_h_pow_toEnd_f _).trans (by simp [hn])
lie_e := (P.lie_e_pow_succ_toEnd_f _).trans (by simp [hn]) }
obtain ⟨m, hm⟩ := this.exists_nat
have : (n : ℤ) < m + 2 * (n + 1) := by lia
exact this.ne (Int.cast_injective (α := R) <| by simpa [sub_eq_iff_eq_add] using hm)
end HasPrimitiveVectorWith
variable {m : M} {μ : R}
local notation "φ " n => ((toEnd R L M e) ^ n) m
lemma lie_e_pow_toEnd_e (n : ℕ) :
⁅e, φ n⁆ = φ (n + 1) := by
simp [pow_succ']
lemma lie_h_pow_toEnd_e (t : IsSl2Triple h e f)
(hm : ⁅h, m⁆ = μ • m) (n : ℕ) :
⁅h, φ n⁆ = (μ + 2 * n) • φ n := by
induction n with
| zero => simpa using hm
| succ n ih =>
rw [pow_succ', Module.End.mul_apply, toEnd_apply_apply, Nat.cast_add, Nat.cast_one,
leibniz_lie h, IsSl2Triple.lie_h_e_smul R t, smul_lie, ih, lie_smul, ← add_smul]
congr 1
ring
section CharZero
variable [IsDomain R] [CharZero R]
[Nontrivial M] [IsTorsionFree R M] [Module.Finite R M] [IsTriangularizable R L M]
(t : IsSl2Triple h e f)
lemma exists_hasPrimitiveVectorWith :
∃ (μ : R) (m : M), m ≠ 0 ∧ HasPrimitiveVectorWith t m μ := by
obtain ⟨μ₀, hμ₀⟩ := IsTriangularizable.exists_hasEigenvalue R L M h
obtain ⟨m₀, hm₀⟩ := hμ₀.exists_hasEigenvector
let evals (n : ℕ) : R := μ₀ + 2 * (n : R)
let e_vecs (n : ℕ) : M := ((toEnd R L M e) ^ n) m₀
have h_exists_zero : ∃ k, e_vecs k = 0 := by
by_contra! contra
have h_inj : Function.Injective evals := fun a b hab ↦ by
simpa [evals, add_right_inj, mul_eq_mul_left_iff, Nat.cast_inj] using hab
have aux (μ : range evals) : (toEnd R L M h).HasEigenvector μ (e_vecs μ.property.choose) := by
set n := μ.property.choose
refine ⟨?_, contra n⟩
rw [Module.End.mem_eigenspace_iff, toEnd_apply_apply, ← μ.property.choose_spec]
exact t.lie_h_pow_toEnd_e hm₀.apply_eq_smul n
have _i := ((toEnd R L M h).eigenvectors_linearIndependent (range evals) _ aux).finite
exact (Set.infinite_range_of_injective h_inj) (Set.toFinite _)
obtain ⟨n, hn_ne, hn_zero⟩ := Nat.exists_not_and_succ_of_not_zero_of_exists hm₀.2 h_exists_zero
exact ⟨evals n, e_vecs n, hn_ne,
{ ne_zero := hn_ne
lie_h := t.lie_h_pow_toEnd_e hm₀.apply_eq_smul n
lie_e := by rwa [lie_e_pow_toEnd_e n] }⟩
end CharZero
end IsSl2Triple