1-- Centralizers and bicommutants in a ring: the elements commuting with a2-- set S form a subring, the bicommutant of a commuting set is a commutative3-- subring containing it, and bicommutantRing(T, S) is that commutative4-- ring; everything here is ZF5-- Part of Cumulus, the Grace17 mathematics library.6-- Copyright (c) 2026 Grant Passmore.7-- Released under the Apache License 2.0. See LICENSE in the repository root.8-- Authors: Grant Passmore910module Grace.Cumulus.Algebra.Ring.Bicommutant11import Subring1213-- The centralizer of S in T, the bicommutant, and the ring on the latter14-- with the operations of T restricted.15def ringCentralizer (T S : Set) : Set:=16 { z ∈ Ring.carrier(T) |17∀ x ∈ S, call2(Ring.mul(T), z, x) = call2(Ring.mul(T), x, z) }18def bicommutant (T S : Set) : Set:= ringCentralizer(T, ringCentralizer(T, S))19def bicommutantRing (T S : Set) : Set:= subringRing(T, bicommutant(T, S))2021theorem bicommutantRing.carrierOf (T S : Set)22shows Ring.carrier(bicommutantRing(T, S)) = bicommutant(T, S)23proof24simp [bicommutantRing, subringRing, Ring.mk.carrier]2526theorem bicommutantRing.addOf (T S : Set)27shows Ring.add(bicommutantRing(T, S)) =28 restrict(Ring.add(T), bicommutant(T, S) × bicommutant(T, S))29proof30simp [bicommutantRing, subringRing, Ring.mk.add]3132theorem bicommutantRing.zeroOf (T S : Set)33shows Ring.zero(bicommutantRing(T, S)) = Ring.zero(T)34proof35simp [bicommutantRing, subringRing, Ring.mk.zero]3637theorem bicommutantRing.negOf (T S : Set)38shows Ring.neg(bicommutantRing(T, S)) = restrict(Ring.neg(T), bicommutant(T, S))39proof40simp [bicommutantRing, subringRing, Ring.mk.neg]4142theorem bicommutantRing.mulOf (T S : Set)43shows Ring.mul(bicommutantRing(T, S)) =44 restrict(Ring.mul(T), bicommutant(T, S) × bicommutant(T, S))45proof46simp [bicommutantRing, subringRing, Ring.mk.mul]4748theorem bicommutantRing.oneOf (T S : Set)49shows Ring.one(bicommutantRing(T, S)) = Ring.one(T)50proof51simp [bicommutantRing, subringRing, Ring.mk.one]5253-- Multiplication by a negation in a ring that need not commute.54theorem IsRing.mul_neg (A add zero neg mul one x y : Set)55requiresring : IsRing(A, add, zero, neg, mul, one)56requires xInA : x ∈ A57requires yInA : y ∈ A58shows call2(mul, x, neg(y)) = neg(call2(mul, x, y))59proof60have additive := IsRing.additive withring61have group := IsAbelianGroup.group with additive62have monoid := IsGroup.monoid with group63have distributive := IsRing.distributive withring64have negIn := IsRing.neg_closed withring, yInA65have product := IsRing.mul_closed withring, xInA, yInA66have negProduct := IsRing.mul_closed withring, xInA, negIn67have inverseIn := IsRing.neg_closed withring, product68have zeroIn := IsRing.zero_in_carrier withring69have rightLaw := distributive with x, xInA, y, yInA, neg(y), negIn70have leftLaw := distributive with x, xInA, neg(y), negIn, y, yInA71have cancelRight := IsRing.add_inverse_right withring, yInA72have cancelLeft := IsRing.add_inverse_left withring, yInA73have vanish := IsRing.mul_zero withring, xInA74have first : IsInverse(A, add, zero, call2(mul, x, y), call2(mul, x, neg(y)))75have sumRight := rightLaw.left76have sumLeft := leftLaw.left77rw cancelRight at sumRight78rw cancelLeft at sumLeft79unfold IsInverse80refine⟨product, negProduct, ?_, ?_⟩81 . cc82 . cc83have second : IsInverse(A, add, zero, call2(mul, x, y), neg(call2(mul, x, y)))84haveleft:= IsRing.add_inverse_left withring, product85haveright:= IsRing.add_inverse_right withring, product86unfold IsInverse87exact⟨product, inverseIn, left, right⟩88exact IsInverse.unique with monoid, first, second8990theorem restrictBinary.commutative_on (A S op : Set)91requires function : IsMagma(A, op)92requires subset : S ⊆ A93requires closed : ClosedBinary(S, op)94requires law : Commutative(S, op)95shows Commutative(S, restrict(op, S × S))96proof97intros x hx y hy98have first := restrictBinary.value with hx, hy99have second := restrictBinary.value with hy, hx100have original := law with x, hx, y, hy101cc102103-- A subring on which the multiplication commutes is a commutative ring104-- under the restricted operations, whether or not the ambient ring is.105theorem IsSubring.comm_ring_of_commutative (A add zero neg mul one S : Set)106requiresring : IsRing(A, add, zero, neg, mul, one)107requires subring : IsSubring(A, add, zero, neg, mul, one, S)108requires commutative : Commutative(S, mul)109shows IsCommRing(S, restrict(add, S × S), zero, restrict(neg, S),110 restrict(mul, S × S), one)111proof112have subset := IsSubring.subset_carrier with subring113have zeroIn := IsSubring.zero_closed with subring114have oneIn := IsSubring.one_closed with subring115have addClosed := IsSubring.add_closed with subring116have mulClosed := IsSubring.mul_closed with subring117have negClosed := IsSubring.neg_closed with subring118have addition : IsMagma(A, add) bysimp [IsRing, IsAbelianGroup, IsGroup, IsMonoid, IsSemigroup]119have multiplication : IsMagma(A, mul) bysimp [IsRing, IsAbelianGroup, IsGroup, IsMonoid, IsSemigroup]120have addAssoc : Associative(A, add) bysimp [IsRing, IsAbelianGroup, IsGroup, IsMonoid, IsSemigroup]121have mulAssoc : Associative(A, mul) bysimp [IsRing, IsAbelianGroup, IsGroup, IsMonoid, IsSemigroup]122have addComm : Commutative(A, add) bysimp [IsRing, IsAbelianGroup, IsGroup, IsMonoid, IsSemigroup]123have addUnit : Identity(A, add, zero) bysimp [IsRing, IsAbelianGroup, IsGroup, IsMonoid, IsSemigroup]124have mulUnit : Identity(A, mul, one) bysimp [IsRing, IsAbelianGroup, IsGroup, IsMonoid, IsSemigroup]125have inverse : Inverse(A, add, zero, neg) bysimp [IsRing, IsAbelianGroup, IsGroup, IsMonoid, IsSemigroup]126have distribute : Distributive(A, add, mul) bysimp [IsRing, IsAbelianGroup, IsGroup, IsMonoid, IsSemigroup]127have negation : neg : A → A bysimp [Inverse]128have addFunction := restrictBinary.function at A, S, add with*129have mulFunction := restrictBinary.function at A, S, mul with*130have restrictedAdd : IsMagma(S, restrict(add, S × S)) byexact addFunction131have restrictedMul : IsMagma(S, restrict(mul, S × S)) byexact mulFunction132have rAddAssoc := restrictBinary.associative at A, S, add with*133have rMulAssoc := restrictBinary.associative at A, S, mul with*134have rAddComm := restrictBinary.commutative at A, S, add with*135have rMulComm := restrictBinary.commutative_on at A, S, mul with*136have rAddUnit := restrictBinary.identity at A, S, add, zero with*137have rMulUnit := restrictBinary.identity at A, S, mul, one with*138have rInverse := restrictUnary.inverse with*139have rDistribute := restrictBinary.distributive with*140simp [IsCommRing, IsRing, IsAbelianGroup, IsGroup, IsMonoid, IsSemigroup]141142section Centralizers143variable (T S : Set)144hypothesisring : Ring(T)145hypothesis bounded : S ⊆ Ring.carrier(T)146147theorem ringCentralizer.subset148shows ringCentralizer(T, S) ⊆ Ring.carrier(T)149proof150intros z hz151have member := ringCentralizer.membership.forward with hz152exact member.left153154theorem ringCentralizer.commutes (z x : Set)155requires central : z ∈ ringCentralizer(T, S)156requires element : x ∈ S157shows call2(Ring.mul(T), z, x) = call2(Ring.mul(T), x, z)158proof159have member := ringCentralizer.membership.forward with central160exact member.right with x, element161162theorem ringCentralizer.mem (z : Set)163requires element : z ∈ Ring.carrier(T)164requires commutes : ∀ x ∈ S, call2(Ring.mul(T), z, x) = call2(Ring.mul(T), x, z)165shows z ∈ ringCentralizer(T, S)166proof167exact ringCentralizer.membership.backward with⟨element, commutes⟩168169theorem ringCentralizer.subring170shows IsSubring(Ring.carrier(T), Ring.add(T), Ring.zero(T), Ring.neg(T),171 Ring.mul(T), Ring.one(T), ringCentralizer(T, S))172proof173have parts := Ring.parts withring174have subset := ringCentralizer.subset at T, S with*175have monoid := IsRing.multiplicative with parts176have assoc := IsMonoid.associative with monoid177have distributive := IsRing.distributive with parts178have zeroIn : Ring.zero(T) ∈ ringCentralizer(T, S)179have zeroCarrier := IsRing.zero_in_carrier with parts180have commutes : ∀ x ∈ S, call2(Ring.mul(T), Ring.zero(T), x) = call2(Ring.mul(T), x, Ring.zero(T))181intros x hx182have xIn := bounded with x, hx183haveleft:= IsRing.zero_mul with parts, xIn184haveright:= IsRing.mul_zero with parts, xIn185cc186exact ringCentralizer.mem with*187have oneIn : Ring.one(T) ∈ ringCentralizer(T, S)188have oneCarrier := IsMonoid.unit_in_carrier with monoid189have commutes : ∀ x ∈ S, call2(Ring.mul(T), Ring.one(T), x) = call2(Ring.mul(T), x, Ring.one(T))190intros x hx191have xIn := bounded with x, hx192haveleft:= IsMonoid.left_identity with monoid, xIn193haveright:= IsMonoid.right_identity with monoid, xIn194cc195exact ringCentralizer.mem with*196have negClosed : ClosedUnary(ringCentralizer(T, S), Ring.neg(T))197intros z hz198have zIn := subset with z, hz199have negIn := IsRing.neg_closed with parts, zIn200have commutes : ∀ x ∈ S, call2(Ring.mul(T), Ring.neg(T)(z), x) = call2(Ring.mul(T), x, Ring.neg(T)(z))201intros x hx202have xIn := bounded with x, hx203have swap := ringCentralizer.commutes at T, S, z, x with*204haveleft:= IsRing.neg_mul with parts, zIn, xIn205haveright:= IsRing.mul_neg with parts, xIn, zIn206cc207exact ringCentralizer.mem with*208have addClosed : ClosedBinary(ringCentralizer(T, S), Ring.add(T))209intros z hz w hw210have zIn := subset with z, hz211have wIn := subset with w, hw212have sumIn := IsRing.add_closed with parts, zIn, wIn213have commutes : ∀ x ∈ S, call2(Ring.mul(T), call2(Ring.add(T), z, w), x) = call2(Ring.mul(T), x, call2(Ring.add(T), z, w))214intros x hx215have xIn := bounded with x, hx216have swapZ := ringCentralizer.commutes at T, S, z, x with*217have swapW := ringCentralizer.commutes at T, S, w, x with*218haveleft:= distributive with z, zIn, w, wIn, x, xIn219haveright:= distributive with x, xIn, z, zIn, w, wIn220have expandLeft :=left.right221have expandRight :=right.left222cc223exact ringCentralizer.mem with*224have mulClosed : ClosedBinary(ringCentralizer(T, S), Ring.mul(T))225intros z hz w hw226have zIn := subset with z, hz227have wIn := subset with w, hw228have productIn := IsRing.mul_closed with parts, zIn, wIn229have commutes : ∀ x ∈ S, call2(Ring.mul(T), call2(Ring.mul(T), z, w), x) = call2(Ring.mul(T), x, call2(Ring.mul(T), z, w))230intros x hx231have xIn := bounded with x, hx232have swapZ := ringCentralizer.commutes at T, S, z, x with*233have swapW := ringCentralizer.commutes at T, S, w, x with*234have first := assoc with z, zIn, w, wIn, x, xIn235have second := assoc with z, zIn, x, xIn, w, wIn236have third := assoc with x, xIn, z, zIn, w, wIn237cc238exact ringCentralizer.mem with*239unfold IsSubring240exact⟨subset, zeroIn, oneIn, negClosed, addClosed, mulClosed⟩241242theorem bicommutant.subset243shows bicommutant(T, S) ⊆ Ring.carrier(T)244proof245have central := ringCentralizer.subset at T, S with*246unfold bicommutant247exact ringCentralizer.subset at T, ringCentralizer(T, S) with*248249theorem bicommutant.contains250shows S ⊆ bicommutant(T, S)251proof252intros s hs253have sIn := bounded with s, hs254have central := ringCentralizer.subset at T, S with*255have commutes : ∀ c ∈ ringCentralizer(T, S), call2(Ring.mul(T), s, c) = call2(Ring.mul(T), c, s)256intros c hc257have swap := ringCentralizer.commutes at T, S, c, s with*258cc259unfold bicommutant260exact ringCentralizer.mem at T, ringCentralizer(T, S), s with*261262theorem bicommutant.subring263shows IsSubring(Ring.carrier(T), Ring.add(T), Ring.zero(T), Ring.neg(T),264 Ring.mul(T), Ring.one(T), bicommutant(T, S))265proof266have central := ringCentralizer.subset at T, S with*267unfold bicommutant268exact ringCentralizer.subring at T, ringCentralizer(T, S) with*269270-- When the generators commute with each other, the bicommutant commutes.271theorem bicommutant.commutative272requires commuting : S ⊆ ringCentralizer(T, S)273shows Commutative(bicommutant(T, S), Ring.mul(T))274proof275have central := ringCentralizer.subset at T, S with*276have double := bicommutant.subset at T, S with*277intros b hb c hc278have cIn := double with c, hc279unfold bicommutant at hb280unfold bicommutant at hc281have cCentral : c ∈ ringCentralizer(T, S)282have commutes : ∀ s ∈ S, call2(Ring.mul(T), c, s) = call2(Ring.mul(T), s, c)283intros s hs284have sCentral := commuting with s, hs285exact ringCentralizer.commutes at T, ringCentralizer(T, S), c, s with*286exact ringCentralizer.mem at T, S, c with*287exact ringCentralizer.commutes at T, ringCentralizer(T, S), b, c with*288289theorem bicommutantRing.comm_ring290requires commuting : S ⊆ ringCentralizer(T, S)291shows CommRing(bicommutantRing(T, S))292proof293have parts := Ring.parts withring294have subring := bicommutant.subring at T, S with*295have commutative := bicommutant.commutative at T, S with*296have engine := IsSubring.comm_ring_of_commutative with parts, subring, commutative297unfold bicommutantRing298unfold subringRing299exact CommRing.of_parts with engine300301-- A single element commutes with itself, so its bicommutant is a302-- commutative ring containing it.303theorem bicommutant.singleton_commuting (a : Set)304requires element : a ∈ Ring.carrier(T)305shows {a} ⊆ ringCentralizer(T, {a})306proof307intros s hs308have equal := singleton.membership.forward with hs309rw equal310have commutes : ∀ x ∈ {a}, call2(Ring.mul(T), a, x) = call2(Ring.mul(T), x, a)311intros x hx312have same := singleton.membership.forward with hx313rw same314rfl315exact ringCentralizer.mem at T, {a}, a with*316317end Centralizers318