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))
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))
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
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)