Пример #1
0
    def create_key_and_extra_args(self, X, Y, category=None, base=ZZ,
                                  check=True):
        """
        Create a key that uniquely determines the Hom-set.
        
        INPUT:
        
        - ``X`` -- a scheme. The domain of the morphisms.
        
        - ``Y`` -- a scheme. The codomain of the morphisms.
        
        - ``category`` -- a category for the Hom-sets (default: schemes over
          given base).

        - ``base`` -- a scheme or a ring. The base scheme of domain
          and codomain schemes. If a ring is specified, the spectrum
          of that ring will be used as base scheme.

        - ``check`` -- boolean (default: ``True``).

        EXAMPLES::
        
            sage: A2 = AffineSpace(QQ,2)
            sage: A3 = AffineSpace(QQ,3)
            sage: A3.Hom(A2)    # indirect doctest
            Set of morphisms
              From: Affine Space of dimension 3 over Rational Field
              To:   Affine Space of dimension 2 over Rational Field
            sage: from sage.schemes.generic.homset import SchemeHomsetFactory
            sage: SHOMfactory = SchemeHomsetFactory('test')
            sage: key, extra = SHOMfactory.create_key_and_extra_args(A3,A2,check=False)
            sage: key
            (..., ..., Category of schemes over Integer Ring)
            sage: extra
            {'Y': Affine Space of dimension 2 over Rational Field,
             'X': Affine Space of dimension 3 over Rational Field,
             'base_ring': Integer Ring, 'check': False}
        """
        if not is_Scheme(X) and is_CommutativeRing(X): 
            X = Spec(X)
        if not is_Scheme(Y) and is_CommutativeRing(Y): 
            Y = Spec(Y)
        if is_Spec(base):
            base_spec = base
            base_ring = base.coordinate_ring()
        elif is_CommutativeRing(base): 
            base_spec = Spec(base)
            base_ring = base
        else:
            raise ValueError(
                        'The base must be a commutative ring or its spectrum.')
        if not category:
            from sage.categories.schemes import Schemes
            category = Schemes(base_spec)
        key = tuple([id(X), id(Y), category])
        extra = {'X':X, 'Y':Y, 'base_ring':base_ring, 'check':check}
        return key, extra
Пример #2
0
    def create_key_and_extra_args(self, X, Y, category=None, base=ZZ,
                                  check=True):
        """
        Create a key that uniquely determines the Hom-set.
        
        INPUT:
        
        - ``X`` -- a scheme. The domain of the morphisms.
        
        - ``Y`` -- a scheme. The codomain of the morphisms.
        
        - ``category`` -- a category for the Hom-sets (default: schemes over
          given base).

        - ``base`` -- a scheme or a ring. The base scheme of domain
          and codomain schemes. If a ring is specified, the spectrum
          of that ring will be used as base scheme.

        - ``check`` -- boolean (default: ``True``).

        EXAMPLES::
        
            sage: A2 = AffineSpace(QQ,2)
            sage: A3 = AffineSpace(QQ,3)
            sage: A3.Hom(A2)    # indirect doctest
            Set of morphisms
              From: Affine Space of dimension 3 over Rational Field
              To:   Affine Space of dimension 2 over Rational Field
            sage: from sage.schemes.generic.homset import SchemeHomsetFactory
            sage: SHOMfactory = SchemeHomsetFactory('test')
            sage: key, extra = SHOMfactory.create_key_and_extra_args(A3,A2,check=False)
            sage: key
            (..., ..., Category of schemes over Integer Ring)
            sage: extra
            {'Y': Affine Space of dimension 2 over Rational Field,
             'X': Affine Space of dimension 3 over Rational Field,
             'base_ring': Integer Ring, 'check': False}
        """
        if not is_Scheme(X) and is_CommutativeRing(X): 
            X = Spec(X)
        if not is_Scheme(Y) and is_CommutativeRing(Y): 
            Y = Spec(Y)
        if is_Spec(base):
            base_spec = base
            base_ring = base.coordinate_ring()
        elif is_CommutativeRing(base): 
            base_spec = Spec(base)
            base_ring = base
        else:
            raise ValueError(
                        'The base must be a commutative ring or its spectrum.')
        if not category:
            from sage.categories.schemes import Schemes
            category = Schemes(base_spec)
        key = tuple([id(X), id(Y), category])
        extra = {'X':X, 'Y':Y, 'base_ring':base_ring, 'check':check}
        return key, extra
Пример #3
0
    def _call_(self, x):
        """
        Construct a scheme from the data in ``x``

        EXAMPLES:

        Let us first construct the category of schemes::

            sage: S = Schemes(); S
            Category of Schemes

        We create a scheme from a ring::

            sage: X = S(ZZ); X                  # indirect doctest
            Spectrum of Integer Ring

        We create a scheme from a scheme (do nothing)::

            sage: S(X)
            Spectrum of Integer Ring

        We create a scheme morphism from a ring homomorphism.x::
\
            sage: phi = ZZ.hom(QQ); phi
            Ring Coercion morphism:
              From: Integer Ring
              To:   Rational Field
            sage: f = S(phi); f                 # indirect doctest
            Affine Scheme morphism:
              From: Spectrum of Rational Field
              To:   Spectrum of Integer Ring
              Defn: Ring Coercion morphism:
                      From: Integer Ring
                      To:   Rational Field

            sage: f.domain()
            Spectrum of Rational Field
            sage: f.codomain()
            Spectrum of Integer Ring
            sage: S(f)                          # indirect doctest
            Affine Scheme morphism:
              From: Spectrum of Rational Field
              To:   Spectrum of Integer Ring
              Defn: Ring Coercion morphism:
                      From: Integer Ring
                      To:   Rational Field

        """
        from sage.rings.all import is_CommutativeRing, is_RingHomomorphism
        from sage.schemes.all import is_Scheme, Spec, is_SchemeMorphism
        if is_Scheme(x) or is_SchemeMorphism(x):
            return x
        elif is_CommutativeRing(x):
            return Spec(x)
        elif is_RingHomomorphism(x):
            A = Spec(x.codomain())
            return A.hom(x)
        else:
            raise TypeError, "No way to create an object or morphism in %s from %s"%(self, x)
