|
| 1 | +/- |
| 2 | +Copyright (c) 2018 Kenny Lau. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Kenny Lau, Mario Carneiro, Johan Commelin, Amelia Livingston, Anne Baanen |
| 5 | +
|
| 6 | +! This file was ported from Lean 3 source module ring_theory.localization.away.basic |
| 7 | +! leanprover-community/mathlib commit a7c017d750512a352b623b1824d75da5998457d0 |
| 8 | +! Please do not edit these lines, except to modify the commit id |
| 9 | +! if you have ported upstream changes. |
| 10 | +-/ |
| 11 | +import Mathlib.RingTheory.UniqueFactorizationDomain |
| 12 | +import Mathlib.RingTheory.Localization.Basic |
| 13 | + |
| 14 | +/-! |
| 15 | +# Localizations away from an element |
| 16 | +
|
| 17 | +## Main definitions |
| 18 | +
|
| 19 | + * `IsLocalization.Away (x : R) S` expresses that `S` is a localization away from `x`, as an |
| 20 | + abbreviation of `IsLocalization (Submonoid.powers x) S`. |
| 21 | + * `exists_reduced_fraction' (hb : b ≠ 0)` produces a reduced fraction of the form `b = a * x^n` for |
| 22 | + some `n : ℤ` and some `a : R` that is not divisible by `x`. |
| 23 | +
|
| 24 | +## Implementation notes |
| 25 | +
|
| 26 | +See `Mathlib/RingTheory/Localization/Basic.lean` for a design overview. |
| 27 | +
|
| 28 | +## Tags |
| 29 | +localization, ring localization, commutative ring localization, characteristic predicate, |
| 30 | +commutative ring, field of fractions |
| 31 | +-/ |
| 32 | + |
| 33 | + |
| 34 | +section CommSemiring |
| 35 | + |
| 36 | +variable {R : Type _} [CommSemiring R] (M : Submonoid R) {S : Type _} [CommSemiring S] |
| 37 | + |
| 38 | +variable [Algebra R S] {P : Type _} [CommSemiring P] |
| 39 | + |
| 40 | +namespace IsLocalization |
| 41 | + |
| 42 | +section Away |
| 43 | + |
| 44 | +variable (x : R) |
| 45 | + |
| 46 | +/-- Given `x : R`, the typeclass `IsLocalization.Away x S` states that `S` is |
| 47 | +isomorphic to the localization of `R` at the submonoid generated by `x`. -/ |
| 48 | +abbrev Away (S : Type _) [CommSemiring S] [Algebra R S] := |
| 49 | + IsLocalization (Submonoid.powers x) S |
| 50 | +#align is_localization.away IsLocalization.Away |
| 51 | + |
| 52 | +namespace Away |
| 53 | + |
| 54 | +variable [IsLocalization.Away x S] |
| 55 | + |
| 56 | +/-- Given `x : R` and a localization map `F : R →+* S` away from `x`, `invSelf` is `(F x)⁻¹`. -/ |
| 57 | +noncomputable def invSelf : S := |
| 58 | + mk' S (1 : R) ⟨x, Submonoid.mem_powers _⟩ |
| 59 | +#align is_localization.away.inv_self IsLocalization.Away.invSelf |
| 60 | + |
| 61 | +@[simp] |
| 62 | +theorem mul_invSelf : algebraMap R S x * invSelf x = 1 := by |
| 63 | + convert IsLocalization.mk'_mul_mk'_eq_one (M := Submonoid.powers x) (S := S) _ 1 |
| 64 | + symm |
| 65 | + apply IsLocalization.mk'_one |
| 66 | +#align is_localization.away.mul_inv_self IsLocalization.Away.mul_invSelf |
| 67 | + |
| 68 | +variable {g : R →+* P} |
| 69 | + |
| 70 | +/-- Given `x : R`, a localization map `F : R →+* S` away from `x`, and a map of `CommSemiring`s |
| 71 | +`g : R →+* P` such that `g x` is invertible, the homomorphism induced from `S` to `P` sending |
| 72 | +`z : S` to `g y * (g x)⁻ⁿ`, where `y : R, n : ℕ` are such that `z = F y * (F x)⁻ⁿ`. -/ |
| 73 | +noncomputable def lift (hg : IsUnit (g x)) : S →+* P := |
| 74 | + IsLocalization.lift fun y : Submonoid.powers x => |
| 75 | + show IsUnit (g y.1) by |
| 76 | + obtain ⟨n, hn⟩ := y.2 |
| 77 | + rw [← hn, g.map_pow] |
| 78 | + exact IsUnit.map (powMonoidHom n : P →* P) hg |
| 79 | +#align is_localization.away.lift IsLocalization.Away.lift |
| 80 | + |
| 81 | +@[simp] |
| 82 | +theorem AwayMap.lift_eq (hg : IsUnit (g x)) (a : R) : lift x hg ((algebraMap R S) a) = g a := |
| 83 | + IsLocalization.lift_eq _ _ |
| 84 | +#align is_localization.away.away_map.lift_eq IsLocalization.Away.AwayMap.lift_eq |
| 85 | + |
| 86 | +@[simp] |
| 87 | +theorem AwayMap.lift_comp (hg : IsUnit (g x)) : (lift x hg).comp (algebraMap R S) = g := |
| 88 | + IsLocalization.lift_comp _ |
| 89 | +#align is_localization.away.away_map.lift_comp IsLocalization.Away.AwayMap.lift_comp |
| 90 | + |
| 91 | +/-- Given `x y : R` and localizations `S`, `P` away from `x` and `x * y` |
| 92 | +respectively, the homomorphism induced from `S` to `P`. -/ |
| 93 | +noncomputable def awayToAwayRight (y : R) [Algebra R P] [IsLocalization.Away (x * y) P] : S →+* P := |
| 94 | + lift x <| |
| 95 | + show IsUnit ((algebraMap R P) x) from |
| 96 | + isUnit_of_mul_eq_one ((algebraMap R P) x) (mk' P y ⟨x * y, Submonoid.mem_powers _⟩) <| by |
| 97 | + rw [mul_mk'_eq_mk'_of_mul, mk'_self] |
| 98 | +#align is_localization.away.away_to_away_right IsLocalization.Away.awayToAwayRight |
| 99 | + |
| 100 | +variable (S) (Q : Type _) [CommSemiring Q] [Algebra P Q] |
| 101 | + |
| 102 | +/-- Given a map `f : R →+* S` and an element `r : R`, we may construct a map `Rᵣ →+* Sᵣ`. -/ |
| 103 | +noncomputable def map (f : R →+* P) (r : R) [IsLocalization.Away r S] |
| 104 | + [IsLocalization.Away (f r) Q] : S →+* Q := |
| 105 | + IsLocalization.map Q f |
| 106 | + (show Submonoid.powers r ≤ (Submonoid.powers (f r)).comap f by |
| 107 | + rintro x ⟨n, rfl⟩ |
| 108 | + use n |
| 109 | + simp) |
| 110 | +#align is_localization.away.map IsLocalization.Away.map |
| 111 | + |
| 112 | +end Away |
| 113 | + |
| 114 | +end Away |
| 115 | + |
| 116 | +variable [IsLocalization M S] |
| 117 | + |
| 118 | +section AtUnits |
| 119 | + |
| 120 | +variable (R) (S) |
| 121 | + |
| 122 | +/-- The localization at a module of units is isomorphic to the ring. -/ |
| 123 | +noncomputable def atUnits (H : ∀ x : M, IsUnit (x : R)) : R ≃ₐ[R] S := by |
| 124 | + refine' AlgEquiv.ofBijective (Algebra.ofId R S) ⟨_, _⟩ |
| 125 | + · intro x y hxy |
| 126 | + obtain ⟨c, eq⟩ := (IsLocalization.eq_iff_exists M S).mp hxy |
| 127 | + obtain ⟨u, hu⟩ := H c |
| 128 | + rwa [← hu, Units.mul_right_inj] at eq |
| 129 | + · intro y |
| 130 | + obtain ⟨⟨x, s⟩, eq⟩ := IsLocalization.surj M y |
| 131 | + obtain ⟨u, hu⟩ := H s |
| 132 | + use x * u.inv |
| 133 | + dsimp [Algebra.ofId, RingHom.toFun_eq_coe, AlgHom.coe_mks] |
| 134 | + rw [RingHom.map_mul, ← eq, ← hu, mul_assoc, ← RingHom.map_mul] |
| 135 | + simp |
| 136 | +#align is_localization.at_units IsLocalization.atUnits |
| 137 | + |
| 138 | +/-- The localization away from a unit is isomorphic to the ring. -/ |
| 139 | +noncomputable def atUnit (x : R) (e : IsUnit x) [IsLocalization.Away x S] : R ≃ₐ[R] S := by |
| 140 | + apply atUnits R (Submonoid.powers x) |
| 141 | + rintro ⟨xn, n, hxn⟩ |
| 142 | + obtain ⟨u, hu⟩ := e |
| 143 | + rw [isUnit_iff_exists_inv] |
| 144 | + use u.inv ^ n |
| 145 | + simp [← hxn, ← hu, ← mul_pow] |
| 146 | +#align is_localization.at_unit IsLocalization.atUnit |
| 147 | + |
| 148 | +/-- The localization at one is isomorphic to the ring. -/ |
| 149 | +noncomputable def atOne [IsLocalization.Away (1 : R) S] : R ≃ₐ[R] S := |
| 150 | + @atUnit R _ S _ _ (1 : R) isUnit_one _ |
| 151 | +#align is_localization.at_one IsLocalization.atOne |
| 152 | + |
| 153 | +theorem away_of_isUnit_of_bijective {R : Type _} (S : Type _) [CommRing R] [CommRing S] |
| 154 | + [Algebra R S] {r : R} (hr : IsUnit r) (H : Function.Bijective (algebraMap R S)) : |
| 155 | + IsLocalization.Away r S := |
| 156 | + { map_units' := by |
| 157 | + rintro ⟨_, n, rfl⟩ |
| 158 | + exact (algebraMap R S).isUnit_map (hr.pow _) |
| 159 | + surj' := fun z => by |
| 160 | + obtain ⟨z', rfl⟩ := H.2 z |
| 161 | + exact ⟨⟨z', 1⟩, by simp⟩ |
| 162 | + eq_iff_exists' := fun {x y} => by |
| 163 | + erw [H.1.eq_iff] |
| 164 | + constructor |
| 165 | + · rintro rfl |
| 166 | + exact ⟨1, rfl⟩ |
| 167 | + · rintro ⟨⟨_, n, rfl⟩, e⟩ |
| 168 | + exact (hr.pow _).mul_right_inj.mp e } |
| 169 | +#align is_localization.away_of_is_unit_of_bijective IsLocalization.away_of_isUnit_of_bijective |
| 170 | + |
| 171 | +end AtUnits |
| 172 | + |
| 173 | +end IsLocalization |
| 174 | + |
| 175 | +namespace Localization |
| 176 | + |
| 177 | +open IsLocalization |
| 178 | + |
| 179 | +variable {M} |
| 180 | + |
| 181 | +/-- Given a map `f : R →+* S` and an element `r : R`, such that `f r` is invertible, |
| 182 | + we may construct a map `Rᵣ →+* S`. -/ |
| 183 | +noncomputable abbrev awayLift (f : R →+* P) (r : R) (hr : IsUnit (f r)) : |
| 184 | + Localization.Away r →+* P := |
| 185 | + IsLocalization.Away.lift r hr |
| 186 | +#align localization.away_lift Localization.awayLift |
| 187 | + |
| 188 | +/-- Given a map `f : R →+* S` and an element `r : R`, we may construct a map `Rᵣ →+* Sᵣ`. -/ |
| 189 | +noncomputable abbrev awayMap (f : R →+* P) (r : R) : |
| 190 | + Localization.Away r →+* Localization.Away (f r) := |
| 191 | + IsLocalization.Away.map _ _ f r |
| 192 | +#align localization.away_map Localization.awayMap |
| 193 | + |
| 194 | +end Localization |
| 195 | + |
| 196 | +end CommSemiring |
| 197 | + |
| 198 | +open Localization |
| 199 | + |
| 200 | +variable {R : Type _} [CommRing R] |
| 201 | + |
| 202 | +section NumDen |
| 203 | + |
| 204 | +open UniqueFactorizationMonoid IsLocalization |
| 205 | + |
| 206 | +variable (x : R) |
| 207 | + |
| 208 | +variable (B : Type _) [CommRing B] [Algebra R B] [IsLocalization.Away x B] |
| 209 | + |
| 210 | +/-- `self_zpow x (m : ℤ)` is `x ^ m` as an element of the localization away from `x`. -/ |
| 211 | +noncomputable def selfZpow (m : ℤ) : B := |
| 212 | + if _ : 0 ≤ m then algebraMap _ _ x ^ m.natAbs else mk' _ (1 : R) (Submonoid.pow x m.natAbs) |
| 213 | +#align self_zpow selfZpow |
| 214 | + |
| 215 | +theorem selfZpow_of_nonneg {n : ℤ} (hn : 0 ≤ n) : selfZpow x B n = algebraMap R B x ^ n.natAbs := |
| 216 | + dif_pos hn |
| 217 | +#align self_zpow_of_nonneg selfZpow_of_nonneg |
| 218 | + |
| 219 | +@[simp] |
| 220 | +theorem selfZpow_coe_nat (d : ℕ) : selfZpow x B d = algebraMap R B x ^ d := |
| 221 | + selfZpow_of_nonneg _ _ (Int.coe_nat_nonneg d) |
| 222 | +#align self_zpow_coe_nat selfZpow_coe_nat |
| 223 | + |
| 224 | +@[simp] |
| 225 | +theorem selfZpow_zero : selfZpow x B 0 = 1 := by |
| 226 | + simp [selfZpow_of_nonneg _ _ le_rfl] |
| 227 | +#align self_zpow_zero selfZpow_zero |
| 228 | + |
| 229 | +theorem selfZpow_of_neg {n : ℤ} (hn : n < 0) : |
| 230 | + selfZpow x B n = mk' _ (1 : R) (Submonoid.pow x n.natAbs) := |
| 231 | + dif_neg hn.not_le |
| 232 | +#align self_zpow_of_neg selfZpow_of_neg |
| 233 | + |
| 234 | +theorem selfZpow_of_nonpos {n : ℤ} (hn : n ≤ 0) : |
| 235 | + selfZpow x B n = mk' _ (1 : R) (Submonoid.pow x n.natAbs) := by |
| 236 | + by_cases hn0 : n = 0 |
| 237 | + · simp [hn0, selfZpow_zero, Submonoid.pow_apply] |
| 238 | + · simp [selfZpow_of_neg _ _ (lt_of_le_of_ne hn hn0)] |
| 239 | +#align self_zpow_of_nonpos selfZpow_of_nonpos |
| 240 | + |
| 241 | +@[simp] |
| 242 | +theorem selfZpow_neg_coe_nat (d : ℕ) : selfZpow x B (-d) = mk' _ (1 : R) (Submonoid.pow x d) := by |
| 243 | + simp [selfZpow_of_nonpos _ _ (neg_nonpos.mpr (Int.coe_nat_nonneg d))] |
| 244 | +#align self_zpow_neg_coe_nat selfZpow_neg_coe_nat |
| 245 | + |
| 246 | +@[simp] |
| 247 | +theorem selfZpow_sub_cast_nat {n m : ℕ} : |
| 248 | + selfZpow x B (n - m) = mk' _ (x ^ n) (Submonoid.pow x m) := by |
| 249 | + by_cases h : m ≤ n |
| 250 | + · rw [IsLocalization.eq_mk'_iff_mul_eq, Submonoid.pow_apply, Subtype.coe_mk, ← Int.ofNat_sub h, |
| 251 | + selfZpow_coe_nat, ← map_pow, ← map_mul, ← pow_add, Nat.sub_add_cancel h] |
| 252 | + · rw [← neg_sub, ← Int.ofNat_sub (le_of_not_le h), selfZpow_neg_coe_nat, |
| 253 | + IsLocalization.mk'_eq_iff_eq] |
| 254 | + simp [Submonoid.pow_apply, ← pow_add, Nat.sub_add_cancel (le_of_not_le h)] |
| 255 | +#align self_zpow_sub_cast_nat selfZpow_sub_cast_nat |
| 256 | + |
| 257 | +@[simp] |
| 258 | +theorem selfZpow_add {n m : ℤ} : selfZpow x B (n + m) = selfZpow x B n * selfZpow x B m := by |
| 259 | + cases' le_or_lt 0 n with hn hn <;> cases' le_or_lt 0 m with hm hm |
| 260 | + · rw [selfZpow_of_nonneg _ _ hn, selfZpow_of_nonneg _ _ hm, |
| 261 | + selfZpow_of_nonneg _ _ (add_nonneg hn hm), Int.natAbs_add_nonneg hn hm, pow_add] |
| 262 | + · have : n + m = n.natAbs - m.natAbs := by |
| 263 | + rw [Int.natAbs_of_nonneg hn, Int.ofNat_natAbs_of_nonpos hm.le, sub_neg_eq_add] |
| 264 | + rw [selfZpow_of_nonneg _ _ hn, selfZpow_of_neg _ _ hm, this, selfZpow_sub_cast_nat, |
| 265 | + IsLocalization.mk'_eq_mul_mk'_one, map_pow] |
| 266 | + · have : n + m = m.natAbs - n.natAbs := by |
| 267 | + rw [Int.natAbs_of_nonneg hm, Int.ofNat_natAbs_of_nonpos hn.le, sub_neg_eq_add, add_comm] |
| 268 | + rw [selfZpow_of_nonneg _ _ hm, selfZpow_of_neg _ _ hn, this, selfZpow_sub_cast_nat, |
| 269 | + IsLocalization.mk'_eq_mul_mk'_one, map_pow, mul_comm] |
| 270 | + · rw [selfZpow_of_neg _ _ hn, selfZpow_of_neg _ _ hm, selfZpow_of_neg _ _ (add_neg hn hm), |
| 271 | + Int.natAbs_add_neg hn hm, ← mk'_mul, one_mul] |
| 272 | + congr |
| 273 | + ext |
| 274 | + simp [pow_add] |
| 275 | +#align self_zpow_add selfZpow_add |
| 276 | + |
| 277 | +theorem selfZpow_mul_neg (d : ℤ) : selfZpow x B d * selfZpow x B (-d) = 1 := by |
| 278 | + by_cases hd : d ≤ 0 |
| 279 | + · erw [selfZpow_of_nonpos x B hd, selfZpow_of_nonneg, ← map_pow, Int.natAbs_neg, |
| 280 | + IsLocalization.mk'_spec, map_one] |
| 281 | + apply nonneg_of_neg_nonpos |
| 282 | + rwa [neg_neg] |
| 283 | + · erw [selfZpow_of_nonneg x B (le_of_not_le hd), selfZpow_of_nonpos, ← map_pow, Int.natAbs_neg, |
| 284 | + @IsLocalization.mk'_spec' R _ (Submonoid.powers x) B _ _ _ 1 (Submonoid.pow x d.natAbs), |
| 285 | + map_one] |
| 286 | + refine' nonpos_of_neg_nonneg (le_of_lt _) |
| 287 | + rwa [neg_neg, ← not_le] |
| 288 | +#align self_zpow_mul_neg selfZpow_mul_neg |
| 289 | + |
| 290 | +theorem selfZpow_neg_mul (d : ℤ) : selfZpow x B (-d) * selfZpow x B d = 1 := by |
| 291 | + rw [mul_comm, selfZpow_mul_neg x B d] |
| 292 | +#align self_zpow_neg_mul selfZpow_neg_mul |
| 293 | + |
| 294 | +theorem selfZpow_pow_sub (a : R) (b : B) (m d : ℤ) : |
| 295 | + selfZpow x B (m - d) * mk' B a (1 : Submonoid.powers x) = b ↔ |
| 296 | + selfZpow x B m * mk' B a (1 : Submonoid.powers x) = selfZpow x B d * b := by |
| 297 | + rw [sub_eq_add_neg, selfZpow_add, mul_assoc, mul_comm _ (mk' B a 1), ← mul_assoc] |
| 298 | + constructor |
| 299 | + · intro h |
| 300 | + have := congr_arg (fun s : B => s * selfZpow x B d) h |
| 301 | + simp only at this |
| 302 | + rwa [mul_assoc, mul_assoc, selfZpow_neg_mul, mul_one, mul_comm b _] at this |
| 303 | + · intro h |
| 304 | + have := congr_arg (fun s : B => s * selfZpow x B (-d)) h |
| 305 | + simp only at this |
| 306 | + rwa [mul_comm _ b, mul_assoc b _ _, selfZpow_mul_neg, mul_one] at this |
| 307 | +#align self_zpow_pow_sub selfZpow_pow_sub |
| 308 | + |
| 309 | +variable [IsDomain R] [NormalizationMonoid R] [UniqueFactorizationMonoid R] |
| 310 | + |
| 311 | +theorem exists_reduced_fraction' {b : B} (hb : b ≠ 0) (hx : Irreducible x) : |
| 312 | + ∃ (a : R) (n : ℤ), ¬x ∣ a ∧ selfZpow x B n * algebraMap R B a = b := by |
| 313 | + obtain ⟨⟨a₀, y⟩, H⟩ := surj (Submonoid.powers x) b |
| 314 | + obtain ⟨d, hy⟩ := (Submonoid.mem_powers_iff y.1 x).mp y.2 |
| 315 | + have ha₀ : a₀ ≠ 0 := by |
| 316 | + haveI := |
| 317 | + @isDomain_of_le_nonZeroDivisors B _ R _ _ _ (Submonoid.powers x) _ |
| 318 | + (powers_le_nonZeroDivisors_of_noZeroDivisors hx.ne_zero) |
| 319 | + simp only [map_zero, ← hy, map_pow] at H |
| 320 | + apply ((injective_iff_map_eq_zero' (algebraMap R B)).mp _ a₀).mpr.mt |
| 321 | + rw [← H] |
| 322 | + apply mul_ne_zero hb (pow_ne_zero _ _) |
| 323 | + exact |
| 324 | + IsLocalization.to_map_ne_zero_of_mem_nonZeroDivisors B |
| 325 | + (powers_le_nonZeroDivisors_of_noZeroDivisors hx.ne_zero) |
| 326 | + (mem_nonZeroDivisors_iff_ne_zero.mpr hx.ne_zero) |
| 327 | + exact IsLocalization.injective B (powers_le_nonZeroDivisors_of_noZeroDivisors hx.ne_zero) |
| 328 | + simp only [← hy] at H |
| 329 | + classical |
| 330 | + obtain ⟨m, a, hyp1, hyp2⟩ := max_power_factor ha₀ hx |
| 331 | + refine' ⟨a, m - d, _⟩ |
| 332 | + rw [← mk'_one (M := Submonoid.powers x) B, selfZpow_pow_sub, selfZpow_coe_nat, selfZpow_coe_nat, |
| 333 | + ← map_pow _ _ d, mul_comm _ b, H, hyp2, map_mul, map_pow _ _ m] |
| 334 | + exact ⟨hyp1, congr_arg _ (IsLocalization.mk'_one _ _)⟩ |
| 335 | +#align exists_reduced_fraction' exists_reduced_fraction' |
| 336 | + |
| 337 | +end NumDen |
0 commit comments