Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
""" Conversion of symbolic expressions to other types
This module provides routines for converting new symbolic expressions to other types. Primarily, it provides a class :class:`Converter` which will walk the expression tree and make calls to methods overridden by subclasses. """ ############################################################################### # Sage: Open Source Mathematical Software # Copyright (C) 2009 Mike Hansen <mhansen@gmail.com> # # Distributed under the terms of the GNU General Public License (GPL), # version 2 or any later version. The full text of the GPL is available at: # http://www.gnu.org/licenses/ ###############################################################################
r""" Pynac represents `x/y` as `xy^{-1}`. Often, tree-walkers would prefer to see divisions instead of multiplications and negative exponents. To allow for this (since Pynac internally doesn't have division at all), there is a possibility to pass use_fake_div=True; this will rewrite an Expression into a mixture of Expression and FakeExpression nodes, where the FakeExpression nodes are used to represent divisions. These nodes are intended to act sufficiently like Expression nodes that tree-walkers won't care about the difference. """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import FakeExpression sage: import operator; x,y = var('x,y') sage: FakeExpression([x, y], operator.truediv) FakeExpression([x, y], <built-in function truediv>) """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import FakeExpression sage: import operator; x,y = var('x,y') sage: FakeExpression([x, y], operator.truediv) FakeExpression([x, y], <built-in function truediv>) """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import FakeExpression sage: import operator; x,y = var('x,y') sage: f = FakeExpression([x, y], operator.truediv) sage: f.pyobject() Traceback (most recent call last): ... TypeError: self must be a numeric expression """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import FakeExpression sage: import operator; x,y = var('x,y') sage: f = FakeExpression([x, y], operator.truediv) sage: f.operands() [x, y] """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import FakeExpression sage: import operator; x,y = var('x,y') sage: f = FakeExpression([x, y], operator.truediv) sage: f[0] x """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import FakeExpression sage: import operator; x,y = var('x,y') sage: f = FakeExpression([x, y], operator.truediv) sage: f.operator() <built-in function truediv> """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import FakeExpression sage: import operator; x,y = var('x,y') sage: f = FakeExpression([x, y], operator.truediv) sage: fast_callable(f, vars=['x','y']).op_list() [('load_arg', 0), ('load_arg', 1), 'div', 'return'] """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import FakeExpression sage: import operator; x,y = var('x,y') sage: f = FakeExpression([x, y], operator.truediv) sage: fast_float(f, 'x', 'y').op_list() [('load_arg', 0), ('load_arg', 1), 'div', 'return'] """ return fast_float(self, *vars)
""" If use_fake_div is set to True, then the converter will try to replace expressions whose operator is operator.mul with the corresponding expression whose operator is operator.truediv.
EXAMPLES::
sage: from sage.symbolic.expression_conversions import Converter sage: c = Converter(use_fake_div=True) sage: c.use_fake_div True """
""" .. NOTE::
If this object does not have an attribute ``ex``, then an argument must be passed into :meth:`__call__`.
EXAMPLES::
sage: from sage.symbolic.expression_conversions import Converter sage: c = Converter(use_fake_div=True) sage: c(SR(2)) Traceback (most recent call last): ... NotImplementedError: pyobject sage: c(x+2) Traceback (most recent call last): ... NotImplementedError: arithmetic sage: c(x) Traceback (most recent call last): ... NotImplementedError: symbol sage: c(x==2) Traceback (most recent call last): ... NotImplementedError: relation sage: c(sin(x)) Traceback (most recent call last): ... NotImplementedError: composition sage: c(function('f', x).diff(x)) Traceback (most recent call last): ... NotImplementedError: derivative
We can set a default value for the argument by setting the ``ex`` attribute::
sage: c.ex = SR(2) sage: c() Traceback (most recent call last): ... NotImplementedError: pyobject """
else:
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import Converter sage: c = Converter(use_fake_div=True) sage: c.get_fake_div(sin(x)/x) FakeExpression([sin(x), x], <built-in function truediv>) sage: c.get_fake_div(-1*sin(x)) FakeExpression([sin(x)], <built-in function neg>) sage: c.get_fake_div(-x) FakeExpression([x], <built-in function neg>) sage: c.get_fake_div((2*x^3+2*x-1)/((x-2)*(x+1))) FakeExpression([2*x^3 + 2*x - 1, FakeExpression([x + 1, x - 2], <built-in function mul>)], <built-in function truediv>)
Check if :trac:`8056` is fixed, i.e., if numerator is 1.::
sage: c.get_fake_div(1/pi/x) FakeExpression([1, FakeExpression([pi, x], <built-in function mul>)], <built-in function truediv>) """ else: except TypeError: n.append(arg)
else: else:
else:
""" The input to this method is the result of calling :meth:`pyobject` on a symbolic expression.
.. note::
Note that if a constant such as ``pi`` is encountered in the expression tree, its corresponding pyobject which is an instance of :class:`sage.symbolic.constants.Pi` will be passed into this method. One cannot do arithmetic using such an object.
TESTS::
sage: from sage.symbolic.expression_conversions import Converter sage: f = SR(1) sage: Converter().pyobject(f, f.pyobject()) Traceback (most recent call last): ... NotImplementedError: pyobject """
""" The input to this method is a symbolic expression which corresponds to a single variable. For example, this method could be used to return a generator for a polynomial ring.
TESTS::
sage: from sage.symbolic.expression_conversions import Converter sage: Converter().symbol(x) Traceback (most recent call last): ... NotImplementedError: symbol """
""" The input to this method is a symbolic expression which corresponds to a relation.
TESTS::
sage: from sage.symbolic.expression_conversions import Converter sage: import operator sage: Converter().relation(x==3, operator.eq) Traceback (most recent call last): ... NotImplementedError: relation sage: Converter().relation(x==3, operator.lt) Traceback (most recent call last): ... NotImplementedError: relation """
""" The input to this method is a symbolic expression which corresponds to a relation.
TESTS::
sage: from sage.symbolic.expression_conversions import Converter sage: a = function('f', x).diff(x); a diff(f(x), x) sage: Converter().derivative(a, a.operator()) Traceback (most recent call last): ... NotImplementedError: derivative """
""" The input to this method is a symbolic expression and the infix operator corresponding to that expression. Typically, one will convert all of the arguments and then perform the operation afterward.
TESTS::
sage: from sage.symbolic.expression_conversions import Converter sage: f = x + 2 sage: Converter().arithmetic(f, f.operator()) Traceback (most recent call last): ... NotImplementedError: arithmetic """
""" The input to this method is a symbolic expression and its operator. This method will get called when you have a symbolic function application.
TESTS::
sage: from sage.symbolic.expression_conversions import Converter sage: f = sin(2) sage: Converter().composition(f, f.operator()) Traceback (most recent call last): ... NotImplementedError: composition """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import InterfaceInit sage: m = InterfaceInit(maxima) sage: a = pi + 2 sage: m(a) '(%pi)+(2)' sage: m(sin(a)) 'sin((%pi)+(2))' sage: m(exp(x^2) + pi + 2) '(%pi)+(exp((_SAGE_VAR_x)^(2)))+(2)'
"""
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import InterfaceInit sage: m = InterfaceInit(maxima) sage: m.symbol(x) '_SAGE_VAR_x' sage: f(x) = x sage: m.symbol(f) '_SAGE_VAR_x' sage: ii = InterfaceInit(gp) sage: ii.symbol(x) 'x' """ else:
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import InterfaceInit sage: ii = InterfaceInit(gp) sage: f = 2+I sage: ii.pyobject(f, f.pyobject()) 'I + 2'
sage: ii.pyobject(SR(2), 2) '2'
sage: ii.pyobject(pi, pi.pyobject()) 'Pi' """ isinstance(obj, NumberFieldElement_quadratic) and obj.parent() == GaussianField):
""" EXAMPLES::
sage: import operator sage: from sage.symbolic.expression_conversions import InterfaceInit sage: m = InterfaceInit(maxima) sage: m.relation(x==3, operator.eq) '_SAGE_VAR_x = 3' sage: m.relation(x==3, operator.lt) '_SAGE_VAR_x < 3' """ self(ex.rhs()))
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import InterfaceInit sage: m = InterfaceInit(maxima) sage: t = SR._force_pyobject((3, 4, e^x)) sage: m.tuple(t) '[3,4,exp(_SAGE_VAR_x)]' """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import InterfaceInit sage: m = InterfaceInit(maxima) sage: f = function('f') sage: a = f(x).diff(x); a diff(f(x), x) sage: print(m.derivative(a, a.operator())) diff('f(_SAGE_VAR_x), _SAGE_VAR_x, 1) sage: b = f(x).diff(x, x) sage: print(m.derivative(b, b.operator())) diff('f(_SAGE_VAR_x), _SAGE_VAR_x, 2)
We can also convert expressions where the argument is not just a variable, but the result is an "at" expression using temporary variables::
sage: y = var('y') sage: t = (f(x*y).diff(x))/y sage: t D[0](f)(x*y) sage: m.derivative(t, t.operator()) "at(diff('f(_SAGE_VAR_t0), _SAGE_VAR_t0, 1), [_SAGE_VAR_t0 = (_SAGE_VAR_x)*(_SAGE_VAR_y)])"
TESTS:
Most of these confirm that :trac:`7401` was fixed::
sage: t = var('t'); f = function('f')(t) sage: a = 2^e^t * f.subs(t=e^t) * diff(f, t).subs(t=e^t) + 2*t sage: solve(a == 0, diff(f, t).subs(t=e^t)) [D[0](f)(e^t) == -2^(-e^t + 1)*t/f(e^t)]
::
sage: f = function('f', x) sage: df = f.diff(x); df diff(f(x), x) sage: maxima(df) 'diff('f(_SAGE_VAR_x),_SAGE_VAR_x,1)
::
sage: a = df.subs(x=exp(x)); a D[0](f)(e^x) sage: b = maxima(a); b %at('diff('f(_SAGE_VAR_t0),_SAGE_VAR_t0,1),_SAGE_VAR_t0=%e^_SAGE_VAR_x) sage: bool(b.sage() == a) True
::
sage: a = df.subs(x=4); a D[0](f)(4) sage: b = maxima(a); b %at('diff('f(_SAGE_VAR_t0),_SAGE_VAR_t0,1),_SAGE_VAR_t0=4) sage: bool(b.sage() == a) True
It also works with more than one variable. Note the preferred syntax ``function('f')(x, y)`` to create a general symbolic function of more than one variable::
sage: x, y = var('x y') sage: f = function('f')(x, y) sage: f_x = f.diff(x); f_x diff(f(x, y), x) sage: maxima(f_x) 'diff('f(_SAGE_VAR_x,_SAGE_VAR_y),_SAGE_VAR_x,1)
::
sage: a = f_x.subs(x=4); a D[0](f)(4, y) sage: b = maxima(a); b %at('diff('f(_SAGE_VAR_t0,_SAGE_VAR_y),_SAGE_VAR_t0,1),_SAGE_VAR_t0=4) sage: bool(b.sage() == a) True
::
sage: a = f_x.subs(x=4).subs(y=8); a D[0](f)(4, 8) sage: b = maxima(a); b %at('diff('f(_SAGE_VAR_t0,8),_SAGE_VAR_t0,1),_SAGE_VAR_t0=4) sage: bool(b.sage() == a) True
Test a special case (:trac:`16697`)::
sage: x,y = var('x,y') sage: (gamma_inc(x,y).diff(x)) diff(gamma(x, y), x) sage: (gamma_inc(x,x+1).diff(x)).simplify() -(x + 1)^(x - 1)*e^(-x - 1) + D[0](gamma)(x, x + 1) """ #This code should probably be moved into the interface #object in a nice way. raise NotImplementedError len(args) != len(set(args))): # An evaluated derivative of the form f'(1) is not a # symbolic variable, yet we would like to treat it like # one. So, we replace the argument `1` with a temporary # variable e.g. `t0` and then evaluate the derivative # f'(t0) symbolically at t0=1. See trac #12796. ", ".join(params), ", ".join(subs)) else: ", ".join(params))
""" EXAMPLES::
sage: import operator sage: from sage.symbolic.expression_conversions import InterfaceInit sage: m = InterfaceInit(maxima) sage: m.arithmetic(x+2, sage.symbolic.operators.add_vararg) '(_SAGE_VAR_x)+(2)' """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import InterfaceInit sage: m = InterfaceInit(maxima) sage: m.composition(sin(x), sin) 'sin(_SAGE_VAR_x)' sage: m.composition(ceil(x), ceil) 'ceiling(_SAGE_VAR_x)'
sage: m = InterfaceInit(mathematica) sage: m.composition(sin(x), sin) 'Sin[x]' """ #FIXME: consider stripping pyobjects() in ops else: except (TypeError, AttributeError): op = repr(operator)
######### # Sympy # ######### """ Converts any expression to SymPy.
EXAMPLES::
sage: import sympy sage: var('x,y') (x, y) sage: f = exp(x^2) - arcsin(pi+x)/y sage: f._sympy_() exp(x**2) - asin(x + pi)/y sage: _._sage_() -arcsin(pi + x)/y + e^(x^2)
sage: sympy.sympify(x) # indirect doctest x
TESTS:
Make sure we can convert I (:trac:`6424`)::
sage: bool(I._sympy_() == I) True sage: (x+I)._sympy_() x + I
"""
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import SympyConverter sage: s = SympyConverter() sage: f = SR(2) sage: s.pyobject(f, f.pyobject()) 2 sage: type(_) <class 'sympy.core.numbers.Integer'> """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import SympyConverter sage: s = SympyConverter() sage: f = x + 2 sage: s.arithmetic(f, f.operator()) x + 2 """ return sympy.Sub(*ops) return sympy.Div(*ops) else: raise NotImplementedError
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import SympyConverter sage: s = SympyConverter() sage: s.symbol(x) x sage: type(_) <class 'sympy.core.symbol.Symbol'> """
""" EXAMPLES::
sage: import operator sage: from sage.symbolic.expression_conversions import SympyConverter sage: s = SympyConverter() sage: s.relation(x == 3, operator.eq) Eq(x, 3) sage: s.relation(pi < 3, operator.lt) pi < 3 sage: s.relation(x != pi, operator.ne) Ne(x, pi) sage: s.relation(x > 0, operator.gt) x > 0 """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import SympyConverter sage: s = SympyConverter() sage: f = sin(2) sage: s.composition(f, f.operator()) sin(2) sage: type(_) sin sage: f = arcsin(2) sage: s.composition(f, f.operator()) asin(2) """
else:
""" Convert the derivative of ``self`` in sympy.
INPUT:
- ``ex`` -- a symbolic expression
- ``operator`` -- operator
TESTS::
sage: var('x','y') (x, y)
sage: f_sage = function('f_sage')(x, y) sage: f_sympy = f_sage._sympy_()
sage: df_sage = f_sage.diff(x, 2, y, 1); df_sage diff(f_sage(x, y), x, x, y) sage: df_sympy = df_sage._sympy_(); df_sympy Derivative(f_sage(x, y), x, x, y) sage: df_sympy == f_sympy.diff(x, 2, y, 1) True """
# retrive derivated function
# retrive order # arguments
############# # Algebraic # ############# """ EXAMPLES::
sage: from sage.symbolic.expression_conversions import AlgebraicConverter sage: a = AlgebraicConverter(QQbar) sage: a.field Algebraic Field sage: a.reciprocal_trig_functions['cot'] tan """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import AlgebraicConverter sage: a = AlgebraicConverter(QQbar) sage: f = SR(2) sage: a.pyobject(f, f.pyobject()) 2 sage: _.parent() Algebraic Field """
""" Convert a symbolic expression to an algebraic number.
EXAMPLES::
sage: from sage.symbolic.expression_conversions import AlgebraicConverter sage: f = 2^(1/2) sage: a = AlgebraicConverter(QQbar) sage: a.arithmetic(f, f.operator()) 1.414213562373095?
TESTS::
sage: f = pi^6 sage: a = AlgebraicConverter(QQbar) sage: a.arithmetic(f, f.operator()) Traceback (most recent call last): ... TypeError: unable to convert pi^6 to Algebraic Field """ # We try to avoid simplifying, because maxima's simplify command # can change the value of a radical expression (by changing which # root is selected). else:
return exp(expt)._algebraic_(self.field)
""" Coerce to an algebraic number.
EXAMPLES::
sage: from sage.symbolic.expression_conversions import AlgebraicConverter sage: a = AlgebraicConverter(QQbar) sage: a.composition(exp(I*pi/3, hold=True), exp) 0.500000000000000? + 0.866025403784439?*I sage: a.composition(sin(pi/7), sin) 0.4338837391175581? + 0.?e-18*I
TESTS::
sage: QQbar(zeta(7)) Traceback (most recent call last): ... TypeError: unable to convert zeta(7) to Algebraic Field
Test :trac:`22571`::
sage: a.composition(exp(0, hold=True), exp) 1 sage: a.composition(exp(1, hold=True), exp) Traceback (most recent call last): ... ValueError: unable to represent as an algebraic number sage: a.composition(exp(pi*I*RR(1), hold=True), exp) Traceback (most recent call last): ... TypeError: no canonical coercion from Real Field with 53 bits of precision to Rational Field sage: a.composition(exp(pi*CC.gen(), hold=True), exp) Traceback (most recent call last): ... TypeError: no canonical coercion from Real Field with 53 bits of precision to Rational Field sage: bool(sin(pi*RR("0.7000000000000002")) > 0) True """
# Note that comparing functions themselves goes via maxima, and is SLOW # Coerce (not convert, see #22571) arg to a rational else: res = -QQbar.zeta(4)*(exp_ia - ~exp_ia)/(exp_ia + ~exp_ia) if func_name == 'sinh': res = (exp_a - ~exp_a)/2 elif func_name == 'cosh': res = (exp_a + ~exp_a)/2 else: res = (exp_a - ~exp_a) / (exp_a + ~exp_a) else: #We have to handle the case where we get the same symbolic #expression back. For example, QQbar(zeta(7)). See #ticket #12665.
""" Returns the symbolic expression *ex* as a element of the algebraic field *field*.
EXAMPLES::
sage: a = SR(5/6) sage: AA(a) 5/6 sage: type(AA(a)) <class 'sage.rings.qqbar.AlgebraicReal'> sage: QQbar(a) 5/6 sage: type(QQbar(a)) <class 'sage.rings.qqbar.AlgebraicNumber'> sage: QQbar(i) I sage: AA(golden_ratio) 1.618033988749895? sage: QQbar(golden_ratio) 1.618033988749895? sage: QQbar(sin(pi/3)) 0.866025403784439?
sage: QQbar(sqrt(2) + sqrt(8)) 4.242640687119285? sage: AA(sqrt(2) ^ 4) == 4 True sage: AA(-golden_ratio) -1.618033988749895? sage: QQbar((2*I)^(1/2)) 1 + 1*I sage: QQbar(e^(pi*I/3)) 0.50000000000000000? + 0.866025403784439?*I
sage: AA(x*sin(0)) 0 sage: QQbar(x*sin(0)) 0 """
############## # Polynomial # ############## """ A converter from symbolic expressions to polynomials.
See :func:`polynomial` for details.
EXAMPLES::
sage: from sage.symbolic.expression_conversions import PolynomialConverter sage: x, y = var('x,y') sage: p = PolynomialConverter(x+y, base_ring=QQ) sage: p.base_ring Rational Field sage: p.ring Multivariate Polynomial Ring in x, y over Rational Field
sage: p = PolynomialConverter(x, base_ring=QQ) sage: p.base_ring Rational Field sage: p.ring Univariate Polynomial Ring in x over Rational Field
sage: p = PolynomialConverter(x, ring=QQ['x,y']) sage: p.base_ring Rational Field sage: p.ring Multivariate Polynomial Ring in x, y over Rational Field
sage: p = PolynomialConverter(x+y, ring=QQ['x']) Traceback (most recent call last): ... TypeError: y is not a variable of Univariate Polynomial Ring in x over Rational Field
TESTS::
sage: t, x, z = SR.var('t,x,z') sage: QQ[i]['x,y,z,t'](4*I*t + 2*x -12*z + 2) 2*x - 12*z + (4*I)*t + 2 """ raise TypeError("either base_ring or ring must be specified, but not both")
else: raise TypeError("either a ring or base ring must be specified")
""" Returns a variable in the polynomial ring.
EXAMPLES::
sage: from sage.symbolic.expression_conversions import PolynomialConverter sage: p = PolynomialConverter(x, base_ring=QQ) sage: p.symbol(x) x sage: _.parent() Univariate Polynomial Ring in x over Rational Field sage: y = var('y') sage: p = PolynomialConverter(x*y, ring=SR['x']) sage: p.symbol(y) y """ #The symbol is one of the polynomial generators #The symbol should go into the base ring
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import PolynomialConverter sage: p = PolynomialConverter(x, base_ring=QQ) sage: f = SR(2) sage: p.pyobject(f, f.pyobject()) 2 sage: _.parent() Rational Field """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import PolynomialConverter sage: a = sin(2) sage: p = PolynomialConverter(a*x, base_ring=RR) sage: p.composition(a, a.operator()) 0.909297426825682 """
""" EXAMPLES::
sage: import operator sage: from sage.symbolic.expression_conversions import PolynomialConverter
sage: x, y = var('x, y') sage: p = PolynomialConverter(x, base_ring=RR)
sage: p.relation(x==3, operator.eq) x - 3.00000000000000 sage: p.relation(x==3, operator.lt) Traceback (most recent call last): ... ValueError: Unable to represent as a polynomial
sage: p = PolynomialConverter(x - y, base_ring=QQ) sage: p.relation(x^2 - y^3 + 1 == x^3, operator.eq) -x^3 - y^3 + x^2 + 1 """ else:
""" EXAMPLES::
sage: import operator sage: from sage.symbolic.expression_conversions import PolynomialConverter
sage: x, y = var('x, y') sage: p = PolynomialConverter(x, base_ring=RR) sage: p.arithmetic(pi+e, operator.add) 5.85987448204884 sage: p.arithmetic(x^2, operator.pow) x^2
sage: p = PolynomialConverter(x+y, base_ring=RR) sage: p.arithmetic(x*y+y^2, operator.add) x*y + y^2
sage: p = PolynomialConverter(y^(3/2), ring=SR['x']) sage: p.arithmetic(y^(3/2), operator.pow) y^(3/2) sage: _.parent() Symbolic Ring """
""" Return a polynomial from the symbolic expression ``ex``.
INPUT:
- ``ex`` -- a symbolic expression
- ``base_ring``, ``ring`` -- Either a ``base_ring`` or a polynomial ``ring`` can be specified for the parent of result. If just a ``base_ring`` is given, then the variables of the ``base_ring`` will be the variables of the expression ``ex``.
OUTPUT:
A polynomial.
EXAMPLES::
sage: from sage.symbolic.expression_conversions import polynomial sage: f = x^2 + 2 sage: polynomial(f, base_ring=QQ) x^2 + 2 sage: _.parent() Univariate Polynomial Ring in x over Rational Field
sage: polynomial(f, ring=QQ['x,y']) x^2 + 2 sage: _.parent() Multivariate Polynomial Ring in x, y over Rational Field
sage: x, y = var('x, y') sage: polynomial(x + y^2, ring=QQ['x,y']) y^2 + x sage: _.parent() Multivariate Polynomial Ring in x, y over Rational Field
sage: s,t=var('s,t') sage: expr=t^2-2*s*t+1 sage: expr.polynomial(None,ring=SR['t']) t^2 - 2*s*t + 1 sage: _.parent() Univariate Polynomial Ring in t over Symbolic Ring
sage: polynomial(x*y, ring=SR['x']) y*x
sage: polynomial(y - sqrt(x), ring=SR['y']) y - sqrt(x) sage: _.list() [-sqrt(x), 1]
The polynomials can have arbitrary (constant) coefficients so long as they coerce into the base ring::
sage: polynomial(2^sin(2)*x^2 + exp(3), base_ring=RR) 1.87813065119873*x^2 + 20.0855369231877 """
""" A converter from symbolic expressions to Laurent polynomials.
See :func:`laurent_polynomial` for details.
TESTS::
sage: from sage.symbolic.expression_conversions import LaurentPolynomialConverter sage: x, y = var('x,y') sage: p = LaurentPolynomialConverter(x+1/y, base_ring=QQ) sage: p.base_ring Rational Field sage: p.ring Multivariate Laurent Polynomial Ring in x, y over Rational Field """
names=self.varnames)
""" Return a Laurent polynomial from the symbolic expression ``ex``.
INPUT:
- ``ex`` -- a symbolic expression
- ``base_ring``, ``ring`` -- Either a ``base_ring`` or a Laurent polynomial ``ring`` can be specified for the parent of result. If just a ``base_ring`` is given, then the variables of the ``base_ring`` will be the variables of the expression ``ex``.
OUTPUT:
A Laurent polynomial.
EXAMPLES::
sage: from sage.symbolic.expression_conversions import laurent_polynomial sage: f = x^2 + 2/x sage: laurent_polynomial(f, base_ring=QQ) 2*x^-1 + x^2 sage: _.parent() Univariate Laurent Polynomial Ring in x over Rational Field
sage: laurent_polynomial(f, ring=LaurentPolynomialRing(QQ, 'x, y')) x^2 + 2*x^-1 sage: _.parent() Multivariate Laurent Polynomial Ring in x, y over Rational Field
sage: x, y = var('x, y') sage: laurent_polynomial(x + 1/y^2, ring=LaurentPolynomialRing(QQ, 'x, y')) x + y^-2 sage: _.parent() Multivariate Laurent Polynomial Ring in x, y over Rational Field """
############## # Fast Float # ##############
""" Returns an object which provides fast floating point evaluation of the symbolic expression *ex*. This is an class used internally and is not meant to be used directly.
See :mod:`sage.ext.fast_eval` for more information.
EXAMPLES::
sage: x,y,z = var('x,y,z') sage: f = 1 + sin(x)/x + sqrt(z^2+y^2)/cosh(x) sage: ff = f._fast_float_('x', 'y', 'z') sage: f(x=1.0,y=2.0,z=3.0).n() 4.1780638977... sage: ff(1.0,2.0,3.0) 4.1780638977...
Using ``_fast_float_`` without specifying the variable names is deprecated::
sage: f = x._fast_float_() doctest:...: DeprecationWarning: Substitution using function-call syntax and unnamed arguments is deprecated and will be removed from a future release of Sage; you can use named arguments instead, like EXPR(x=..., y=...) See http://trac.sagemath.org/5930 for details. sage: f(1.2) 1.2
Using ``_fast_float_`` on a function which is the identity is Using _fast_float_ on a function which is the identity is now supported (see :trac:`10246`)::
sage: f = symbolic_expression(x).function(x) sage: f._fast_float_(x) <sage.ext.fast_eval.FastDoubleFunc object at ...> sage: f(22) 22 """
except AttributeError: vars = ex.variables()
""" EXAMPLES::
sage: ff = fast_float(x == 2, 'x') sage: ff(2) 0.0 sage: ff(4) 2.0 sage: ff = fast_float(x < 2, 'x') Traceback (most recent call last): ... NotImplementedError """ raise NotImplementedError
""" EXAMPLES::
sage: f = SR(2)._fast_float_() sage: f(3) 2.0 """
r""" EXAMPLES::
sage: f = x._fast_float_('x', 'y') sage: f(1,2) 1.0 sage: f = x._fast_float_('y', 'x') sage: f(1,2) 2.0 """ return self.ff.fast_float_arg(0)
try: return self.ff.fast_float_constant(float(ex)) except TypeError: raise NotImplementedError("free variable: %s" % repr(ex))
""" EXAMPLES::
sage: x,y = var('x,y') sage: f = x*x-y sage: ff = f._fast_float_('x','y') sage: ff(2,3) 1.0
sage: a = x + 2*y sage: f = a._fast_float_('x', 'y') sage: f(1,0) 1.0 sage: f(0,1) 2.0
sage: f = sqrt(x)._fast_float_('x'); f.op_list() ['load 0', 'call sqrt(1)']
sage: f = (1/2*x)._fast_float_('x'); f.op_list() ['load 0', 'push 0.5', 'mul'] """
""" EXAMPLES::
sage: f = sqrt(x)._fast_float_('x') sage: f(2) 1.41421356237309... sage: y = var('y') sage: f = sqrt(x+y)._fast_float_('x', 'y') sage: f(1,1) 1.41421356237309...
::
sage: f = sqrt(x+2*y)._fast_float_('x', 'y') sage: f(2,0) 1.41421356237309... sage: f(0,1) 1.41421356237309... """ return abs(*g) # special case else:
""" Returns an object which provides fast floating point evaluation of the symbolic expression *ex*.
See :mod:`sage.ext.fast_eval` for more information.
EXAMPLES::
sage: from sage.symbolic.expression_conversions import fast_float sage: f = sqrt(x+1) sage: ff = fast_float(f, 'x') sage: ff(1.0) 1.4142135623730951 """
################# # Fast Callable # #################
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import FastCallableConverter sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=['x']) sage: f = FastCallableConverter(x+2, etb) sage: f.ex x + 2 sage: f.etb <sage.ext.fast_callable.ExpressionTreeBuilder object at 0x...> sage: f.use_fake_div True """
r""" EXAMPLES::
sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=['x']) sage: pi._fast_callable_(etb) pi sage: etb = ExpressionTreeBuilder(vars=['x'], domain=RDF) sage: pi._fast_callable_(etb) 3.141592653589793 """
""" EXAMPLES::
sage: ff = fast_callable(x == 2, vars=['x']) sage: ff(2) 0 sage: ff(4) 2 sage: ff = fast_callable(x < 2, vars=['x']) Traceback (most recent call last): ... NotImplementedError """
r""" EXAMPLES::
sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=['x','y']) sage: var('x,y') (x, y) sage: (x+y)._fast_callable_(etb) add(v_0, v_1) sage: (-x)._fast_callable_(etb) neg(v_0) sage: (x+y+x^2)._fast_callable_(etb) add(add(ipow(v_0, 2), v_0), v_1)
TESTS:
Check if rational functions with numerator 1 can be converted. (:trac:`8056`)::
sage: (1/pi/x)._fast_callable_(etb) div(1, mul(pi, v_0))
sage: etb = ExpressionTreeBuilder(vars=['x'], domain=RDF) sage: (x^7)._fast_callable_(etb) ipow(v_0, 7) sage: f(x)=1/pi/x; plot(f,2,3) Graphics object consisting of 1 graphics primitive """ # This used to convert the operands first. Doing it this way # instead gives a chance to notice powers with an integer # exponent before the exponent gets (potentially) converted # to another type.
r""" Given an ExpressionTreeBuilder, return an Expression representing this value.
EXAMPLES::
sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=['x','y']) sage: x, y, z = var('x,y,z') sage: x._fast_callable_(etb) v_0 sage: y._fast_callable_(etb) v_1 sage: z._fast_callable_(etb) Traceback (most recent call last): ... ValueError: Variable 'z' not found """
r""" Given an ExpressionTreeBuilder, return an Expression representing this value.
EXAMPLES::
sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=['x','y']) sage: x,y = var('x,y') sage: sin(sqrt(x+y))._fast_callable_(etb) sin(sqrt(add(v_0, v_1))) sage: arctan2(x,y)._fast_callable_(etb) {arctan2}(v_0, v_1) """
r""" Given a symbolic tuple, return its elements as a Python list.
EXAMPLES::
sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=['x']) sage: SR._force_pyobject((2, 3, x^2))._fast_callable_(etb) [2, 3, x^2] """
""" Given an ExpressionTreeBuilder *etb*, return an Expression representing the symbolic expression *ex*.
EXAMPLES::
sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=['x','y']) sage: x,y = var('x,y') sage: f = y+2*x^2 sage: f._fast_callable_(etb) add(mul(ipow(v_0, 2), 2), v_1)
sage: f = (2*x^3+2*x-1)/((x-2)*(x+1)) sage: f._fast_callable_(etb) div(add(add(mul(ipow(v_0, 3), 2), mul(v_0, 2)), -1), mul(add(v_0, 1), add(v_0, -2)))
"""
""" A class to convert expressions to other rings.
EXAMPLES::
sage: from sage.symbolic.expression_conversions import RingConverter sage: R = RingConverter(RIF, subs_dict={x:2}) sage: R.ring Real Interval Field with 53 bits of precision sage: R.subs_dict {x: 2} sage: R(pi+e) 5.85987448204884? sage: loads(dumps(R)) <sage.symbolic.expression_conversions.RingConverter object at 0x...> """
""" All symbols appearing in the expression must appear in *subs_dict* in order for the conversion to be successful.
EXAMPLES::
sage: from sage.symbolic.expression_conversions import RingConverter sage: R = RingConverter(RIF, subs_dict={x:2}) sage: R(x+pi) 5.141592653589794?
sage: R = RingConverter(RIF) sage: R(x+pi) Traceback (most recent call last): ... TypeError """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import RingConverter sage: R = RingConverter(RIF) sage: R(SR(5/2)) 2.5000000000000000? """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import RingConverter sage: P.<z> = ZZ[] sage: R = RingConverter(P, subs_dict={x:z}) sage: a = 2*x^2 + x + 3 sage: R(a) 2*z^2 + z + 3 """ raise TypeError
from sage.functions.all import sqrt return sqrt(self(base)) except TypeError: pass
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import RingConverter sage: R = RingConverter(RIF) sage: R(cos(2)) -0.4161468365471424? """ raise TypeError else:
""" A class that walks the tree. Mainly for subclassing.
EXAMPLES::
sage: from sage.symbolic.expression_conversions import ExpressionTreeWalker sage: from sage.symbolic.random_tests import random_expr sage: ex = sin(atan(0,hold=True)+hypergeometric((1,),(1,),x)) sage: s = ExpressionTreeWalker(ex) sage: bool(s() == ex) True sage: foo = random_expr(20, nvars=2) sage: s = ExpressionTreeWalker(foo) sage: bool(s() == foo) True """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import ExpressionTreeWalker sage: s = ExpressionTreeWalker(x) sage: bool(s.symbol(x) == x) True """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import ExpressionTreeWalker sage: f = SR(2) sage: s = ExpressionTreeWalker(f) sage: bool(s.pyobject(f, f.pyobject()) == f.pyobject()) True """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import ExpressionTreeWalker sage: foo = function('foo') sage: eq = foo(x) == x sage: s = ExpressionTreeWalker(eq) sage: s.relation(eq, eq.operator()) == eq True """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import ExpressionTreeWalker sage: foo = function('foo') sage: f = x*foo(x) + pi/foo(x) sage: s = ExpressionTreeWalker(f) sage: bool(s.arithmetic(f, f.operator()) == f) True """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import ExpressionTreeWalker sage: foo = function('foo') sage: f = foo(atan2(0, 0, hold=True)) sage: s = ExpressionTreeWalker(f) sage: bool(s.composition(f, f.operator()) == f) True """ else: return operator(*map(self, ex.operands()))
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import ExpressionTreeWalker sage: foo = function('foo') sage: f = foo(x).diff(x) sage: s = ExpressionTreeWalker(f) sage: bool(s.derivative(f, f.operator()) == f) True """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import ExpressionTreeWalker sage: foo = function('foo') sage: f = hypergeometric((1,2,3,),(x,),x) sage: s = ExpressionTreeWalker(f) sage: bool(s() == f) True """
""" A class that walks the tree and replaces occurrences of a function with another.
EXAMPLES::
sage: from sage.symbolic.expression_conversions import SubstituteFunction sage: foo = function('foo'); bar = function('bar') sage: s = SubstituteFunction(foo(x), foo, bar) sage: s(1/foo(foo(x)) + foo(2)) 1/bar(bar(x)) + bar(2) """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import SubstituteFunction sage: foo = function('foo'); bar = function('bar') sage: s = SubstituteFunction(foo(x), foo, bar) sage: f = foo(x) sage: s.composition(f, f.operator()) bar(x) sage: f = foo(foo(x)) sage: s.composition(f, f.operator()) bar(bar(x)) sage: f = sin(foo(x)) sage: s.composition(f, f.operator()) sin(bar(x)) sage: f = foo(sin(x)) sage: s.composition(f, f.operator()) bar(sin(x)) """ else:
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import SubstituteFunction sage: foo = function('foo'); bar = function('bar') sage: s = SubstituteFunction(foo(x), foo, bar) sage: f = foo(x).diff(x) sage: s.derivative(f, f.operator()) diff(bar(x), x)
TESTS:
We can substitute functions under a derivative operator, :trac:`12801`::
sage: f = function('f') sage: g = function('g') sage: f(g(x)).diff(x).substitute_function(g, sin) cos(x)*D[0](f)(sin(x))
""" else:
""" A class that walks the tree and evaluates every operator that is not in a given list of exceptions.
EXAMPLES::
sage: from sage.symbolic.expression_conversions import HoldRemover sage: ex = sin(pi*cos(0, hold=True), hold=True); ex sin(pi*cos(0)) sage: h = HoldRemover(ex) sage: h() 0 sage: h = HoldRemover(ex, [sin]) sage: h() sin(pi) sage: h = HoldRemover(ex, [cos]) sage: h() sin(pi*cos(0)) sage: ex = atan2(0, 0, hold=True) + hypergeometric([1,2], [3,4], 0, hold=True) sage: h = HoldRemover(ex, [atan2]) sage: h() arctan2(0, 0) + 1 sage: h = HoldRemover(ex, [hypergeometric]) sage: h() NaN + hypergeometric((1, 2), (3, 4), 0) """
""" EXAMPLES::
sage: from sage.symbolic.expression_conversions import HoldRemover sage: ex = sin(pi*cos(0, hold=True), hold=True); ex sin(pi*cos(0)) sage: h = HoldRemover(ex) sage: h() 0 """ return self else: |