The type [QuotientRing] is used to represent rings constructed explicitly as quotients (of a ring by an ideal).
Beyond the usual functions offered by a ring, there are the following functions
QuotientRing NewQuotientRing(const ring& R, const ideal& I); QuotientRing NewZmod(const RingZ& Z, int n); QuotientRing NewZmod(const RingZ& Z, const ZZ& n); bool IsQuotientRing(const ring& R); const ring& BaseRing(const QuotientRing& RmodI); const ideal& DefiningIdeal(const QuotientRing& RmodI); const RingHom& QuotientingHom(const QuotientRing& RmodI); RingHom NewInducedHom(const QuotientRing& RmodI, const RingHom& phi); RingElem CanonRepr(const RingElem& r); // given x in R/I produces X in R s.t. QuotientingHom(X)=x
NewQuotientRing(R, I)
creates a new ring representing the quotient R/I.
I must be an ideal of R; odd things may happen if I=R. If I is zero
then the result is isomorphic to R but not equal to R; arithmetic in R
is more efficient than arithmetic in R/ideal(0).
NewZmod(Z, n)
creates a new ring representing the quotient Z/ideal(n)
where Z must be the ring of integers (see RingZ
).
A CoCoALib error will be thrown if n=1 or n=-1. Currently an error will
be thrown also if n=0 (see BUGS).
IsQuotientRing(R)
returns true iff R is implemented as a QuotientRing
QuotientRing(R)
returns a QuotientRing identical to the ring R if
R is implemented as a QuotientRing, otherwise throws ERR::NotQuotientRing.
BaseRing(RmodI)
returns a reference to the base ring of RmodI;
if RmodI represents the quotient R/I then BaseRing(RmodI) gives R.
DefiningIdeal(RmodI)
returns a reference to the ideal used to create
the QuotientRing RmodI; if RmodI represents R/I then
DefiningIdeal(RmodI) gives I (an ideal of the ring R).
QuotientingHom(RmodI)
returns a reference to the quotienting homomorphism
from R to RmodI where RmodI is a QuotientRing representing R/I.
NewInducedHom(RmodI, phi)
creates a new ring homomorphism from RmodI to
S where phi is a ring homomorphism from R to S, and where RmodI is a
QuotientRing representing R/I. Two types of error may occur:
ERR::BadInducingHom
if domain(phi) is not BaseRing(RmodI)
ERR::BadInducingHomKer
if phi does not map the gens of I to zero.
CanonRepr(r)
where r is a RingElem belonging to a QuotientRing RmodI produces
a RingElem belonging to BaseRing(RmodI) whose image under QuotientingHom(RmodI)
is r. For instance, if r = -3 in Z/(10) then CanonRepr(r) could give 7
as an element of Z.
Extended example of use:
RingZ Z = NewRingZ(); // a copy of the ring of integers ring Zmod10 = NewZmod(Z, 10); // represents Z/(10) integers modulo 10 ring Zmod10a = NewQuotientRing(Z, ideal(Z, 10)); // same as Zmod10 RingHom phi = QuotientingHom(Zmod10); // ring hom from Z to Zmod10 RingElem r(Zmod10, -3); // an element of Zmod10 RingElem preimage = CanonRepr(r); // an element of Z = BaseRing(Zmod10) ring S = NewZmod(2); // another ring S, details do not matter much RingHom theta = QuotientingHom(S); // any ring hom from Z to S will do instead RingHom theta_bar = NewInducedHom(Zmod10, theta); // induced ring hom from Zmod10 to S
While considering the design of this code it may help to keep in mind these two canonical implementations:
GeneralQuotientRingImpl
RingFpImpl
QuotientRingBase
is an abstract class derived from RingBase, and is the
base class for all quotient rings. It adds the following four new pure
virtual member functions which must be defined in every concrete
quotient ring:
virtual RingElem myCanonRepr(ConstRawValue r) const; virtual void myReduction(RawValue& image, ConstRawValue arg) const; virtual const RingHom& myQuotientingHom() const; virtual RingHom myInducedHomCtor(const RingHom& InducingHom) const;
The member function myCanonRepr has to return a copy of the value since we cannot be sure that the internal representation is compatible with the internal representation of elements of the base ring.
IamGCDDomain always returns false. We can be clever in some easy cases, but it is hard in general (think of rings of algebraic integers which are gcd domains, but not euclidean domains).
Should NewZmod(Z, n) allow the case n==0? There's no mathematical reason to forbid it, but forbidding it may help detect programmer errors more quickly -- it seems unlikely that one would really want to quotient by ideal(0).
FAIRLY SERIOUS CONFUSION: the code seems to make REPEATED sanity checks see
QuotientRingBase::QuotientRingBase NewQuotientRing QuotientRingHomBase::QuotientRingHomBase NewInducedHom
I suspect that the C++ ctors should use CoCoA_ASSERT instead of checking always (and throwing an exception).
FURTHER SERIOUS CONFUSION: there is ambiguity about the difference between myBaseRing and myReprRing esp. for creating induced homomorphisms: given ring R, and ring S = R/I, create ring T = S/J An induced hom from T should start from a hom with domain S; or is it reasonable to accept a hom with domain R? In this case for T myReprRing is R but myBaseRing is S.
Given a RingHom from a QuotientRing it is not generally possible to obtain a reference to an "inducing hom": consider the hom from Z/(2) to Z/(2)[x] created by CoeffEmbeddingHom. A RingHom equivalent to the inducing hom can be produced by composing QuotientingHom with the given hom.
20 March 2004: I have added the possibility of making a trivial ring by quotienting: previously this was disallowed for no good reason that I could discern.