Skip to content

Commit b26203f

Browse files
committed
feat(RingTheory/Etale): standard etale maps (#30867)
1 parent 29507cc commit b26203f

File tree

5 files changed

+321
-1
lines changed

5 files changed

+321
-1
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5712,6 +5712,7 @@ public import Mathlib.RingTheory.Etale.Basic
57125712
public import Mathlib.RingTheory.Etale.Field
57135713
public import Mathlib.RingTheory.Etale.Kaehler
57145714
public import Mathlib.RingTheory.Etale.Pi
5715+
public import Mathlib.RingTheory.Etale.StandardEtale
57155716
public import Mathlib.RingTheory.EuclideanDomain
57165717
public import Mathlib.RingTheory.Extension
57175718
public import Mathlib.RingTheory.Extension.Basic

Mathlib/Algebra/Polynomial/Bivariate.lean

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Authors: Junyan Xu
66
module
77

88
public import Mathlib.RingTheory.AdjoinRoot
9+
public import Mathlib.Algebra.MvPolynomial.PDeriv
10+
public import Mathlib.RingTheory.Derivation.MapCoeffs
911

1012
/-!
1113
# Bivariate polynomials
@@ -205,7 +207,7 @@ section aevalAeval
205207

206208
noncomputable section
207209

208-
variable {R A : Type*} [CommRing R] [CommRing A] [Algebra R A]
210+
variable {R A : Type*} [CommSemiring R] [CommSemiring A] [Algebra R A]
209211

210212
/-- `aevalAeval x y` is the `R`-algebra evaluation morphism sending a two-variable polynomial
211213
`p : R[X][Y]` to `p(x,y)`. -/
@@ -255,6 +257,69 @@ end
255257

256258
end aevalAeval
257259

260+
namespace Bivariate
261+
section MvPolynomial
262+
263+
variable {R : Type*} [CommSemiring R]
264+
265+
variable (R) in
266+
/-- The equiv between `R[X][Y]` and `R[X, Y]`. -/
267+
noncomputable
268+
def equivMvPolynomial : R[X][Y] ≃ₐ[R] MvPolynomial (Fin 2) R :=
269+
.ofAlgHom (aevalAeval (.X 0) (.X 1)) (MvPolynomial.aeval ![.C X, X])
270+
(by ext i; fin_cases i <;> simp) (by ext <;> simp)
271+
272+
@[simp]
273+
lemma equivMvPolynomial_C_C {a} : equivMvPolynomial R (C (C a)) = .C a := by
274+
simp [equivMvPolynomial]
275+
276+
@[simp]
277+
lemma equivMvPolynomial_C_X : equivMvPolynomial R (C X) = .X 0 := by
278+
simp [equivMvPolynomial]
279+
280+
@[simp]
281+
lemma equivMvPolynomial_X : equivMvPolynomial R X = .X 1 := by
282+
simp [equivMvPolynomial]
283+
284+
@[simp]
285+
lemma equivMvPolynomial_symm_X_0 : (equivMvPolynomial R).symm (.X 0) = C X := by
286+
simp [equivMvPolynomial]
287+
288+
@[simp]
289+
lemma equivMvPolynomial_symm_X_1 : (equivMvPolynomial R).symm (.X 1) = X := by
290+
simp [equivMvPolynomial]
291+
292+
@[simp]
293+
lemma equivMvPolynomial_symm_C (a : R) : (equivMvPolynomial R).symm (.C a) = C (C a) := by
294+
simp [equivMvPolynomial]
295+
296+
lemma Polynomial.Bivariate.pderiv_zero_equivMvPolynomial {R : Type*} [CommRing R] (p : R[X][Y]) :
297+
(equivMvPolynomial R p).pderiv 0 = equivMvPolynomial R
298+
(PolynomialModule.equivPolynomialSelf (derivative'.mapCoeffs p)) := by
299+
induction p using Polynomial.induction_on' with
300+
| add p q _ _ => aesop
301+
| monomial n p =>
302+
induction p using Polynomial.induction_on' with
303+
| add p q _ _ => aesop
304+
| monomial m a =>
305+
simp_rw [← Polynomial.C_mul_X_pow_eq_monomial]
306+
simp [map_nsmul]
307+
308+
lemma Polynomial.Bivariate.pderiv_one_equivMvPolynomial (p : R[X][Y]) :
309+
(equivMvPolynomial R p).pderiv 1 = equivMvPolynomial R (derivative p) := by
310+
induction p using Polynomial.induction_on' with
311+
| add p q _ _ => aesop
312+
| monomial n p =>
313+
induction p using Polynomial.induction_on' with
314+
| add p q _ _ => aesop
315+
| monomial m a =>
316+
simp_rw [← Polynomial.C_mul_X_pow_eq_monomial]
317+
simp [derivative_pow]
318+
319+
end MvPolynomial
320+
321+
end Bivariate
322+
258323
end Polynomial
259324

260325
open Polynomial

Mathlib/Algebra/Polynomial/Taylor.lean

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ theorem eval_add_of_sq_eq_zero (p : R[X]) (x y : R) (hy : y ^ 2 = 0) :
163163
Finset.sum_range_succ', Finset.sum_range_succ']
164164
simp [pow_succ, mul_assoc, ← pow_two, hy, add_comm (eval x p)]
165165

166+
theorem aeval_add_of_sq_eq_zero {S : Type*} [CommRing S] [Algebra R S]
167+
(p : R[X]) (x y : S) (hy : y ^ 2 = 0) :
168+
p.aeval (x + y) = p.aeval x + p.derivative.aeval x * y := by
169+
simp only [← eval_map_algebraMap, Polynomial.eval_add_of_sq_eq_zero _ _ _ hy, derivative_map]
170+
166171
end CommSemiring
167172

168173
section CommRing
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
/-
2+
Copyright (c) 2025 Andrew Yang. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Andrew Yang
5+
-/
6+
module
7+
8+
public import Mathlib.Algebra.Polynomial.Bivariate
9+
public import Mathlib.Algebra.Polynomial.Taylor
10+
public import Mathlib.RingTheory.Etale.Basic
11+
12+
/-!
13+
14+
# Standard etale maps
15+
16+
# Main definitions
17+
- `StandardEtalePair`:
18+
A pair `f g : R[X]` such that `f` is monic and `f'` is invertible in `R[X][1/g]`.
19+
- `StandardEtalePair`: The standard etale algebra corresponding to a `StandardEtalePair`.
20+
- `StandardEtalePair.equivPolynomialQuotient` : `P.Ring ≃ R[X][Y]/⟨f, Yg-1⟩`
21+
- `StandardEtalePair.equivAwayAdjoinRoot` : `P.Ring ≃ (R[X]/f)[1/g]`
22+
- `StandardEtalePair.equivAwayQuotient` : `P.Ring ≃ R[X][1/g]/f`
23+
- `StandardEtalePair.equivMvPolynomialQuotient` : `P.Ring ≃ R[X, Y]/⟨f, Yg-1⟩`
24+
- `StandardEtalePair.homEquiv`:
25+
Maps out of `P.Ring` corresponds to `x` such that `f(x) = 0` and `g(x)` is invertible.
26+
- We also provide the instance that `P.Ring` is etale over `R`.
27+
28+
-/
29+
30+
@[expose] public section
31+
32+
universe u
33+
34+
open Polynomial
35+
36+
open scoped Bivariate
37+
38+
noncomputable section
39+
40+
variable {R S T : Type*} [CommRing R] [CommRing S] [CommRing T] [Algebra R S] [Algebra R T]
41+
42+
variable (R) in
43+
/-- A `StandardEtalePair R` is a pair `f g : R[X]` such that `f` is monic,
44+
and `f'` is invertible in `R[X][1/g]/f`. -/
45+
structure StandardEtalePair : Type _ where
46+
/-- The monic polynomial to be quotiented out in a standard etale algebra. -/
47+
f : R[X]
48+
monic_f : f.Monic
49+
/-- The polynomial to be localized away from in a standard etale algebra. -/
50+
g : R[X]
51+
cond : ∃ p₁ p₂ n, derivative f * p₁ + f * p₂ = g ^ n
52+
53+
variable (P : StandardEtalePair R)
54+
55+
/-- The standard etale algebra `R[X][Y]/⟨f, Yg-1⟩` associated to a `StandardEtalePair R`.
56+
Also see
57+
`equivPolynomialQuotient : P.Ring ≃ R[X][Y]/⟨f, Yg-1⟩`
58+
`equivAwayAdjoinRoot : P.Ring ≃ (R[X]/f)[1/g]`
59+
`equivAwayQuotient : P.Ring ≃ R[X][1/g]/f`
60+
`equivMvPolynomialQuotient : P.Ring ≃ R[X, Y]/⟨f, Yg-1⟩` -/
61+
protected def StandardEtalePair.Ring := R[X][Y] ⧸ Ideal.span {C P.f, Y * C P.g - 1}
62+
deriving CommRing, Algebra R
63+
64+
namespace StandardEtalePair
65+
66+
/-- The `X` in the standard etale algebra `R[X][Y]/⟨f, Yg-1⟩`. -/
67+
protected def X : P.Ring := Ideal.Quotient.mk _ (C .X)
68+
69+
/-- There is a map from a standard etale algebra `R[X][Y]/⟨f, Yg-1⟩` to `S` sending `X` to `x` iff
70+
`f(x) = 0` and `g(x)` is invertible. Also see `StandardEtalePair.homEquiv`. -/
71+
def HasMap (x : S) : Prop :=
72+
aeval x P.f = 0 ∧ IsUnit (aeval x P.g)
73+
74+
/-- The map `R[X][Y]/⟨f, Yg-1⟩ →ₐ[R] S` sending `X` to `x`, given `P.HasMap x`. -/
75+
def lift (x : S) (h : P.HasMap x) : P.Ring →ₐ[R] S :=
76+
Ideal.Quotient.liftₐ _ (aevalAeval x ↑(h.2.unit⁻¹))
77+
(Ideal.span_le (I := RingHom.ker _).mpr (by simp [Set.pair_subset_iff, h.1]))
78+
79+
@[simp]
80+
lemma lift_X (x : S) (h : P.HasMap x) : P.lift x h P.X = x := by
81+
simp [lift, StandardEtalePair.Ring, StandardEtalePair.X]
82+
83+
variable {P} in
84+
lemma HasMap.map {x : S} (h : P.HasMap x) (f : S →ₐ[R] T) : P.HasMap (f x) :=
85+
by simp [aeval_algHom, h.1], by simpa [aeval_algHom] using h.2.map f⟩
86+
87+
lemma HasMap.isUnit_derivative_f {x : S} (h : P.HasMap x) :
88+
IsUnit (P.f.derivative.aeval x) := by
89+
obtain ⟨p₁, p₂, n, e⟩ := P.cond
90+
have : aeval x P.f.derivative ∣ aeval x P.g ^ n :=
91+
⟨_, by simpa [h.1] using congr(aeval x $e.symm)⟩
92+
exact isUnit_of_dvd_unit this (.pow _ h.2)
93+
94+
lemma aeval_X_g_mul_mk_X : aeval P.X P.g * Ideal.Quotient.mk _ .X = 1 := by
95+
have : aeval (R := R) P.X = (Ideal.Quotient.mkₐ _ _).comp Polynomial.CAlgHom := by
96+
ext; simp [StandardEtalePair.Ring, StandardEtalePair.X]
97+
rw [this]
98+
dsimp [StandardEtalePair.Ring]
99+
rw [← map_mul, ← map_one (Ideal.Quotient.mk _), ← sub_eq_zero, ← map_sub, mul_comm]
100+
exact Ideal.Quotient.eq_zero_iff_mem.mpr (Ideal.subset_span (Set.mem_insert_of_mem _ rfl))
101+
102+
variable {P} in
103+
lemma hasMap_X : P.HasMap P.X :=
104+
have : aeval (R := R) P.X = (Ideal.Quotient.mkₐ _ _).comp Polynomial.CAlgHom := by
105+
ext; simp [StandardEtalePair.Ring, StandardEtalePair.X]
106+
⟨this ▸ Ideal.Quotient.eq_zero_iff_mem.mpr (Ideal.subset_span (Set.mem_insert _ _)),
107+
IsUnit.of_mul_eq_one _ P.aeval_X_g_mul_mk_X⟩
108+
109+
variable {P} in
110+
@[ext]
111+
lemma hom_ext {f g : P.Ring →ₐ[R] S} (H : f P.X = g P.X) : f = g := by
112+
have H : (f.comp (Ideal.Quotient.mkₐ R _)).comp CAlgHom =
113+
(g.comp (Ideal.Quotient.mkₐ R _)).comp CAlgHom := Polynomial.algHom_ext (by simpa)
114+
have H' : aeval (R := R) P.X = (Ideal.Quotient.mkₐ _ _).comp Polynomial.CAlgHom := by
115+
ext; simp [StandardEtalePair.Ring, StandardEtalePair.X]
116+
refine Ideal.Quotient.algHom_ext _ (Polynomial.algHom_ext' H ?_)
117+
change f.toMonoidHom (Ideal.Quotient.mk _ .X) = g.toMonoidHom (Ideal.Quotient.mk _ .X)
118+
rw [← show (↑P.hasMap_X.2.unit⁻¹ : P.Ring) = Ideal.Quotient.mk _ .X from
119+
Units.mul_eq_one_iff_inv_eq.mp P.aeval_X_g_mul_mk_X, ← Units.coe_map_inv, ← Units.coe_map_inv]
120+
congr 2
121+
ext
122+
simpa [H'] using congr($H _)
123+
124+
@[simp]
125+
lemma lift_X_left : P.lift P.X P.hasMap_X = .id _ _ :=
126+
P.hom_ext (by simp)
127+
128+
lemma inv_aeval_X_g :
129+
(↑P.hasMap_X.2.unit⁻¹ : P.Ring) = Ideal.Quotient.mk _ .X :=
130+
Units.mul_eq_one_iff_inv_eq.mp P.aeval_X_g_mul_mk_X
131+
132+
/-- Maps out of `R[X][Y]/⟨f, Yg-1⟩` corresponds bijectively with
133+
`x` such that `f(x) = 0` and `g(x)` is invertible. -/
134+
@[simps]
135+
def homEquiv : (P.Ring →ₐ[R] S) ≃ { x : S // P.HasMap x } where
136+
toFun f := ⟨f P.X, hasMap_X.map f⟩
137+
invFun x := P.lift x.1 x.2
138+
left_inv f := P.hom_ext (by simp)
139+
right_inv x := by simp
140+
141+
lemma existsUnique_hasMap_of_hasMap_quotient_of_sq_eq_bot
142+
(I : Ideal S) (hI : I ^ 2 = ⊥) (x : S) (hx : P.HasMap (Ideal.Quotient.mk I x)) :
143+
∃! ε, ε ∈ I ∧ P.HasMap (x + ε) := by
144+
have hf := Ideal.Quotient.eq_zero_iff_mem.mp
145+
((aeval_algHom_apply (Ideal.Quotient.mkₐ R I) _ _).symm.trans hx.1)
146+
obtain ⟨⟨_, a, ha, -⟩, rfl⟩ := hx.2
147+
obtain ⟨a, rfl⟩ := Ideal.Quotient.mk_surjective a
148+
simp_rw [← Ideal.Quotient.mkₐ_eq_mk R, aeval_algHom_apply, ← map_mul, ← map_one
149+
(Ideal.Quotient.mkₐ R I), Ideal.Quotient.mkₐ_eq_mk, Ideal.Quotient.mk_eq_mk_iff_sub_mem] at ha
150+
obtain ⟨p₁, p₂, n, e⟩ := P.cond
151+
apply_fun aeval x at e
152+
simp only [map_add, map_mul, map_pow] at e
153+
obtain ⟨ε, hεI, b, hb⟩ : ∃ ε ∈ I, ∃ b, aeval x (derivative P.f) * b = 1 + ε := by
154+
refine ⟨_, ?_, (a ^ n * aeval x p₁), sub_eq_iff_eq_add'.mp rfl⟩
155+
convert_to (aeval x P.g * a) ^ n - 1 - aeval x P.f * (a ^ n * aeval x p₂) ∈ I
156+
· linear_combination a ^ n * e
157+
· exact sub_mem (Ideal.mem_of_dvd _ (sub_one_dvd_pow_sub_one _ _) ha) (I.mul_mem_right _ hf)
158+
have : aeval x P.f ^ 2 = 0 := hI.le (Ideal.pow_mem_pow hf 2)
159+
have : aeval x P.f * ε = 0 := ((pow_two _).symm.trans hI).le (Ideal.mul_mem_mul hf hεI)
160+
refine ⟨aeval x P.f * -b, ⟨I.mul_mem_right _ hf, ?_, ?_⟩, ?_⟩
161+
· rw [Polynomial.aeval_add_of_sq_eq_zero _ _ _ (by grind)]; grind
162+
· rw [← IsNilpotent.isUnit_quotient_mk_iff (I := I) ⟨2, hI⟩, ← Ideal.Quotient.mkₐ_eq_mk R,
163+
← aeval_algHom_apply, Ideal.Quotient.mkₐ_eq_mk, map_add,
164+
Ideal.Quotient.eq_zero_iff_mem.mpr (I.mul_mem_right _ hf), add_zero]
165+
exact hx.2
166+
· rintro ε' ⟨hε'I, hε', hε''⟩
167+
rw [Polynomial.aeval_add_of_sq_eq_zero _ _ _ (hI.le (Ideal.pow_mem_pow hε'I 2))] at hε'
168+
have : ε * ε' = 0 := ((pow_two _).symm.trans hI).le (Ideal.mul_mem_mul hεI hε'I)
169+
grind
170+
171+
-- This works even if `f` is not monic. Generalize if we care.
172+
instance : Algebra.FormallyEtale R P.Ring := by
173+
refine Algebra.FormallyEtale.iff_comp_bijective.mpr fun S _ _ I hI ↦ ?_
174+
rw [← P.homEquiv.symm.bijective.of_comp_iff, ← P.homEquiv.bijective.of_comp_iff']
175+
suffices ∀ x, P.HasMap (Ideal.Quotient.mk I x) → ∃! a : { x : S // P.HasMap x }, a - x ∈ I by
176+
simpa [Function.bijective_iff_existsUnique, Ideal.Quotient.mk_surjective.forall,
177+
Subtype.ext_iff, Ideal.Quotient.mk_eq_mk_iff_sub_mem]
178+
intro x hx
179+
obtain ⟨ε, ⟨hεI, hε⟩, H⟩ := P.existsUnique_hasMap_of_hasMap_quotient_of_sq_eq_bot I hI _ hx
180+
exact ⟨⟨x + ε, hε⟩, by simpa, fun y hy ↦
181+
Subtype.ext (sub_eq_iff_eq_add'.mp (H _ ⟨hy, by simpa using y.2⟩))⟩
182+
183+
/-- An `AlgEquiv` between `P.Ring` and `R[X][Y]/⟨f, Yg-1⟩`,
184+
to not abuse the defeq between the two. -/
185+
def equivPolynomialQuotient :
186+
P.Ring ≃ₐ[R] R[X][Y] ⧸ Ideal.span {C P.f, Y * C P.g - 1} := .refl ..
187+
188+
/-- `R[X][Y]/⟨f, Yg-1⟩ ≃ (R[X]/f)[1/g]` -/
189+
def equivAwayAdjoinRoot :
190+
P.Ring ≃ₐ[R] Localization.Away (AdjoinRoot.mk P.f P.g) := by
191+
refine .ofAlgHom (P.lift (algebraMap (AdjoinRoot P.f) _ (.root P.f)) ⟨?_, ?_⟩)
192+
(IsLocalization.liftAlgHom (M := .powers <| AdjoinRoot.mk P.f P.g)
193+
(f := AdjoinRoot.liftAlgHom _ _ P.X P.hasMap_X.1) <| Subtype.forall.mpr ?_) ?_ ?_
194+
· rw [aeval_algebraMap_apply, AdjoinRoot.aeval_eq, AdjoinRoot.mk_self, map_zero]
195+
· rw [aeval_algebraMap_apply, AdjoinRoot.aeval_eq]
196+
exact IsLocalization.Away.algebraMap_isUnit ..
197+
· change Submonoid.powers _ ≤ (IsUnit.submonoid _).comap _
198+
simpa [Submonoid.powers_le, IsUnit.mem_submonoid_iff] using P.hasMap_X.2
199+
· ext; simp [Algebra.algHom]
200+
· ext; simp
201+
202+
/-- `R[X][Y]/⟨f, Yg-1⟩ ≃ R[X][1/g]/f` -/
203+
def equivAwayQuotient :
204+
P.Ring ≃ₐ[R] Localization.Away P.g ⧸ Ideal.span {algebraMap _ (Localization.Away P.g) P.f} := by
205+
refine .ofAlgHom (P.lift (algebraMap R[X] _ .X) ⟨?_, ?_⟩)
206+
(Ideal.Quotient.liftₐ _ (IsLocalization.liftAlgHom (M := .powers <| P.g)
207+
(f := aeval P.X) <| Subtype.forall.mpr ?_) ?_)
208+
?_ ?_
209+
· rw [aeval_algebraMap_apply, IsScalarTower.algebraMap_apply _ (Localization.Away P.g) (_ ⧸ _),
210+
Ideal.Quotient.algebraMap_eq, aeval_X_left_apply, Ideal.Quotient.mk_singleton_self]
211+
· rw [aeval_algebraMap_apply, IsScalarTower.algebraMap_apply _ (Localization.Away P.g) (_ ⧸ _),
212+
aeval_X_left_apply]
213+
exact (IsLocalization.Away.algebraMap_isUnit ..).map _
214+
· change Submonoid.powers _ ≤ (IsUnit.submonoid _).comap _
215+
simpa [Submonoid.powers_le, IsUnit.mem_submonoid_iff] using P.hasMap_X.2
216+
· change Ideal.span _ ≤ RingHom.ker _
217+
simpa [Ideal.span_le] using P.hasMap_X.1
218+
· apply Ideal.Quotient.algHom_ext
219+
ext
220+
simp [Algebra.algHom, IsScalarTower.algebraMap_apply R[X] (Localization.Away P.g) (_ ⧸ _),
221+
-Ideal.Quotient.mk_algebraMap]
222+
· ext; simp [IsScalarTower.algebraMap_apply R[X] (Localization.Away P.g) (_ ⧸ _),
223+
-Ideal.Quotient.mk_algebraMap]
224+
225+
/-- `R[X][Y]/⟨f, Yg-1⟩ ≃ R[X, Y]/⟨f, Yg-1⟩` -/
226+
def equivMvPolynomialQuotient :
227+
P.Ring ≃ₐ[R] MvPolynomial (Fin 2) R ⧸ Ideal.span
228+
{Bivariate.equivMvPolynomial R (C P.f), Bivariate.equivMvPolynomial R (.X * C P.g - 1)} :=
229+
Ideal.quotientEquivAlg _ _ (Bivariate.equivMvPolynomial R)
230+
(by simp only [Ideal.map_span, Set.image_insert_eq, Set.image_singleton]; rfl)
231+
232+
@[simp]
233+
lemma equivMvPolynomialQuotient_symm_apply :
234+
P.equivMvPolynomialQuotient.symm (Ideal.Quotient.mk _ (.X 0)) = P.X := by
235+
simp [equivMvPolynomialQuotient, StandardEtalePair.Ring]; rfl
236+
237+
end StandardEtalePair

Mathlib/RingTheory/Ideal/Quotient/Operations.lean

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,18 @@ def quotientEquivAlg (f : A ≃ₐ[R₁] B) (hIJ : J = I.map (f : A →+* B)) :
653653
{ quotientEquiv I J (f : A ≃+* B) hIJ with
654654
commutes' r := by simp }
655655

656+
@[simp]
657+
lemma quotientEquivAlg_symm (f : A ≃ₐ[R₁] B) (hIJ : J = I.map (f : A →+* B)) :
658+
(quotientEquivAlg I J f hIJ).symm = quotientEquivAlg J I f.symm
659+
(by simp only [← AlgEquiv.toAlgHom_toRingHom, hIJ, map_map, ← AlgHom.comp_toRingHom,
660+
AlgEquiv.symm_comp, AlgHom.id_toRingHom, map_id]) :=
661+
rfl
662+
663+
@[simp]
664+
lemma quotientEquivAlg_mk (f : A ≃ₐ[R₁] B) (hIJ : J = I.map (f : A →+* B)) (x : A) :
665+
Ideal.quotientEquivAlg I J f hIJ x = f x :=
666+
rfl
667+
656668
end
657669

658670
/-- If `P` lies over `p`, then `R / p` has a canonical map to `A / P`. -/

0 commit comments

Comments
 (0)