From d7da52cfd46a01f6710b79a01ea2f05ec4e9b96a Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Wed, 3 Dec 2014 15:52:39 +0100 Subject: [PATCH 1/3] 17438: implement coeff list --- src/sage/symbolic/expression.pyx | 39 ++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 021c40c91eb..12a4d14904b 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -5124,7 +5124,7 @@ cdef class Expression(CommutativeRingElement): coeff = coefficient - def coefficients(self, x=None): + def coefficients(self, x=None, sparse=True): r""" Return the coefficients of this symbolic expression as a polynomial in x. @@ -5144,18 +5144,33 @@ cdef class Expression(CommutativeRingElement): sage: p = x^3 - (x-3)*(x^2+x) + 1 sage: p.coefficients() [[1, 0], [3, 1], [2, 2]] + sage: p.coefficients(sparse=False) + [1, 3, 2] + sage: p = x - x^3 + 5/7*x^5 + sage: p.coefficients() + [[1, 1], [-1, 3], [5/7, 5]] + sage: p.coefficients(sparse=False) + [0, 1, 0, -1, 0, 5/7] sage: p = expand((x-a*sqrt(2))^2 + x + 1); p -2*sqrt(2)*a*x + 2*a^2 + x^2 + x + 1 sage: p.coefficients(a) [[x^2 + x + 1, 0], [-2*sqrt(2)*x, 1], [2, 2]] + sage: p.coefficients(a, sparse=False) + [x^2 + x + 1, -2*sqrt(2)*x, 2] sage: p.coefficients(x) [[2*a^2 + 1, 0], [-2*sqrt(2)*a + 1, 1], [1, 2]] + sage: p.coefficients(x, sparse=False) + [2*a^2 + 1, -2*sqrt(2)*a + 1, 1] - A polynomial with wacky exponents:: + The behaviour is undefined with noninteger or negative exponents:: sage: p = (17/3*a)*x^(3/2) + x*y + 1/x + x^x sage: p.coefficients(x) [[1, -1], [x^x, 0], [y, 1], [17/3*a, 3/2]] + sage: p.coefficients(x, sparse=False) + Traceback (most recent call last): + ... + ValueError: Cannot return dense coefficient list with noninteger exponents. """ f = self._maxima_() maxima = f.parent() @@ -5166,9 +5181,23 @@ cdef class Expression(CommutativeRingElement): G = f.coeffs(x) from sage.calculus.calculus import symbolic_expression_from_maxima_string S = symbolic_expression_from_maxima_string(repr(G)) - return S[1:] - - coeffs = coefficients + l = S[1:] + if sparse is True: + return l + else: + from sage.rings.integer_ring import ZZ + if any(not c[1] in ZZ for c in l): + raise ValueError("Cannot return dense coefficient list with noninteger exponents.") + val = l[0][1] + if val < 0: + raise ValueError("Cannot return dense coefficient list with negative valuation.") + deg = l[-1][1] + ret = [ZZ(0)] * int(deg+1) + for c in l: + ret[c[1]] = c[0] + return ret + + coeffs = coefficients def leading_coefficient(self, s): """ From 9452fa934b8064657743e4ba32869430304fdb13 Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Thu, 4 Dec 2014 10:17:18 +0100 Subject: [PATCH 2/3] 17438: deprecate ex.coeff/coeffs() --- src/sage/calculus/calculus.py | 2 +- src/sage/combinat/tutorial.py | 2 +- src/sage/databases/oeis.py | 2 +- src/sage/matrix/constructor.py | 2 +- src/sage/modules/vector_space_morphism.py | 2 +- src/sage/rings/padics/factory.py | 2 +- src/sage/symbolic/expression.pyx | 48 ++++++++++++------- src/sage/symbolic/function_factory.py | 4 +- .../tests/french_book/nonlinear_doctest.py | 2 +- 9 files changed, 40 insertions(+), 26 deletions(-) diff --git a/src/sage/calculus/calculus.py b/src/sage/calculus/calculus.py index 7e340e5ba06..63a7af8ad52 100644 --- a/src/sage/calculus/calculus.py +++ b/src/sage/calculus/calculus.py @@ -379,7 +379,7 @@ + 4*euler_gamma*(sqrt(3)*pi + 9*log(3)) + 27*log(3)^2 + 12*psi(1, 1/3))*x^2*gamma(1/3) - 1/6*(6*euler_gamma + sqrt(3)*pi + 9*log(3))*x*gamma(1/3) + gamma(1/3) - sage: map(lambda f:f[0].n(), _.coeffs()) # numerical coefficients to make comparison easier; Maple 12 gives same answer + sage: map(lambda f:f[0].n(), _.coefficients()) # numerical coefficients to make comparison easier; Maple 12 gives same answer [2.6789385347..., -8.3905259853..., 26.662447494..., -80.683148377...] Ensure that ticket #8582 is fixed:: diff --git a/src/sage/combinat/tutorial.py b/src/sage/combinat/tutorial.py index ddd5a87a785..b38a543e527 100644 --- a/src/sage/combinat/tutorial.py +++ b/src/sage/combinat/tutorial.py @@ -319,7 +319,7 @@ or calculate, more or less instantaneously, the 100-th coefficient:: - sage: C.series(z, 101).coeff(z,100) + sage: C.series(z, 101).coefficient(z,100) 227508830794229349661819540395688853956041682601541047340 It is unfortunate to have to recalculate everything if at some point we diff --git a/src/sage/databases/oeis.py b/src/sage/databases/oeis.py index 99a3d56ab9f..66a556ccb48 100644 --- a/src/sage/databases/oeis.py +++ b/src/sage/databases/oeis.py @@ -95,7 +95,7 @@ :: sage: x = var('x') ; f(x) = e^(e^x - 1) - sage: L = [a*factorial(b) for a,b in taylor(f(x), x, 0, 20).coeffs()] ; L + sage: L = [a*factorial(b) for a,b in taylor(f(x), x, 0, 20).coefficients()] ; L [1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147, 115975, 678570, 4213597, 27644437, 190899322, 1382958545, 10480142147, 82864869804, 682076806159, 5832742205057, 51724158235372] diff --git a/src/sage/matrix/constructor.py b/src/sage/matrix/constructor.py index 552a22f6b59..4ccc9d0fe08 100644 --- a/src/sage/matrix/constructor.py +++ b/src/sage/matrix/constructor.py @@ -2906,7 +2906,7 @@ def companion_matrix(poly, format='right'): ... TypeError: input must be a polynomial (not a symbolic expression, see docstring), or other iterable, not y^3 - 2*y + 1 - sage: coeff_list = [q(y=0)] + [q.coeff(y^k) for k in range(1, q.degree(y)+1)] + sage: coeff_list = [q(y=0)] + [q.coefficient(y^k) for k in range(1, q.degree(y)+1)] sage: coeff_list [1, -2, 0, 1] sage: companion_matrix(coeff_list) diff --git a/src/sage/modules/vector_space_morphism.py b/src/sage/modules/vector_space_morphism.py index 63f43024377..6e7961ce69a 100644 --- a/src/sage/modules/vector_space_morphism.py +++ b/src/sage/modules/vector_space_morphism.py @@ -748,7 +748,7 @@ def linear_transformation(arg0, arg1=None, arg2=None, side='left'): raise ValueError('symbolic function has the wrong number of inputs for domain') if n != C.degree(): raise ValueError('symbolic function has the wrong number of outputs for codomain') - arg2 = [[e.coeff(a) for e in exprs] for a in args] + arg2 = [[e.coefficient(a) for e in exprs] for a in args] try: arg2 = matrix(D.base_ring(), m, n, arg2) except TypeError as e: diff --git a/src/sage/rings/padics/factory.py b/src/sage/rings/padics/factory.py index bf6edc5f89f..a5b3593e483 100644 --- a/src/sage/rings/padics/factory.py +++ b/src/sage/rings/padics/factory.py @@ -2277,7 +2277,7 @@ def create_key_and_extra_args(self, base, premodulus, prec = None, print_mode = # the information needed to shift right with full precision from the premodulus. if is_Expression(premodulus): # Here we assume that the output of coeffs is sorted in increasing order by exponent: - coeffs = premodulus.coeffs() + coeffs = premodulus.coefficients() preseed = premodulus / coeffs[-1][0] preseed -= preseed.variables()[0]**coeffs[-1][1] preseed /= base.prime() # here we assume that the base is unramified over Qp diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 12a4d14904b..d56febeb191 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -832,21 +832,21 @@ cdef class Expression(CommutativeRingElement): EXAMPLES:: sage: f = x^3 + 17*x -3 - sage: ZZ(f.coeff(x^3)) + sage: ZZ(f.coefficient(x^3)) 1 - sage: ZZ(f.coeff(x)) + sage: ZZ(f.coefficient(x)) 17 - sage: ZZ(f.coeff(x,0)) + sage: ZZ(f.coefficient(x,0)) -3 - sage: type(ZZ(f.coeff(x,0))) + sage: type(ZZ(f.coefficient(x,0))) Coercion is done if necessary:: sage: f = x^3 + 17/1*x - sage: ZZ(f.coeff(x)) + sage: ZZ(f.coefficient(x)) 17 - sage: type(ZZ(f.coeff(x))) + sage: type(ZZ(f.coefficient(x))) If the symbolic expression is just a wrapper around an integer, @@ -914,15 +914,15 @@ cdef class Expression(CommutativeRingElement): EXAMPLES:: sage: f = x^3 + 17/1*x - 3/8 - sage: QQ(f.coeff(x^2)) + sage: QQ(f.coefficient(x^2)) 0 - sage: QQ(f.coeff(x^3)) + sage: QQ(f.coefficient(x^3)) 1 - sage: a = QQ(f.coeff(x)); a + sage: a = QQ(f.coefficient(x)); a 17 sage: type(a) - sage: QQ(f.coeff(x,0)) + sage: QQ(f.coefficient(x,0)) -3/8 If the symbolic expression is just a wrapper around a rational, @@ -4093,9 +4093,9 @@ cdef class Expression(CommutativeRingElement): False sage: (4*x^2 + x + 3).has(x) True - sage: (4*x^2 - x + 3).coeff(x,1) + sage: (4*x^2 - x + 3).coefficient(x,1) -1 - sage: (4*x^2 + x + 3).coeff(x,1) + sage: (4*x^2 + x + 3).coefficient(x,1) 1 """ cdef Expression p = self.coerce_in(pattern) @@ -5103,12 +5103,19 @@ cdef class Expression(CommutativeRingElement): sage: var('x,y,z') (x, y, z) sage: f = x*y*z^2 - sage: f.coeff(x*y) + sage: f.coefficient(x*y) z^2 - sage: f.coeff(x*y, 2) + sage: f.coefficient(x*y, 2) Traceback (most recent call last): ... TypeError: n != 1 only allowed for s being a variable + + Using ``coeff()`` is now deprecated (:trac:`17438`):: + + sage: x.coeff(x) + doctest:...: DeprecationWarning: coeff is deprecated. Please use coefficient instead. + See http://trac.sagemath.org/17438 for details. + 1 """ cdef Expression ss = self.coerce_in(s) if n != 1 and not is_a_symbol(ss._gobj): @@ -5118,11 +5125,11 @@ cdef class Expression(CommutativeRingElement): if is_a_mul(ss._gobj): # necessarily n=1 here res = self for i from 0 <= i < ss._gobj.nops(): - res = res.coeff(new_Expression_from_GEx(self._parent, ss._gobj.op(i))) + res = res.coefficient(new_Expression_from_GEx(self._parent, ss._gobj.op(i))) return res return new_Expression_from_GEx(self._parent, self._gobj.coeff(ss._gobj, n)) - coeff = coefficient + coeff = deprecated_function_alias(17438, coefficient) def coefficients(self, x=None, sparse=True): r""" @@ -5171,6 +5178,13 @@ cdef class Expression(CommutativeRingElement): Traceback (most recent call last): ... ValueError: Cannot return dense coefficient list with noninteger exponents. + + Using ``coeffs()`` is now deprecated (:trac:`17438`):: + + sage: x.coeffs() + doctest:...: DeprecationWarning: coeffs is deprecated. Please use coefficients instead. + See http://trac.sagemath.org/17438 for details. + [[1, 1]] """ f = self._maxima_() maxima = f.parent() @@ -5197,7 +5211,7 @@ cdef class Expression(CommutativeRingElement): ret[c[1]] = c[0] return ret - coeffs = coefficients + coeffs = deprecated_function_alias(17438, coefficients) def leading_coefficient(self, s): """ diff --git a/src/sage/symbolic/function_factory.py b/src/sage/symbolic/function_factory.py index a72a4ec8f4e..42012a3d3a5 100644 --- a/src/sage/symbolic/function_factory.py +++ b/src/sage/symbolic/function_factory.py @@ -217,9 +217,9 @@ def function(s, *args, **kwds): (r^2*D[0, 0](psi)(r) + 2*r*D[0](psi)(r))/r^2 sage: g.expand() 2*D[0](psi)(r)/r + D[0, 0](psi)(r) - sage: g.coeff(psi.derivative(r,2)) + sage: g.coefficient(psi.derivative(r,2)) 1 - sage: g.coeff(psi.derivative(r,1)) + sage: g.coefficient(psi.derivative(r,1)) 2/r Defining custom methods for automatic or numeric evaluation, derivation, diff --git a/src/sage/tests/french_book/nonlinear_doctest.py b/src/sage/tests/french_book/nonlinear_doctest.py index f00eeaa4bf3..d61bba5cf20 100644 --- a/src/sage/tests/french_book/nonlinear_doctest.py +++ b/src/sage/tests/french_book/nonlinear_doctest.py @@ -73,7 +73,7 @@ sage: x, a, b, c, d = var('x, a, b, c, d') sage: P = a * x^3 + b * x^2 + c * x + d sage: alpha = var('alpha') - sage: P.subs(x=x + alpha).expand().coeff(x, 2) + sage: P.subs(x=x + alpha).expand().coefficient(x, 2) 3*a*alpha + b sage: P.subs(x = x - b / (3 * a)).expand().collect(x) a*x^3 - 1/3*(b^2/a - 3*c)*x + 2/27*b^3/a^2 - 1/3*b*c/a + d From 0fec129b1055535de50cf4e5c663662e0d877742 Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Thu, 4 Dec 2014 10:35:08 +0100 Subject: [PATCH 3/3] 17438: implement ex.list() --- src/sage/symbolic/expression.pyx | 41 ++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index d56febeb191..dccf1b7d119 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -5140,9 +5140,14 @@ cdef class Expression(CommutativeRingElement): - ``x`` -- optional variable. OUTPUT: + + Depending on the value of ``sparse``, - A list of pairs ``(expr, n)``, where ``expr`` is a symbolic - expression and ``n`` is a power. + - A list of pairs ``(expr, n)``, where ``expr`` is a symbolic + expression and ``n`` is a power (``sparse=True``, default) + + - A list of expressions where the ``n``-th element is the coefficient of + ``x^n`` when self is seen as polynomial in ``x`` (``sparse=False``). EXAMPLES:: @@ -5212,6 +5217,38 @@ cdef class Expression(CommutativeRingElement): return ret coeffs = deprecated_function_alias(17438, coefficients) + + def list(self, x=None): + r""" + Return the coefficients of this symbolic expression as a polynomial in x. + + INPUT: + + - ``x`` -- optional variable. + + OUTPUT: + + A list of expressions where the ``n``-th element is the coefficient of + ``x^n`` when self is seen as polynomial in ``x``. + + EXAMPLES:: + + sage: var('x, y, a') + (x, y, a) + sage: (x^5).list() + [0, 0, 0, 0, 0, 1] + sage: p = x^3 - (x-3)*(x^2+x) + 1 + sage: p.list() + [1, 3, 2] + sage: p = x - x^3 + 5/7*x^5 + sage: p.list() + [0, 1, 0, -1, 0, 5/7] + sage: p = expand((x-a*sqrt(2))^2 + x + 1); p + -2*sqrt(2)*a*x + 2*a^2 + x^2 + x + 1 + sage: p.list(a) + [x^2 + x + 1, -2*sqrt(2)*x, 2] + """ + return self.coefficients(x=x, sparse=False) def leading_coefficient(self, s): """