1-- Quotient rings of a bundled ring: the congruence modulo an ideal, the2-- quotient ring R ⧸ I (the value quotientRing(R, I)) on its classes, the ring laws of the3-- quotient, and the classes of sums, products, and negations; everything4-- 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.Quotient11import QuotientCore12import PrimeIdeal1314-- x and y are related modulo I when x - y lies in I.15def quotientRelation (R I : Set) : Set:=16 idealRelation(R.carrier, R.add, R.neg, I)1718-- The quotient ring of R by I: the classes modulo I with the induced19-- operations and the classes of zero and one.20def quotientRing (R I : Set) : Set:=21 Ring.mk((R.carrier ⧸ quotientRelation(R, I)),22 quotientBinary(R.carrier, quotientRelation(R, I), R.add),23 ⟦R.zero⟧[R.carrier, quotientRelation(R, I)],24 quotientUnary(R.carrier, quotientRelation(R, I), R.neg),25 quotientBinary(R.carrier, quotientRelation(R, I), R.mul),26 ⟦R.one⟧[R.carrier, quotientRelation(R, I)])2728-- The quotient is written R ⧸ I wherever R is the ring of a hypothesis in29-- scope; the set quotient A ⧸ r keeps its meaning on every other left30-- operand.31notationinfixl70"⧸"=> quotientRing(R, _) viahypothesis Ring(R) for R32notationinfixl70"⧸"=> quotientRing(R, _) viahypothesis CommRing(R) for R33notationinfixl70"⧸"=> quotientRing(R, _) viahypothesis Ideal(R, I) for R3435theorem quotientRelation.value (R I : Set)36shows quotientRelation(R, I) = idealRelation(R.carrier, R.add, R.neg, I)37proof38simp [quotientRelation]3940theorem quotientRing.carrierOf (R I : Set)41shows Ring.carrier(quotientRing(R, I)) =42 (R.carrier ⧸ quotientRelation(R, I))43proof44simp [quotientRing, Ring.mk.carrier]4546theorem quotientRing.addOf (R I : Set)47shows Ring.add(quotientRing(R, I)) =48 quotientBinary(R.carrier, quotientRelation(R, I), R.add)49proof50simp [quotientRing, Ring.mk.add]5152theorem quotientRing.zeroOf (R I : Set)53shows Ring.zero(quotientRing(R, I)) =54 ⟦R.zero⟧[R.carrier, quotientRelation(R, I)]55proof56simp [quotientRing, Ring.mk.zero]5758theorem quotientRing.negOf (R I : Set)59shows Ring.neg(quotientRing(R, I)) =60 quotientUnary(R.carrier, quotientRelation(R, I), R.neg)61proof62simp [quotientRing, Ring.mk.neg]6364theorem quotientRing.mulOf (R I : Set)65shows Ring.mul(quotientRing(R, I)) =66 quotientBinary(R.carrier, quotientRelation(R, I), R.mul)67proof68simp [quotientRing, Ring.mk.mul]6970theorem quotientRing.oneOf (R I : Set)71shows Ring.one(quotientRing(R, I)) =72 ⟦R.one⟧[R.carrier, quotientRelation(R, I)]73proof74simp [quotientRing, Ring.mk.one]7576section QuotientRings77variable (R I : Set)78hypothesis comm : CommRing(R)79hypothesis ideal : Ideal(R, I)8081theorem quotientRelation.relates (x y : R)82shows relates(quotientRelation(R, I), x, y) ↔ x - y ∈ I83proof84have xIn : x ∈ R byassumption85have yIn : y ∈ R byassumption86have criterion := idealRelation.relates at R.carrier, R.add, R.neg, I, x, y87with xIn, yIn88rw [quotientRelation.value, Ring.sub.value]89constructor90 . intro related91have same := criterion.forward with related92unfold Congruent at same93exact same94 . intro member95have same : Congruent(R.add, R.neg, I, x, y)96unfold Congruent97exact member98exact criterion.backward with same99100theorem quotientRelation.equivalence101shows Equivalence(R.carrier, quotientRelation(R, I))102proof103have parts := CommRing.parts with comm104have idealParts := Ideal.parts with ideal105rw quotientRelation.value106exact idealRelation.equivalence with parts, idealParts107108-- The quotient is a commutative ring.109theorem quotientRing.comm_ring110shows CommRing(R ⧸ I)111proof112have parts := CommRing.parts with comm113have idealParts := Ideal.parts with ideal114have engine := idealQuotient.comm_ring with parts, idealParts115unfold quotientRing116apply CommRing.of_parts117rw quotientRelation.value118exact engine119120instance quotientRing.class_mem (x : R)121shows ⟦x⟧[R.carrier, quotientRelation(R, I)] ∈122 Ring.carrier(R ⧸ I)123proof124have equivalence := quotientRelation.equivalence with comm, ideal125rw quotientRing.carrierOf126exact quotient.contains_class with equivalence, *127128theorem quotientRing.representative (X : Set)129requires hX : X ∈ Ring.carrier(R ⧸ I)130shows∃ x ∈ R, X = ⟦x⟧[R.carrier, quotientRelation(R, I)]131proof132rw quotientRing.carrierOf at hX133exact quotient.representative with hX134135-- Two classes are equal exactly when the difference of representatives136-- lies in the ideal; a class is zero exactly when its representative does.137theorem quotientRing.class_eq_iff (x y : R)138shows ⟦x⟧[R.carrier, quotientRelation(R, I)] =139 ⟦y⟧[R.carrier, quotientRelation(R, I)] ↔ x - y ∈ I140proof141have parts := CommRing.parts with comm142have idealParts := Ideal.parts with ideal143have xIn : x ∈ R byassumption144have yIn : y ∈ R byassumption145have criterion := idealClass.eq_iff_congruent with parts, idealParts, xIn, yIn146rw [quotientRelation.value, Ring.sub.value]147constructor148 . intro equal149have same := criterion.forward with equal150unfold Congruent at same151exact same152 . intro member153have same : Congruent(R.add, R.neg, I, x, y)154unfold Congruent155exact member156exact criterion.backward with same157158theorem quotientRing.class_eq_zero_iff (x : R)159shows ⟦x⟧[R.carrier, quotientRelation(R, I)] =160 ⟦R[0]⟧[R.carrier, quotientRelation(R, I)] ↔ x ∈ I161proof162have parts := CommRing.parts with comm163have idealParts := Ideal.parts with ideal164have xIn : x ∈ R byassumption165rw quotientRelation.value166exact idealClass.eq_zero with parts, idealParts, xIn167168-- The operations on classes are the classes of the operations.169theorem quotientRing.add_class (x y : R)170shows Ring.add(R ⧸ I)(⟦x⟧[R.carrier, quotientRelation(R, I)],171 ⟦y⟧[R.carrier, quotientRelation(R, I)]) =172 ⟦x + y⟧[R.carrier, quotientRelation(R, I)]173proof174have parts := CommRing.parts with comm175have idealParts := Ideal.parts with ideal176have equivalence := quotientRelation.equivalence with comm, ideal177have compatible := idealRelation.add_compatible with parts, idealParts178have magma : IsMagma(R.carrier, R.add) := IsGroup.magma with179 (IsAbelianGroup.group with (IsRing.additive with (IsCommRing.ring with parts)))180rw [quotientRing.addOf, quotientRelation.value]181rw quotientRelation.value at equivalence182exact quotientBinary.classes with equivalence, magma, compatible, *183184theorem quotientRing.mul_class (x y : R)185shows Ring.mul(R ⧸ I)(⟦x⟧[R.carrier, quotientRelation(R, I)],186 ⟦y⟧[R.carrier, quotientRelation(R, I)]) =187 ⟦x * y⟧[R.carrier, quotientRelation(R, I)]188proof189have parts := CommRing.parts with comm190have idealParts := Ideal.parts with ideal191have equivalence := quotientRelation.equivalence with comm, ideal192have compatible := idealRelation.mul_compatible with parts, idealParts193have monoid := IsRing.multiplicative with (IsCommRing.ring with parts)194have magma : IsMagma(R.carrier, R.mul) := IsSemigroup.magma with195 (IsMonoid.semigroup with monoid)196rw [quotientRing.mulOf, quotientRelation.value]197rw quotientRelation.value at equivalence198exact quotientBinary.classes with equivalence, magma, compatible, *199200theorem quotientRing.neg_class (x : R)201shows Ring.neg(R ⧸ I)(⟦x⟧[R.carrier, quotientRelation(R, I)])202= ⟦-x⟧[R.carrier, quotientRelation(R, I)]203proof204have parts := CommRing.parts with comm205have idealParts := Ideal.parts with ideal206have equivalence := quotientRelation.equivalence with comm, ideal207have compatible := idealRelation.neg_compatible with parts, idealParts208obtain⟨negF, inverses⟩:= IsGroup.inverse with209 (IsAbelianGroup.group with (IsRing.additive with (IsCommRing.ring with parts)))210rw [quotientRing.negOf, quotientRelation.value]211rw quotientRelation.value at equivalence212exact quotientUnary.classes with equivalence, negF, compatible, *213214end QuotientRings215