Ask Your Question

construction of product rings Z/nZ x Z/mZ

asked 2013-07-11 11:46:09 -0500

jack77 gravatar image


is it possible in Sage to construct a product ring of two integer modulo rings?

When just creating an cartesian_product, it is for example not possible to add its elements:

elem=CR((3,2)) # ok, element construction
elem*elem # ok
elem+elem # fails 
CR.list() #  not implemented
CR.list_of_elements_of_multiplicative_group # not implemented
edit retag flag offensive close merge delete


Good question! I need this myself.

Stefan gravatar imageStefan ( 2013-08-29 04:32:42 -0500 )edit

3 answers

Sort by ยป oldest newest most voted

answered 2013-09-12 12:13:28 -0500

Stefan gravatar image

The code below (following this tutorial) seems to do the trick. I might turn it into an addition to the Sage codebase at some point (it needs documentation and tests for that, at the very least), but I don't have the time. If you feel like doing that, be my guest!

Just save to and, in Sage do sage: %runfile # from command line


load # from notebook.

import sage
from sage.rings.ring import Ring
from sage.rings.all import ZZ
from sage.structure.element import RingElement
from sage.categories.category import Category
from sage.structure.unique_representation import UniqueRepresentation
from sage.categories.rings import Rings
from sage.categories.pushout import ConstructionFunctor

class ProductRingElement(RingElement):
    def __init__(self, data, parent=None):
        if parent is None:
            raise ValueError, "The parent must be provided"
        self._data = tuple(data)

    def _repr_(self):
        return "(" + ", ".join(x._repr_() for x in self._data) + ")"

    def __cmp__(self, other):
        return cmp(self._data, other._data)

    def _add_(self, other):
        C = self.__class__
        z = zip(self._data, other._data)
        return C(tuple(zz[0]._add_(zz[1]) for zz in z), parent=self.parent())

    def _sub_(self, other):
        C = self.__class__
        z = zip(self._data, other._data)
        return C(tuple(zz[0]._sub_(zz[1]) for zz in z), parent=self.parent())

    def _mul_(self, other):
        C = self.__class__
        z = zip(self._data, other._data)
        return C(tuple(zz[0]._mul_(zz[1]) for zz in z), parent=self.parent())

    def _div_(self, other):
        C = self.__class__
        z = zip(self._data, other._data)
        return C(tuple(zz[0]._div_(zz[1]) for zz in z), parent=self.parent())

    def __iter__(self):
        Returns an iterator of the entries of ``self``.
        for x in self._data:
            yield x

class ProductRing(UniqueRepresentation, Ring):
    The product ring of a finite number of rings, with elementwise addition
    and multiplication.
    Element = ProductRingElement

    def __init__(self,rings, base=ZZ, category=None):

        - ``rings`` -- a tuple of rings.
        from sage.categories.rings import Rings

        if not all(R.is_ring() for R in rings):
            raise TypeError("Expected a tuple of rings as input.")
        self._rings = tuple(rings)
        Ring.__init__(self, base=base, category=category or Rings())

    def _repr_(self):
        return "Product ring: (" + ", ".join(R._repr_() for R in self._rings) + ")"

    def _element_constructor_(self, *args, **kwds):
        if len(args) == len(self._rings):
            z = zip(self._rings, args)
        elif len(args) == 1:
                if len(args[0]) != len(self._rings):
                    raise TypeError  # also if args[0] has no len()
                z = zip(self._rings, args[0])
            except TypeError:
                z = zip(self._rings, [args[0] for x in self._rings])
            raise TypeError("Wrong number of ring elements")
        return self.element_class(tuple(zz[0](zz[1]) for zz in z), parent=self, **kwds)

    def _coerce_map_from_(self, S):
        if all(R.has_coerce_map_from(S) for R in self._rings):
            return True

    def __pow__(self,n):
        Returns the ``n``-th power of self as a vector space.
        from sage.modules ...
edit flag offensive delete link more

answered 2013-07-11 12:16:58 -0500

kcrisman gravatar image

Here is part of the problem - the Cartesian product business seems to be about categories, not the actual rings. And it doesn't really give you what you want. In fact, I find this all somewhat disturbing.

sage: type(CR)
sage: type(R5)
sage: elem*elem
(9, 4)
sage: elem.summand_projection(1)
sage: type(elem.summand_projection(1))

You can do it with just the groups, but of course that's not what you want.

edit flag offensive delete link more


'You can do it with just the groups' - you mean using summand_projection? 'of course that's not what you want' - yes, I would like something more comfortable

jack77 gravatar imagejack77 ( 2013-07-11 22:18:09 -0500 )edit

answered 2013-07-11 12:17:28 -0500

tmonteil gravatar image

It seems that CR forgot its ring structure, and kept only its multiplicative operation:

sage: elem.parent().category()
Category of Cartesian products of monoids
edit flag offensive delete link more


Right... but the question is what went wrong?

kcrisman gravatar imagekcrisman ( 2013-07-11 13:01:31 -0500 )edit

Well, the question is, is there a way to construct the product ring Z/nZ x Z/mZ in sage

jack77 gravatar imagejack77 ( 2013-07-11 22:13:28 -0500 )edit

I do not know, i asked to the `sage.categories` specialists.

tmonteil gravatar imagetmonteil ( 2013-07-12 02:54:54 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools


Asked: 2013-07-11 11:46:09 -0500

Seen: 629 times

Last updated: Sep 12 '13