Skip to content

Commit 4512b13

Browse files
committed
feat(GroupTheory): add DivisibleHull
1 parent 1c58764 commit 4512b13

2 files changed

Lines changed: 274 additions & 0 deletions

File tree

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3878,6 +3878,7 @@ import Mathlib.GroupTheory.Coxeter.Inversion
38783878
import Mathlib.GroupTheory.Coxeter.Length
38793879
import Mathlib.GroupTheory.Coxeter.Matrix
38803880
import Mathlib.GroupTheory.Divisible
3881+
import Mathlib.GroupTheory.DivisibleHull
38813882
import Mathlib.GroupTheory.DoubleCoset
38823883
import Mathlib.GroupTheory.EckmannHilton
38833884
import Mathlib.GroupTheory.Exponent
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
/-
2+
Copyright (c) 2025 Weiyi Wang. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Weiyi Wang
5+
-/
6+
7+
import Mathlib.Algebra.Module.LocalizedModule.Basic
8+
import Mathlib.Algebra.Order.GroupWithZero.Submonoid
9+
import Mathlib.Algebra.Order.Module.Archimedean
10+
import Mathlib.Algebra.Order.Module.Defs
11+
import Mathlib.GroupTheory.Divisible
12+
import Mathlib.RingTheory.Localization.FractionRing
13+
14+
/-!
15+
# Divisible Hull of an Abelian group
16+
17+
This file constructs the divisible hull of an Abelian group as a ℤ-module localized by
18+
`Submonoid.pos ℤ`. Further more, we show that `DivisibleHul` is an ordered ℚ-module when the source
19+
group is linearly ordered, and that `ArchimedeanClass` are preserved.
20+
21+
## Implementation notes
22+
23+
This could be equivalently implemented as localization by `ℤ`, but it will complicate the ordering
24+
implementation.
25+
26+
-/
27+
28+
instance : IsLocalization (Submonoid.pos ℤ) ℚ where
29+
map_units' a := by simpa using ne_of_gt a.prop
30+
surj' z := by
31+
obtain ⟨⟨x1, x2⟩, hx⟩ := IsLocalization.surj (nonZeroDivisors ℤ) z
32+
obtain hx2 | hx2 := lt_or_gt_of_ne (show x2.val ≠ 0 by simp)
33+
· exact ⟨⟨-x1, ⟨-x2.val, by simpa using hx2⟩⟩, by simpa using hx⟩
34+
· exact ⟨⟨x1, ⟨x2.val, hx2⟩⟩, hx⟩
35+
exists_of_eq {x y} h := ⟨1, by simpa using Rat.intCast_inj.mp h⟩
36+
37+
variable (M : Type*) [AddCommGroup M]
38+
39+
abbrev DivisibleHull := LocalizedModule (Submonoid.pos ℤ) M
40+
41+
namespace DivisibleHull
42+
variable {M}
43+
44+
def mk (m : M) (s : Submonoid.pos ℤ) : DivisibleHull M := LocalizedModule.mk m s
45+
46+
theorem ind {motive : DivisibleHull M → Prop} (mk : ∀ num den, motive (.mk num den)) :
47+
∀ x, motive x := by
48+
apply LocalizedModule.induction_on
49+
intro a
50+
apply mk
51+
52+
def liftOn {α : Type*} (x : DivisibleHull M)
53+
(f : M → (Submonoid.pos ℤ) → α)
54+
(h : ∀ (m m' : M) (s s' : Submonoid.pos ℤ), mk m s = mk m' s' → f m s = f m' s') : α :=
55+
LocalizedModule.liftOn x (Function.uncurry f) fun p p' heq ↦
56+
h p.1 p'.1 p.2 p'.2 (Quotient.eq'.mpr heq)
57+
58+
@[simp]
59+
theorem liftOn_mk {α : Type*} (m : M) (s : Submonoid.pos ℤ)
60+
(f : M → (Submonoid.pos ℤ) → α)
61+
(h : ∀ (m m' : M) (s s' : Submonoid.pos ℤ), mk m s = mk m' s' → f m s = f m' s') :
62+
liftOn (mk m s) f h = f m s := rfl
63+
64+
def liftOn₂ {α : Type*} (x y : DivisibleHull M)
65+
(f : M → (Submonoid.pos ℤ) → M → (Submonoid.pos ℤ) → α)
66+
(h : ∀ (m n m' n' : M) (s t s' t' : Submonoid.pos ℤ),
67+
mk m s = mk m' s' → mk n t = mk n' t' → f m s n t = f m' s' n' t') : α :=
68+
LocalizedModule.liftOn₂ x y (fun p q ↦ f p.1 p.2 q.1 q.2) fun p q p' q' heq heq' ↦
69+
h p.1 q.1 p'.1 q'.1 p.2 q.2 p'.2 q'.2 (Quotient.eq'.mpr heq) (Quotient.eq'.mpr heq')
70+
71+
theorem mk_eq_mk {m m' : M} {s s' : Submonoid.pos ℤ} :
72+
mk m s = mk m' s' ↔ ∃ u : Submonoid.pos ℤ, u • s' • m = u • s • m' := by
73+
unfold mk
74+
exact LocalizedModule.mk_eq
75+
76+
theorem mk_eq_mk_iff_smul_eq_smul [IsAddTorsionFree M] {m m' : M} {s s' : Submonoid.pos ℤ} :
77+
mk m s = mk m' s' ↔ s' • m = s • m' := by
78+
rw [mk_eq_mk]
79+
constructor
80+
· intro ⟨u, h⟩
81+
simp_rw [Submonoid.smul_def] at ⊢ h
82+
exact (smul_right_inj (ne_of_gt u.prop)).mp h
83+
· intro hr
84+
use 1
85+
rw [hr]
86+
87+
theorem mk_add_mk {m1 m2 : M} {s1 s2 : Submonoid.pos ℤ} :
88+
mk m1 s1 + mk m2 s2 = mk (s2 • m1 + s1 • m2) (s1 * s2) := LocalizedModule.mk_add_mk
89+
90+
theorem mk_neg (m : M) (s : Submonoid.pos ℤ) : mk (-m) s = -mk m s := LocalizedModule.mk_neg
91+
92+
theorem qsmul_mk (a : ℚ) (m : M) (s : Submonoid.pos ℤ) :
93+
a • mk m s = mk (a.num • m) (⟨a.den, Int.natCast_pos.mpr a.den_pos⟩ * s) := by
94+
convert LocalizedModule.mk'_smul_mk ℚ a.num m ⟨a.den, Int.natCast_pos.mpr a.den_pos⟩ s
95+
rw [IsLocalization.eq_mk'_iff_mul_eq]
96+
simp
97+
98+
theorem zsmul_mk (a : ℤ) (m : M) (s : Submonoid.pos ℤ) : a • mk m s = mk (a • m) s := by
99+
suffices (a : ℚ) • mk m s = mk (a • m) s by
100+
rw [Int.cast_smul_eq_zsmul] at this
101+
exact this
102+
rw [qsmul_mk]
103+
exact congrArg _ <| Subtype.eq (by simp)
104+
105+
theorem nsmul_mk (a : ℕ) (m : M) (s : Submonoid.pos ℤ) : a • mk m s = mk (a • m) s := by
106+
suffices (a : ℤ) • mk m s = mk ((a : ℤ) • m) s by simpa using this
107+
exact zsmul_mk _ _ _
108+
109+
instance : DivisibleBy (DivisibleHull M) ℕ where
110+
div m n :=
111+
if h : n = 0 then
112+
0
113+
else
114+
liftOn m (fun m s ↦ mk m (⟨s.val * n, by
115+
rw [Submonoid.mem_pos]
116+
apply mul_pos s.prop
117+
simpa using Nat.pos_of_ne_zero h
118+
⟩)) (by
119+
intro m m' s s'
120+
suffices ∀ a : ℤ, 0 < a → a • s' • m = a • s • m' →
121+
∃ a : ℤ, 0 < a ∧ a • (s'.val * n) • m = a • (s.val * n) • m' by simpa [mk_eq_mk]
122+
intro a ha h
123+
simp_rw [Submonoid.smul_def] at h
124+
refine ⟨a, ha, ?_⟩
125+
simp_rw [smul_smul, ← mul_assoc, mul_comm _ (n : ℤ)]
126+
simp_rw [mul_smul]
127+
rw [h]
128+
)
129+
div_zero := by simp
130+
div_cancel n {m} h := by
131+
induction m using ind with | mk m s
132+
suffices ∃ a : ℤ, 0 < a ∧ a • s • n • m = a • (s.val * n) • m by simpa [h, nsmul_mk, mk_eq_mk]
133+
use 1
134+
suffices s • n • m = (s.val * n) • m by simpa
135+
rw [mul_smul, natCast_zsmul, Submonoid.smul_def]
136+
137+
variable [LinearOrder M] [IsOrderedAddMonoid M]
138+
139+
instance : LE (DivisibleHull M) where
140+
le x y := liftOn₂ x y (fun m s n t ↦ t • m ≤ s • n) fun m n m' n' s t s' t' h h' ↦ by
141+
rw [mk_eq_mk_iff_smul_eq_smul] at h h'
142+
suffices t • m ≤ s • n ↔ t' • m' ≤ s' • n' by simpa
143+
simp_rw [Submonoid.smul_def] at ⊢ h h'
144+
rw [← zsmul_le_zsmul_iff_right (mul_pos s'.prop t'.prop)]
145+
rw [show (s'.val * t'.val) • t.val • m = (t.val * t'.val) • s'.val • m by
146+
simp_rw [smul_smul]
147+
ring_nf]
148+
rw [show (s'.val * t'.val) • s.val • n = (s.val * s'.val) • t'.val • n by
149+
simp_rw [smul_smul]
150+
ring_nf]
151+
rw [h, h']
152+
rw [show (t.val * t'.val) • s.val • m' = (s.val * t.val) • t'.val • m' by
153+
simp_rw [smul_smul]
154+
ring_nf]
155+
rw [show (s.val * s'.val) • t.val • n' = (s.val * t.val) • s'.val • n' by
156+
simp_rw [smul_smul]
157+
ring_nf]
158+
exact zsmul_le_zsmul_iff_right (mul_pos s.prop t.prop)
159+
160+
theorem mk_le_mk {m m' : M} {s s' : Submonoid.pos ℤ} :
161+
mk m s ≤ mk m' s' ↔ s' • m ≤ s • m' := by rfl
162+
163+
theorem mk_le_mk_left {m m' : M} {s : Submonoid.pos ℤ} :
164+
mk m s ≤ mk m' s ↔ m ≤ m' := by
165+
simpa [mk_le_mk, Submonoid.smul_def] using zsmul_le_zsmul_iff_right s.prop
166+
167+
instance : PartialOrder (DivisibleHull M) where
168+
le_refl a := by
169+
induction a using ind with | mk m s
170+
rw [mk_le_mk]
171+
le_trans a b c hab hbc := by
172+
induction a using ind with | mk ma sa
173+
induction b using ind with | mk mb sb
174+
induction c using ind with | mk mc sc
175+
rw [mk_le_mk, Submonoid.smul_def] at ⊢ hab hbc
176+
rw [← zsmul_le_zsmul_iff_right (show 0 < sb.val from sb.prop)]
177+
rw [← zsmul_le_zsmul_iff_right (show 0 < sc.val from sc.prop)] at hab
178+
rw [← zsmul_le_zsmul_iff_right (show 0 < sa.val from sa.prop)] at hbc
179+
rw [smul_comm _ _ ma, smul_comm _ _ mc]
180+
rw [smul_comm _ _ mb] at hab
181+
exact hab.trans hbc
182+
le_antisymm a b h h' := by
183+
induction a using ind with | mk ma sa
184+
induction b using ind with | mk mb sb
185+
rw [mk_le_mk] at h h'
186+
rw [mk_eq_mk_iff_smul_eq_smul]
187+
exact le_antisymm h h'
188+
189+
noncomputable
190+
instance : LinearOrder (DivisibleHull M) where
191+
le_total a b := by
192+
induction a using ind with | mk ma sa
193+
induction b using ind with | mk mb sb
194+
exact le_total _ _
195+
toDecidableLE := Classical.decRel LE.le
196+
197+
noncomputable
198+
instance : IsOrderedAddMonoid (DivisibleHull M) where
199+
add_le_add_left a b h c := by
200+
induction a using ind with | mk ma sa
201+
induction b using ind with | mk mb sb
202+
induction c using ind with | mk mc sc
203+
rw [mk_le_mk] at h
204+
simp_rw [mk_add_mk, mk_le_mk, smul_add, ← mul_smul]
205+
rw [mul_right_comm sc sa sb, add_le_add_iff_left]
206+
rw [mul_right_comm sc sa sc, mul_right_comm sc sb sc]
207+
rw [mul_smul _ _ ma, mul_smul _ _ mb]
208+
exact zsmul_le_zsmul_right (le_of_lt (sc * sc).prop) h
209+
210+
noncomputable
211+
instance : PosSMulStrictMono ℚ (DivisibleHull M) where
212+
elim a ha b c h := by
213+
induction b using ind with | mk mb sb
214+
induction c using ind with | mk mc sc
215+
contrapose! h
216+
simp_rw [qsmul_mk, mk_le_mk, Submonoid.smul_def, Submonoid.mul_def] at h
217+
simp_rw [← mul_smul, mul_right_comm _ _ a.num, mul_smul _ _ mc, mul_smul _ _ mb] at h
218+
rw [mk_le_mk]
219+
refine (zsmul_le_zsmul_iff_right ?_).mp h
220+
exact mul_pos (Int.natCast_pos.mpr a.den_pos) (Rat.num_pos.mpr ha)
221+
222+
variable (M) in
223+
noncomputable
224+
def orderAddMonoidHom : M →+o DivisibleHull M where
225+
__ := LocalizedModule.mkLinearMap _ _
226+
map_zero' := by simp
227+
monotone' := by
228+
intro a b h
229+
suffices mk a 1 ≤ mk b 1 by simpa using this
230+
rw [mk_le_mk]
231+
simpa using h
232+
233+
@[simp]
234+
theorem orderAddMonoidHom_apply (a : M) : (orderAddMonoidHom M) a = mk a 1 := by rfl
235+
236+
variable (M) in
237+
theorem orderAddMonoidHom_injective : Function.Injective (orderAddMonoidHom M) := by
238+
intro a b
239+
simp [mk_eq_mk_iff_smul_eq_smul]
240+
241+
theorem mk_max (m1 m2 : M) (s : Submonoid.pos ℤ) : mk (max m1 m2) s = max (mk m1 s) (mk m2 s) := by
242+
obtain h | h := le_total m1 m2
243+
all_goals simpa [h] using mk_le_mk_left.mpr h
244+
245+
theorem mk_min (m1 m2 : M) (s : Submonoid.pos ℤ) : mk (min m1 m2) s = min (mk m1 s) (mk m2 s) := by
246+
obtain h | h := le_total m1 m2
247+
all_goals simpa [h] using mk_le_mk_left.mpr h
248+
249+
theorem mk_abs (m : M) (s : Submonoid.pos ℤ) : mk |m| s = |mk m s| := by
250+
simp_rw [abs, mk_max, mk_neg]
251+
252+
variable (M) in
253+
noncomputable
254+
def archimedeanClassOrderHom : ArchimedeanClass M →o ArchimedeanClass (DivisibleHull M) :=
255+
ArchimedeanClass.orderHom (orderAddMonoidHom M)
256+
257+
variable (M) in
258+
theorem archimedeanClassOrderHom_injective : Function.Injective (archimedeanClassOrderHom M) :=
259+
ArchimedeanClass.orderHom_injective (orderAddMonoidHom_injective M)
260+
261+
variable (M) in
262+
theorem archimedeanClassOrderHom_surjective : Function.Surjective (archimedeanClassOrderHom M) := by
263+
intro A
264+
induction A using ArchimedeanClass.ind with | mk a
265+
induction a using ind with | mk m s
266+
use ArchimedeanClass.mk m
267+
suffices ArchimedeanClass.mk (mk m 1) = ArchimedeanClass.mk (mk m s) by
268+
simpa using this
269+
rw [show mk m 1 = s.val • mk m s by
270+
simp [zsmul_mk, mk_eq_mk_iff_smul_eq_smul, Submonoid.smul_def]]
271+
exact ArchimedeanClass.mk_smul _ (ne_of_gt s.prop)
272+
273+
end DivisibleHull

0 commit comments

Comments
 (0)