Zulip Chat Archive
Stream: Is there code for X?
Topic: Localization commutes with tensor products
Dion Leijnse (Nov 12 2025 at 12:50):
I am trying to prove that the localization of a geometrically reduced algebra is again geometrically reduced. Being geometrically reduced is defined in the following way:
class IsGeometricallyReduced (k A : Type*) [Field k] [Ring A] [Algebra k A] : Prop where
isReduced_algebraicClosure_tensorProduct : IsReduced (AlgebraicClosure k ⊗[k] A)
The proof of the result boils down to the fact that localization commutes with tensor products. Here there are some choices. Suppose we have a field k, two commutative k-algebras A and B, a submonoid M : Submonoid A, and these satisfy [IsLocalization M B]. I found two ways to state that, for a commutative k- algebra R the tensor product, R ⊗[k] B is a localization of R ⊗[k] A:
- We let
M'be the image ofMunder the mapA → R ⊗[k] A, and then we want thatR ⊗[k] Bis the localization ofR ⊗[k] Awith respect toM'. This can be formalized as:
let M' : Submonoid (R ⊗[k] A) :=
M.map Algebra.TensorProduct.includeRight.toRingHom.toMonoidHom
example : IsLocalization M' (R ⊗[k] B)
- Turn
R ⊗[k] Ainto anA- algebra, and then we can write
IsLocalization (algebraMapSubmonoid (R ⊗[k] A) M) (R ⊗[k] B)
To me the second way seems to be the better way to go given the current results in Mathlib. In particular, I can use Algebra.isLocalization_iff_isPushout to reduce to showing that something is a pushout. However, when doing this, I need to manually provide a lot of instances of Algebra and IsScalarTower. And then when I actually try to prove that the thing I want to be a pushout is actually a pushout (see code below), I need to provide even more instances manually. Is there a more efficient way to do this, or do all these manual instances really have to be provided?
Here is the full code:
import Mathlib
open TensorProduct
namespace Algebra
/-- The `k`-algebra `A` is geometrically reduced iff its base change to `AlgebraicClosure k` is
reduced. -/
@[mk_iff]
class IsGeometricallyReduced (k A : Type*) [Field k] [Ring A] [Algebra k A] : Prop where
isReduced_algebraicClosure_tensorProduct : IsReduced (AlgebraicClosure k ⊗[k] A)
attribute [instance] IsGeometricallyReduced.isReduced_algebraicClosure_tensorProduct
variable (k A B R : Type) [Field k] [CommRing R] [CommRing A] [CommRing B] (S : Submonoid A)
[Algebra A B] [Algebra k A] [Algebra k B] [IsScalarTower k A B] [IsLocalization S B]
[Algebra k R]
-- corresponds with the first way of taking localization
theorem IsGeometricallyReduced.of_localization2 {k A B : Type} [CommRing B] [CommRing A]
[h : Algebra A B] [Field k] [Algebra k A] [Algebra k B] [IsScalarTower k A B] {M : Submonoid A}
[Algebra.IsGeometricallyReduced k A] [IsLocalization M B] :
Algebra.IsGeometricallyReduced k B := by
have : Algebra (AlgebraicClosure k ⊗[k] A) (AlgebraicClosure k ⊗[k] B) :=
RingHom.toAlgebra (Algebra.TensorProduct.map
(AlgHom.id k (AlgebraicClosure k)) (Algebra.algHom k A B))
let M' : Submonoid (AlgebraicClosure k ⊗[k] A) :=
M.map Algebra.TensorProduct.includeRight.toRingHom.toMonoidHom
have hLoc : IsLocalization M' (AlgebraicClosure k ⊗[k] B) := by
sorry
rw [Algebra.isGeometricallyReduced_iff]
apply isReduced_localizationPreserves M' (AlgebraicClosure k ⊗[k] B)
infer_instance
-- corresponds with the second way of taking the localization
theorem IsGeometricallyReduced.of_localization {k A B : Type} [CommRing B] [CommRing A]
[h : Algebra A B] [Field k] [Algebra k A] [Algebra k B] [IsScalarTower k A B] {M : Submonoid A}
[Algebra.IsGeometricallyReduced k A] [IsLocalization M B] :
Algebra.IsGeometricallyReduced k B := by
have : Algebra (AlgebraicClosure k ⊗[k] A) (AlgebraicClosure k ⊗[k] B) :=
RingHom.toAlgebra (Algebra.TensorProduct.map
(AlgHom.id k (AlgebraicClosure k)) (Algebra.algHom k A B))
have : Algebra A (AlgebraicClosure k ⊗[k] A) :=
RingHom.toAlgebra (TensorProduct.includeRight : A →ₐ[k] AlgebraicClosure k ⊗[k] A)
have : Algebra A (AlgebraicClosure k ⊗[k] B) := RingHom.toAlgebra
((TensorProduct.includeRight : B →ₐ[k] AlgebraicClosure k ⊗[k] B).toRingHom.comp
(RingHom.smulOneHom : A →+* B))
have : Algebra B (AlgebraicClosure k ⊗[k] B) :=
RingHom.toAlgebra (TensorProduct.includeRight : B →ₐ[k] AlgebraicClosure k ⊗[k] B)
have : IsScalarTower A (AlgebraicClosure k ⊗[k] A) (AlgebraicClosure k ⊗[k] B) := by
sorry
have : IsScalarTower A B (AlgebraicClosure k ⊗[k] B) := by sorry
have hLoc' : IsLocalization (algebraMapSubmonoid (AlgebraicClosure k ⊗[k] A) M)
(AlgebraicClosure k ⊗[k] B) := by
rw [isLocalization_iff_isPushout M B]
-- Current goal:
-- ⊢ IsPushout A (AlgebraicClosure k ⊗[k] A) B (AlgebraicClosure k ⊗[k] B)
sorry
rw [Algebra.isGeometricallyReduced_iff]
apply isReduced_localizationPreserves (algebraMapSubmonoid (AlgebraicClosure k ⊗[k] A) M)
(AlgebraicClosure k ⊗[k] B)
infer_instance
Junyan Xu (Nov 12 2025 at 18:31):
A possible solution:
open Algebra.TensorProduct in
theorem IsGeometricallyReduced.of_localization {k A B : Type} [CommRing B] [CommRing A]
[h : Algebra A B] [Field k] [Algebra k A] [Algebra k B] [IsScalarTower k A B] {M : Submonoid A}
[Algebra.IsGeometricallyReduced k A] [IsLocalization M B] :
Algebra.IsGeometricallyReduced k B := by
rw [Algebra.isGeometricallyReduced_iff]
set kbar := AlgebraicClosure k
have : IsReduced (B ⊗[A] (A ⊗[k] kbar)) :=
let _ := @rightAlgebra
isReduced_localizationPreserves (algebraMapSubmonoid (A ⊗[k] kbar) M)
(B ⊗[A] (A ⊗[k] kbar)) (isReduced_of_injective _ (TensorProduct.comm ..).injective)
have e₁ := TensorProduct.congr (.refl (R := k) (A₁ := kbar)) ((TensorProduct.rid A A B).restrictScalars k)
have e₂ := (TensorProduct.comm ..).trans <| (TensorProduct.assoc k A B A kbar).restrictScalars k
exact isReduced_of_injective _ (e₁.symm.trans e₂).injective
I'd expect some of the Algebra.TensorProduct defs could be generalized to make this smoother.
Junyan Xu (Nov 12 2025 at 18:33):
By the way, why are you using have (not let) for data like Algebra that are later used in IsScalarTower?
Dion Leijnse (Nov 14 2025 at 21:00):
Thanks, that looks a lot cleaner than what I was trying! I mostly used have because I didn't know when to use let vs have.
Kenny Lau (Nov 14 2025 at 21:20):
@Dion Leijnse the rule of thumb is that you use let when the thing contains data, and have when it's just a theorem
Dion Leijnse (Nov 14 2025 at 21:25):
Thanks!
Junyan Xu (Nov 14 2025 at 21:46):
I'm breaking that rule, since I just want the existence of an AlgEquiv (MulEquiv would be enough actually).
Junyan Xu (Nov 14 2025 at 21:47):
By the way we should have a universe polymorphic version of isReduced_localizationPreserves (just like IsLocalization.noZeroDivisors etc.)
Kenny Lau (Nov 14 2025 at 21:59):
Sure, but before you break the rule you have to know the rule
Last updated: Dec 20 2025 at 21:32 UTC