Пример #4
0
 def __init__(self,
              group = arithgroup.Gamma0(1),
              weight = 2,
              sign = 0,
              base_ring = rings.QQ,
              character = None):
     """
     Space of boundary symbols for a congruence subgroup of SL_2(Z).
     
     This class is an abstract base class, so only derived classes
     should be instantiated.
     
     INPUT:
     
     
     -  ``weight`` - int, the weight
     
     -  ``group`` - arithgroup.congroup_generic.CongruenceSubgroup, a congruence
        subgroup.
     
     -  ``sign`` - int, either -1, 0, or 1
     
     -  ``base_ring`` - rings.Ring (defaults to the
        rational numbers)
     
     
     EXAMPLES::
     
         sage: B = ModularSymbols(Gamma0(11),2).boundary_space()
         sage: isinstance(B, sage.modular.modsym.boundary.BoundarySpace)
         True
         sage: B == loads(dumps(B))
         True
     """
     weight = int(weight)
     if weight <= 1:
         raise ArithmeticError, "weight must be at least 2"
     if not arithgroup.is_CongruenceSubgroup(group):
         raise TypeError, "group must be a congruence subgroup"
     sign = int(sign)
     if not isinstance(base_ring, rings.Ring) and rings.is_CommutativeRing(base_ring):
         raise TypeError, "base_ring must be a commutative ring"
     if character == None and arithgroup.is_Gamma0(group):
         character = dirichlet.TrivialCharacter(group.level(), base_ring)
     (self.__group, self.__weight, self.__character,
       self.__sign, self.__base_ring) = (group, weight,
                                          character, sign, base_ring)
     self._known_gens = []
     self._known_gens_repr = []
     self._is_zero = []
     hecke.HeckeModule_generic.__init__(self, base_ring, group.level())
Пример #5
0
def canonical_parameters(group, weight, sign, base_ring):
    """
    Return the canonically normalized parameters associated to a choice
    of group, weight, sign, and base_ring. That is, normalize each of
    these to be of the correct type, perform all appropriate type
    checking, etc.
    
    EXAMPLES::
    
        sage: p1 = sage.modular.modsym.modsym.canonical_parameters(5,int(2),1,QQ) ; p1
        (Congruence Subgroup Gamma0(5), 2, 1, Rational Field)
        sage: p2 = sage.modular.modsym.modsym.canonical_parameters(Gamma0(5),2,1,QQ) ; p2
        (Congruence Subgroup Gamma0(5), 2, 1, Rational Field)
        sage: p1 == p2
        True
        sage: type(p1[1])
        <type 'sage.rings.integer.Integer'>
    """
    sign = rings.Integer(sign)
    if not (sign in [-1, 0, 1]):
        raise ValueError, "sign must be -1, 0, or 1"

    weight = rings.Integer(weight)
    if weight <= 1:
        raise ValueError, "the weight must be at least 2"

    if isinstance(group, (int, rings.Integer)):
        group = arithgroup.Gamma0(group)

    elif isinstance(group, dirichlet.DirichletCharacter):
        try:
            eps = group.minimize_base_ring()
        except NotImplementedError:
            # TODO -- implement minimize_base_ring over finite fields
            eps = group
        G = eps.parent()
        if eps.is_trivial():
            group = arithgroup.Gamma0(eps.modulus())
        else:
            group = (eps, G)
        if base_ring is None: base_ring = eps.base_ring()

    if base_ring is None: base_ring = rational_field.RationalField()

    if not rings.is_CommutativeRing(base_ring):
        raise TypeError, "base_ring (=%s) must be a commutative ring" % base_ring

    if not base_ring.is_field():
        raise TypeError, "(currently) base_ring (=%s) must be a field" % base_ring

    return group, weight, sign, base_ring
Пример #6
0
def canonical_parameters(group, weight, sign, base_ring):
    """
    Return the canonically normalized parameters associated to a choice
    of group, weight, sign, and base_ring. That is, normalize each of
    these to be of the correct type, perform all appropriate type
    checking, etc.

    EXAMPLES::

        sage: p1 = sage.modular.modsym.modsym.canonical_parameters(5,int(2),1,QQ) ; p1
        (Congruence Subgroup Gamma0(5), 2, 1, Rational Field)
        sage: p2 = sage.modular.modsym.modsym.canonical_parameters(Gamma0(5),2,1,QQ) ; p2
        (Congruence Subgroup Gamma0(5), 2, 1, Rational Field)
        sage: p1 == p2
        True
        sage: type(p1[1])
        <type 'sage.rings.integer.Integer'>
    """
    sign = rings.Integer(sign)
    if not (sign in [-1,0,1]):
        raise ValueError, "sign must be -1, 0, or 1"

    weight = rings.Integer(weight)
    if weight <= 1:
        raise ValueError, "the weight must be at least 2"

    if isinstance(group, (int, rings.Integer)):
        group = arithgroup.Gamma0(group)

    elif isinstance(group, dirichlet.DirichletCharacter):
        try:
            eps = group.minimize_base_ring()
        except NotImplementedError:
        # TODO -- implement minimize_base_ring over finite fields
            eps = group
        G = eps.parent()
        if eps.is_trivial():
            group = arithgroup.Gamma0(eps.modulus())
        else:
            group = (eps, G)
        if base_ring is None: base_ring = eps.base_ring()

    if base_ring is None: base_ring = rational_field.RationalField()

    if not rings.is_CommutativeRing(base_ring):
        raise TypeError, "base_ring (=%s) must be a commutative ring"%base_ring

    if not base_ring.is_field():
        raise TypeError, "(currently) base_ring (=%s) must be a field"%base_ring

    return group, weight, sign, base_ring
