Example #1
0
    def __init__(self, ambient_space_functor, generators):
        r"""
        Construction functor for the forms sub space
        for the given ``generators`` inside the ambient space
        which is constructed by the ``ambient_space_functor``.

        The functor can only be applied to rings for which the generators
        can be converted into the corresponding forms space
        given by the ``ambient_space_functor`` applied to the ring.

        See :meth:`__call__` for a description of the functor.

        INPUT:

        - ``ambient_space_functor`` -- A FormsSpaceFunctor

        - ``generators``            -- A list of elements of some ambient space
                                       over some base ring.

        OUTPUT:

        The construction functor for the corresponding forms sub space.

        EXAMPLES::

            sage: from sage.modular.modform_hecketriangle.functors import (FormsSpaceFunctor, FormsSubSpaceFunctor)
            sage: from sage.modular.modform_hecketriangle.space import ModularForms
            sage: ambient_space = ModularForms(n=4, k=12, ep=1)
            sage: ambient_space_functor = FormsSpaceFunctor("holo", group=4, k=12, ep=1)
            sage: ambient_space_functor
            ModularFormsFunctor(n=4, k=12, ep=1)
            sage: el = ambient_space.gen(0).full_reduce()
            sage: FormsSubSpaceFunctor(ambient_space_functor, [el])
            FormsSubSpaceFunctor with 1 generator for the ModularFormsFunctor(n=4, k=12, ep=1)
        """

        Functor.__init__(self, Rings(), CommutativeAdditiveGroups())
        if not isinstance(ambient_space_functor, FormsSpaceFunctor):
            raise ValueError("{} is not a FormsSpaceFunctor!".format(ambient_space_functor))
        # TODO: canonical parameters? Some checks?
        # The generators should have an associated base ring
        # self._generators_ring = ...
        # on call check if there is a coercion from self._generators_ring to R

        self._ambient_space_functor = ambient_space_functor
        self._generators = generators
Example #2
0
    def __init__(self, n=1):
        r"""
        Initialization.

        EXAMPLES::

            sage: from sage.groups.additive_abelian.qmodnz import QmodnZ
            sage: G = QmodnZ(2)
            sage: G
            Q/2Z

        TESTS::

            sage: G = QQ/(19*ZZ)
            sage: TestSuite(G).run()
        """
        self.n = QQ(n).abs()
        category = CommutativeAdditiveGroups().Infinite()
        Parent.__init__(self, base=ZZ, category=category)
        self._populate_coercion_lists_(coerce_list=[QQ])
Example #3
0
    def __init__(self, field):
        """
        Initialize.

        INPUT:

        - ``field`` -- function field

        EXAMPLES::

            sage: K.<x> = FunctionField(GF(5)); _.<t> = PolynomialRing(K)
            sage: F.<y> = K.extension(t^2-x^3-1)
            sage: F.divisor_group()
            Divisor group of Function field in y defined by y^2 + 4*x^3 + 4
        """
        Parent.__init__(self,
                        base=IntegerRing(),
                        category=CommutativeAdditiveGroups())

        self._field = field  # function field
Example #4
0
def EilenbergMacLaneSpace(G, n):
    r"""
    Return the Eilenberg-MacLane space ``K(G, n)`` as a Kenzo simplicial group.

    The Eilenberg-MacLane space ``K(G, n)`` is the space whose has n'th homotopy
    group isomorphic to ``G``, and the rest of the homotopy groups are trivial.

    INPUT:

    - ``G`` -- group. Currently only ``ZZ`` and the additive group of two
      elements are supported.

    - ``n`` -- the dimension in which the homotopy is not trivial


    OUTPUT:

    - A :class:`KenzoSimplicialGroup`

    EXAMPLES::

        sage: from sage.interfaces.kenzo import EilenbergMacLaneSpace    # optional - kenzo
        sage: e3 = EilenbergMacLaneSpace(ZZ, 3)                          # optional - kenzo
        sage: [e3.homology(i) for i in range(8)]                         # optional - kenzo
        [Z, 0, 0, Z, 0, C2, 0, C3]
        sage: f3 = EilenbergMacLaneSpace(AdditiveAbelianGroup([2]), 3)   # optional - kenzo
        sage: [f3.homology(i) for i in range(8)]                         # optional - kenzo
        [Z, 0, 0, C2, 0, C2, C2, C2]
    """
    if G == ZZ:
        kenzospace = k_z(n)
        return KenzoSimplicialGroup(kenzospace)
    elif G == AdditiveAbelianGroup([2]):
        kenzospace = k_z2(n)
        return KenzoSimplicialGroup(kenzospace)
    elif G in CommutativeAdditiveGroups() and G.is_cyclic():
        kenzospace = k_zp(G.cardinality(), n)
        return KenzoSimplicialGroup(kenzospace)
    else:
        raise NotImplementedError(
            "Eilenberg-MacLane spaces are only supported over ZZ and ZZ_n")
