|
| 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