Пример #7
0
    def __init__(self,
                 group = arithgroup.Gamma0(1),
                 weight = 2,
                 sign = 0,
                 base_ring = rings.QQ,
                 character = None):
        """
        Space of boundary symbols for a congruence subgroup of SL_2(Z).

        This class is an abstract base class, so only derived classes
        should be instantiated.

        INPUT:


        -  ``weight`` - int, the weight

        -  ``group`` - arithgroup.congroup_generic.CongruenceSubgroup, a congruence
           subgroup.

        -  ``sign`` - int, either -1, 0, or 1

        -  ``base_ring`` - rings.Ring (defaults to the
           rational numbers)


        EXAMPLES::

            sage: B = ModularSymbols(Gamma0(11),2).boundary_space()
            sage: isinstance(B, sage.modular.modsym.boundary.BoundarySpace)
            True
            sage: B == loads(dumps(B))
            True
        """
        weight = int(weight)
        if weight <= 1:
            raise ArithmeticError("weight must be at least 2")
        if not arithgroup.is_CongruenceSubgroup(group):
            raise TypeError("group must be a congruence subgroup")
        sign = int(sign)
        if not isinstance(base_ring, rings.Ring) and rings.is_CommutativeRing(base_ring):
            raise TypeError("base_ring must be a commutative ring")
        if character is None and arithgroup.is_Gamma0(group):
            character = dirichlet.TrivialCharacter(group.level(), base_ring)
        (self.__group, self.__weight, self.__character,
          self.__sign, self.__base_ring) = (group, weight,
                                             character, sign, base_ring)
        self._known_gens = []
        self._known_gens_repr = []
        self._is_zero = []
        hecke.HeckeModule_generic.__init__(self, base_ring, group.level())
Пример #8
0
    def __init__(self, n, R=ZZ):
        """
        TEST::

            sage: from sage.schemes.generic.ambient_space import AmbientSpace
            sage: A = AmbientSpace(5, ZZ)
            sage: TestSuite(A).run() # not tested (abstract scheme with no elements?)
        """
        if not is_CommutativeRing(R):
            raise TypeError, "R (=%s) must be a commutative ring"%R
        n = Integer(n)
        if n < 0:
            raise ValueError, "n (=%s) must be nonnegative"%n
        self._dimension_relative = n
        Scheme.__init__(self, R)
Пример #9
0
    def __init__(self, n, R=ZZ):
        """
        TEST::

            sage: from sage.schemes.generic.ambient_space import AmbientSpace
            sage: A = AmbientSpace(5, ZZ)
            sage: TestSuite(A).run() # not tested (abstract scheme with no elements?)
        """
        if not is_CommutativeRing(R):
            raise TypeError, "R (=%s) must be a commutative ring" % R
        n = Integer(n)
        if n < 0:
            raise ValueError, "n (=%s) must be nonnegative" % n
        self._dimension_relative = n
        Scheme.__init__(self, R)
Пример #10
0
    def __init__(self, X=None, category=None):
        """
        Construct a scheme.

        TESTS::
        
            sage: R.<x, y> = QQ[]
            sage: I = (x^2 - y^2)*R
            sage: RmodI = R.quotient(I)
            sage: X = Spec(RmodI)
            sage: TestSuite(X).run(skip = ["_test_an_element", "_test_elements", 
            ...                            "_test_some_elements", "_test_category"]) # See #7946
        """
        from sage.schemes.generic.spec import is_Spec
        from sage.schemes.generic.morphism import is_SchemeMorphism

        if X is None:
            try:
                from sage.schemes.generic.spec import SpecZ
                self._base_scheme = SpecZ
            except ImportError:  # we are currently constructing SpecZ
                self._base_ring = ZZ
        elif is_Scheme(X):
            self._base_scheme = X
        elif is_SchemeMorphism(X):
            self._base_morphism = X
        elif is_CommutativeRing(X):
            self._base_ring = X
        elif is_RingHomomorphism(X):
            self._base_ring = X.codomain()
        else:
            raise ValueError('The base must be define by a scheme, '
                             'scheme morphism, or commutative ring.')
        
        from sage.categories.schemes import Schemes
        if not X:
            default_category = Schemes()
        else:
            default_category = Schemes(self.base_scheme())
        if category is None:
            category = default_category
        else:
            assert category.is_subcategory(default_category), \
                "%s is not a subcategory of %s"%(category, default_category)

        Parent.__init__(self, self.base_ring(), category = category)
Пример #11
0
    def __init__(self, X=None, category=None):
        """
        Construct a scheme.

        TESTS::

            sage: R.<x, y> = QQ[]
            sage: I = (x^2 - y^2)*R
            sage: RmodI = R.quotient(I)
            sage: X = Spec(RmodI)
            sage: TestSuite(X).run(skip = ["_test_an_element", "_test_elements",
            ...                            "_test_some_elements", "_test_category"]) # See #7946
        """
        from sage.schemes.generic.spec import is_Spec
        from sage.schemes.generic.morphism import is_SchemeMorphism

        if X is None:
            try:
                from sage.schemes.generic.spec import SpecZ
                self._base_scheme = SpecZ
            except ImportError:  # we are currently constructing SpecZ
                self._base_ring = ZZ
        elif is_Scheme(X):
            self._base_scheme = X
        elif is_SchemeMorphism(X):
            self._base_morphism = X
        elif is_CommutativeRing(X):
            self._base_ring = X
        elif is_RingHomomorphism(X):
            self._base_ring = X.codomain()
        else:
            raise ValueError('The base must be define by a scheme, '
                             'scheme morphism, or commutative ring.')

        from sage.categories.schemes import Schemes
        if not X:
            default_category = Schemes()
        else:
            default_category = Schemes(self.base_scheme())
        if category is None:
            category = default_category
        else:
            assert category.is_subcategory(default_category), \
                "%s is not a subcategory of %s"%(category, default_category)

        Parent.__init__(self, self.base_ring(), category=category)
Пример #12
0
    def __init__(self, n, R=ZZ):
        """
        TEST::

            sage: from sage.schemes.generic.ambient_space import AmbientSpace
            sage: A = AmbientSpace(5, ZZ)
            sage: TestSuite(A).run() # not tested (abstract scheme with no elements?)
        """
        if not is_CommutativeRing(R):
            raise TypeError, "R (=%s) must be a commutative ring" % R
        n = Integer(n)
        if n < 0:
            raise ValueError, "n (=%s) must be nonnegative" % n
        self.__n = n
        self._base_ring = R
        # NT: this seems to set improperly self._base_scheme to X instead of Spec(X)????
        # scheme.Scheme.__init__(self, R)
        # This should be cleaned up by someone who knows about schemes (not me!)
        from sage.categories.schemes import Schemes
        Parent.__init__(self, R, category=Schemes(self.base_scheme()))
