-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Expand file tree
/
Copy pathBase.lean
More file actions
274 lines (230 loc) · 11.2 KB
/
Base.lean
File metadata and controls
274 lines (230 loc) · 11.2 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
/-
Copyright (c) 2025 Oliver Nash. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Oliver Nash
-/
import Mathlib.LinearAlgebra.RootSystem.IsValuedIn
/-!
# Bases for root pairings / systems
This file contains a theory of bases for root pairings / systems.
## Implementation details
For reduced root pairings `RootSystem.Base` is equivalent to the usual definition appearing in the
informal literature (e.g., it follows from [serre1965](Ch. V, §8, Proposition 7) that
`RootSystem.Base` is equivalent to both [serre1965](Ch. V, §8, Definition 5) and
[bourbaki1968](Ch. VI, §1.5) for reduced pairings). However for non-reduced root pairings, it is
more restrictive because it includes axioms on coroots as well as on roots. For example by
`RootPairing.Base.eq_one_or_neg_one_of_mem_support_of_smul_mem` it is clear that the 1-dimensional
root system `{-2, -1, 0, 1, 2} ⊆ ℝ` has no base in the sense of `RootSystem.Base`.
It is also worth remembering that it is only for reduced root systems that one has the simply
transitive action of the Weyl group on the set of bases, and that the Weyl group of a non-reduced
root system is the same as that of the reduced root system obtained by passing to the indivisible
roots.
For infinite root systems, `RootSystem.Base` is usually not the right notion: linear independence
is too strong.
## Main definitions / results:
* `RootSystem.Base`: a base of a root pairing.
## TODO
* Develop a theory of base / separation / positive roots for infinite systems which specialises to
the concept here for finite systems.
-/
noncomputable section
open Function Set Submodule
variable {ι R M N : Type*} [CommRing R] [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N]
namespace RootPairing
/-- A base of a root pairing.
For reduced root pairings this definition is equivalent to the usual definition appearing in the
informal literature but not for non-reduced root pairings it is more restrictive. See the module
doc string for further remarks. -/
structure Base (P : RootPairing ι R M N) where
/-- The set of roots / coroots belonging to the base. -/
support : Set ι
linInd_root : LinearIndepOn R P.root support
linInd_coroot : LinearIndepOn R P.coroot support
root_mem_or_neg_mem (i : ι) : P.root i ∈ AddSubmonoid.closure (P.root '' support) ∨
- P.root i ∈ AddSubmonoid.closure (P.root '' support)
coroot_mem_or_neg_mem (i : ι) : P.coroot i ∈ AddSubmonoid.closure (P.coroot '' support) ∨
- P.coroot i ∈ AddSubmonoid.closure (P.coroot '' support)
namespace Base
section RootPairing
variable {P : RootPairing ι R M N} (b : P.Base)
/-- Interchanging roots and coroots, one still has a base of a root pairing. -/
@[simps] protected def flip :
P.flip.Base where
support := b.support
linInd_root := b.linInd_coroot
linInd_coroot := b.linInd_root
root_mem_or_neg_mem := b.coroot_mem_or_neg_mem
coroot_mem_or_neg_mem := b.root_mem_or_neg_mem
include b in
lemma root_ne_neg_of_ne [Nontrivial R] {i j : ι}
(hi : i ∈ b.support) (hj : j ∈ b.support) (hij : i ≠ j) :
P.root i ≠ - P.root j := by
classical
intro contra
have := linearIndepOn_iff'.mp b.linInd_root ({i, j} : Finset ι) 1
(by simp [Set.insert_subset_iff, hi, hj]) (by simp [Finset.sum_pair hij, contra])
aesop
lemma root_mem_span_int (i : ι) :
P.root i ∈ span ℤ (P.root '' b.support) := by
have := b.root_mem_or_neg_mem i
simp only [← span_nat_eq_addSubmonoid_closure, mem_toAddSubmonoid] at this
rw [← span_span_of_tower (R := ℕ)]
rcases this with hi | hi
· exact subset_span hi
· rw [← neg_mem_iff]
exact subset_span hi
lemma coroot_mem_span_int (i : ι) :
P.coroot i ∈ span ℤ (P.coroot '' b.support) :=
b.flip.root_mem_span_int i
@[simp]
lemma span_int_root_support :
span ℤ (P.root '' b.support) = span ℤ (range P.root) := by
refine le_antisymm (span_mono <| image_subset_range _ _) (span_le.mpr ?_)
rintro - ⟨i, rfl⟩
exact b.root_mem_span_int i
@[simp]
lemma span_int_coroot_support :
span ℤ (P.coroot '' b.support) = span ℤ (range P.coroot) :=
b.flip.span_int_root_support
@[simp]
lemma span_root_support :
span R (P.root '' b.support) = P.rootSpan R := by
rw [← span_span_of_tower (R := ℤ), span_int_root_support, span_span_of_tower]
@[simp]
lemma span_coroot_support :
span R (P.coroot '' b.support) = P.corootSpan R :=
b.flip.span_root_support
open Finsupp in
lemma eq_one_or_neg_one_of_mem_support_of_smul_mem_aux [Finite ι]
[NoZeroSMulDivisors ℤ M] [NoZeroSMulDivisors ℤ N]
(i : ι) (h : i ∈ b.support) (t : R) (ht : t • P.root i ∈ range P.root) :
∃ z : ℤ, z * t = 1 := by
classical
have : Fintype ι := Fintype.ofFinite ι
obtain ⟨j, hj⟩ := ht
obtain ⟨f, hf⟩ : ∃ f : b.support → ℤ, P.coroot i = ∑ i, (t * f i) • P.coroot i := by
have : P.coroot j ∈ span ℤ (P.coroot '' b.support) := b.coroot_mem_span_int j
rw [image_eq_range, mem_span_range_iff_exists_fun] at this
refine this.imp fun f hf ↦ ?_
simp_rw [mul_smul, ← Finset.smul_sum, Int.cast_smul_eq_zsmul, hf,
coroot_eq_smul_coroot_iff.mpr hj]
use f ⟨i, h⟩
replace hf : P.coroot i = linearCombination R (fun k : b.support ↦ P.coroot k)
(t • (linearEquivFunOnFinite R _ _).symm (fun x ↦ (f x : R))) := by
rw [map_smul, linearCombination_eq_fintype_linearCombination_apply,
Fintype.linearCombination_apply, hf]
simp_rw [mul_smul, ← Finset.smul_sum]
let g : b.support →₀ R := single ⟨i, h⟩ 1
have hg : P.coroot i = linearCombination R (fun k : b.support ↦ P.coroot k) g := by simp [g]
rw [hg] at hf
have : Injective (linearCombination R fun k : b.support ↦ P.coroot k) := b.linInd_coroot
simpa [g, linearEquivFunOnFinite, mul_comm t] using (DFunLike.congr_fun (this hf) ⟨i, h⟩).symm
lemma eq_one_or_neg_one_of_mem_support_of_smul_mem [Finite ι] [CharZero R]
[NoZeroSMulDivisors ℤ M] [NoZeroSMulDivisors ℤ N]
(i : ι) (h : i ∈ b.support) (t : R) (ht : t • P.root i ∈ range P.root) :
t = 1 ∨ t = - 1 := by
obtain ⟨z, hz⟩ := b.eq_one_or_neg_one_of_mem_support_of_smul_mem_aux i h t ht
obtain ⟨s, hs⟩ := IsUnit.exists_left_inv <| isUnit_of_mul_eq_one_right _ t hz
replace ht : s • P.coroot i ∈ range P.coroot := by
obtain ⟨j, hj⟩ := ht
simpa only [coroot_eq_smul_coroot_iff.mpr hj, smul_smul, hs, one_smul] using mem_range_self j
obtain ⟨w, hw⟩ := b.flip.eq_one_or_neg_one_of_mem_support_of_smul_mem_aux i h s ht
have : (z : R) * w = 1 := by
simpa [mul_mul_mul_comm _ t _ s, mul_comm t s, hs] using congr_arg₂ (· * ·) hz hw
suffices z = 1 ∨ z = - 1 by
rcases this with rfl | rfl
· left; simpa using hz
· right; simpa [neg_eq_iff_eq_neg] using hz
norm_cast at this
rw [Int.mul_eq_one_iff_eq_one_or_neg_one] at this
tauto
lemma pos_or_neg_of_sum_smul_root_mem [CharZero R] [Fintype ι] (f : ι → ℤ)
(hf : ∑ j, f j • P.root j ∈ range P.root) (hf₀ : f.support ⊆ b.support) :
0 ≤ f ∨ f ≤ 0 := by
suffices ∀ (f : ι → ℤ)
(hf : ∑ j, f j • P.root j ∈ AddSubmonoid.closure (P.root '' b.support))
(hf₀ : f.support ⊆ b.support), 0 ≤ f by
obtain ⟨k, hk⟩ := hf
rcases b.root_mem_or_neg_mem k with hk' | hk' <;> rw [hk] at hk'
· left; exact this f hk' hf₀
· right; simpa using this (-f) (by convert hk'; simp) (by simpa only [support_neg'])
intro f hf hf₀
have _i : Fintype b.support := Fintype.ofFinite b.support
let f' : b.support → ℤ := fun i ↦ f i
replace hf : ∑ j, f' j • P.root j ∈ AddSubmonoid.closure (P.root '' b.support) := by
suffices ∑ j, f' j • P.root j = ∑ j, f j • P.root j by rwa [this]
rw [← Fintype.sum_subset (s := b.support.toFinset) (by aesop), ← Finset.sum_set_coe]
rw [← span_nat_eq_addSubmonoid_closure, mem_toAddSubmonoid,
Fintype.mem_span_image_iff_exists_fun] at hf
obtain ⟨c, hc⟩ := hf
replace hc (i : b.support) : c i = f' i := Fintype.linearIndependent_iffₛ.mp
(b.linInd_root.restrict_scalars' ℤ) (Int.ofNat ∘ c) f' (by simpa) i
intro i
by_cases hi : i ∈ b.support
· change 0 ≤ f' ⟨i, hi⟩
simp [← hc]
· replace hi : i ∉ f.support := by contrapose! hi; exact hf₀ hi
aesop
lemma sub_nmem_range_root [CharZero R] [Finite ι]
{i j : ι} (hi : i ∈ b.support) (hj : j ∈ b.support) :
P.root i - P.root j ∉ range P.root := by
rcases eq_or_ne j i with rfl | hij
· simpa only [sub_self, mem_range, not_exists] using fun k ↦ P.ne_zero k
classical
have _i : Fintype ι := Fintype.ofFinite ι
let f : ι → ℤ := fun k ↦ if k = i then 1 else if k = j then -1 else 0
have hf : ∑ k, f k • P.root k = P.root i - P.root j := by
rw [← Fintype.sum_subset (s := {i, j}) (by aesop), Finset.sum_insert (by aesop),
Finset.sum_singleton]
simp [f, hij, sub_eq_add_neg]
intro contra
rcases b.pos_or_neg_of_sum_smul_root_mem f (by rwa [hf]) (by aesop) with pos | neg
· simpa [hij, f] using pos j
· simpa [hij, f] using neg i
lemma sub_nmem_range_coroot [CharZero R] [Finite ι]
{i j : ι} (hi : i ∈ b.support) (hj : j ∈ b.support) :
P.coroot i - P.coroot j ∉ range P.coroot :=
b.flip.sub_nmem_range_root hi hj
end RootPairing
section RootSystem
variable {P : RootSystem ι R M N} (b : P.Base)
/-- A base of a root system yields a basis of the root space. -/
@[simps!] def toWeightBasis :
Basis b.support R M :=
Basis.mk b.linInd_root <| by
change ⊤ ≤ span R (range <| P.root ∘ ((↑) : b.support → ι))
rw [top_le_iff, range_comp, Subtype.range_coe_subtype, setOf_mem_eq, b.span_root_support]
exact P.span_root_eq_top
/-- A base of a root system yields a basis of the coroot space. -/
def toCoweightBasis :
Basis b.support R N :=
Base.toWeightBasis (P := P.flip) b.flip
include b
variable [Fintype ι]
lemma exists_root_eq_sum_nat_or_neg (i : ι) :
∃ f : ι → ℕ, P.root i = ∑ j, f j • P.root j ∨ P.root i = - ∑ j, f j • P.root j := by
classical
simp_rw [← neg_eq_iff_eq_neg]
suffices ∀ m ∈ AddSubmonoid.closure (P.root '' b.support), ∃ f : ι → ℕ, m = ∑ j, f j • P.root j by
rcases b.root_mem_or_neg_mem i with hi | hi
· obtain ⟨f, hf⟩ := this _ hi
exact ⟨f, Or.inl hf⟩
· obtain ⟨f, hf⟩ := this _ hi
exact ⟨f, Or.inr hf⟩
intro m hm
refine AddSubmonoid.closure_induction ?_ ⟨0, by simp⟩ ?_ hm
· rintro - ⟨j, hj, rfl⟩
exact ⟨Pi.single j 1, by simp [Pi.single_apply]⟩
· intro _ _ _ _ ⟨f, hf⟩ ⟨g, hg⟩
exact ⟨f + g, by simp [hf, hg, add_smul, Finset.sum_add_distrib]⟩
lemma exists_root_eq_sum_int (i : ι) :
∃ f : ι → ℤ, (0 ≤ f ∨ f ≤ 0) ∧ P.root i = ∑ j, f j • P.root j := by
obtain ⟨f, hf | hf⟩ := b.exists_root_eq_sum_nat_or_neg i
· exact ⟨ Nat.cast ∘ f, Or.inl fun _ ↦ by simp, by simp [hf]⟩
· exact ⟨- Nat.cast ∘ f, Or.inr fun _ ↦ by simp, by simp [hf]⟩
lemma exists_coroot_eq_sum_int (i : ι) :
∃ f : ι → ℤ, (0 ≤ f ∨ f ≤ 0) ∧ P.coroot i = ∑ j, f j • P.coroot j :=
b.flip.exists_root_eq_sum_int i (P := P.flip)
end RootSystem
end Base
end RootPairing