Zulip Chat Archive
Stream: Is there code for X?
Topic: Subring.closure_induction proof
Edison Xie (Jun 13 2025 at 01:30):
Is there a quicker (shorter) proof than this? Thanks in advance!
import Mathlib
example (K D : Type*) [Field K] [DivisionRing D] [Algebra K D]
(L : Subalgebra K D) (L_comm : ∀ x ∈ L, ∀ y ∈ L, x * y = y * x) (a x y : D)
(hx : x ∈ Subring.closure (insert a (Set.range ⇑(algebraMap K D) ∪ ↑L)))
(hy : y ∈ Subring.closure (insert a (Set.range ⇑(algebraMap K D) ∪ ↑L))) (ha : ∀ g ∈ L, g * a = a * g) (x1 y1 : D)
(hx1 : x1 ∈ insert a (Set.range ⇑(algebraMap K D) ∪ ↑L)) (hy1 : y1 ∈ insert a (Set.range ⇑(algebraMap K D) ∪ ↑L)) :
x1 * y1 = y1 * x1 := by
simp at hx1 hy1
obtain hx11 | hx12 | hx13 := hx1
all_goals obtain hy11 | hy12 | hy13 := hy1
· simp_all
· obtain ⟨b, rfl⟩ := hy12
exact Algebra.commutes _ _ |>.symm
· subst hx11
exact ha _ hy13|>.symm
· obtain ⟨b, rfl⟩ := hx12
exact Algebra.commutes _ _
· obtain ⟨b, rfl⟩ := hx12
exact Algebra.commutes _ _
· obtain ⟨b, rfl⟩ := hx12
exact Algebra.commutes _ _
· subst hy11
exact ha _ hx13
· obtain ⟨b, rfl⟩ := hy12
exact Algebra.commutes _ _ |>.symm
· exact L_comm x1 hx13 y1 hy13
Edison Xie (Jun 13 2025 at 01:43):
Or equivalently, is there a shorter proof to prove this? Subalgebra.adjoin_induction2 doesn't seem to work...
import Mathlib
lemma SubField.adjoin_centralizer_mul_comm (K D : Type*) [Field K] [DivisionRing D] [Algebra K D]
(L : Subalgebra K D) (a : D) (ha : a ∈ Subalgebra.centralizer K L)
(L_comm : ∀ x ∈ L, ∀ y ∈ L, x * y = y * x): ∀ (x y : D), x ∈ Algebra.adjoin K (L ∪ {a}) →
y ∈ Algebra.adjoin K (L ∪ {a}) → x * y = y * x :=
fun x y hx hy ↦ by
simp only [Set.union_singleton, Algebra.mem_adjoin_iff, Set.union_insert,
Subalgebra.mem_centralizer_iff, SetLike.mem_coe] at hx hy ha
refine Subring.closure_induction₂ (R := D) (fun x1 y1 hx1 hy1 ↦ by
simp only [Set.mem_insert_iff, Set.mem_union, Set.mem_range, SetLike.mem_coe] at hx1 hy1
obtain hx11 | hx12 | hx13 := hx1
all_goals obtain hy11 | hy12 | hy13 := hy1
· simp_all
· obtain ⟨b, rfl⟩ := hy12
exact Algebra.commutes _ _ |>.symm
· subst hx11
exact ha _ hy13|>.symm
· obtain ⟨b, rfl⟩ := hx12
exact Algebra.commutes _ _
· obtain ⟨b, rfl⟩ := hx12
exact Algebra.commutes _ _
· obtain ⟨b, rfl⟩ := hx12
exact Algebra.commutes _ _
· subst hy11
exact ha _ hx13
· obtain ⟨b, rfl⟩ := hy12
exact Algebra.commutes _ _ |>.symm
· exact L_comm x1 hx13 y1 hy13) ?_ ?_ ?_ ?_ ?_ ?_ ?_ ?_ ?_ ?_ hx hy
all_goals try simp_all [add_mul, mul_add]
· rintro x y z - - - hxz hyz
rw [mul_assoc, hyz, ← mul_assoc, hxz, mul_assoc]
· rintro x y z - - - hxy hxz
rw [← mul_assoc, hxy, mul_assoc, hxz, ← mul_assoc]
Kenny Lau (Jun 13 2025 at 09:25):
@Edison Xie
import Mathlib
open Set
lemma SubField.adjoin_centralizer_mul_comm (K D : Type*) [Field K] [DivisionRing D] [Algebra K D]
(L : Subalgebra K D) (a : D) (ha : a ∈ Subalgebra.centralizer K L)
(L_comm : ∀ x ∈ L, ∀ y ∈ L, x * y = y * x): ∀ (x y : D), x ∈ Algebra.adjoin K (L ∪ {a}) →
y ∈ Algebra.adjoin K (L ∪ {a}) → x * y = y * x :=
fun x y hx hy ↦ by
refine (fun h₃ ↦ Algebra.adjoin_induction₂ ?_ ?_ h₃ ?_ ?_ ?_ ?_ ?_ hx hy) ?_
· intro r x hx; exact Or.elim hx (fun hx ↦ (L_comm x hx _ (algebraMap_mem ..)).symm)
(fun _ ↦ by convert ha _ (algebraMap_mem ..))
· exact fun x y hx hy ↦ Or.elim hx
(fun hx ↦ Or.elim hy (L_comm x hx y) (fun _ ↦ by convert ha x hx))
fun hx ↦ Or.elim hy (fun hy ↦ by convert (ha y hy).symm) (fun hy ↦ by rw [hx, hy])
· intros r₁ r₂; rw [← map_mul, ← map_mul, mul_comm]
· intro r x hx; rw [h₃ r x hx]
· intros; simp only [add_mul, mul_add, *]
· intros; simp only [add_mul, mul_add, *]
· intros _ _ _ _ _ _ hxz hyz; rw [mul_assoc, hyz, ← mul_assoc, hxz, mul_assoc]
· intros _ _ _ _ _ _ hxy hxz; rw [← mul_assoc, hxy, mul_assoc, hxz, mul_assoc]
Kenny Lau (Jun 13 2025 at 09:26):
I used Algebra.adjoin_induction₂ and a clever trick to re-use a proof in two goals
Kenny Lau (Jun 13 2025 at 09:26):
but actually I think I would split this into two lemmas
Kenny Lau (Jun 13 2025 at 09:57):
aha, i tried to split into two lemmas but failed: Algebra ↥L D is not true!
Kenny Lau (Jun 13 2025 at 09:58):
so yeah there's no way to write it as Algebra.adjoin L {a} it seems...
(there is a way to do it, but now it doesn't feel like it's worth the effort, because you're proving this theorem regardless)
Eric Wieser (Jun 13 2025 at 10:15):
Is this true more generally for any two commutative subalgebras whose elements also commute?
Kenny Lau (Jun 13 2025 at 10:17):
it would seem so
Kenny Lau (Jun 13 2025 at 10:18):
well it doesn't seem to be exactly more general, crucially here {a} is not a subalgebra, and we get commutativity on {a} for free
Kenny Lau (Jun 13 2025 at 10:19):
so maybe a more general statement could be... Algebra R A, s t : Set A, then Algebra.adjoin R (s ∪ t) is commutative if s is commutative, t is commutative, and s commutes with t
Kenny Lau (Jun 13 2025 at 10:19):
indeed actually the generalisation we might want, is "is commutative" as a property of subalgebras
Kenny Lau (Jun 13 2025 at 10:21):
import Mathlib
namespace Subalgebra
def IsComm {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] (S : Subalgebra R A) : Prop :=
∀ x ∈ S, ∀ y ∈ S, x * y = y * x
variable {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A]
theorem IsComm.bot : IsComm (⊥ : Subalgebra R A) := by
refine fun x hx y hy ↦ ?_
rw [Algebra.mem_bot, Set.mem_range] at hx hy
rcases hx with ⟨x, rfl⟩; rcases hy with ⟨y, rfl⟩
rw [← map_mul, ← map_mul, mul_comm]
end Subalgebra
Edison Xie (Jun 13 2025 at 10:22):
Eric Wieser said:
Is this true more generally for any two commutative subalgebras whose elements also commute?
note that the centralizer of L need not to be commutative
Kenny Lau (Jun 13 2025 at 10:28):
does anyone want to adopt IsComm as a PR? :melt:
Kenny Lau (Jun 13 2025 at 10:28):
it's a bit hard to adopt things now because branches have to be personal...
Andrew Yang (Jun 13 2025 at 10:44):
We have docs#IsMulCommutative
Eric Wieser (Jun 13 2025 at 10:46):
Edison Xie said:
note that the centralizer of
Lneed not to be commutative
Don't you only care that Algebra.adjoin K {a} is commutative?
Eric Wieser (Jun 13 2025 at 10:49):
The statement I have in mind is
lemma Subalgebra.isComm_sup {R A} [CommSemiring R] [Semiring A] [Algebra R A]
(S₁ S₂ : Subalgebra R A) (h₁ : IsMulCommutative S₁) (h₂ : IsMulCommutative S₁)
(h₁₂ : ∀ x₁ ∈ S₁, ∀ x₂ ∈ S₂, Commute x₁ x₂) :
IsMulCommutative ↥(S₁ ⊔ S₂) :=
sorry
Eric Wieser (Jun 13 2025 at 10:52):
(deleted)
Eric Wieser (Jun 13 2025 at 11:05):
lemma Subalgebra.isComm_sup {ι R A} [CommSemiring R] [Semiring A] [Algebra R A]
(S : ι → Subalgebra R A) (h₁ : ∀ i, IsMulCommutative (S i))
(h₁₂ : Pairwise fun i j => ∀ x₁ ∈ S i, ∀ x₂ ∈ S j, Commute x₁ x₂) :
IsMulCommutative ↥(⨆ i, S i) := by
constructor
constructor
rintro ⟨x, hx⟩ ⟨y, hy⟩
ext
show Commute x y
induction hx using Algebra.iSup_induction' with
| zero => exact .zero_left _
| one => exact .one_left _
| add x₁ x₂ hx hx₂ ihx₁ ihx₂ => exact ihx₁.add_left ihx₂
| mul x₁ x₂ hx hx₂ ihx₁ ihx₂ => exact ihx₁.mul_left ihx₂
| algebraMap r => exact Algebra.commutes _ _
| basic i x hx =>
induction hy using Algebra.iSup_induction' with
| zero => exact .zero_right _
| one => exact .one_right _
| add x₁ x₂ hx hx₂ ihx₁ ihx₂ => exact ihx₁.add_right ihx₂
| mul x₁ x₂ hx hx₂ ihx₁ ihx₂ => exact ihx₁.mul_right ihx₂
| algebraMap r => exact (Algebra.commutes _ _).symm
| basic j y hy =>
obtain rfl | hij := eq_or_ne i j
· exact congrArg Subtype.val <| h₁ _ |>.is_comm.comm ⟨x, hx⟩ ⟨y, hy⟩
· exact h₁₂ hij _ hx _ hy
Eric Wieser (Jun 13 2025 at 11:05):
I think there's some machinery around docs#IsMulCommutative that could improve here
Eric Wieser (Jun 13 2025 at 11:06):
@loogle IsMulCommutative, Commute
loogle (Jun 13 2025 at 11:06):
:shrug: nothing found
Jireh Loreaux (Jun 13 2025 at 20:29):
I think you should be able to get all this from docs#Subalgebra.centralizer_coe_sup and the fact that a subalgebra is commutative iff its contained in it's centralizer.
Jireh Loreaux (Jun 17 2025 at 03:12):
@Eric Wieser I'd prefer not to spell things in terms of IsMulCommutative unless we need to. In this case, I think there is a bit of missing API for Subalgebra.centralizer and a few other things, but once you use the correct spelling, it's quite natural. @Edison Xie or @Kenny Lau, you might be interested in this also. Note the original request appears in the bottom two lemmas.
import Mathlib.Algebra.Algebra.Subalgebra.Centralizer
open Algebra Subalgebra
-- this is the heart of the result you want.
lemma Subalgebra.sup_le_centralizer_self {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A]
{S₁ S₂ : Subalgebra R A} (h₁ : S₁ ≤ centralizer R S₁) (h₂ : S₂ ≤ centralizer R S₂)
(h₁₂ : S₁ ≤ centralizer R S₂) :
(S₁ ⊔ S₂) ≤ centralizer R ↑(S₁ ⊔ S₂) := by
simpa [centralizer_coe_sup, sup_le_iff, le_inf_iff, h₁, h₂, le_centralizer_iff (S := S₂)] using h₁₂
-- Maybe this should be about `S : Subalgebra R A` and `T : Set A` instead? I'm not sure.
lemma Subalgebra.le_centralizer_iff_commute {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A]
(S T : Subalgebra R A) :
S ≤ centralizer R T ↔ ∀ y ∈ S, ∀ x ∈ T, Commute x y := by
rfl
lemma Subalgebra.centralizer_adjoin {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A]
(s : Set A) : centralizer R (adjoin R s) = centralizer R s := by
apply le_antisymm (centralizer_le _ _ _ subset_adjoin)
intro z hz
simp only [mem_centralizer_iff, SetLike.mem_coe] at hz ⊢
intro y hy
induction hy using Algebra.adjoin_induction with
| mem x hx => exact hz x hx
| algebraMap r => exact commutes r z
| add x y hx hy h₁ h₂ => simp [add_mul, mul_add, h₁, h₂]
| mul x y hx hy h₁ h₂ => rw [← mul_assoc, ← h₁]; simp only [mul_assoc, h₂]
-- missing, and handy, we should have these for `adjoin/span/closure` and `ofClass` I think.
-- not marked `@[simp]` so that we don't introduce `ofClass` arbitrarily.
lemma Algebra.adjoin_subalgebra {R S A : Type*} [CommSemiring R] [Semiring A] [Algebra R A]
[SetLike S A] [SubsemiringClass S A] [SMulMemClass S R A] (s : S) :
adjoin R (s : Set A) = .ofClass s :=
le_antisymm (adjoin_le <| by simp) subset_adjoin
-- missing, and handy, we should have these for the `ofClass` of the corresponding subobject.
@[simp]
lemma Subalgebra.ofClass_eq_self {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A]
(s : Subalgebra R A) : Subalgebra.ofClass s = s := by
simp [SetLike.ext'_iff]
lemma SubField.adjoin_centralizer_mul_comm (K D : Type*) [Field K] [DivisionRing D] [Algebra K D]
(L : Subalgebra K D) (a : D) (ha : a ∈ Subalgebra.centralizer K L)
(L_comm : ∀ x ∈ L, ∀ y ∈ L, x * y = y * x) :
∀ x ∈ Algebra.adjoin K (L ∪ {a}), ∀ y ∈ Algebra.adjoin K (L ∪ {a}), x * y = y * x := by
simp_rw [← commute_iff_eq] at L_comm ⊢
rw [forall₂_swap, ← le_centralizer_iff_commute] at L_comm ⊢
simp only [adjoin_union, adjoin_subalgebra, ofClass_eq_self]
refine sup_le_centralizer_self L_comm ?_ ?_
· apply adjoin_le
simp [- coe_centralizer, centralizer_adjoin, mem_centralizer_iff]
· simpa [le_centralizer_iff, adjoin_le_iff]
-- note the first few lines of the previous proof are really just converting to the `centralizer` spelling
-- if you spell with centralizers, it's rather nice.
example (K D : Type*) [Field K] [DivisionRing D] [Algebra K D]
(L : Subalgebra K D) (a : D) (ha : a ∈ Subalgebra.centralizer K L)
(L_comm : L ≤ centralizer K L) :
L ⊔ adjoin K {a} ≤ centralizer K ↑(L ⊔ adjoin K {a}):= by
refine sup_le_centralizer_self L_comm ?_ ?_
· apply adjoin_le
simp [- coe_centralizer, centralizer_adjoin, mem_centralizer_iff]
· simpa [le_centralizer_iff, adjoin_le_iff]
Jireh Loreaux (Jun 17 2025 at 03:36):
Note that, with the centralizer spelling, the iSup result becomes two lines, without a weird split into two hypotheses. And even jumping through the hoops to get the IsMulCommutative version you wrote is still less work with the centralizer approach.
lemma Subalgebra.iSup_le_centralizer_self {ι R A} [CommSemiring R] [Semiring A] [Algebra R A]
{S : ι → Subalgebra R A} (h : ∀ i j, S i ≤ centralizer R (S j)) :
(⨆ i, S i) ≤ centralizer R ↑(⨆ i, S i) := by
rw [centralizer_coe_iSup]
exact iSup_le fun i ↦ le_iInf fun j ↦ h i j
lemma Subalgebra.isComm_sup {ι R A} [CommSemiring R] [Semiring A] [Algebra R A]
(S : ι → Subalgebra R A) (h₁ : ∀ i, IsMulCommutative (S i))
(h₁₂ : Pairwise fun i j => ∀ x₁ ∈ S i, ∀ x₂ ∈ S j, Commute x₁ x₂) :
IsMulCommutative ↥(⨆ i, S i) where
is_comm := by
refine ⟨?_⟩
simp only [Subtype.forall, MulMemClass.mk_mul_mk, Subtype.mk.injEq]
simp_rw [← commute_iff_eq]
rw [forall₂_swap, ← Subalgebra.le_centralizer_iff_commute]
apply Subalgebra.iSup_le_centralizer_self fun i j ↦ ?_
obtain (rfl | h) := eq_or_ne j i
· have := h₁ j |>.is_comm.comm
simp at this
rwa [Subalgebra.le_centralizer_iff_commute, forall₂_swap]
· rw [Subalgebra.le_centralizer_iff_commute, forall₂_swap]
exact h₁₂ h
Kenny Lau (Jun 17 2025 at 08:53):
@Jireh Loreaux I was thinking that maybe we were missing maybe Subalgebra.IsComm and SubAlgebra.IsDivisionRing; do you think these two yet-to-exist typeclasses might be in the wrong direction?
Kenny Lau (Jun 17 2025 at 08:54):
as in, I see that your plan to replace Subalgebra.IsComm is the idiom s <= centraliser s?
Jireh Loreaux (Jun 17 2025 at 12:49):
That's essentially what I'm arguing, yes.
Eric Wieser (Jun 17 2025 at 13:05):
One argument against that spelling is that s appears twice
Last updated: Dec 20 2025 at 21:32 UTC