Пример #13
0
    def base_extend(self, R):
        """
        Return the natural extension of ``self`` over ``R``.
        
        INPUT:
        
        - ``R`` -- a commutative ring, such that there is a natural map from
          the base ring of self to ``R``.
        
        OUTPUT:
        
        - an ambient space over ``R`` of the same structure as ``self``.

        .. NOTE::
        
            A ``ValueError`` is raised if there is no such natural map. If
            you need to drop this condition, use ``self.change_ring(R)``.
        
        EXAMPLES::

            sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)
            sage: PQ = P.base_extend(QQ); PQ
            Projective Space of dimension 2 over Rational Field
            sage: PQ.base_extend(GF(5))
            Traceback (most recent call last):
            ...
            ValueError: no natural map from the base ring (=Rational Field)
            to R (=Finite Field of size 5)!
        """
        if is_CommutativeRing(R):
            if self.base_ring() == R:
                return self
            if not R.has_coerce_map_from(self.base_ring()):
                raise ValueError(
                    "no natural map from the base ring (=%s) to R (=%s)!"
                    % (self.base_ring(), R))
            return self.change_ring(R)
        else:
            raise NotImplementedError(
                        "extension of spaces over %s to %s is not implemented!"
                        % (self.base_ring(), R))
Пример #14
0
    def base_extend(self, R):
        """
        Return the natural extension of ``self`` over ``R``.
        
        INPUT:
        
        - ``R`` -- a commutative ring, such that there is a natural map from
          the base ring of self to ``R``.
        
        OUTPUT:
        
        - an ambient space over ``R`` of the same structure as ``self``.

        .. NOTE::
        
            A ``ValueError`` is raised if there is no such natural map. If
            you need to drop this condition, use ``self.change_ring(R)``.
        
        EXAMPLES::

            sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)
            sage: PQ = P.base_extend(QQ); PQ
            Projective Space of dimension 2 over Rational Field
            sage: PQ.base_extend(GF(5))
            Traceback (most recent call last):
            ...
            ValueError: no natural map from the base ring (=Rational Field)
            to R (=Finite Field of size 5)!
        """
        if is_CommutativeRing(R):
            if self.base_ring() == R:
                return self
            if not R.has_coerce_map_from(self.base_ring()):
                raise ValueError(
                    "no natural map from the base ring (=%s) to R (=%s)!" %
                    (self.base_ring(), R))
            return self.change_ring(R)
        else:
            raise NotImplementedError(
                "extension of spaces over %s to %s is not implemented!" %
                (self.base_ring(), R))
Пример #15
0
    def __init__(self, abvar, base):
        """
        This is an abstract base class, so it is called implicitly in the
        following examples.

        EXAMPLES::

            sage: H = J0(43).integral_homology()
            sage: type(H)
            <class 'sage.modular.abvar.homology.IntegralHomology_with_category'>

        TESTS::

            sage: H = J0(43).integral_homology()
            sage: loads(dumps(H)) == H
            True
        """
        if not is_CommutativeRing(base):
            raise TypeError, "base ring must be a commutative ring"
        HeckeModule_free_module.__init__(self, base, abvar.level(), weight=2)
        self.__abvar = abvar
Пример #16
0
    def __init__(self, abvar, base):
        """
        This is an abstract base class, so it is called implicitly in the
        following examples.

        EXAMPLES::

            sage: H = J0(43).integral_homology()
            sage: type(H)
            <class 'sage.modular.abvar.homology.IntegralHomology_with_category'>

        TESTS::

            sage: H = J0(43).integral_homology()
            sage: loads(dumps(H)) == H
            True
        """
        if not is_CommutativeRing(base):
            raise TypeError, "base ring must be a commutative ring"
        HeckeModule_free_module.__init__(self, base, abvar.level(), weight=2)
        self.__abvar = abvar
Пример #17
0
    def _get_action_(self, other, op, self_is_left):
        """
        Register actions with the coercion model.

        The monoid actions are Minkowski sum and cartesian product. In
        addition, we want multiplication by a scalar to be dilation
        and addition by a vector to be translation. This is
        implemented as an action in the coercion model.

        INPUT:

        - ``other`` -- a scalar or a vector.

        - ``op`` -- the operator.

        - ``self_is_left`` -- boolean. Whether ``self`` is on the left
          of the operator.

        OUTPUT:

        An action that is used by the coercion model.

        EXAMPLES::

            sage: from sage.geometry.polyhedron.parent import Polyhedra
            sage: Polyhedra(ZZ,2).get_action(ZZ)   # indirect doctest
            Right action by Integer Ring on Polyhedra in ZZ^2
            sage: Polyhedra(ZZ,2).get_action(QQ)
            Right action by Rational Field on Polyhedra in QQ^2
            with precomposition on left by Conversion map:
              From: Polyhedra in ZZ^2
              To:   Polyhedra in QQ^2
            with precomposition on right by Identity endomorphism of Rational Field
            sage: Polyhedra(QQ,2).get_action(ZZ)
            Right action by Integer Ring on Polyhedra in QQ^2
            sage: Polyhedra(QQ,2).get_action(QQ)
            Right action by Rational Field on Polyhedra in QQ^2

            sage: Polyhedra(ZZ,2).an_element() * 2
            A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices
            sage: Polyhedra(ZZ,2).an_element() * (2/3)
            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
            sage: Polyhedra(QQ,2).an_element() * 2
            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
            sage: Polyhedra(QQ,2).an_element() * (2/3)
            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices

            sage: 2     * Polyhedra(ZZ,2).an_element()
            A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices
            sage: (2/3) * Polyhedra(ZZ,2).an_element()
            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
            sage: 2     * Polyhedra(QQ,2).an_element()
            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
            sage: (2/3) * Polyhedra(QQ,2).an_element()
            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices

            sage: from sage.geometry.polyhedron.parent import Polyhedra
            sage: Polyhedra(ZZ,2).get_action( ZZ^2, op=operator.add)
            Right action by Ambient free module of rank 2 over the principal ideal
            domain Integer Ring on Polyhedra in ZZ^2
            with precomposition on left by Identity endomorphism of Polyhedra in ZZ^2
            with precomposition on right by Free module morphism defined by the matrix
            [1 0]
            [0 1]
            Domain: Ambient free module of rank 2 over the principal ideal domain ...
            Codomain: Ambient free module of rank 2 over the principal ideal domain ...
        """
        import operator
        from sage.structure.coerce_actions import ActedUponAction
        from sage.categories.action import PrecomposedAction

        if op is operator.add and is_FreeModule(other):
            base_ring = self._coerce_base_ring(other)
            extended_self = self.base_extend(base_ring)
            extended_other = other.base_extend(base_ring)
            action = ActedUponAction(extended_other, extended_self, not self_is_left)
            if self_is_left:
                action = PrecomposedAction(action,
                                           extended_self.coerce_map_from(self),
                                           extended_other.coerce_map_from(other))
            else:
                action = PrecomposedAction(action,
                                           extended_other.coerce_map_from(other),
                                           extended_self.coerce_map_from(self))
            return action

        if op is operator.mul and is_CommutativeRing(other):
            ring = self._coerce_base_ring(other)
            if ring is self.base_ring():
                return ActedUponAction(other, self, not self_is_left)
            extended = self.base_extend(ring)
            action = ActedUponAction(ring, extended, not self_is_left)
            if self_is_left:
                action = PrecomposedAction(action,
                                           extended.coerce_map_from(self),
                                           ring.coerce_map_from(other))
            else:
                action = PrecomposedAction(action,
                                           ring.coerce_map_from(other),
                                           extended.coerce_map_from(self))
            return action
