Example #1
0
    def __call__(self, x):
        """
        Coerce x into a boundary symbol space.

        If x is a modular symbol (with the same group, weight, character,
        sign, and base field), this returns the image of that modular
        symbol under the boundary map.

        EXAMPLES::

            sage: M = ModularSymbols(Gamma0(15), 2) ; B = M.boundary_space()
            sage: B(M.0)
            [Infinity] - [0]
            sage: B(Cusp(1))
            [0]
            sage: B(Cusp(oo))
            [Infinity]
            sage: B(7)
            Traceback (most recent call last):
            ...
            TypeError: Coercion of 7 (of type <type 'sage.rings.integer.Integer'>) into Space of Boundary Modular Symbols for Congruence Subgroup Gamma0(15) of weight 2 and over Rational Field not (yet) defined.
        """
        from .ambient import ModularSymbolsAmbient
        if isinstance(x, int) and x == 0:
            return BoundarySpaceElement(self, {})

        elif isinstance(x, cusps.Cusp):
            return self._coerce_cusp(x)

        elif isinstance(x, ManinSymbol):
            return self._coerce_in_manin_symbol(x)

        elif element.is_ModularSymbolsElement(x):
            M = x.parent()
            if not isinstance(M, ModularSymbolsAmbient):
                raise TypeError(
                    "x (=%s) must be an element of a space of modular symbols of type ModularSymbolsAmbient"
                    % x)
            if M.level() != self.level():
                raise TypeError("x (=%s) must have level %s but has level %s" %
                                (x, self.level(), M.level()))
            S = x.manin_symbol_rep()
            if len(S) == 0:
                return self(0)
            return sum([c * self._coerce_in_manin_symbol(v) for c, v in S])

        elif is_FreeModuleElement(x):
            y = dict([(i, x[i]) for i in xrange(len(x))])
            return BoundarySpaceElement(self, y)

        raise TypeError(
            "Coercion of %s (of type %s) into %s not (yet) defined." %
            (x, type(x), self))
Example #2
0
    def __call__(self, x):
        """
        Coerce x into a boundary symbol space.

        If x is a modular symbol (with the same group, weight, character,
        sign, and base field), this returns the image of that modular
        symbol under the boundary map.

        EXAMPLES::

            sage: M = ModularSymbols(Gamma0(15), 2) ; B = M.boundary_space()
            sage: B(M.0)
            [Infinity] - [0]
            sage: B(Cusp(1))
            [0]
            sage: B(Cusp(oo))
            [Infinity]
            sage: B(7)
            Traceback (most recent call last):
            ...
            TypeError: Coercion of 7 (of type <type 'sage.rings.integer.Integer'>) into Space of Boundary Modular Symbols for Congruence Subgroup Gamma0(15) of weight 2 and over Rational Field not (yet) defined.
        """
        from .ambient import ModularSymbolsAmbient
        if isinstance(x, int) and x == 0:
            return BoundarySpaceElement(self, {})

        elif isinstance(x, cusps.Cusp):
            return self._coerce_cusp(x)

        elif isinstance(x, ManinSymbol):
            return self._coerce_in_manin_symbol(x)

        elif element.is_ModularSymbolsElement(x):
            M = x.parent()
            if not isinstance(M, ModularSymbolsAmbient):
                raise TypeError("x (=%s) must be an element of a space of modular symbols of type ModularSymbolsAmbient"%x)
            if M.level() != self.level():
                raise TypeError("x (=%s) must have level %s but has level %s"%(
                    x, self.level(), M.level()))
            S = x.manin_symbol_rep()
            if len(S) == 0:
                return self(0)
            return sum([c*self._coerce_in_manin_symbol(v) for c, v in S])

        elif is_FreeModuleElement(x):
            y = dict([(i,x[i]) for i in range(len(x))])
            return BoundarySpaceElement(self, y)

        raise TypeError("Coercion of %s (of type %s) into %s not (yet) defined."%(x, type(x), self))