Example #5
0
    def __init__(self, analytic_type, group, k, ep):
        r"""
        Construction functor for the forms space
        (or forms ring, see above) with
        the given ``analytic_type``, ``group``,
        weight ``k`` and multiplier ``ep``.

        See :meth:`__call__` for a description of the functor.

        INPUT:

        - ``analytic_type``  -- An element of ``AnalyticType()``.

        - ``group``          -- The index of a Hecke Triangle group.

        - ``k``              -- A rational number, the weight of the space.

        - ``ep``             -- `1` or `-1`, the multiplier of the space.

        OUTPUT:

        The construction functor for the corresponding forms space/ring.

        EXAMPLES::

            sage: from sage.modular.modform_hecketriangle.functors import FormsSpaceFunctor
            sage: FormsSpaceFunctor(["holo", "weak"], group=4, k=0, ep=-1)
            WeakModularFormsFunctor(n=4, k=0, ep=-1)
        """

        Functor.__init__(self, Rings(), CommutativeAdditiveGroups())
        from .space import canonical_parameters
        (self._group, R, self._k, self._ep,
         n) = canonical_parameters(group, ZZ, k, ep)

        self._analytic_type = self.AT(analytic_type)
Example #6
0
        def _test_yacop_grading(self, tester=None, **options):
            from sage.misc.sage_unittest import TestSuite
            from sage.misc.lazy_format import LazyFormat
            from sage.categories.enumerated_sets import EnumeratedSets
            from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets

            is_sub_testsuite = tester is not None
            tester = self._tester(tester=tester, **options)

            if hasattr(self.grading(), "_domain"):
                tester.assertTrue(
                    self is self.grading()._domain,
                    LazyFormat("grading of %s has wrong _domain attribute %s")
                    % (self, self.grading()._domain),
                )

            bbox = self.bbox()
            tester.assertTrue(
                bbox.__class__ == region,
                LazyFormat("bounding box of %s is not a region") % (self, ),
            )

            # make sure we can get a basis of the entire module
            basis = self.graded_basis()
            tester.assertTrue(
                basis in EnumeratedSets(),
                LazyFormat("graded basis of %s is not an EnumeratedSet") %
                (self, ),
            )

            # nontrivial_degrees
            ntdegs = self.nontrivial_degrees()
            tester.assertTrue(
                basis in EnumeratedSets(),
                LazyFormat("nontrivial_degrees of %s is not an EnumeratedSet")
                % (self, ),
            )

            # check whether a presumably finite piece is also an EnumeratedSet
            rg = region(tmax=10,
                        tmin=-10,
                        smax=10,
                        smin=-10,
                        emax=10,
                        emin=-10)
            basis = self.graded_basis(rg)
            tester.assertTrue(
                basis in EnumeratedSets(),
                LazyFormat(
                    "graded basis of %s in the region %s is not an EnumeratedSet"
                ) % (self, rg),
            )

            for (deg, elem) in self._some_homogeneous_elements():
                deg2 = self.degree(elem)
                if hasattr(elem, "degree"):
                    deg3 = elem.degree()
                    tester.assertEqual(
                        deg2,
                        deg3,
                        LazyFormat(
                            "parent.degree(el) != (el).degree() for parent %s and element %s"
                        ) % (self, elem),
                    )

                tester.assertEqual(
                    deg2,
                    deg,
                    LazyFormat(
                        "homogeneuous_decomposition claims %s has degree %s, but degree says %s"
                    ) % (elem, deg, deg2),
                )

                # test graded_basis_coefficients
                b = self.grading().basis(deg)
                tester.assertTrue(
                    b.cardinality() < Infinity,
                    LazyFormat("%s not finite in degree %s") % (self, deg),
                )

            from sage.categories.commutative_additive_groups import (
                CommutativeAdditiveGroups, )

            if self in CommutativeAdditiveGroups():
                el = self.an_element()
                sp = el.homogeneous_decomposition()
                for (deg, elem) in list(sp.items()):
                    b = self.grading().basis(deg)
                    c = self.graded_basis_coefficients(elem, deg)
                    sm = sum(cf * be for (cf, be) in zip(c, b))
                    if elem != sm:
                        print(("self=", self))
                        print(("elem=", elem))
                        print(("deg=", deg))
                        print(("graded basis=", list(b)))
                        print(("lhs=", elem.monomial_coefficients()))
                        print(("rhs=", sm.monomial_coefficients()))
                    tester.assertEqual(
                        elem,
                        sm,
                        LazyFormat(
                            "graded_basis_coefficients failed on element %s of %s: sums to %s"
                        ) % (elem, self, sm),
                    )

                el2 = sum(smd for (key, smd) in list(sp.items()))
                tester.assertEqual(
                    el.parent(),
                    el2.parent(),
                    LazyFormat(
                        "%s and the sum of its homogeneous pieces have different parents:\n   %s\n!= %s"
                    ) % (
                        el,
                        el.parent(),
                        el2.parent(),
                    ),
                )
                if el.parent() is el2.parent():
                    tester.assertEqual(
                        el,
                        el2,
                        LazyFormat(
                            "%s is not the sum of its homogeneous pieces (which is %s)"
                        ) % (
                            el,
                            el2,
                        ),
                    )
