Skip to content

Commit db7cc7d

Browse files
int-y1ChrisHughes24
andcommitted
feat: port RingTheory.Localization.Away.Basic (#4139)
Co-authored-by: ChrisHughes24 <chrishughes24@gmail.com>
1 parent 870712f commit db7cc7d

File tree

3 files changed

+350
-0
lines changed

3 files changed

+350
-0
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1896,6 +1896,7 @@ import Mathlib.RingTheory.Ideal.QuotientOperations
18961896
import Mathlib.RingTheory.Int.Basic
18971897
import Mathlib.RingTheory.JacobsonIdeal
18981898
import Mathlib.RingTheory.Localization.AtPrime
1899+
import Mathlib.RingTheory.Localization.Away.Basic
18991900
import Mathlib.RingTheory.Localization.Basic
19001901
import Mathlib.RingTheory.Localization.FractionRing
19011902
import Mathlib.RingTheory.Localization.Ideal

Mathlib/Init/Data/Int/Basic.lean

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,18 @@ theorem natAbs_pos_of_ne_zero {a : ℤ} (h : a ≠ 0) : 0 < natAbs a := natAbs_p
132132
def natMod (m n : ℤ) : ℕ := (m % n).toNat
133133
#align int.nat_mod Int.natMod
134134

135+
theorem natAbs_add_nonneg : ∀ {a b : Int}, 0 ≤ a → 0 ≤ b →
136+
natAbs (a + b) = natAbs a + natAbs b
137+
| ofNat n, ofNat m => by simp
138+
| _, negSucc n => by simp
139+
| negSucc n, _ => by simp
140+
#align int.nat_abs_add_nonneg Int.natAbs_add_nonneg
141+
142+
theorem natAbs_add_neg : ∀ {a b : Int}, a < 0 → b < 0
143+
natAbs (a + b) = natAbs a + natAbs b
144+
| negSucc n, negSucc m, _, _ => by simp [Nat.succ_add, Nat.add_succ]
145+
#align int.nat_abs_add_neg Int.natAbs_add_neg
146+
135147
#align int.sign_mul_nat_abs Int.sign_mul_natAbs
136148

137149
#align int.to_nat' Int.toNat'
Lines changed: 337 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
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

Comments
 (0)