Example #3
0
    def _element_constructor_(self, x):
        r"""
        Return ``x`` coerced into this forms space.

        EXAMPLES::

            sage: from graded_ring import MModularFormsRing
            sage: from space import ModularForms
            sage: MF = ModularForms(k=12, ep=1)
            sage: (x,y,z,d) = MF.pol_ring().gens()

            sage: Delta = MModularFormsRing().Delta()
            sage: Delta.parent()
            MeromorphicModularFormsRing(n=3) over Integer Ring
            sage: MF(Delta)
            q - 24*q^2 + 252*q^3 - 1472*q^4 + O(q^5)
            sage: MF(Delta).parent() == MF
            True

            sage: MF(x^3)
            1 + 720*q + 179280*q^2 + 16954560*q^3 + 396974160*q^4 + O(q^5)
            sage: MF(x^3).parent() == MF
            True

            sage: qexp = Delta.q_expansion(prec=2)
            sage: qexp
            q + O(q^2)
            sage: qexp.parent()
            Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
            sage: MF(qexp)
            q - 24*q^2 + 252*q^3 - 1472*q^4 + O(q^5)
            sage: MF(qexp) == MF(Delta)
            True

            sage: MF([0,1]) == MF(Delta)
            True
            sage: MF([1,0]) == MF(x^3) - 720*MF(Delta) # todo: this should give True, the result is False because d!=1/1728 but a formal parameter
            False

            sage: vec = MF(Delta).coordinate_vector()
            sage: vec
            (0, 1)
            sage: vec.parent()
            Vector space of dimension 2 over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
            sage: vec in MF.module()
            True
            sage: MF(vec) == MF(Delta)
            True

            sage: subspace = MF.subspace([MF(Delta)])
            sage: subspace
            Subspace of dimension 1 of ModularForms(n=3, k=12, ep=1) over Integer Ring
            sage: subspace(MF(Delta)) == subspace(d*(x^3-y^2)) == subspace(qexp) == subspace([0,1]) == subspace(vec) == subspace.gen()
            True
            sage: subspace(MF(Delta)).parent() == subspace(d*(x^3-y^2)).parent() == subspace(qexp).parent() == subspace([0,1]).parent() == subspace(vec).parent()
            True
            sage: subspace([1]) == subspace.gen()
            True
            sage: ssvec = subspace(vec).coordinate_vector()
            sage: ssvec
            (1)
            sage: ssvec.parent()
            Vector space of dimension 1 over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
            sage: ambvec = subspace(vec).ambient_coordinate_vector()
            sage: ambvec
            (0, 1)
            sage: ambvec.parent()
            Vector space of degree 2 and dimension 1 over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
            Basis matrix:
            [0 1]
            sage: subspace(ambvec) == subspace(vec) and subspace(ambvec).parent() == subspace(vec).parent()
            True
        """

        from graded_ring_element import FormsRingElement
        if isinstance(x, FormsRingElement):
            return self.element_class(self, x._rat)
        if hasattr(x, 'parent') and (is_LaurentSeriesRing(x.parent()) or is_PowerSeriesRing(x.parent())):
            # This assumes that the series corresponds to a weakly holomorphic modular form!
            # But the construction method (with the assumption) may also be used for more general form spaces...
            return self.construct_form(x)
        if is_FreeModuleElement(x) and (self.module() == x.parent() or self.ambient_module() == x.parent()):
            return self.element_from_ambient_coordinates(x)
        if (not self.is_ambient()) and (isinstance(x, list) or isinstance(x, tuple) or is_FreeModuleElement(x)) and len(x) == self.rank():
            try:
                return self.element_from_coordinates(x)
            except ArithmeticError, TypeError:
                pass