Пример #18
0
 def __call__(self, *args):
     """
     If S is a ring or scheme, return the set `X(S)` of
     `S`-valued points on `X`. If `S` is a list
     or tuple or just the coordinates, return a point in `X(T)`,
     where `T` is the base scheme of self.
     
     EXAMPLES::
     
         sage: A = AffineSpace(2, QQ)
     
     We create some point sets::
     
         sage: A(QQ)
         Set of Rational Points of Affine Space of dimension 2 over Rational Field            
         sage: A(RR)
         Set of Rational Points of Affine Space of dimension 2 over Real Field with 53 bits of precision
     
     Space of dimension 2 over Rational Field
     
     ::
     
         sage: R.<x> = PolynomialRing(QQ)
         sage: A(NumberField(x^2+1, 'a'))
         Set of Rational Points of Affine Space of dimension 2 over Number Field in a with defining polynomial x^2 + 1
         sage: A(GF(7))
         Traceback (most recent call last):
         ...
         ValueError: no natural map from the base ring (=Rational Field) to R (=Finite Field of size 7)!
     
     We create some points::
     
         sage: A(QQ)([1,0])
         (1, 0)
     
     We create the same point by giving the coordinates of the point
     directly.
     
     ::
     
         sage: A( 1,0 )
         (1, 0)
     """
     if len(args) == 0:
         raise TypeError, "0-dimensional affine space has no points"
     
     S = args[0]
     if is_CommutativeRing(S):
         return self.point_homset(S)
     elif is_Scheme(S):
         return S.Hom(self)
     elif isinstance(S, (list, tuple)):
         args = S
     elif isinstance(S, morphism.SchemeMorphism_coordinates):
         if S.codomain() == self:
             return S
     else:
         # TODO: fix circular import resulting from non-multiple inheritance
         from sage.schemes.elliptic_curves.ell_point import EllipticCurvePoint_field
         if isinstance(S, EllipticCurvePoint_field):
             if S.codomain() == self:
                 return S
             else:
                 return self.point(S)
     return self.point(args)
Пример #19
0
    def _get_action_(self, other, op, self_is_left):
        """
        Register actions with the coercion model.

        The monoid actions are Minkowski sum and cartesian product. In
        addition, we want multiplication by a scalar to be dilation
        and addition by a vector to be translation. This is
        implemented as an action in the coercion model.

        INPUT:

        - ``other`` -- a scalar or a vector.

        - ``op`` -- the operator.

        - ``self_is_left`` -- boolean. Whether ``self`` is on the left
          of the operator.

        OUTPUT:

        An action that is used by the coercion model.

        EXAMPLES::

            sage: from sage.geometry.polyhedron.parent import Polyhedra
            sage: Polyhedra(ZZ,2).get_action(ZZ)   # indirect doctest
            Right action by Integer Ring on Polyhedra in ZZ^2
            sage: Polyhedra(ZZ,2).get_action(QQ)
            Right action by Rational Field on Polyhedra in QQ^2
            with precomposition on left by Conversion map:
              From: Polyhedra in ZZ^2
              To:   Polyhedra in QQ^2
            with precomposition on right by Identity endomorphism of Rational Field
            sage: Polyhedra(QQ,2).get_action(ZZ)
            Right action by Integer Ring on Polyhedra in QQ^2
            sage: Polyhedra(QQ,2).get_action(QQ)
            Right action by Rational Field on Polyhedra in QQ^2

            sage: Polyhedra(ZZ,2).an_element() * 2
            A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices
            sage: Polyhedra(ZZ,2).an_element() * (2/3)
            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
            sage: Polyhedra(QQ,2).an_element() * 2
            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
            sage: Polyhedra(QQ,2).an_element() * (2/3)
            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices

            sage: 2     * Polyhedra(ZZ,2).an_element()
            A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices
            sage: (2/3) * Polyhedra(ZZ,2).an_element()
            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
            sage: 2     * Polyhedra(QQ,2).an_element()
            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
            sage: (2/3) * Polyhedra(QQ,2).an_element()
            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices

            sage: from sage.geometry.polyhedron.parent import Polyhedra
            sage: Polyhedra(ZZ,2).get_action( ZZ^2, op=operator.add)
            Right action by Ambient free module of rank 2 over the principal ideal
            domain Integer Ring on Polyhedra in ZZ^2
            with precomposition on left by Identity endomorphism of Polyhedra in ZZ^2
            with precomposition on right by Free module morphism defined by the matrix
            [1 0]
            [0 1]
            Domain: Ambient free module of rank 2 over the principal ideal domain ...
            Codomain: Ambient free module of rank 2 over the principal ideal domain ...
        """
        import operator
        from sage.structure.coerce_actions import ActedUponAction
        from sage.categories.action import PrecomposedAction

        if op is operator.add and is_FreeModule(other):
            base_ring = self._coerce_base_ring(other)
            extended_self = self.base_extend(base_ring)
            extended_other = other.base_extend(base_ring)
            action = ActedUponAction(extended_other, extended_self, not self_is_left)
            if self_is_left:
                action = PrecomposedAction(action,
                                           extended_self.coerce_map_from(self),
                                           extended_other.coerce_map_from(other))
            else:
                action = PrecomposedAction(action,
                                           extended_other.coerce_map_from(other),
                                           extended_self.coerce_map_from(self))
            return action

        if op is operator.mul and is_CommutativeRing(other):
            ring = self._coerce_base_ring(other)
            if ring is self.base_ring():
                return ActedUponAction(other, self, not self_is_left)
            extended = self.base_extend(ring)
            action = ActedUponAction(ring, extended, not self_is_left)
            if self_is_left:
                action = PrecomposedAction(action,
                                           extended.coerce_map_from(self),
                                           ring.coerce_map_from(other))
            else:
                action = PrecomposedAction(action,
                                           ring.coerce_map_from(other),
                                           extended.coerce_map_from(self))
            return action
