Sympy: Drop higher order terms in polynomial
Asked Answered
R

2

11

Using Sympy, say we have an expression f, which is a polynomial of the Symbol "x" (and of potentially other symbols).

I would like to know what if there is an efficient way to drop all terms in f of order greater than some integer n.

As a special case I have a very complicated function but i want to only keep terms up to 2nd order in x. What's the efficient way to do this?

The obvious, not-very-efficient way to do it would be for each m less than n, take m derivatives and set x to 0 to obtain the coefficient of x^m. We obtain each coefficient this way then reconstruct the polynomial. But taking derivatives is not the most efficient thing.

Roberto answered 28/7, 2014 at 18:32 Comment(2)
Please excuse my ignorance. How do you define the "order" of a term? Does it mean the same thing as degree?Throb
Sorry yes, the degree of a particular term in the polynomialRoberto
F
18

An easy way to do this is to add O(x**n) to the expression, like

In [23]: x + x**2 + x**4 + x**10 + O(x**3)
Out[23]:
     2    ⎛ 3⎞
x + x  + O⎝x ⎠

If you want to later remove it, use the removeO method

In [24]: (x + x**2 + x**4 + x**10 + O(x**3)).removeO()
Out[24]:
 2
x  + x

You can also use series to take the series expansion of the expression. The difference here is the behavior if a non-polynomial term ends up in the expression:

In [25]: x + sin(x) + O(x**3)
Out[25]:
              ⎛ 3⎞
sin(x) + x + O⎝x ⎠

In [26]: (x + sin(x)).series(x, 0, 3)
Out[26]:
       ⎛ 3⎞
2⋅x + O⎝x ⎠
Foundry answered 3/8, 2014 at 19:37 Comment(1)
It's great that this also works for multivariate polynomials, e.g.: + O(x*y) or + O(x**2*y). Thanks :)Gratis
I
2

If you take a look at the polynomial module docs:

http://docs.sympy.org/latest/modules/polys/reference.html

there will be plenty of ways to go about it, depending on the specifics of your situation. A couple different ways that would work:

Using .coeffs():

>>> f = 3 * x**3 + 2 * x**2 + x * y + y**3 + 1
>>> order = 2

>>> coeffs = Poly(f, x).coeffs()
>>> f_new = sum(x**n * coeffs[-(n+1)] for n in range(order+1)) # the +1 is to get 0th order
>>> f_new
2*x**2 + x*y + y**3 + 1

Alternatively, you could iterate over items in .all_terms():

>>> all_terms = Poly(f, x).all_terms()
>>> sum(x**n * term for (n,), term in all_terms() if n <= order)

There are plenty of manipulation functions in the module that you should be able to work with the expression directly rather than doing calculations/taking derivatives/etc.

Io answered 29/7, 2014 at 3:5 Comment(3)
hmm alright I'll have to test out how efficient it is to convert a complicated expression into a polynomial via PolyRoberto
It's pretty slow, I think the process of converting to polynomial does roughly what I suggested in the question, i.e. taking derivatives etc.Roberto
Hmm, maybe you could expand() the function and iterate over the .args: sum(term for term in expand(f).args if degree(term, x) <= order)Io

© 2022 - 2024 — McMap. All rights reserved.