Search code examples
pythonsympypolynomials

Express a finite Laurent series (a Laurent polynomial) as a dictionary


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?


Solution

  • 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}