Пример #20
0
    def __call__(self, *args):
        """
        Call syntax for schemes.

        INPUT/OUTPUT:
        
        The arguments must be one of the following:

        - a ring or a scheme `S`. Output will be the set `X(S)` of
          `S`-valued points on `X`.

        - If `S` is a list or tuple or just the coordinates, return a
          point in `X(T)`, where `T` is the base scheme of self.
        
        EXAMPLES::
        
            sage: A = AffineSpace(2, QQ)
        
        We create some point sets::
        
            sage: A(QQ)
            Set of rational points of Affine Space of dimension 2 over Rational Field
            sage: A(RR)
            Set of rational points of Affine Space of dimension 2 over Real Field 
            with 53 bits of precision
        
        Space of dimension 2 over Rational Field::
        
            sage: R.<x> = PolynomialRing(QQ)
            sage: A(NumberField(x^2+1, 'a'))
            Set of rational points of Affine Space of dimension 2 over Number Field 
            in a with defining polynomial x^2 + 1
            sage: A(GF(7))
            Traceback (most recent call last):
            ...
            ValueError: There must be a natural map S --> R, but 
            S = Rational Field and R = Finite Field of size 7
        
        We create some points::
        
            sage: A(QQ)([1,0])
            (1, 0)
        
        We create the same point by giving the coordinates of the point
        directly::
        
            sage: A( 1,0 )
            (1, 0)
        """
        if len(args) == 0:
            raise TypeError('You need to specify at least one argument.')
        
        S = args[0]
        if is_CommutativeRing(S):
            return self.point_homset(S)
        if is_Scheme(S):
            return S.Hom(self)
        from sage.schemes.generic.morphism import SchemeMorphism_point
        if isinstance(S, (list, tuple)):
            args = S
        elif isinstance(S, SchemeMorphism_point):
            if S.codomain() == self:
                return S
        else:
            # TODO: fix circular import resulting from non-multiple inheritance
            from sage.schemes.elliptic_curves.ell_point import EllipticCurvePoint_field
            if isinstance(S, EllipticCurvePoint_field):
                if S.codomain() == self:
                    return S
                else:
                    return self.point(S)
        return self.point(args)
Пример #21
0
def canonical_parameters(group, level, weight, base_ring):
    """
    Given a group, level, weight, and base_ring as input by the user,
    return a canonicalized version of them, where level is a Sage
    integer, group really is a group, weight is a Sage integer, and
    base_ring a Sage ring. Note that we can't just get the level from
    the group, because we have the convention that the character for
    Gamma1(N) is None (which makes good sense).
    
    INPUT:
    
    
    -  ``group`` - int, long, Sage integer, group,
       dirichlet character, or
    
    -  ``level`` - int, long, Sage integer, or group
    
    -  ``weight`` - coercible to Sage integer
    
    -  ``base_ring`` - commutative Sage ring
    
    
    OUTPUT:
    
    
    -  ``level`` - Sage integer
    
    -  ``group`` - congruence subgroup
    
    -  ``weight`` - Sage integer
    
    -  ``ring`` - commutative Sage ring
    
    
    EXAMPLES::
    
        sage: from sage.modular.modform.constructor import canonical_parameters
        sage: v = canonical_parameters(5, 5, int(7), ZZ); v
        (5, Congruence Subgroup Gamma0(5), 7, Integer Ring)
        sage: type(v[0]), type(v[1]), type(v[2]), type(v[3])
        (<type 'sage.rings.integer.Integer'>,
         <class 'sage.modular.arithgroup.congroup_gamma0.Gamma0_class_with_category'>,
         <type 'sage.rings.integer.Integer'>,
         <type 'sage.rings.integer_ring.IntegerRing_class'>)
        sage: canonical_parameters( 5, 7, 7, ZZ )
        Traceback (most recent call last):
        ...
        ValueError: group and level do not match.
    """
    weight = rings.Integer(weight)
    if weight <= 0:
        raise NotImplementedError, "weight must be at least 1"
 
    if isinstance(group, dirichlet.DirichletCharacter):
        if ( group.level() != rings.Integer(level) ):
            raise ValueError, "group.level() and level do not match."
        group = group.minimize_base_ring()
        level = rings.Integer(level)

    elif arithgroup.is_CongruenceSubgroup(group):
        if ( rings.Integer(level) != group.level() ):
            raise ValueError, "group.level() and level do not match."
        # normalize the case of SL2Z
        if arithgroup.is_SL2Z(group) or \
           arithgroup.is_Gamma1(group) and group.level() == rings.Integer(1):
            group = arithgroup.Gamma0(rings.Integer(1))
       
    elif group is None:
        pass

    else: 
        try: 
            m = rings.Integer(group)
        except TypeError:
            raise TypeError, "group of unknown type."
        level = rings.Integer(level)
        if ( m != level ):
            raise ValueError, "group and level do not match."
        group = arithgroup.Gamma0(m)
       
    if not rings.is_CommutativeRing(base_ring):
        raise TypeError, "base_ring (=%s) must be a commutative ring"%base_ring

    # it is *very* important to include the level as part of the data
    # that defines the key, since dirichlet characters of different
    # levels can compare equal, but define much different modular
    # forms spaces.
    return level, group, weight, base_ring
