Best way to isolate one coefficient of a multivariate polynomial in sympy
Asked Answered
V

2

10

I have a multivariate polynomial (which in the general case many many variables) whose coefficients list some data that I need to read off, but it doesn't seem like sympy gives a good way to do this.

The collect function seemed like the right idea, but when you use it with several variables, it doesn't actually give you the individual monomials, but rather strange groupings of monomials that depend on the order you listed the variables.

Does anyone know of a way to do this?

Vacuum answered 24/4, 2016 at 0:38 Comment(0)
E
14

The documentation of polynomial module lists plenty of ways to handle coefficients. For example:

>>> import sympy
>>> x,y,z = sympy.symbols('x,y,z')
>>> p = sympy.poly((x+2*y-z)**3)
>>> p.coeffs()
[1, 6, -3, 12, -12, 3, 8, -12, 6, -1]

These are nonzero coefficients in lexicographic order. To see the monomials in matching order, use

>>> p.monoms()
[(3, 0, 0), (2, 1, 0), (2, 0, 1), (1, 2, 0), (1, 1, 1), (1, 0, 2), (0, 3, 0), (0, 2, 1), (0, 1, 2), (0, 0, 3)]

To get the coefficient of a particular monomial, use

>>> p.coeff_monomial(x**2*y)
6
Espagnole answered 24/4, 2016 at 0:56 Comment(1)
Instead of relying on implicit variable ordering, you can pass the variables to poly in whatever order you want, like poly((x+2*y-z)**3, x, y, z).Boon
C
5

The monomials of a Polynomial are listed in order that the generators appear (and that order is under the user's control):

>>> from sympy import Poly
>>> from sympy.abc import x, y, z
>>> Poly(x + 3*y**2, x, y).monoms()
[(1, 0), (0, 2)]
>>> Poly(x + 3*y**2, y, x).monoms()
[(2, 0), (0, 1)]

When querying to get the coefficients, either a monomial-tuple or an expression can be used:

>>> Poly(x + 3*y**2, x, y).coeff_monomial(y**2)
3
>>> Poly(x + 3*y**2, x, y).coeff_monomial((0, 2))
3

A dictionary of all coefficients for different monomials can be obtained in monomial-expression form by converting the Poly to an expression and then using the as_coefficients_dict method:

>>> p = Poly((x+2*y-z)**3)
>>> p.as_expr().as_coefficients_dict()
defaultdict(<class 'int'>, {
x**3: 1, z**3: -1, y**3: 8, y**2*z: -12, x**2*z: -3,
x*z**2: 3, x**2*y: 6, y*z**2: 6, x*y**2: 12, x*y*z: -12})

Or, if you prefer the monomial-tuple form, you can use:

>>> [(m,p.coeff_monomial(m)) for m in p.monoms()]
[((3, 0, 0), 1), ((2, 1, 0), 6), ((2, 0, 1), -3), ((1, 2, 0), 12), ((1, 1, 1),
-12), ((1, 0, 2), 3), ((0, 3, 0), 8), ((0, 2, 1), -12), ((0, 1, 2), 6),
((0, 0, 3), -1)]

And that can be turned into a defaultdict that will give 0 for a non-existing monomial with:

>>> defaultdict(int, _)
defaultdict(<class 'int'>, {(3, 0, 0): 1, (2, 1, 0): 6, (2, 0, 1): -3,
(1, 2, 0): 12, (1, 1, 1): -12, (1, 0, 2): 3, (0, 3, 0): 8, (0, 2, 1): -12,
(0, 1, 2): 6, (0, 0, 3): -1})
>>> c = _; c[(2,2,2)]  # there is no term of order 6 so coeff is 0
0
Centenarian answered 26/5, 2020 at 14:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.