Skip to content

Commit 8e23334

Browse files
committed
feat: ArchimedeanSubgroup
1 parent dfad543 commit 8e23334

File tree

5 files changed

+1353
-0
lines changed

5 files changed

+1353
-0
lines changed

Mathlib.lean

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,9 +871,11 @@ import Mathlib.Algebra.Order.Interval.Set.SuccPred
871871
import Mathlib.Algebra.Order.Invertible
872872
import Mathlib.Algebra.Order.Kleene
873873
import Mathlib.Algebra.Order.Module.Algebra
874+
import Mathlib.Algebra.Order.Module.Archimedean
874875
import Mathlib.Algebra.Order.Module.Basic
875876
import Mathlib.Algebra.Order.Module.Defs
876877
import Mathlib.Algebra.Order.Module.Field
878+
import Mathlib.Algebra.Order.Module.HahnEmbedding
877879
import Mathlib.Algebra.Order.Module.OrderedSMul
878880
import Mathlib.Algebra.Order.Module.Pointwise
879881
import Mathlib.Algebra.Order.Module.PositiveLinearMap

Mathlib/Algebra/Order/Archimedean/Class.lean

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,15 @@ Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Weiyi Wang
55
-/
66
import Mathlib.Algebra.BigOperators.Group.Finset.Basic
7+
import Mathlib.Algebra.Group.Subgroup.Lattice
8+
import Mathlib.Algebra.Group.Subgroup.Order
79
import Mathlib.Algebra.Order.Archimedean.Basic
810
import Mathlib.Algebra.Order.Hom.Monoid
911
import Mathlib.Data.Finset.Max
1012
import Mathlib.Order.Antisymmetrization
13+
import Mathlib.Order.SupIndep
14+
import Mathlib.Order.UpperLower.CompleteLattice
15+
import Mathlib.Order.UpperLower.Principal
1116