Пример #22
0
    def __call__(self, *args):
        """
        If S is a ring or scheme, return the set `X(S)` of
        `S`-valued points on `X`. If `S` is a list
        or tuple or just the coordinates, return a point in `X(T)`,
        where `T` is the base scheme of self.
        
        EXAMPLES::
        
            sage: A = AffineSpace(2, QQ)
        
        We create some point sets::
        
            sage: A(QQ)
            Set of Rational Points of Affine Space of dimension 2 over Rational Field            
            sage: A(RR)
            Set of Rational Points of Affine Space of dimension 2 over Real Field with 53 bits of precision
        
        Space of dimension 2 over Rational Field
        
        ::
        
            sage: R.<x> = PolynomialRing(QQ)
            sage: A(NumberField(x^2+1, 'a'))
            Set of Rational Points of Affine Space of dimension 2 over Number Field in a with defining polynomial x^2 + 1
            sage: A(GF(7))
            Traceback (most recent call last):
            ...
            ValueError: no natural map from the base ring (=Rational Field) to R (=Finite Field of size 7)!
        
        We create some points::
        
            sage: A(QQ)([1,0])
            (1, 0)
        
        We create the same point by giving the coordinates of the point
        directly.
        
        ::
        
            sage: A( 1,0 )
            (1, 0)
        """
        if len(args) == 0:
            raise TypeError, "0-dimensional affine space has no points"

        S = args[0]
        if is_CommutativeRing(S):
            return self.point_homset(S)
        elif is_Scheme(S):
            return S.Hom(self)
        elif isinstance(S, (list, tuple)):
            args = S
        elif isinstance(S, morphism.SchemeMorphism_coordinates):
            if S.codomain() == self:
                return S
        else:
            # TODO: fix circular import resulting from non-multiple inheritance
            from sage.schemes.elliptic_curves.ell_point import EllipticCurvePoint_field
            if isinstance(S, EllipticCurvePoint_field):
                if S.codomain() == self:
                    return S
                else:
                    return self.point(S)
        return self.point(args)
Пример #23
0
    def __call__(self, *args):
        """
        Call syntax for schemes.

        INPUT/OUTPUT:

        The arguments must be one of the following:

        - a ring or a scheme `S`. Output will be the set `X(S)` of
          `S`-valued points on `X`.

        - If `S` is a list or tuple or just the coordinates, return a
          point in `X(T)`, where `T` is the base scheme of self.

        EXAMPLES::

            sage: A = AffineSpace(2, QQ)

        We create some point sets::

            sage: A(QQ)
            Set of rational points of Affine Space of dimension 2 over Rational Field
            sage: A(RR)
            Set of rational points of Affine Space of dimension 2 over Real Field
            with 53 bits of precision

        Space of dimension 2 over Rational Field::

            sage: R.<x> = PolynomialRing(QQ)
            sage: A(NumberField(x^2+1, 'a'))
            Set of rational points of Affine Space of dimension 2 over Number Field
            in a with defining polynomial x^2 + 1
            sage: A(GF(7))
            Traceback (most recent call last):
            ...
            ValueError: There must be a natural map S --> R, but
            S = Rational Field and R = Finite Field of size 7

        We create some points::

            sage: A(QQ)([1,0])
            (1, 0)

        We create the same point by giving the coordinates of the point
        directly::

            sage: A( 1,0 )
            (1, 0)
        """
        if len(args) == 0:
            raise TypeError('You need to specify at least one argument.')

        S = args[0]
        if is_CommutativeRing(S):
            return self.point_homset(S)
        if is_Scheme(S):
            return S.Hom(self)
        from sage.schemes.generic.morphism import SchemeMorphism_point
        if isinstance(S, (list, tuple)):
            args = S
        elif isinstance(S, SchemeMorphism_point):
            if S.codomain() == self:
                return S
        else:
            # TODO: fix circular import resulting from non-multiple inheritance
            from sage.schemes.elliptic_curves.ell_point import EllipticCurvePoint_field
            if isinstance(S, EllipticCurvePoint_field):
                if S.codomain() == self:
                    return S
                else:
                    return self.point(S)
        return self.point(args)
Пример #24
0
def ProjectiveSpace(n, R=None, names='x'):
    r"""
    Return projective space of dimension `n` over the ring `R`.

    EXAMPLES: The dimension and ring can be given in either order.

    ::

        sage: ProjectiveSpace(3, QQ)
        Projective Space of dimension 3 over Rational Field
        sage: ProjectiveSpace(5, QQ)
        Projective Space of dimension 5 over Rational Field
        sage: P = ProjectiveSpace(2, QQ, names='XYZ'); P
        Projective Space of dimension 2 over Rational Field
        sage: P.coordinate_ring()
        Multivariate Polynomial Ring in X, Y, Z over Rational Field

    The divide operator does base extension.

    ::

        sage: ProjectiveSpace(5)/GF(17)
        Projective Space of dimension 5 over Finite Field of size 17

    The default base ring is `\ZZ`.

    ::

        sage: ProjectiveSpace(5)
        Projective Space of dimension 5 over Integer Ring

    There is also an projective space associated each polynomial ring.

    ::

        sage: R = GF(7)['x,y,z']
        sage: P = ProjectiveSpace(R); P
        Projective Space of dimension 2 over Finite Field of size 7
        sage: P.coordinate_ring()
        Multivariate Polynomial Ring in x, y, z over Finite Field of size 7
        sage: P.coordinate_ring() is R
        True

    ::

        sage: ProjectiveSpace(3, Zp(5), 'y')
        Projective Space of dimension 3 over 5-adic Ring with capped relative precision 20

    ::

        sage: ProjectiveSpace(2,QQ,'x,y,z')
        Projective Space of dimension 2 over Rational Field

    ::

        sage: PS.<x,y>=ProjectiveSpace(1,CC)
        sage: PS
        Projective Space of dimension 1 over Complex Field with 53 bits of precision

    Projective spaces are not cached, i.e., there can be several with
    the same base ring and dimension (to facilitate gluing
    constructions).
    """
    if is_MPolynomialRing(n) and R is None:
        A = ProjectiveSpace(n.ngens() - 1, n.base_ring())
        A._coordinate_ring = n
        return A
    if isinstance(R, (int, long, Integer)):
        n, R = R, n
    if R is None:
        R = ZZ  # default is the integers
    if R in _Fields:
        if is_FiniteField(R):
            return ProjectiveSpace_finite_field(n, R, names)
        if is_RationalField(R):
            return ProjectiveSpace_rational_field(n, R, names)
        else:
            return ProjectiveSpace_field(n, R, names)
    elif is_CommutativeRing(R):
        return ProjectiveSpace_ring(n, R, names)
    else:
        raise TypeError, "R (=%s) must be a commutative ring" % R
