Series Manipulation using Polynomials¶
Any finite Taylor series, for all practical purposes is, in fact a polynomial.
This module makes use of the efficient representation and operations of sparse
polynomials for very fast multivariate series manipulations. Typical speedups
compared to SymPy’s series
method are in the range 20-100, with the gap
widening as the series being handled gets larger.
All the functions expand any given series on some ring specified by the user. Thus, the coefficients of the calculated series depend on the ring being used. For example:
>>> from sympy.polys import ring, QQ, RR
>>> from sympy.polys.ring_series import rs_sin
>>> R, x, y = ring('x, y', QQ)
>>> rs_sin(x*y, x, 5)
-1/6*x**3*y**3 + x*y
QQ
stands for the Rational domain. Here all coefficients are rationals. It
is recommended to use QQ
with ring series as it automatically chooses the
fastest Rational type.
Similarly, if a Real domain is used:
>>> R, x, y = ring('x, y', RR)
>>> rs_sin(x*y, x, 5)
-0.166666666666667*x**3*y**3 + x*y
Though the definition of a polynomial limits the use of Polynomial module to Taylor series, we extend it to allow Laurent and even Puiseux series (with fractional exponents):
>>> from sympy.polys.ring_series import rs_cos, rs_tan
>>> from sympy.polys.puiseux import puiseux_ring
>>> R, x, y = puiseux_ring('x, y', QQ)
>>> rs_cos(x + x*y, x, 3)/x**3
x**(-3) + -1/2*x**(-1) + -1*x**(-1)*y + -1/2*x**(-1)*y**2
>>> rs_tan(x**QQ(2, 5)*y**QQ(1, 2), x, 2)
x**(2/5)*y**(1/2) + 1/3*x**(6/5)*y**(3/2)
Since polynomial rings cannot handle negative or fractional exponents, we use
the sympy.polys.puiseux.puiseux_ring()
function to create a ring that can
represent such series.
All series returned by the functions of this module are instances of
PolyElement
or PuiseuxPoly
. To use them with other SymPy types, convert
them to
Expr
:
>>> from sympy.polys.ring_series import rs_exp
>>> from sympy.abc import a, b, c
>>> series = rs_exp(x, x, 5)
>>> a + series.as_expr()
a + x**4/24 + x**3/6 + x**2/2 + x + 1
rs_series¶
Direct use of elementary ring series functions does give more control, but is limiting at the same time. Creating an appropriate ring for the desired series expansion and knowing which ring series function to call, are things not everyone might be familiar with.
\(rs\_series\) is a function that takes an arbitrary Expr
and returns its
expansion by calling the appropriate ring series functions. The returned series
is a polynomial over the simplest (almost) possible ring that does the job. It
recursively builds the ring as it parses the given expression, adding
generators to the ring when it needs them. Some examples:
>>> from sympy.polys.ring_series import rs_series
>>> from sympy.functions.elementary.trigonometric import sin
>>> rs_series(sin(a + b), a, 5)
1/24*sin(b)*a**4 - 1/2*sin(b)*a**2 + sin(b) - 1/6*cos(b)*a**3 + cos(b)*a
>>> rs_series(sin(exp(a*b) + cos(a + c)), a, 2)
-sin(c)*cos(cos(c) + 1)*a + cos(cos(c) + 1)*a*b + sin(cos(c) + 1)
>>> rs_series(sin(a + b)*cos(a + c)*tan(a**2 + b), a, 2)
cos(b)*cos(c)*tan(b)*a - sin(b)*sin(c)*tan(b)*a + sin(b)*cos(c)*tan(b)
It can expand complicated multivariate expressions involving multiple functions and most importantly, it does so blazingly fast:
>>> %timeit ((sin(a) + cos(a))**10).series(a, 0, 5)
1 loops, best of 3: 1.33 s per loop
>>> %timeit rs_series((sin(a) + cos(a))**10, a, 5)
100 loops, best of 3: 4.13 ms per loop
\(rs\_series\) is over 300 times faster. Given an expression to expand, there is some fixed overhead to parse it. Thus, for larger orders, the speed improvement becomes more prominent:
>>> %timeit rs_series((sin(a) + cos(a))**10, a, 100)
10 loops, best of 3: 32.8 ms per loop
To figure out the right ring for a given expression, \(rs\_series\) uses the
sring
function, which in turn uses other functions of polys
. As
explained above, non-natural exponents are not allowed. But the restriction is
on exponents and not generators. So, polys
allows all sorts of symbolic
terms as generators to make sure that the exponent is a natural number:
>>> from sympy.polys.rings import sring
>>> R, expr = sring(1/a**3 + a**QQ(3, 7)); R
Polynomial ring in 1/a, a**(1/7) over ZZ with lex order
In the above example, \(1/a\) and \(a**(1/7)\) will be treated as completely different atoms. For all practical purposes, we could let \(b = 1/a\) and \(c = a**(1/7)\) and do the manipulations. Effectively, expressions involving \(1/a\) and \(a**(1/7)\) (and their powers) will never simplify:
>>> expr*R(1/a)
(1/a)**4 + (1/a)*(a**(1/7))**3
This leads to similar issues with manipulating Laurent and Puiseux series as
faced earlier. Fortunately, this time we have an elegant solution and are able
to isolate the series
and polys
behaviour from one another. We
introduce a boolean flag series
in the list of allowed Options
for
polynomials (see sympy.polys.polyoptions.Options
). Thus, when we want
sring
to allow rational exponents we supply a series=True
flag to
sring
:
>>> rs_series(sin(a**QQ(1, 3)), a, 3)
-1/5040*a**(7/3) + 1/120*a**(5/3) - 1/6*a + a**(1/3)
Contribute¶
\(rs\_series\) is not fully implemented yet. As of now, it supports only
multivariate Taylor expansions of expressions involving sin
, cos
,
exp
and tan
. Adding the remaining functions is not at all difficult and
they will be gradually added. If you are interested in helping, read the
comments in ring_series.py
. Currently, it does not support Puiseux series
(though the elementary functions do). This is expected to be fixed soon.
You can also add more functions to ring_series.py
. Only elementary
functions are supported currently. The long term goal is to replace SymPy’s
current series
method with rs_series
.
Reference¶
Functions in this module carry the prefix rs_
, standing for “ring series”.
They manipulate finite power series in the sparse representation provided
by polys.ring.ring
.
Elementary functions
- sympy.polys.ring_series.rs_log(p, x, prec)[source]¶
The Logarithm of
p
moduloO(x**prec)
.Notes
Truncation of
integral dx p**-1*d p/dx
is used.Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.puiseux import puiseux_ring >>> from sympy.polys.ring_series import rs_log >>> R, x = puiseux_ring('x', QQ) >>> rs_log(1 + x, x, 8) x + -1/2*x**2 + 1/3*x**3 + -1/4*x**4 + 1/5*x**5 + -1/6*x**6 + 1/7*x**7 >>> rs_log(x**QQ(3, 2) + 1, x, 5) x**(3/2) + -1/2*x**3 + 1/3*x**(9/2)
- sympy.polys.ring_series.rs_LambertW(p, x, prec)[source]¶
Calculate the series expansion of the principal branch of the Lambert W function.
Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_LambertW >>> R, x, y = ring('x, y', QQ) >>> rs_LambertW(x + x*y, x, 3) -x**2*y**2 - 2*x**2*y - x**2 + x*y + x
See also
- sympy.polys.ring_series.rs_exp(p, x, prec)[source]¶
Exponentiation of a series modulo
O(x**prec)
Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_exp >>> R, x = ring('x', QQ) >>> rs_exp(x**2, x, 7) 1/6*x**6 + 1/2*x**4 + x**2 + 1
- sympy.polys.ring_series.rs_atan(p, x, prec)[source]¶
The arctangent of a series
Return the series expansion of the atan of
p
, about 0.Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_atan >>> R, x, y = ring('x, y', QQ) >>> rs_atan(x + x*y, x, 4) -1/3*x**3*y**3 - x**3*y**2 - x**3*y - 1/3*x**3 + x*y + x
See also
- sympy.polys.ring_series.rs_asin(p, x, prec)[source]¶
Arcsine of a series
Return the series expansion of the asin of
p
, about 0.Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_asin >>> R, x, y = ring('x, y', QQ) >>> rs_asin(x, x, 8) 5/112*x**7 + 3/40*x**5 + 1/6*x**3 + x
See also
- sympy.polys.ring_series.rs_tan(p, x, prec)[source]¶
Tangent of a series.
Return the series expansion of the tan of
p
, about 0.Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_tan >>> R, x, y = ring('x, y', QQ) >>> rs_tan(x + x*y, x, 4) 1/3*x**3*y**3 + x**3*y**2 + x**3*y + 1/3*x**3 + x*y + x
- sympy.polys.ring_series._tan1(p, x, prec)[source]¶
Helper function of
rs_tan()
.Return the series expansion of tan of a univariate series using Newton’s method. It takes advantage of the fact that series expansion of atan is easier than that of tan.
Consider \(f(x) = y - \arctan(x)\) Let r be a root of f(x) found using Newton’s method. Then \(f(r) = 0\) Or \(y = \arctan(x)\) where \(x = \tan(y)\) as required.
- sympy.polys.ring_series.rs_cot(p, x, prec)[source]¶
Cotangent of a series
Return the series expansion of the cot of
p
, about 0.Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_cot >>> R, x, y = ring('x, y', QQ) >>> rs_cot(x, x, 6) -2/945*x**5 - 1/45*x**3 - 1/3*x + x**(-1)
See also
- sympy.polys.ring_series.rs_sin(p, x, prec)[source]¶
Sine of a series
Return the series expansion of the sin of
p
, about 0.Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.puiseux import puiseux_ring >>> from sympy.polys.ring_series import rs_sin >>> R, x, y = puiseux_ring('x, y', QQ) >>> rs_sin(x + x*y, x, 4) x + x*y + -1/6*x**3 + -1/2*x**3*y + -1/2*x**3*y**2 + -1/6*x**3*y**3 >>> rs_sin(x**QQ(3, 2) + x*y**QQ(7, 5), x, 4) x*y**(7/5) + x**(3/2) + -1/6*x**3*y**(21/5) + -1/2*x**(7/2)*y**(14/5)
See also
- sympy.polys.ring_series.rs_cos(p, x, prec)[source]¶
Cosine of a series
Return the series expansion of the cos of
p
, about 0.Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.puiseux import puiseux_ring >>> from sympy.polys.ring_series import rs_cos >>> R, x, y = puiseux_ring('x, y', QQ) >>> rs_cos(x + x*y, x, 4) 1 + -1/2*x**2 + -1*x**2*y + -1/2*x**2*y**2 >>> rs_cos(x + x*y, x, 4)/x**QQ(7, 5) x**(-7/5) + -1/2*x**(3/5) + -1*x**(3/5)*y + -1/2*x**(3/5)*y**2
See also
- sympy.polys.ring_series.rs_cos_sin(p, x, prec)[source]¶
Return the tuple
(rs_cos(p, x, prec)`, `rs_sin(p, x, prec))
.Is faster than calling rs_cos and rs_sin separately
- sympy.polys.ring_series.rs_atanh(p, x, prec)[source]¶
Hyperbolic arctangent of a series
Return the series expansion of the atanh of
p
, about 0.Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_atanh >>> R, x, y = ring('x, y', QQ) >>> rs_atanh(x + x*y, x, 4) 1/3*x**3*y**3 + x**3*y**2 + x**3*y + 1/3*x**3 + x*y + x
See also
- sympy.polys.ring_series.rs_asinh(p, x, prec)[source]¶
Hyperbolic arcsine of a series
Return the series expansion of the arcsinh of
p
, about 0.Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_asinh >>> R, x = ring('x', QQ) >>> rs_asinh(x, x, 9) -5/112*x**7 + 3/40*x**5 - 1/6*x**3 + x
See also
- sympy.polys.ring_series.rs_sinh(p, x, prec)[source]¶
Hyperbolic sine of a series
Return the series expansion of the sinh of
p
, about 0.Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_sinh >>> R, x, y = ring('x, y', QQ) >>> rs_sinh(x + x*y, x, 4) 1/6*x**3*y**3 + 1/2*x**3*y**2 + 1/2*x**3*y + 1/6*x**3 + x*y + x
See also
- sympy.polys.ring_series.rs_cosh(p, x, prec)[source]¶
Hyperbolic cosine of a series
Return the series expansion of the cosh of
p
, about 0.Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_cosh >>> R, x, y = ring('x, y', QQ) >>> rs_cosh(x + x*y, x, 4) 1/2*x**2*y**2 + x**2*y + 1/2*x**2 + 1
See also
- sympy.polys.ring_series.rs_tanh(p, x, prec)[source]¶
Hyperbolic tangent of a series
Return the series expansion of the tanh of
p
, about 0.Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_tanh >>> R, x, y = ring('x, y', QQ) >>> rs_tanh(x + x*y, x, 4) -1/3*x**3*y**3 - x**3*y**2 - x**3*y - 1/3*x**3 + x*y + x
See also
- sympy.polys.ring_series.rs_hadamard_exp(p1, inverse=False)[source]¶
Return
sum f_i/i!*x**i
fromsum f_i*x**i
, wherex
is the first variable.If
inverse=True
returnsum f_i*i!*x**i
Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_hadamard_exp >>> R, x = ring('x', QQ) >>> p = 1 + x + x**2 + x**3 >>> rs_hadamard_exp(p) 1/6*x**3 + 1/2*x**2 + x + 1
Operations
- sympy.polys.ring_series.rs_mul(p1, p2, x, prec)[source]¶
Return the product of the given two series, modulo
O(x**prec)
.x
is the series variable or its position in the generators.Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_mul >>> R, x = ring('x', QQ) >>> p1 = x**2 + 2*x + 1 >>> p2 = x + 1 >>> rs_mul(p1, p2, x, 3) 3*x**2 + 3*x + 1
- sympy.polys.ring_series.rs_square(p1, x, prec)[source]¶
Square the series modulo
O(x**prec)
Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_square >>> R, x = ring('x', QQ) >>> p = x**2 + 2*x + 1 >>> rs_square(p, x, 3) 6*x**2 + 4*x + 1
- sympy.polys.ring_series.rs_pow(p1, n, x, prec)[source]¶
Return
p1**n
moduloO(x**prec)
Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_pow >>> R, x = ring('x', QQ) >>> p = x + 1 >>> rs_pow(p, 4, x, 3) 6*x**2 + 4*x + 1
- sympy.polys.ring_series.rs_series_inversion(p, x, prec)[source]¶
Multivariate series inversion
1/p
moduloO(x**prec)
.Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_series_inversion >>> R, x, y = ring('x, y', QQ) >>> rs_series_inversion(1 + x*y**2, x, 4) -x**3*y**6 + x**2*y**4 - x*y**2 + 1 >>> rs_series_inversion(1 + x*y**2, y, 4) -x*y**2 + 1 >>> rs_series_inversion(x + x**2, x, 4) x**3 - x**2 + x - 1 + x**(-1)
- sympy.polys.ring_series.rs_series_reversion(p, x, n, y)[source]¶
Reversion of a series.
p
is a series withO(x**n)
of the form \(p = ax + f(x)\) where \(a\) is a number different from 0.\(f(x) = \sum_{k=2}^{n-1} a_kx_k\)
- Parameters:
a_k : Can depend polynomially on other variables, not indicated.
x : Variable with name x. y : Variable with name y.
- Returns:
Solve \(p = y\), that is, given \(ax + f(x) - y = 0\),
find the solution \(x = r(y)\) up to \(O(y^n)\).
Algorithm
If \(r_i\) is the solution at order \(i\), then: \(ar_i + f(r_i) - y = O\left(y^{i + 1}\right)\)
and if \(r_{i + 1}\) is the solution at order \(i + 1\), then: \(ar_{i + 1} + f(r_{i + 1}) - y = O\left(y^{i + 2}\right)\)
We have, \(r_{i + 1} = r_i + e\), such that, \(ae + f(r_i) = O\left(y^{i + 2}\right)\) or \(e = -f(r_i)/a\)
So we use the recursion relation: \(r_{i + 1} = r_i - f(r_i)/a\) with the boundary condition: \(r_1 = y\)
Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_series_reversion, rs_trunc >>> R, x, y, a, b = ring('x, y, a, b', QQ) >>> p = x - x**2 - 2*b*x**2 + 2*a*b*x**2 >>> p1 = rs_series_reversion(p, x, 3, y); p1 -2*y**2*a*b + 2*y**2*b + y**2 + y >>> rs_trunc(p.compose(x, p1), y, 3) y
- sympy.polys.ring_series.rs_nth_root(p, n, x, prec)[source]¶
Multivariate series expansion of the nth root of
p
.- Parameters:
p : Expr
The polynomial to computer the root of.
n : integer
The order of the root to be computed.
x :
PolyElement
prec : integer
Order of the expanded series.
Notes
The result of this function is dependent on the ring over which the polynomial has been defined. If the answer involves a root of a constant, make sure that the polynomial is over a real field. It cannot yet handle roots of symbols.
Examples
>>> from sympy.polys.domains import QQ, RR >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_nth_root >>> R, x, y = ring('x, y', QQ) >>> rs_nth_root(1 + x + x*y, -3, x, 3) 2/9*x**2*y**2 + 4/9*x**2*y + 2/9*x**2 - 1/3*x*y - 1/3*x + 1 >>> R, x, y = ring('x, y', RR) >>> rs_nth_root(3 + x + x*y, 3, x, 2) 0.160249952256379*x*y + 0.160249952256379*x + 1.44224957030741
- sympy.polys.ring_series.rs_trunc(p1, x, prec)[source]¶
Truncate the series in the
x
variable with precisionprec
, that is, moduloO(x**prec)
Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_trunc >>> R, x = ring('x', QQ) >>> p = x**10 + x**5 + x + 1 >>> rs_trunc(p, x, 12) x**10 + x**5 + x + 1 >>> rs_trunc(p, x, 10) x**5 + x + 1
- sympy.polys.ring_series.rs_subs(p, rules, x, prec)[source]¶
Substitution with truncation according to the mapping in
rules
.Return a series with precision
prec
in the generatorx
Note that substitutions are not done one after the other
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_subs >>> R, x, y = ring('x, y', QQ) >>> p = x**2 + y**2 >>> rs_subs(p, {x: x+ y, y: x+ 2*y}, x, 3) 2*x**2 + 6*x*y + 5*y**2 >>> (x + y)**2 + (x + 2*y)**2 2*x**2 + 6*x*y + 5*y**2
which differs from
>>> rs_subs(rs_subs(p, {x: x+ y}, x, 3), {y: x+ 2*y}, x, 3) 5*x**2 + 12*x*y + 8*y**2
- Parameters:
p :
PolyElement
Input series.rules :
dict
with substitution mappings.x :
PolyElement
in which the series truncation is to be done.prec :
Integer
order of the series after truncation.
Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_subs >>> R, x, y = ring('x, y', QQ) >>> rs_subs(x**2+y**2, {y: (x+y)**2}, x, 3) 6*x**2*y**2 + x**2 + 4*x*y**3 + y**4
- sympy.polys.ring_series.rs_diff(p, x)[source]¶
Return partial derivative of
p
with respect tox
.- Parameters:
x :
PolyElement
with respect to whichp
is differentiated.
Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_diff >>> R, x, y = ring('x, y', QQ) >>> p = x + x**2*y**3 >>> rs_diff(p, x) 2*x*y**3 + 1
- sympy.polys.ring_series.rs_integrate(p, x)[source]¶
Integrate
p
with respect tox
.- Parameters:
x :
PolyElement
with respect to whichp
is integrated.
Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_integrate >>> R, x, y = ring('x, y', QQ) >>> p = x + x**2*y**3 >>> rs_integrate(p, x) 1/3*x**3*y**3 + 1/2*x**2
- sympy.polys.ring_series.rs_newton(p, x, prec)[source]¶
Compute the truncated Newton sum of the polynomial
p
Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_newton >>> R, x = ring('x', QQ) >>> p = x**2 - 2 >>> rs_newton(p, x, 5) 8*x**4 + 4*x**2 + 2
- sympy.polys.ring_series.rs_compose_add(p1, p2)[source]¶
compute the composed sum
prod(p2(x - beta) for beta root of p1)
Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_compose_add >>> R, x = ring('x', QQ) >>> f = x**2 - 2 >>> g = x**2 - 3 >>> rs_compose_add(f, g) x**4 - 10*x**2 + 1
References
[R836]A. Bostan, P. Flajolet, B. Salvy and E. Schost “Fast Computation with Two Algebraic Numbers”, (2002) Research Report 4579, Institut National de Recherche en Informatique et en Automatique
Utility functions
- sympy.polys.ring_series.rs_series(expr, a, prec)[source]¶
Return the series expansion of an expression about 0.
- Parameters:
expr :
Expr
a :
Symbol
with respect to which expr is to be expandedprec : order of the series expansion
Currently supports multivariate Taylor series expansion. This is much
faster that SymPy’s series method as it uses sparse polynomial operations.
It automatically creates the simplest ring required to represent the series
expansion through repeated calls to sring.
Examples
>>> from sympy.polys.ring_series import rs_series >>> from sympy import sin, cos, exp, tan, symbols, QQ >>> a, b, c = symbols('a, b, c') >>> rs_series(sin(a) + exp(a), a, 5) 1/24*a**4 + 1/2*a**2 + 2*a + 1 >>> series = rs_series(tan(a + b)*cos(a + c), a, 2) >>> series.as_expr() -a*sin(c)*tan(b) + a*cos(c)*tan(b)**2 + a*cos(c) + cos(c)*tan(b) >>> series = rs_series(exp(a**QQ(1,3) + a**QQ(2, 5)), a, 1) >>> series.as_expr() a**(11/15) + a**(4/5)/2 + a**(2/5) + a**(2/3)/2 + a**(1/3) + 1
- sympy.polys.ring_series.rs_is_puiseux(p, x)[source]¶
Test if
p
is Puiseux series inx
.Raise an exception if it has a negative power in
x
.Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.puiseux import puiseux_ring >>> from sympy.polys.ring_series import rs_is_puiseux >>> R, x = puiseux_ring('x', QQ) >>> p = x**QQ(2,5) + x**QQ(2,3) + x >>> rs_is_puiseux(p, x) True
- sympy.polys.ring_series.rs_puiseux(f, p, x, prec)[source]¶
Return the puiseux series for \(f(p, x, prec)\).
To be used when function
f
is implemented only for regular series.Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.puiseux import puiseux_ring >>> from sympy.polys.ring_series import rs_puiseux, rs_exp >>> R, x = puiseux_ring('x', QQ) >>> p = x**QQ(2,5) + x**QQ(2,3) + x >>> rs_puiseux(rs_exp,p, x, 1) 1 + x**(2/5) + x**(2/3) + 1/2*x**(4/5)
- sympy.polys.ring_series.rs_puiseux2(f, p, q, x, prec)[source]¶
Return the puiseux series for \(f(p, q, x, prec)\).
To be used when function
f
is implemented only for regular series.
- sympy.polys.ring_series.rs_series_from_list(p, c, x, prec, concur=1)[source]¶
Return a series \(sum c[n]*p**n\) modulo \(O(x**prec)\).
It reduces the number of multiplications by summing concurrently.
\(ax = [1, p, p**2, .., p**(J - 1)]\) \(s = sum(c[i]*ax[i]\) for i in \(range(r, (r + 1)*J))*p**((K - 1)*J)\) with \(K >= (n + 1)/J\)
Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_series_from_list, rs_trunc >>> R, x = ring('x', QQ) >>> p = x**2 + x + 1 >>> c = [1, 2, 3] >>> rs_series_from_list(p, c, x, 4) 6*x**3 + 11*x**2 + 8*x + 6 >>> rs_trunc(1 + 2*p + 3*p**2, x, 4) 6*x**3 + 11*x**2 + 8*x + 6 >>> pc = R.from_list(list(reversed(c))) >>> rs_trunc(pc.compose(x, p), x, 4) 6*x**3 + 11*x**2 + 8*x + 6
- sympy.polys.ring_series.rs_fun(p, f, *args)[source]¶
Function of a multivariate series computed by substitution.
The case with f method name is used to compute \(rs\_tan\) and \(rs\_nth\_root\) of a multivariate series:
\(rs\_fun(p, tan, iv, prec)\)
tan series is first computed for a dummy variable _x, i.e, \(rs\_tan(\_x, iv, prec)\). Then we substitute _x with p to get the desired series
- Parameters:
p :
PolyElement
The multivariate series to be expanded.f : \(ring\_series\) function to be applied on \(p\).
args[-2] :
PolyElement
with respect to which, the series is to be expanded.args[-1] : Required order of the expanded series.
Examples
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_fun, _tan1 >>> R, x, y = ring('x, y', QQ) >>> p = x + x*y + x**2*y + x**3*y**2 >>> rs_fun(p, _tan1, x, 4) 1/3*x**3*y**3 + 2*x**3*y**2 + x**3*y + 1/3*x**3 + x**2*y + x*y + x
- sympy.polys.ring_series.mul_xin(p, i, n)[source]¶
Return \(p*x_i**n\).
\(x\_i\) is the ith variable in
p
.
- sympy.polys.ring_series.pow_xin(p, i, n)[source]¶
>>> from sympy.polys.domains import QQ >>> from sympy.polys.puiseux import puiseux_ring >>> from sympy.polys.ring_series import pow_xin >>> R, x, y = puiseux_ring('x, y', QQ) >>> p = x**QQ(2,5) + x + x**QQ(2,3) >>> index = p.ring.gens.index(x) >>> pow_xin(p, index, 15) x**6 + x**10 + x**15
Puiseux rings
- sympy.polys.puiseux.puiseux_ring( ) tuple[PuiseuxRing, Unpack[tuple[PuiseuxPoly, ...]]] [source]¶
Construct a Puiseux ring.
This function constructs a Puiseux ring with the given symbols and domain.
>>> from sympy.polys.domains import QQ >>> from sympy.polys.puiseux import puiseux_ring >>> R, x, y = puiseux_ring('x y', QQ) >>> R PuiseuxRing((x, y), QQ) >>> p = 5*x**QQ(1,2) + 7/y >>> p 7*y**(-1) + 5*x**(1/2)
- class sympy.polys.puiseux.PuiseuxRing( )[source]¶
Ring of Puiseux polynomials.
A Puiseux polynomial is a truncated Puiseux series. The exponents of the monomials can be negative or rational numbers. This ring is used by the ring_series module:
>>> from sympy.polys.domains import QQ >>> from sympy.polys.puiseux import puiseux_ring >>> from sympy.polys.ring_series import rs_exp, rs_nth_root >>> ring, x, y = puiseux_ring('x y', QQ) >>> f = x**2 + y**3 >>> f y**3 + x**2 >>> f.diff(x) 2*x >>> rs_exp(x, x, 5) 1 + x + 1/2*x**2 + 1/6*x**3 + 1/24*x**4
Importantly the Puiseux ring can represent truncated series with negative and fractional exponents:
>>> f = 1/x + 1/y**2 >>> f x**(-1) + y**(-2) >>> f.diff(x) -1*x**(-2)
>>> rs_nth_root(8*x + x**2 + x**3, 3, x, 5) 2*x**(1/3) + 1/12*x**(4/3) + 23/288*x**(7/3) + -139/20736*x**(10/3)
See also
- domain_new(arg: Any) Any [source]¶
Create a new element of the domain.
>>> from sympy.polys.domains import QQ >>> from sympy.polys.puiseux import puiseux_ring >>> R, x = puiseux_ring('x', QQ) >>> R.domain_new(3) 3 >>> QQ.of_type(_) True
- from_dict(
- terms: dict[tuple[int, ...], Any],
Create a Puiseux polynomial from a dictionary of terms.
>>> from sympy.polys.domains import QQ >>> from sympy.polys.puiseux import puiseux_ring >>> R, x = puiseux_ring('x', QQ) >>> R.from_dict({(QQ(1,2),): QQ(3)}) 3*x**(1/2)
- from_int(
- n: int,
Create a Puiseux polynomial from an integer.
>>> from sympy.polys.domains import QQ >>> from sympy.polys.puiseux import puiseux_ring >>> R, x = puiseux_ring('x', QQ) >>> R.from_int(3) 3
- from_poly(
- poly: PolyElement,
Create a Puiseux polynomial from a polynomial.
>>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.puiseux import puiseux_ring >>> R1, x1 = ring('x', QQ) >>> R2, x2 = puiseux_ring('x', QQ) >>> R2.from_poly(x1**2) x**2
- ground_new(arg: Any) PuiseuxPoly [source]¶
Create a new element from a ground element.
>>> from sympy.polys.domains import QQ >>> from sympy.polys.puiseux import puiseux_ring, PuiseuxPoly >>> R, x = puiseux_ring('x', QQ) >>> R.ground_new(3) 3 >>> isinstance(_, PuiseuxPoly) True
- index(
- x: PuiseuxPoly,
Return the index of a generator.
>>> from sympy.polys.domains import QQ >>> from sympy.polys.puiseux import puiseux_ring >>> R, x, y = puiseux_ring('x y', QQ) >>> R.index(x) 0 >>> R.index(y) 1
- class sympy.polys.puiseux.PuiseuxPoly(
- poly: PolyElement,
- ring: PuiseuxRing,
Puiseux polynomial. Represents a truncated Puiseux series.
See the
PuiseuxRing
class for more information.>>> from sympy import QQ >>> from sympy.polys.puiseux import puiseux_ring >>> R, x, y = puiseux_ring('x, y', QQ) >>> p = 5*x**2 + 7*y**3 >>> p 7*y**3 + 5*x**2
The internal representation of a Puiseux polynomial wraps a normal polynomial. To support negative powers the polynomial is considered to be divided by a monomial.
>>> p2 = 1/x + 1/y**2 >>> p2.monom # x*y**2 (1, 2) >>> p2.poly x + y**2 >>> (y**2 + x) / (x*y**2) == p2 True
To support fractional powers the polynomial is considered to be a function of
x**(1/nx), y**(1/ny), ...
. The representation keeps track of a monomial and a list of exponent denominators so that the polynomial can be used to represent both negative and fractional powers.>>> p3 = x**QQ(1,2) + y**QQ(2,3) >>> p3.ns (2, 3) >>> p3.poly x + y**2
- as_expr() Expr [source]¶
Convert a Puiseux polynomial to
Expr
.>>> from sympy import QQ, Expr >>> from sympy.polys.puiseux import puiseux_ring >>> R, x = puiseux_ring('x', QQ) >>> p = 5*x**2 + 7*x**3 >>> p.as_expr() 7*x**3 + 5*x**2 >>> isinstance(_, Expr) True
- diff(
- x: PuiseuxPoly,
Differentiate a Puiseux polynomial with respect to a variable.
>>> from sympy import QQ >>> from sympy.polys.puiseux import puiseux_ring >>> R, x, y = puiseux_ring('x, y', QQ) >>> p = 5*x**2 + 7*y**3 >>> p.diff(x) 10*x >>> p.diff(y) 21*y**2
- classmethod from_dict(
- terms: dict[tuple[Any, ...], Any],
- ring: PuiseuxRing,
Create a Puiseux polynomial from a dictionary of terms.
>>> from sympy import QQ >>> from sympy.polys.puiseux import puiseux_ring, PuiseuxPoly >>> R, x = puiseux_ring('x', QQ) >>> PuiseuxPoly.from_dict({(QQ(1,2),): QQ(3)}, R) 3*x**(1/2) >>> R.from_dict({(QQ(1,2),): QQ(3)}) 3*x**(1/2)
- property is_term: bool¶
Return True if the Puiseux polynomial is a single term.
- itermonoms() Iterator[tuple[Any, ...]] [source]¶
Iterate over the monomials of a Puiseux polynomial.
>>> from sympy import QQ >>> from sympy.polys.puiseux import puiseux_ring >>> R, x, y = puiseux_ring('x, y', QQ) >>> p = 5*x**2 + 7*y**3 >>> list(p.itermonoms()) [(2, 0), (0, 3)] >>> p[(2, 0)] 5
- iterterms() Iterator[tuple[tuple[Any, ...], Any]] [source]¶
Iterate over the terms of a Puiseux polynomial.
>>> from sympy import QQ >>> from sympy.polys.puiseux import puiseux_ring >>> R, x, y = puiseux_ring('x, y', QQ) >>> p = 5*x**2 + 7*y**3 >>> list(p.iterterms()) [((2, 0), 5), ((0, 3), 7)]