1217
/-!
1318
# Archimedean classes of a linearly ordered group
@@ -451,6 +456,185 @@ theorem liftOrderHom_mk (f : M → α) (h : ∀ a b, mk a ≤ mk b → f a ≤ f
451456

452457
end LiftHom
453458

459+
/-- Given a non-empty `UpperSet` of `MulArchimedeanClass`,
460+
all group elements belonging to these classes form a subgroup. -/
461+
@[to_additive "Given a non-empty `UpperSet` of `ArchimedeanClass`,
462+
all group elements belonging to these classes form a subgroup."]
463+
def subgroup' {s : UpperSet (MulArchimedeanClass M)} (hs : s ≠ ⊤) : Subgroup M where
464+
carrier := mk ⁻¹' s
465+
mul_mem' {a b} ha hb := by
466+
rw [Set.mem_preimage] at ha hb ⊢
467+
obtain h | h := min_le_iff.mp (min_le_mk_mul a b)
468+
· exact s.upper h ha
469+
· exact s.upper h hb
470+
one_mem' := by
471+
rw [Set.mem_preimage]
472+
obtain ⟨u, hu⟩ := UpperSet.coe_nonempty.mpr hs
473+
simpa using s.upper (by simp) hu
474+
inv_mem' {a} h := by simpa using h
475+
476+
/-- Extend `MulArchimedeanClass.subgroup'` to any `UpperSet`
477+
with a junk value `⊥` assigned to the empty set. -/
478+
@[to_additive "Extend `ArchimedeanClass.subgroup'` to any `UpperSet`
479+
with a junk value `⊥` assigned to the empty set."]
480+
noncomputable
481+
def subgroup (s : UpperSet (MulArchimedeanClass M)) : Subgroup M :=
482+
open Classical in
483+
if hs : s = ⊤ then
484+
485+
else
486+
subgroup' hs
487+
488+
variable {s : UpperSet (MulArchimedeanClass M)}
489+
490+
@[to_additive]
491+
theorem subgroup_eq_of_ne_top (hs : s ≠ ⊤) : subgroup s = subgroup' hs := by
492+
simp [subgroup, hs]
493+
494+
variable (M) in
495+
@[to_additive (attr := simp)]
496+
theorem subgroup_eq_bot : subgroup (M := M) ⊤ = ⊥ := by
497+
simp [subgroup]
498+
499+
@[to_additive]
500+
theorem mem_subgroup_iff (hs : s ≠ ⊤) : a ∈ subgroup s ↔ mk a ∈ s := by
501+
rw [subgroup_eq_of_ne_top hs]
502+
exact Set.mem_preimage
503+
504+
/-- An open ball defined by `MulArchimedeanClass.subgroup` of `UpperSet.Ioi A`.
505+
For `A = ⊤`, we assign the junk value `⊥`. -/
506+
@[to_additive "An open ball defined by `ArchimedeanClass.addSubgroup` of `UpperSet.Ioi A`.
507+
For `A = ⊤`, we assign the junk value `⊥`. "]
508+
noncomputable
509+
abbrev ballSubgroup (A : MulArchimedeanClass M) := subgroup (UpperSet.Ioi A)
510+
511+
/-- A closed ball defined by `MulArchimedeanClass.subgroup` of `UpperSet.Ici A`. -/
512+
@[to_additive "An closed ball defined by `ArchimedeanClass.addSubgroup` of `UpperSet.Ici A`."]
513+
noncomputable
514+
abbrev closedBallSubgroup (A : MulArchimedeanClass M) := subgroup (UpperSet.Ici A)
515+
516+
@[to_additive]
517+
theorem mem_ballSubgroup_iff {a : M} {A : MulArchimedeanClass M} (hA : A ≠ ⊤) :
518+
a ∈ ballSubgroup A ↔ A < mk a := by
519+
have : UpperSet.Ioi A ≠ ⊤ := by
520+
contrapose! hA
521+
rw [UpperSet.ext_iff] at hA
522+
simpa using hA
523+
simp [mem_subgroup_iff this]
524+
525+
@[to_additive (attr := simp)]
526+
theorem mem_closedBallSubgroup_iff {a : M} {A : MulArchimedeanClass M} :
527+
a ∈ closedBallSubgroup A ↔ A ≤ mk a := by
528+
have : UpperSet.Ici A ≠ ⊤ := by simp
529+
simp [mem_subgroup_iff this]
530+
531+
variable (M) in
532+
@[to_additive (attr := simp)]
533+
theorem ballSubgroup_top : ballSubgroup (M := M) ⊤ = ⊥ := by
534+
convert subgroup_eq_bot M
535+
simp
536+
537+
variable (M) in
538+
@[to_additive (attr := simp)]
539+
theorem closedBallSubgroup_top : closedBallSubgroup (M := M) ⊤ = ⊥ := by
540+
ext
541+
simp
542+
543+
variable (M) in
544+
@[to_additive]
545+
theorem subgroup_strictAntiOn : StrictAntiOn (subgroup (M := M)) (Set.Iio ⊤) := by
546+
intro s hs t ht hst
547+
rw [subgroup_eq_of_ne_top (Set.mem_Iio.mp hs).ne_top]
548+
rw [subgroup_eq_of_ne_top (Set.mem_Iio.mp ht).ne_top]
549+
apply lt_of_le_of_ne
550+
· rw [Subgroup.mk_le_mk]
551+
exact (Set.preimage_subset_preimage_iff (by simp)).mpr (by simpa using hst.le)
552+
· contrapose! hst with heq
553+
apply le_of_eq
554+
simpa [mk_surjective, subgroup'] using heq
555+
556+
variable (M) in
557+
@[to_additive]
558+
theorem subgroup_antitone : Antitone (subgroup (M := M)) := by
559+
intro s t hst
560+
obtain hs | rfl := ne_or_eq s ⊤
561+
· obtain ht | rfl := ne_or_eq t ⊤
562+
· exact ((subgroup_strictAntiOn M).le_iff_le
563+
(Set.mem_Iio.mpr ht.lt_top) (Set.mem_Iio.mpr hs.lt_top)).mpr hst
564+
· simp
565+
· rw [eq_top_iff.mpr hst]
566+
567+
variable (M) in
568+
@[to_additive]
569+
theorem ballSubgroup_antitone : Antitone (ballSubgroup (M := M)) := by
570+
intro A B h
571+
exact subgroup_antitone _ <| (UpperSet.Ioi_strictMono _).monotone h
572+
573+
574+
/-- A subgroup `G` is called a grade at `c` iff
575+
`ballSubgroup c` and `G` are complements in the lattice under `closedBallSubgroup c`. -/
576+
@[to_additive /-- A subgroup `G` is called a grade at `c` iff
577+
`ballAddSubgroup c` and `G` are complements in the lattice under `closedBallAddSubgroup c`. -/]
578+
def IsGradeSubgroup (c : MulArchimedeanClass M) (G : Subgroup M) : Prop :=
579+
Disjoint (ballSubgroup c) G ∧ ballSubgroup c ⊔ G = closedBallSubgroup c
580+
581+
namespace IsGradeSubgroup
582+
variable {c : MulArchimedeanClass M} {G : Subgroup M}
583+
584+
@[to_additive]
585+
theorem disjoint (hgrade : IsGradeSubgroup c G) : Disjoint (ballSubgroup c) G := hgrade.1
586+
587+
@[to_additive]
588+
theorem sup_eq (hgrade : IsGradeSubgroup c G) : ballSubgroup c ⊔ G = closedBallSubgroup c :=
589+
hgrade.2
590+
591+
@[to_additive]
592+
theorem eq_bot_iff (hgrade : IsGradeSubgroup c G) : G = ⊥ ↔ c = ⊤ := by
593+
obtain hsup := hgrade.sup_eq
594+
constructor
595+
· rintro rfl
596+
replace hsup : c.ballSubgroup = c.closedBallSubgroup := by simpa using hsup
597+
contrapose! hsup with h
598+
apply Subgroup.ext_iff.not.mpr
599+
induction c using ind with | mk a
600+
rw [not_forall]
601+
exact ⟨a, by simp [h]⟩
602+
· rintro rfl
603+
simpa using hsup
604+
605+
@[to_additive]
606+
theorem nontrivial (hgrade : IsGradeSubgroup c G) (h : c ≠ ⊤) : Nontrivial G :=
607+
(Subgroup.nontrivial_iff_ne_bot _).mpr (hgrade.eq_bot_iff.ne.mpr h)
608+
609+
@[to_additive]
610+
theorem le_closedBallSubgroup (hgrade : IsGradeSubgroup c G) : G ≤ closedBallSubgroup c := by
611+
simp [← hgrade.sup_eq]
612+
613+
@[to_additive archimedeanClassMk_eq]
614+
theorem mulArchimedeanClassMk_eq (hgrade : IsGradeSubgroup c G) {a : M} (ha : a ∈ G) (h0 : a ≠ 1) :
615+
mk a = c := by
616+
apply le_antisymm
617+
· have hA : c ≠ ⊤ := by
618+
contrapose! h0
619+
rw [hgrade.eq_bot_iff.mpr h0] at ha
620+
simpa using ha
621+
contrapose! h0 with hlt
622+
have ha' : a ∈ ballSubgroup c := (mem_ballSubgroup_iff hA).mpr hlt
623+
exact (Subgroup.disjoint_def.mp hgrade.disjoint) ha' ha
624+
· simpa using hgrade.le_closedBallSubgroup ha
625+
626+
@[to_additive archimedean]
627+
theorem mulArchimedean (hgrade : IsGradeSubgroup c G) : MulArchimedean G := by
628+
apply mulArchimedean_of_mk_eq_mk
629+
intro a ha b hb
630+
suffices mk a.val = mk b.val by
631+
rw [mk_eq_mk] at this ⊢
632+
exact this
633+
rw [hgrade.mulArchimedeanClassMk_eq a.prop (by simpa using ha)]
634+
rw [hgrade.mulArchimedeanClassMk_eq b.prop (by simpa using hb)]
635+
636+
end IsGradeSubgroup
637+
454638
end MulArchimedeanClass
455639

456640
variable (M) in
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
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.Submodule.Order
8+
import Mathlib.Algebra.Order.Archimedean.Class
9+
import Mathlib.Algebra.Order.Module.Basic
10+
import Mathlib.LinearAlgebra.DFinsupp
11+
12+
/-!
13+
# Further lemmas related to Archimedean classes for ordered module.
14+
15+
## Main definitions
16+
* `ArchimedeanClass.ball` and `ArchimedeanClass.closedBall`:
17+
`ArchimedeanClass.ballAddSubgroup` and `ArchimedeanClass.closedBallAddSubgroup` as a submodules.
18+
* `ArchimedeanClass.IsGrade`: The module version of `ArchimedeanClass.IsGradeAddSubgroup`.
19+
-/
20+
21+
namespace ArchimedeanClass
22+
23+
variable {M : Type*}
24+
variable [AddCommGroup M] [LinearOrder M] [IsOrderedAddMonoid M]
25+
variable {K : Type*} [Ring K] [LinearOrder K] [IsOrderedRing K] [Archimedean K]
26+
variable [Module K M] [PosSMulMono K M]
27+
28+
variable (K) in
29+
/-- For a ordered module over an `Archimedean` ring,
30+
`ArchimedeanClass.addSubgroup` is a submodule. -/
31+
noncomputable
32+
def submodule (s : UpperSet (ArchimedeanClass M)) : Submodule K M where
33+
__ := addSubgroup s
34+
smul_mem' k {a} := by
35+
obtain rfl | hs := eq_or_ne s ⊤
36+
· aesop
37+
· change a ∈ addSubgroup s → k • a ∈ addSubgroup s
38+
simp_rw [mem_addSubgroup_iff hs]
39+
intro ha
40+
obtain _ | _ := subsingleton_or_nontrivial K
41+
· rw [Subsingleton.eq_zero k]
42+
simpa using (IsUpperSet.top_mem s.upper).mpr <| UpperSet.coe_nonempty.mpr hs
43+
· obtain ⟨n, hn⟩ := Archimedean.arch |k| (show 0 < 1 by simp)
44+
refine s.upper (mk_le_mk.mpr ⟨n, ?_⟩) ha
45+
have : n • |a| = (n • (1 : K)) • |a| := by rw [smul_assoc, one_smul]
46+
rw [this, abs_smul]
47+
exact smul_le_smul_of_nonneg_right hn (by simp)
48+
49+
variable (K) in
50+
/-- `ArchimedeanClass.ballAddSubgroup` as a submodule. -/
51+
noncomputable
52+
abbrev ball (A : ArchimedeanClass M) := submodule K (UpperSet.Ioi A)
53+
54+
variable (K) in
55+
/-- `ArchimedeanClass.closedBallAddSubgroup` as a submodule. -/
56+
noncomputable
57+
abbrev closedBall (A : ArchimedeanClass M) := submodule K (UpperSet.Ici A)
58+
59+
variable (K) in
60+
theorem toAddSubgroup_ball (A : ArchimedeanClass M) :
61+
(ball K A).toAddSubgroup = ballAddSubgroup A := rfl
62+
63+
variable (K) in
64+
theorem toAddSubgroup_closedBall (A : ArchimedeanClass M) :
65+
(closedBall K A).toAddSubgroup = closedBallAddSubgroup A := rfl
66+
67+
variable (K) in
68+
theorem mem_ball_iff {a : M} {A : ArchimedeanClass M} (hA : A ≠ ⊤) : a ∈ ball K A ↔ A < mk a :=
69+
mem_ballAddSubgroup_iff hA
70+
71+
variable (K) in
72+
@[simp]
73+
theorem mem_closedBall_iff {a : M} {A : ArchimedeanClass M} : a ∈ closedBall K A ↔ A ≤ mk a :=
74+
mem_closedBallAddSubgroup_iff
75+
76+
variable (M K) in
77+
@[simp]
78+
theorem ball_top : ball (M := M) K ⊤ = ⊥ :=
79+
(Submodule.toAddSubgroup_inj _ _).mp <| ballAddSubgroup_top M
80+
81+
variable (M K) in
82+
@[simp]
83+
theorem closedBall_top : closedBall (M := M) K ⊤ = ⊥ :=
84+
(Submodule.toAddSubgroup_inj _ _).mp <| closedBallAddSubgroup_top M
85+
86+
variable (M K) in
87+
theorem ball_antitone : Antitone (ball (M := M) K) := by
88+
intro A B h
89+
exact (Submodule.toAddSubgroup_le _ _).mp <| ballAddSubgroup_antitone M h
90+
91+
/-- The module version of `ArchimedeanClass.IsGradeAddSubgroup`. -/
92+
def IsGrade (A : ArchimedeanClass M) (G : Submodule K M) :=
93+
Disjoint (ball K A) G ∧ ball K A ⊔ G = closedBall K A
94+
95+
namespace IsGrade
96+
variable {A : ArchimedeanClass M} {G : Submodule K M}
97+
98+
theorem disjoint (hgrade : IsGrade A G) : Disjoint (ball K A) G := hgrade.1
99+
100+
theorem sup_eq (hgrade : IsGrade A G) : ball K A ⊔ G = closedBall K A := hgrade.2
101+
102+
theorem isGradeAddSubgroup (hgrade : IsGrade A G) : IsGradeAddSubgroup A G.toAddSubgroup := by
103+
constructor
104+
· simpa [disjoint_iff, ← SetLike.coe_set_eq] using hgrade.disjoint
105+
· rw [← toAddSubgroup_ball K A, ← toAddSubgroup_closedBall K A]
106+
rw [← Submodule.sup_toAddSubgroup, hgrade.sup_eq]
107+
108+
theorem nontrivial (hgrade : IsGrade A G) (h : A ≠ ⊤) : Nontrivial G :=
109+
hgrade.isGradeAddSubgroup.nontrivial h
110+
111+
theorem archimedeanClass_eq (hgrade : IsGrade A G) {a : M} (ha : a ∈ G) (h0 : a ≠ 0) : mk a = A :=
112+
hgrade.isGradeAddSubgroup.archimedeanClass_eq ha h0
113+
114+
theorem archimedean (hgrade : IsGrade A G) : Archimedean G :=
115+
hgrade.isGradeAddSubgroup.archimedean
116+
117+
end IsGrade
118+
119+
theorem iSupIndep_of_isGrade {F : ArchimedeanClass M → Submodule K M}
120+
(hgrade : ∀ A : ArchimedeanClass M, IsGrade A (F A)) : iSupIndep F := by
121+
rw [iSupIndep_def]
122+
intro A
123+
rw [Submodule.disjoint_def']
124+
intro a ha b hb hab
125+
obtain ⟨f, hf⟩ := (Submodule.mem_iSup_iff_exists_dfinsupp' _ b).mp hb
126+
obtain hf' := congrArg mk hf
127+
contrapose! hf' with h0
128+
rw [← hab, DFinsupp.sum]
129+
by_cases hnonempty : f.support.Nonempty
130+
· have hmem (x : ArchimedeanClass M) : (f x).val ∈ F x :=
131+
Set.mem_of_mem_of_subset (f x).prop (by simp)
132+
have hmono : StrictMonoOn (fun i ↦ mk (f i).val) f.support := by
133+
intro x hx y hy hxy
134+
change mk (f x).val < mk (f y).val
135+
rw [(hgrade x).archimedeanClass_eq (hmem x) (by simpa using hx)]
136+
rw [(hgrade y).archimedeanClass_eq (hmem y) (by simpa using hy)]
137+
exact hxy
138+
rw [mk_sum hnonempty hmono]
139+
rw [(hgrade _).archimedeanClass_eq (hmem _)
140+
(by simpa using Finset.min'_mem f.support hnonempty)]
141+
by_contra!
142+
obtain h := this ▸ Finset.min'_mem f.support hnonempty
143+
contrapose! h
144+
rw [DFinsupp.notMem_support_iff, (hgrade _).archimedeanClass_eq ha h0]
145+
simpa using (f A).prop
146+
· rw [Finset.not_nonempty_iff_eq_empty.mp hnonempty]
147+
symm
148+
simpa using h0
149+
150+
end ArchimedeanClass

0 commit comments

Comments
 (0)