Пример #25
0
def ProjectiveSpace(n, R=None, names='x'):
    r"""
    Return projective space of dimension `n` over the ring `R`.

    EXAMPLES: The dimension and ring can be given in either order.

    ::

        sage: ProjectiveSpace(3, QQ)
        Projective Space of dimension 3 over Rational Field
        sage: ProjectiveSpace(5, QQ)
        Projective Space of dimension 5 over Rational Field
        sage: P = ProjectiveSpace(2, QQ, names='XYZ'); P
        Projective Space of dimension 2 over Rational Field
        sage: P.coordinate_ring()
        Multivariate Polynomial Ring in X, Y, Z over Rational Field

    The divide operator does base extension.

    ::

        sage: ProjectiveSpace(5)/GF(17)
        Projective Space of dimension 5 over Finite Field of size 17

    The default base ring is `\ZZ`.

    ::

        sage: ProjectiveSpace(5)
        Projective Space of dimension 5 over Integer Ring

    There is also an projective space associated each polynomial ring.

    ::

        sage: R = GF(7)['x,y,z']
        sage: P = ProjectiveSpace(R); P
        Projective Space of dimension 2 over Finite Field of size 7
        sage: P.coordinate_ring()
        Multivariate Polynomial Ring in x, y, z over Finite Field of size 7
        sage: P.coordinate_ring() is R
        True

    ::

        sage: ProjectiveSpace(3, Zp(5), 'y')
        Projective Space of dimension 3 over 5-adic Ring with capped relative precision 20

    ::

        sage: ProjectiveSpace(2,QQ,'x,y,z')
        Projective Space of dimension 2 over Rational Field

    ::

        sage: PS.<x,y>=ProjectiveSpace(1,CC)
        sage: PS
        Projective Space of dimension 1 over Complex Field with 53 bits of precision

    Projective spaces are not cached, i.e., there can be several with
    the same base ring and dimension (to facilitate gluing
    constructions).
    """
    if is_MPolynomialRing(n) and R is None:
        A = ProjectiveSpace(n.ngens()-1, n.base_ring())
        A._coordinate_ring = n
        return A
    if isinstance(R, (int, long, Integer)):
        n, R = R, n
    if R is None:
        R = ZZ  # default is the integers
    if R in _Fields:
        if is_FiniteField(R):
            return ProjectiveSpace_finite_field(n, R, names)
        if is_RationalField(R):
            return ProjectiveSpace_rational_field(n, R, names)
        else:
            return ProjectiveSpace_field(n, R, names)
    elif is_CommutativeRing(R):
        return ProjectiveSpace_ring(n, R, names)
    else:
        raise TypeError("R (=%s) must be a commutative ring"%R)
Пример #26
0
def canonical_parameters(group, level, weight, base_ring):
    """
    Given a group, level, weight, and base_ring as input by the user,
    return a canonicalized version of them, where level is a Sage
    integer, group really is a group, weight is a Sage integer, and
    base_ring a Sage ring. Note that we can't just get the level from
    the group, because we have the convention that the character for
    Gamma1(N) is None (which makes good sense).

    INPUT:


    -  ``group`` - int, long, Sage integer, group,
       dirichlet character, or

    -  ``level`` - int, long, Sage integer, or group

    -  ``weight`` - coercible to Sage integer

    -  ``base_ring`` - commutative Sage ring


    OUTPUT:


    -  ``level`` - Sage integer

    -  ``group`` - congruence subgroup

    -  ``weight`` - Sage integer

    -  ``ring`` - commutative Sage ring


    EXAMPLES::

        sage: from sage.modular.modform.constructor import canonical_parameters
        sage: v = canonical_parameters(5, 5, int(7), ZZ); v
        (5, Congruence Subgroup Gamma0(5), 7, Integer Ring)
        sage: type(v[0]), type(v[1]), type(v[2]), type(v[3])
        (<type 'sage.rings.integer.Integer'>,
         <class 'sage.modular.arithgroup.congroup_gamma0.Gamma0_class_with_category'>,
         <type 'sage.rings.integer.Integer'>,
         <type 'sage.rings.integer_ring.IntegerRing_class'>)
        sage: canonical_parameters( 5, 7, 7, ZZ )
        Traceback (most recent call last):
        ...
        ValueError: group and level do not match.
    """
    weight = rings.Integer(weight)
    if weight <= 0:
        raise NotImplementedError, "weight must be at least 1"

    if isinstance(group, dirichlet.DirichletCharacter):
        if ( group.level() != rings.Integer(level) ):
            raise ValueError, "group.level() and level do not match."
        group = group.minimize_base_ring()
        level = rings.Integer(level)

    elif arithgroup.is_CongruenceSubgroup(group):
        if ( rings.Integer(level) != group.level() ):
            raise ValueError, "group.level() and level do not match."
        # normalize the case of SL2Z
        if arithgroup.is_SL2Z(group) or \
           arithgroup.is_Gamma1(group) and group.level() == rings.Integer(1):
            group = arithgroup.Gamma0(rings.Integer(1))

    elif group is None:
        pass

    else:
        try:
            m = rings.Integer(group)
        except TypeError:
            raise TypeError, "group of unknown type."
        level = rings.Integer(level)
        if ( m != level ):
            raise ValueError, "group and level do not match."
        group = arithgroup.Gamma0(m)

    if not rings.is_CommutativeRing(base_ring):
        raise TypeError, "base_ring (=%s) must be a commutative ring"%base_ring

    # it is *very* important to include the level as part of the data
    # that defines the key, since dirichlet characters of different
    # levels can compare equal, but define much different modular
    # forms spaces.
    return level, group, weight, base_ring