|
| 1 | +/- |
| 2 | +Copyright (c) 2025 Kenny Lau. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Kenny Lau |
| 5 | +-/ |
| 6 | +module |
| 7 | + |
| 8 | +public import Mathlib.Algebra.Divisibility.Basic |
| 9 | +public import Mathlib.Algebra.Group.Submonoid.Basic |
| 10 | +public import Mathlib.Order.ConditionallyCompleteLattice.Basic |
| 11 | +public import Mathlib.Order.OmegaCompletePartialOrder |
| 12 | + |
| 13 | +/-! # Saturation of a submonoid |
| 14 | +
|
| 15 | +We define a submonoid `s` to be saturated if `x * y ∈ s → x ∈ s ∧ y ∈ s`. The type of all |
| 16 | +saturated submonoids forms a complete lattice. For a given submonoid `s` we construct the saturation |
| 17 | +of `s` as the smallest saturated submonoid containing `s`, which when the underlying type is a |
| 18 | +commutative monoid, is given by the formula `{x : M | ∃ y : M, x * y ∈ s}`. |
| 19 | +
|
| 20 | +Saturated submonoids are used in the context of localisations. |
| 21 | +
|
| 22 | +We also define the type of saturated submonoids, and endow on it the structure of a complete |
| 23 | +lattice. |
| 24 | +
|
| 25 | +## Main Definitions |
| 26 | +
|
| 27 | +* `Submonoid.MulSaturated`: the condition `x * y ∈ s ↔ x ∈ s ∧ y ∈ s`. Not to be confused with |
| 28 | + `Submonoid.PowSaturated`. |
| 29 | +* `SaturatedSubmonoid`: the type of `Submonoid` satisfying `MulSaturated`. It is a complete lattice. |
| 30 | +* `Submonoid.saturation`: the smallest saturated submonoid containing a given submonoid. |
| 31 | +
|
| 32 | +-/ |
| 33 | + |
| 34 | +@[expose] public section |
| 35 | + |
| 36 | +namespace Submonoid |
| 37 | + |
| 38 | +/-- Given a submonoid `s` of `M`, we say that `s` is **saturated** if it satisfies |
| 39 | +`x * y ∈ s → x ∈ s ∧ y ∈ s`. |
| 40 | +
|
| 41 | +It is called `MulSaturated` here to be distinguished from `Submonoid.PowSaturated` or |
| 42 | +`AddSubmonoid.NSMulSaturated`, which is also called "saturated" in the literature. -/ |
| 43 | +@[to_additive |
| 44 | +/-- Given an additive submonoid `s` of `M`, we say that `s` is **saturated** if it satisfies |
| 45 | +`x + y ∈ s → x ∈ s ∧ y ∈ s`. |
| 46 | +
|
| 47 | +It is called `AddSaturated` here to be distinguished from `Submonoid.PowSaturated` or |
| 48 | +`AddSubmonoid.NSMulSaturated`, which is also called "saturated" in the literature. -/] |
| 49 | +def MulSaturated {M : Type*} [MulOneClass M] (s : Submonoid M) : Prop := |
| 50 | + ∀ ⦃x y⦄, x * y ∈ s → x ∈ s ∧ y ∈ s |
| 51 | + |
| 52 | +namespace MulSaturated |
| 53 | +variable {M : Type*} [MulOneClass M] {s s₁ s₂ : Submonoid M} |
| 54 | + (h : s.MulSaturated) (h₁ : s₁.MulSaturated) (h₂ : s₂.MulSaturated) |
| 55 | + |
| 56 | +include h in |
| 57 | +@[to_additive] |
| 58 | +theorem mul_mem_iff {x y : M} : x * y ∈ s ↔ x ∈ s ∧ y ∈ s := |
| 59 | + ⟨@h _ _, and_imp.mpr mul_mem⟩ |
| 60 | + |
| 61 | +@[to_additive] |
| 62 | +theorem top : MulSaturated (⊤ : Submonoid M) := fun _ _ _ ↦ ⟨trivial, trivial⟩ |
| 63 | + |
| 64 | +include h₁ h₂ in |
| 65 | +@[to_additive] |
| 66 | +theorem inf : MulSaturated (s₁ ⊓ s₂) := |
| 67 | + fun _ _ hxy ↦ ⟨⟨(h₁ hxy.1).1, (h₂ hxy.2).1⟩, (h₁ hxy.1).2, (h₂ hxy.2).2⟩ |
| 68 | + |
| 69 | +@[to_additive] |
| 70 | +theorem sInf {f : Set (Submonoid M)} (hf : ∀ s ∈ f, s.MulSaturated) : |
| 71 | + (sInf f).MulSaturated := fun _ _ hxy ↦ by |
| 72 | + simp_rw [mem_sInf] at hxy ⊢ |
| 73 | + exact ⟨fun s hs ↦ (hf s hs <| hxy s hs).1, fun s hs ↦ (hf s hs <| hxy s hs).2⟩ |
| 74 | + |
| 75 | +@[to_additive] |
| 76 | +theorem iInf {ι : Sort*} {f : ι → Submonoid M} (hf : ∀ i, (f i).MulSaturated) : |
| 77 | + (iInf f).MulSaturated := |
| 78 | + sInf <| Set.forall_mem_range.mpr hf |
| 79 | + |
| 80 | +/-- If `M` is commutative, we only need to check the left condition `x ∈ s`. -/ |
| 81 | +@[to_additive /-- If `M` is commutative, we only need to check the left condition `x ∈ s`. -/] |
| 82 | +theorem of_left {M : Type*} [CommMonoid M] {s : Submonoid M} |
| 83 | + (h : ∀ ⦃x y⦄, x * y ∈ s → x ∈ s) : s.MulSaturated := |
| 84 | + fun x y hxy ↦ ⟨h hxy, h <| mul_comm x y ▸ hxy⟩ |
| 85 | + |
| 86 | +/-- If `M` is commutative, we only need to check the right condition `y ∈ s`. -/ |
| 87 | +@[to_additive /-- If `M` is commutative, we only need to check the right condition `y ∈ s`. -/] |
| 88 | +theorem of_right {M : Type*} [CommMonoid M] {s : Submonoid M} |
| 89 | + (h : ∀ ⦃x y⦄, x * y ∈ s → y ∈ s) : s.MulSaturated := |
| 90 | + of_left fun x y ↦ mul_comm x y ▸ @h y x |
| 91 | + |
| 92 | +end MulSaturated |
| 93 | + |
| 94 | +end Submonoid |
| 95 | + |
| 96 | +-- automatic generation failed |
| 97 | +/-- A saturated additive submonoid is a submonoid `s` that satisfies `x + y ∈ s → x ∈ s ∧ y ∈ s`. -/ |
| 98 | +structure SaturatedAddSubmonoid (M : Type*) [AddZeroClass M] extends AddSubmonoid M where |
| 99 | + addSaturated : toAddSubmonoid.AddSaturated |
| 100 | + |
| 101 | +/-- A saturated submonoid is a submonoid `s` that satisfies `x * y ∈ s → x ∈ s ∧ y ∈ s`. -/ |
| 102 | +@[to_additive] structure SaturatedSubmonoid (M : Type*) [MulOneClass M] extends Submonoid M where |
| 103 | + mulSaturated : toSubmonoid.MulSaturated |
| 104 | + |
| 105 | +namespace SaturatedSubmonoid |
| 106 | +variable {M : Type*} [MulOneClass M] |
| 107 | + |
| 108 | +attribute [simp] mulSaturated SaturatedAddSubmonoid.addSaturated |
| 109 | + |
| 110 | +@[to_additive] |
| 111 | +theorem toSubmonoid_injective : (toSubmonoid (M := M)).Injective := |
| 112 | + fun ⟨s₁, h₁⟩ ⟨s₂, h₂⟩ eq ↦ by congr |
| 113 | + |
| 114 | +@[to_additive (attr := ext)] |
| 115 | +lemma ext {s₁ s₂ : SaturatedSubmonoid M} (h : s₁.toSubmonoid = s₂.toSubmonoid) : s₁ = s₂ := |
| 116 | + toSubmonoid_injective h |
| 117 | + |
| 118 | +variable (M) in |
| 119 | +@[to_additive] |
| 120 | +instance : SetLike (SaturatedSubmonoid M) M where |
| 121 | + coe := (·.carrier) |
| 122 | + coe_injective' _ _ h := toSubmonoid_injective <| SetLike.coe_injective h |
| 123 | + |
| 124 | +@[to_additive] |
| 125 | +instance : PartialOrder (SaturatedSubmonoid M) := .ofSetLike .. |
| 126 | + |
| 127 | +@[to_additive] |
| 128 | +lemma ext' {s₁ s₂ : SaturatedSubmonoid M} (h : ∀ x, x ∈ s₁ ↔ x ∈ s₂) : s₁ = s₂ := |
| 129 | + SetLike.ext h |
| 130 | + |
| 131 | +variable (M) in |
| 132 | +@[to_additive] |
| 133 | +instance : SubmonoidClass (SaturatedSubmonoid M) M where |
| 134 | + mul_mem {s} := s.mul_mem |
| 135 | + one_mem {s} := s.one_mem |
| 136 | + |
| 137 | +@[to_additive (attr := simp)] |
| 138 | +lemma mem_toSubmonoid {s : SaturatedSubmonoid M} {x : M} : x ∈ s.toSubmonoid ↔ x ∈ s := |
| 139 | + Iff.rfl |
| 140 | + |
| 141 | +@[to_additive] |
| 142 | +instance : Top (SaturatedSubmonoid M) where |
| 143 | + top := { (⊤ : Submonoid M) with mulSaturated := .top } |
| 144 | + |
| 145 | +@[to_additive (attr := simp)] |
| 146 | +theorem mem_top {x : M} : x ∈ (⊤ : SaturatedSubmonoid M) := trivial |
| 147 | + |
| 148 | +variable (M) in |
| 149 | +@[to_additive] |
| 150 | +instance : Min (SaturatedSubmonoid M) where |
| 151 | + min s₁ s₂ := { s₁.toSubmonoid ⊓ s₂.toSubmonoid with mulSaturated := .inf s₁.2 s₂.2 } |
| 152 | + |
| 153 | +variable (M) in |
| 154 | +@[to_additive] |
| 155 | +instance : InfSet (SaturatedSubmonoid M) where |
| 156 | + sInf f := |
| 157 | + { carrier := ⋂ s ∈ f, s |
| 158 | + mul_mem' hx hy := by rw [Set.mem_iInter₂] at *; exact fun s hs ↦ mul_mem (hx s hs) (hy s hs) |
| 159 | + one_mem' := Set.mem_iInter₂.mpr fun _ _ ↦ one_mem _ |
| 160 | + mulSaturated := by |
| 161 | + convert Submonoid.MulSaturated.sInf (f := toSubmonoid '' f) (by simp) |
| 162 | + ext; simp [Submonoid.mem_sInf] } |
| 163 | + |
| 164 | +@[to_additive] |
| 165 | +theorem mem_sInf {f : Set (SaturatedSubmonoid M)} {x : M} : x ∈ sInf f ↔ ∀ s ∈ f, x ∈ s := |
| 166 | + Set.mem_iInter₂ |
| 167 | + |
| 168 | +variable (M) in |
| 169 | +@[to_additive] |
| 170 | +instance : CompleteSemilatticeInf (SaturatedSubmonoid M) where |
| 171 | + sInf_le f s hs x hx := mem_sInf.1 hx s hs |
| 172 | + le_sInf f s ih x hx := mem_sInf.2 <| by tauto |
| 173 | + |
| 174 | +end SaturatedSubmonoid |
| 175 | + |
| 176 | +namespace Submonoid |
| 177 | + |
| 178 | +/-- The saturation of a submonoid `s` is the intersection of all saturated submonoids that contain |
| 179 | +`s`. |
| 180 | +
|
| 181 | +If `M` is a commutative monoid, then this is `{x : M | ∃ y : M, x * y ∈ s}`. -/ |
| 182 | +@[to_additive |
| 183 | +/-- The saturation of an additive submonoid `s` is the intersection of all saturated submonoids |
| 184 | +that contain `s`. |
| 185 | +
|
| 186 | +If `M` is a commutative additive monoid, then this is `{x : M | ∃ y : M, x + y ∈ s}`. -/] |
| 187 | +def saturation {M : Type*} [MulOneClass M] (s : Submonoid M) : SaturatedSubmonoid M := |
| 188 | + sInf {t | s ≤ t.toSubmonoid} |
| 189 | + |
| 190 | +variable {M : Type*} |
| 191 | + |
| 192 | +section MulOneClass |
| 193 | +variable [MulOneClass M] |
| 194 | + |
| 195 | +variable (M) in |
| 196 | +@[to_additive] |
| 197 | +theorem gc_saturation : GaloisConnection (saturation (M := M)) (·.toSubmonoid) := fun _ _ ↦ |
| 198 | + ⟨fun ih _ hx ↦ ih <| SaturatedSubmonoid.mem_sInf.mpr fun _ ht ↦ ht hx, |
| 199 | + fun ih _ hx ↦ SaturatedSubmonoid.mem_sInf.mp hx _ ih⟩ |
| 200 | + |
| 201 | +variable (M) in |
| 202 | +/-- `saturation` forms a `GaloisInsertion` with the forgetful functor |
| 203 | +`SaturatedSubmonoid.toSubmonoid`. -/ |
| 204 | +@[to_additive |
| 205 | +/-- `saturation` forms a `GaloisInsertion` with the forgetful functor |
| 206 | +`SaturatedAddSubmonoid.toAddSubmonoid`. -/] |
| 207 | +def giSaturation : GaloisInsertion (saturation (M := M)) (·.toSubmonoid) where |
| 208 | + choice s hs := { s with mulSaturated := le_antisymm ((gc_saturation M).le_u_l s) hs ▸ by simp } |
| 209 | + gc := gc_saturation M |
| 210 | + le_l_u s := (gc_saturation M).le_u_l s.toSubmonoid |
| 211 | + choice_eq s h := le_antisymm ((gc_saturation M).le_u_l s) h |
| 212 | + |
| 213 | +variable {a : Submonoid M} {b : SaturatedSubmonoid M} |
| 214 | + |
| 215 | +@[to_additive] |
| 216 | +theorem saturation_le_iff_le : a.saturation ≤ b ↔ a ≤ b.toSubmonoid := gc_saturation .. |
| 217 | + |
| 218 | +@[to_additive] |
| 219 | +alias ⟨_, saturation_le_of_le⟩ := saturation_le_iff_le |
| 220 | + |
| 221 | +@[to_additive] |
| 222 | +theorem le_toSubmonoid_saturation : a ≤ a.saturation.toSubmonoid := (gc_saturation M).le_u_l a |
| 223 | + |
| 224 | +@[to_additive (attr := simp)] |
| 225 | +theorem saturation_toSubmonoid : b.saturation = b := (giSaturation M).l_u_eq b |
| 226 | + |
| 227 | +@[to_additive (attr := elab_as_elim)] |
| 228 | +theorem saturation_induction {s : Submonoid M} |
| 229 | + {p : (x : M) → x ∈ s.saturation → Prop} |
| 230 | + (mem : ∀ (x) (hx : x ∈ s), p x (le_toSubmonoid_saturation hx)) |
| 231 | + (mul : ∀ x y hx hy, p x hx → p y hy → p (x * y) (mul_mem hx hy)) |
| 232 | + (of_mul : ∀ (x y) (hxy : x * y ∈ s.saturation), |
| 233 | + p (x * y) hxy → p x (s.saturation.2 hxy).1 ∧ p y (s.saturation.2 hxy).2) |
| 234 | + {x : M} (hx : x ∈ s.saturation) : p x hx := by |
| 235 | + let s' : SaturatedSubmonoid M := |
| 236 | + { carrier := { x | ∃ hx, p x hx } |
| 237 | + one_mem' := ⟨_ , mem 1 <| one_mem s⟩ |
| 238 | + mul_mem' := fun ⟨_, hpx⟩ ⟨_, hpy⟩ ↦ ⟨_, mul _ _ _ _ hpx hpy⟩ |
| 239 | + mulSaturated := fun x y ⟨_, hpxy⟩ ↦ ⟨⟨_, (of_mul _ _ _ hpxy).1⟩, ⟨_, (of_mul _ _ _ hpxy).2⟩⟩ } |
| 240 | + exact SaturatedSubmonoid.mem_sInf.mp hx s' (fun _ h ↦ ⟨_, mem _ h⟩) |>.2 |
| 241 | + |
| 242 | +end MulOneClass |
| 243 | + |
| 244 | +section CommMonoid |
| 245 | +variable [CommMonoid M] |
| 246 | + |
| 247 | +variable {s : Submonoid M} {x : M} |
| 248 | + |
| 249 | +@[to_additive] |
| 250 | +theorem mem_saturation_iff : x ∈ s.saturation ↔ ∃ y, x * y ∈ s := by |
| 251 | + refine ⟨fun h ↦ ?_, fun ⟨y, hxy⟩ ↦ (s.saturation.2 <| le_toSubmonoid_saturation hxy).1⟩ |
| 252 | + induction h using saturation_induction with |
| 253 | + | mem _ hx => exact ⟨1, by simpa⟩ |
| 254 | + | mul _ _ _ _ ih₁ ih₂ => |
| 255 | + exact ih₁.elim fun y₁ h₁ ↦ ih₂.elim fun y₂ h₂ ↦ |
| 256 | + ⟨y₁ * y₂, by rw [mul_mul_mul_comm]; exact mul_mem h₁ h₂⟩ |
| 257 | + | of_mul x₁ x₂ _ ih => |
| 258 | + exact ih.elim fun y h ↦ ⟨⟨x₂ * y, by rwa [← mul_assoc]⟩, |
| 259 | + ⟨x₁ * y, by rwa [mul_left_comm, ← mul_assoc]⟩⟩ |
| 260 | + |
| 261 | +@[to_additive] |
| 262 | +theorem mem_saturation_iff' : x ∈ s.saturation ↔ ∃ y, y * x ∈ s := by |
| 263 | + simp_rw [mem_saturation_iff, mul_comm x] |
| 264 | + |
| 265 | +theorem mem_saturation_iff_exists_dvd : x ∈ s.saturation ↔ ∃ m ∈ s, x ∣ m := by |
| 266 | + simp_rw [dvd_def, existsAndEq, and_true, mem_saturation_iff] |
| 267 | + |
| 268 | +end CommMonoid |
| 269 | + |
| 270 | +end Submonoid |
| 271 | + |
| 272 | +namespace SaturatedSubmonoid |
| 273 | + |
| 274 | +@[to_additive] |
| 275 | +instance (M : Type*) [MulOneClass M] : |
| 276 | + CompleteLattice (SaturatedSubmonoid M) := |
| 277 | + { inferInstanceAs (PartialOrder (SaturatedSubmonoid M)), |
| 278 | + inferInstanceAs (Top (SaturatedSubmonoid M)), |
| 279 | + inferInstanceAs (Min (SaturatedSubmonoid M)), |
| 280 | + inferInstanceAs (CompleteSemilatticeInf (SaturatedSubmonoid M)), |
| 281 | + (Submonoid.giSaturation M).liftCompleteLattice with } |
| 282 | + |
| 283 | +variable {M : Type*} |
| 284 | + |
| 285 | +section MulOneClass |
| 286 | +variable [MulOneClass M] |
| 287 | + |
| 288 | +@[to_additive] |
| 289 | +theorem bot_def : (⊥ : SaturatedSubmonoid M) = Submonoid.saturation ⊥ := rfl |
| 290 | + |
| 291 | +@[to_additive] |
| 292 | +theorem sup_def {s₁ s₂ : SaturatedSubmonoid M} : |
| 293 | + s₁ ⊔ s₂ = (s₁.toSubmonoid ⊔ s₂.toSubmonoid).saturation := rfl |
| 294 | + |
| 295 | +@[to_additive] |
| 296 | +theorem sSup_def {f : Set (SaturatedSubmonoid M)} : |
| 297 | + sSup f = (sSup (toSubmonoid '' f)).saturation := rfl |
| 298 | + |
| 299 | +@[to_additive] |
| 300 | +theorem iSup_def {ι : Sort*} {f : ι → SaturatedSubmonoid M} : |
| 301 | + iSup f = (⨆ i, (f i).toSubmonoid).saturation := |
| 302 | + (Submonoid.giSaturation M).l_iSup_u f |>.symm |
| 303 | + |
| 304 | +end MulOneClass |
| 305 | + |
| 306 | +section CommMonoid |
| 307 | +variable [CommMonoid M] |
| 308 | + |
| 309 | +@[to_additive] |
| 310 | +theorem mem_bot_iff {x : M} : x ∈ (⊥ : SaturatedSubmonoid M) ↔ IsUnit x := by |
| 311 | + simp_rw [bot_def, Submonoid.mem_saturation_iff, Submonoid.mem_bot, isUnit_iff_exists_inv] |
| 312 | + |
| 313 | +end CommMonoid |
| 314 | + |
| 315 | +end SaturatedSubmonoid |
| 316 | + |
| 317 | +namespace Submonoid |
| 318 | +variable {M : Type*} [MulOneClass M] |
| 319 | + |
| 320 | +@[to_additive (attr := simp)] |
| 321 | +theorem saturation_bot : (⊥ : Submonoid M).saturation = ⊥ := (gc_saturation M).l_bot |
| 322 | + |
| 323 | +@[to_additive (attr := simp)] |
| 324 | +theorem saturation_top : (⊤ : Submonoid M).saturation = ⊤ := (giSaturation M).l_top |
| 325 | + |
| 326 | +@[to_additive (attr := simp)] |
| 327 | +theorem saturation_sup {s₁ s₂ : Submonoid M} : |
| 328 | + (s₁ ⊔ s₂).saturation = s₁.saturation ⊔ s₂.saturation := (gc_saturation M).l_sup |
| 329 | + |
| 330 | +-- note that it does not preserve inf: |
| 331 | +-- if s₁ = {6 ^ n | n : ℕ} and s₂ = {15 ^ n | n : ℕ} then |
| 332 | +-- (s₁ ⊓ s₂).saturation = {1} and |
| 333 | +-- s₁.saturation ⊓ s₂.saturation = {3 ^ n | n : ℕ} |
| 334 | + |
| 335 | +@[to_additive (attr := simp)] |
| 336 | +theorem saturation_sSup {f : Set (Submonoid M)} : |
| 337 | + (sSup f).saturation = ⨆ s ∈ f, s.saturation := (gc_saturation M).l_sSup |
| 338 | + |
| 339 | +@[to_additive (attr := simp)] |
| 340 | +theorem saturation_iSup {ι : Sort*} {f : ι → Submonoid M} : |
| 341 | + (iSup f).saturation = ⨆ i, (f i).saturation := (gc_saturation M).l_iSup |
| 342 | + |
| 343 | +end Submonoid |
0 commit comments