Collect similar terms in sympy

Viewed 159

I'm solving the Maxwell Garnett equation with SymPy:

solveset(Eq((e-m)/(e+2*m) = n*(a-m)/(a+2*m)), m)

enter image description here

Is it possible to simplify the solution by grouping similar terms together like Mathematica does?

enter image description here

The closest recipe I've found is SymPy: How to collect multi-variable terms?, but it is not directly applicable here.

I've progressed as far as: enter image description here But how do I get to the even more compact form?

2 Answers

It is possible to call collect and give it a function that should apply to the coefficients after collection and so we can use factor to factorise the coefficients:

In [2]: e, a, m, n = symbols('e, a, m, n')

In [3]: sol = solveset(Eq((e-m)/(e+2*m), n*(a-m)/(a+2*m)), m)

In [4]: s1, s2 = sol.args[0]

In [5]: s1
Out[5]: 
                           _____________________________________________________________________________
                          ╱    2  2      2      2          2                       2  2      2        2 
2⋅a⋅n + a - e⋅n - 2⋅e   ╲╱  4⋅a ⋅n  + 4⋅a ⋅n + a  + 4⋅a⋅e⋅n  - 26⋅a⋅e⋅n + 4⋅a⋅e + e ⋅n  + 4⋅e ⋅n + 4⋅e  
───────────────────── - ────────────────────────────────────────────────────────────────────────────────
      4⋅(n - 1)                                            4⋅(n - 1)                                    

In [6]: s1.collect(e, lambda c: c.factor() if c.is_polynomial() else c)
Out[6]: 
                              _______________________________________________________
                             ╱  2          2         ⎛   2           ⎞    2        2 
a⋅(2⋅n + 1) + e⋅(-n - 2)   ╲╱  a ⋅(2⋅n + 1)  + 2⋅a⋅e⋅⎝2⋅n  - 13⋅n + 2⎠ + e ⋅(n + 2)  
──────────────────────── - ──────────────────────────────────────────────────────────
       4⋅(n - 1)                                   4⋅(n - 1)                         

In [7]: s2.collect(e, lambda c: c.factor() if c.is_polynomial() else c)
Out[7]: 
                              _______________________________________________________
                             ╱  2          2         ⎛   2           ⎞    2        2 
a⋅(2⋅n + 1) + e⋅(-n - 2)   ╲╱  a ⋅(2⋅n + 1)  + 2⋅a⋅e⋅⎝2⋅n  - 13⋅n + 2⎠ + e ⋅(n + 2)  
──────────────────────── + ──────────────────────────────────────────────────────────
       4⋅(n - 1)                                   4⋅(n - 1) 

The is_polynomial check is to stop collect from applying factor to the final expression after it is done recursing subexpressions (a final call to factor expands everything again). There might be a better check that could be used for more general situations.

The question is ill-defined. There are infinitely many ways to write a polynomial as a sum of products of polynomials. The completely expanded form is unique. If the whole polynomial can be factored over integers, this factorization is also unique. But writing it as a sum of products of polynomials can be done in infinitely many ways.

Related