Example #4
0
def symbolic_expression(x):
    """
    Create a symbolic expression or vector of symbolic expressions from x.

    INPUT:

    - ``x`` - an object

    OUTPUT:

    - a symbolic expression.

    EXAMPLES::

        sage: a = symbolic_expression(3/2); a
        3/2
        sage: type(a)
        <class 'sage.symbolic.expression.Expression'>
        sage: R.<x> = QQ[]; type(x)
        <class 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint'>
        sage: a = symbolic_expression(2*x^2 + 3); a
        2*x^2 + 3
        sage: type(a)
        <class 'sage.symbolic.expression.Expression'>
        sage: from sage.structure.element import Expression
        sage: isinstance(a, Expression)
        True
        sage: a in SR
        True
        sage: a.parent()
        Symbolic Ring

    Note that equations exist in the symbolic ring::

        sage: E = EllipticCurve('15a'); E
        Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 10*x - 10 over Rational Field
        sage: symbolic_expression(E)
        x*y + y^2 + y == x^3 + x^2 - 10*x - 10
        sage: symbolic_expression(E) in SR
        True

    If ``x`` is a list or tuple, create a vector of symbolic expressions::

        sage: v=symbolic_expression([x,1]); v
        (x, 1)
        sage: v.base_ring()
        Symbolic Ring
        sage: v=symbolic_expression((x,1)); v
        (x, 1)
        sage: v.base_ring()
        Symbolic Ring
        sage: v=symbolic_expression((3,1)); v
        (3, 1)
        sage: v.base_ring()
        Symbolic Ring
        sage: E = EllipticCurve('15a'); E
        Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 10*x - 10 over Rational Field
        sage: v=symbolic_expression([E,E]); v
        (x*y + y^2 + y == x^3 + x^2 - 10*x - 10, x*y + y^2 + y == x^3 + x^2 - 10*x - 10)
        sage: v.base_ring()
        Symbolic Ring

    Likewise, if ``x`` is a vector, create a vector of symbolic expressions::

        sage: u = vector([1, 2, 3])
        sage: v = symbolic_expression(u); v
        (1, 2, 3)
        sage: v.parent()
        Vector space of dimension 3 over Symbolic Ring

    If ``x`` is a list or tuple of lists/tuples/vectors, create a matrix of symbolic expressions::

        sage: M = symbolic_expression([[1, x, x^2], (x, x^2, x^3), vector([x^2, x^3, x^4])]); M
        [  1   x x^2]
        [  x x^2 x^3]
        [x^2 x^3 x^4]
        sage: M.parent()
        Full MatrixSpace of 3 by 3 dense matrices over Symbolic Ring

    If ``x`` is a matrix, create a matrix of symbolic expressions::

        sage: A = matrix([[1, 2, 3], [4, 5, 6]])
        sage: B = symbolic_expression(A); B
        [1 2 3]
        [4 5 6]
        sage: B.parent()
        Full MatrixSpace of 2 by 3 dense matrices over Symbolic Ring

    If ``x`` is a function, for example defined by a ``lambda`` expression, create a
    symbolic function::

        sage: f = symbolic_expression(lambda z: z^2 + 1); f
        z |--> z^2 + 1
        sage: f.parent()
        Callable function ring with argument z
        sage: f(7)
        50

    If ``x`` is a list or tuple of functions, or if ``x`` is a function that returns a list
    or tuple, create a callable symbolic vector::

        sage: symbolic_expression([lambda mu, nu: mu^2 + nu^2, lambda mu, nu: mu^2 - nu^2])
        (mu, nu) |--> (mu^2 + nu^2, mu^2 - nu^2)
        sage: f = symbolic_expression(lambda uwu: [1, uwu, uwu^2]); f
        uwu |--> (1, uwu, uwu^2)
        sage: f.parent()
        Vector space of dimension 3 over Callable function ring with argument uwu
        sage: f(5)
        (1, 5, 25)
        sage: f(5).parent()
        Vector space of dimension 3 over Symbolic Ring

    TESTS:

    Lists, tuples, and vectors of length 0 become vectors over a symbolic ring::

        sage: symbolic_expression([]).parent()
        Vector space of dimension 0 over Symbolic Ring
        sage: symbolic_expression(()).parent()
        Vector space of dimension 0 over Symbolic Ring
        sage: symbolic_expression(vector(QQ, 0)).parent()
        Vector space of dimension 0 over Symbolic Ring

    If a matrix has dimension 0, the result is still a matrix over a symbolic ring::

        sage: symbolic_expression(matrix(QQ, 2, 0)).parent()
        Full MatrixSpace of 2 by 0 dense matrices over Symbolic Ring
        sage: symbolic_expression(matrix(QQ, 0, 3)).parent()
        Full MatrixSpace of 0 by 3 dense matrices over Symbolic Ring

    Also functions defined using ``def`` can be used, but we do not advertise it as a use case::

        sage: def sos(x, y):
        ....:     return x^2 + y^2
        sage: symbolic_expression(sos)
        (x, y) |--> x^2 + y^2

    Functions that take a varying number of arguments or keyword-only arguments are not accepted::

        sage: def variadic(x, *y):
        ....:     return x
        sage: symbolic_expression(variadic)
        Traceback (most recent call last):
        ...
        TypeError: unable to convert <function variadic at 0x...> to a symbolic expression

        sage: def function_with_keyword_only_arg(x, *, sign=1):
        ....:     return sign * x
        sage: symbolic_expression(function_with_keyword_only_arg)
        Traceback (most recent call last):
        ...
        TypeError: unable to convert <function function_with_keyword_only_arg at 0x...>
        to a symbolic expression
    """
    from sage.symbolic.expression import Expression
    from sage.symbolic.ring import SR
    from sage.modules.free_module_element import is_FreeModuleElement
    from sage.structure.element import is_Matrix

    if isinstance(x, Expression):
        return x
    elif hasattr(x, '_symbolic_'):
        return x._symbolic_(SR)
    elif isinstance(x, (tuple, list)) or is_FreeModuleElement(x):
        expressions = [symbolic_expression(item) for item in x]
        if not expressions:
            # Make sure it is symbolic also when length is 0
            return vector(SR, 0)
        if is_FreeModuleElement(expressions[0]):
            return matrix(expressions)
        return vector(expressions)
    elif is_Matrix(x):
        if not x.nrows() or not x.ncols():
            # Make sure it is symbolic and of correct dimensions
            # also when a matrix dimension is 0
            return matrix(SR, x.nrows(), x.ncols())
        rows = [symbolic_expression(row) for row in x.rows()]
        return matrix(rows)
    elif callable(x):
        from inspect import signature, Parameter
        try:
            s = signature(x)
        except ValueError:
            pass
        else:
            if all(param.kind in (Parameter.POSITIONAL_ONLY,
                                  Parameter.POSITIONAL_OR_KEYWORD)
                   for param in s.parameters.values()):
                vars = [SR.var(name) for name in s.parameters.keys()]
                result = x(*vars)
                if isinstance(result, (tuple, list)):
                    return vector(SR, result).function(*vars)
                else:
                    return SR(result).function(*vars)
    return SR(x)