Example #7
0
        def __init_extra__(self):
            """
            Declare the canonical coercion from ``self.base_ring()``
            to ``self``, if there has been none before.

            EXAMPLES::

                sage: A = AlgebrasWithBasis(QQ).example(); A
                An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field
                sage: coercion_model = sage.structure.element.get_coercion_model()
                sage: coercion_model.discover_coercion(QQ, A)
                (Generic morphism:
                  From: Rational Field
                  To:   An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field, None)
                sage: A(1)          # indirect doctest
                B[word: ]

            TESTS:

            Ensure that :trac:`28328` is fixed and that non-associative
            algebras are supported::

                sage: class Foo(CombinatorialFreeModule):
                ....:     def one(self):
                ....:         return self.monomial(0)
                sage: from sage.categories.magmatic_algebras \
                ....:   import MagmaticAlgebras
                sage: C = MagmaticAlgebras(QQ).WithBasis().Unital()
                sage: F = Foo(QQ,(1,),category=C)
                sage: F(0)
                0
                sage: F(3)
                3*B[0]

            """
            # If self has an attribute _no_generic_basering_coercion
            # set to True, then this declaration is skipped.
            # This trick, introduced in #11900, is used in
            # sage.matrix.matrix_space.py and
            # sage.rings.polynomial.polynomial_ring.
            # It will hopefully be refactored into something more
            # conceptual later on.
            if getattr(self, '_no_generic_basering_coercion', False):
                return

            base_ring = self.base_ring()
            if base_ring is self:
                # There are rings that are their own base rings. No need to register that.
                return
            if self._is_coercion_cached(base_ring):
                # We will not use any generic stuff, since a (presumably) better conversion
                # has already been registered.
                return

            # Pick a homset for the morphism to live in...
            if self in Rings():
                # The algebra is associative, and thus a ring. The
                # base ring is also a ring. Everything is OK.
                H = Hom(base_ring, self, Rings())
            else:
                # If the algebra isn't associative, we would like to
                # use the category of unital magmatic algebras (which
                # are not necessarily associative) instead. But,
                # unfortunately, certain important rings like QQ
                # aren't in that category. As a result, we have to use
                # something weaker.
                cat = Magmas().Unital()
                cat = Category.join([cat, CommutativeAdditiveGroups()])
                cat = cat.Distributive()
                H = Hom(base_ring, self, cat)

            # We need to register a coercion from the base ring to self.
            #
            # There is a generic method from_base_ring(), that just does
            # multiplication with the multiplicative unit. However, the
            # unit is constructed repeatedly, which is slow.
            # So, if the unit is available *now*, then we can create a
            # faster coercion map.
            #
            # This only applies for the generic from_base_ring() method.
            # If there is a specialised from_base_ring(), then it should
            # be used unconditionally.
            generic_from_base_ring = self.category(
            ).parent_class.from_base_ring
            if type(self).from_base_ring != generic_from_base_ring:
                # Custom from_base_ring()
                use_from_base_ring = True
            if isinstance(generic_from_base_ring, lazy_attribute):
                # If the category implements from_base_ring() as lazy
                # attribute, then we always use it.
                # This is for backwards compatibility, see Trac #25181
                use_from_base_ring = True
            else:
                try:
                    one = self.one()
                    use_from_base_ring = False
                except (NotImplementedError, AttributeError, TypeError):
                    # The unit is not available, yet. But there are cases
                    # in which it will be available later. So, we use
                    # the generic from_base_ring() after all.
                    use_from_base_ring = True

            mor = None
            if use_from_base_ring:
                mor = SetMorphism(function=self.from_base_ring, parent=H)
            else:
                # We have the multiplicative unit, so implement the
                # coercion from the base ring as multiplying with that.
                #
                # But first we check that it actually works. If not,
                # then the generic implementation of from_base_ring()
                # would fail as well so we don't use it.
                try:
                    if one._lmul_(base_ring.an_element()) is not None:
                        # There are cases in which lmul returns None,
                        # which means that it's not implemented.
                        # One example: Hecke algebras.
                        mor = SetMorphism(function=one._lmul_, parent=H)
                except (NotImplementedError, AttributeError, TypeError):
                    pass
            if mor is not None:
                try:
                    self.register_coercion(mor)
                except AssertionError:
                    pass
        def _coerce_map_from_base_ring(self):
            """
            Return a suitable coercion map from the base ring of ``self``.

            TESTS::

                sage: A = cartesian_product((QQ['z'],)); A
                The Cartesian product of (Univariate Polynomial Ring in z over Rational Field,)
                sage: A.base_ring()
                Rational Field
                sage: A._coerce_map_from_base_ring()
                Generic morphism:
                From: Rational Field
                To:   The Cartesian product of (Univariate Polynomial Ring in z over Rational Field,)

            Check that :trac:`29312` is fixed::

                sage: F.<x,y,z> = FreeAlgebra(QQ, implementation='letterplace')
                sage: F._coerce_map_from_base_ring()
                Generic morphism:
                  From: Rational Field
                  To:   Free Associative Unital Algebra on 3 generators (x, y, z) over Rational Field
            """
            base_ring = self.base_ring()

            # Pick a homset for the morphism to live in...
            if self in Rings():
                # The algebra is associative, and thus a ring. The
                # base ring is also a ring. Everything is OK.
                H = Hom(base_ring, self, Rings())
            else:
                # If the algebra isn't associative, we would like to
                # use the category of unital magmatic algebras (which
                # are not necessarily associative) instead. But,
                # unfortunately, certain important rings like QQ
                # aren't in that category. As a result, we have to use
                # something weaker.
                cat = Magmas().Unital()
                cat = Category.join([cat, CommutativeAdditiveGroups()])
                cat = cat.Distributive()
                H = Hom(base_ring, self, cat)

            # We need to construct a coercion from the base ring to self.
            #
            # There is a generic method from_base_ring(), that just does
            # multiplication with the multiplicative unit. However, the
            # unit is constructed repeatedly, which is slow.
            # So, if the unit is available *now*, then we can create a
            # faster coercion map.
            #
            # This only applies for the generic from_base_ring() method.
            # If there is a specialised from_base_ring(), then it should
            # be used unconditionally.
            generic_from_base_ring = self.category(
            ).parent_class.from_base_ring
            from_base_ring = self.from_base_ring  # bound method
            if from_base_ring.__func__ != generic_from_base_ring:
                # Custom from_base_ring()
                use_from_base_ring = True
            elif isinstance(generic_from_base_ring, lazy_attribute):
                # If the category implements from_base_ring() as lazy
                # attribute, then we always use it.
                # This is for backwards compatibility, see Trac #25181
                use_from_base_ring = True
            else:
                try:
                    one = self.one()
                    use_from_base_ring = False
                except (NotImplementedError, AttributeError, TypeError):
                    # The unit is not available, yet. But there are cases
                    # in which it will be available later. So, we use
                    # the generic from_base_ring() after all.
                    use_from_base_ring = True

            mor = None
            if use_from_base_ring:
                mor = SetMorphism(function=from_base_ring, parent=H)
            else:
                # We have the multiplicative unit, so implement the
                # coercion from the base ring as multiplying with that.
                #
                # But first we check that it actually works. If not,
                # then the generic implementation of from_base_ring()
                # would fail as well so we don't use it.
                try:
                    if one._lmul_(base_ring.an_element()) is not None:
                        # There are cases in which lmul returns None,
                        # which means that it's not implemented.
                        # One example: Hecke algebras.
                        mor = SetMorphism(function=one._lmul_, parent=H)
                except (NotImplementedError, AttributeError, TypeError):
                    pass
            return mor