Suppose you have a multivariate polynomial expression and you want to characterize it as a dictionary by the degree and the coefficient of each of the monomials.
Example:
p=Poly(3*x1**2 - x1*x2 + 5*x2 +7)
You want:
dic={"(2,0)":3 , "(1,1)":-1 , "(0,1)": 5 , "(0,0)": 7}
p.as_dict()
nicely solves the problem.
Now, you have the same problem but now the multivariate polynomial expression admits negative exponents (a finite Laurent series).
So if you have:
p=Poly(3*x1**-2 - x1*x2 + 5*x2)
p.as_dict()
will print:
{(0, 0, 2): 3, (0, 1, 0): 5, (1, 1, 0): -1}
But, I would like to have this:
{(-2, 0): 3, (0, 1): 5, (1, 1): -1}
How can I achive this in an elegant way?
It seems easiest to multiply the expression by a sufficiently large power of each variable so that it becomes an actual polynomial. Convert that to a dictionary, then subtract the power that we multiplied by. Setup:
x1, x2 = symbols('x1 x2')
syms = (x1, x2) # specify the desired order of symbols: do not rely on default order being what you want
expr = 3*x1**(-2) - x1*x2 + 5*x2 # just an expression so far, not a polynomial
The main code:
d = max(Poly(expr).degree_list())
prelim = Poly(expr*prod([x**d for x in syms]), syms).as_dict()
final = {tuple(deg - d for deg in key): prelim[key] for key in prelim}
Explanation: Poly(expr)
creates a polynomial in variables x1, x2, 1/x1. By letting
d
be the maximal degree in each variable, it is assured that x1**d * x2**d * expr
will not have negative powers. This product is made a polynomial in (x1, x2)
and converted to a "preliminary" dictionary: {(0, 2): 3, (2, 3): 5, (3, 3): -1}
. Then the dictionary is adjusted by subtracting d
everywhere. Final result:
{(-2, 0): 3, (0, 1): 5, (1, 1): -1}