# Collecting factors of polynomials

First up, I'm new to Mathematica and MathematicaSE, so please correct me if I'm doing anything wrong.

My problem is the following: I have a bunch of complicated polynomials in $3$ variables $x_1,x_2,x_3$ in which I would like to gather up certain terms, namely the following: $$x_3, \hspace{2mm} x_1^2 x_2^2, \hspace{2mm} (x_1^2+x_2^2), \hspace{2mm} (x_1^2-x_2^2)$$ So I'd like to have a function in which I can input a polynomial, for example $3 x_1^4 x_3 - 3 x_2^4 x_3 + 6 x_1^2 x_3^3 - 6 x_2^2 x_3^3$, and the result is $3 (x_1^2 - x_2^2) (x_1^2 + x_2^2) x_3 + 6 (x_1^2 - x_2^2) x_3^3$. I've played around a bit with Collect, Expand and Simplify. The possibilities I've come up with so far are

f[p_]:=Collect[Simplify[ExpandAll[p]], {x3, (x1^2 - x2^2), (x1^2 + x2^2), (x1^2*x2^2)}]


and

f[p_]:=Collect[ExpandAll[p], {x3, (x1^2 - x2^2), (x1^2 + x2^2), (x1^2*x2^2)}, Simplify]


Both these solutions work decently in many cases, though not perfectly. For instance, I've encountered the following example:

p = -x1^10 x3^3 + x1^6 x2^4 x3^3 - x1^4 x2^6 x3^3 + x2^10 x3^3


then for both possibilities of f above, the result is

f[p]=(-x1^10 + x1^6 x2^4 - x1^4 x2^6 + x2^10) x3^3


instead of what I want: $$3 x_3 x_1^2 x_2^2 (x_1^2+x_2^2) (x_1^2-x_2^2) + x_3 (x_1^2+x_2^2)^4$$

I'd appreciate any help!

• Have you seen SymmetricReduction[] by any chance? It's not a full solution, but it should help you get there. – J. M. is in limbo Jan 31 '17 at 8:34
• @J.M. Thanks for your comment! I briefly checked out SymmetricReduction, but I'm not entirely sure how it can be helpful here.In the example that I've given above I do have some symmetric terms that I want to gather up, like $x_1^2 x_2^2$ and $(x_1^2+x_2^2)$. However, a slightly more general solution, where I can gather up any terms I like (not just symmetric or antisymmetric things) would be more beautiful. So I might also want to factor out the term $(x_1^2+x_2-2x_3)$ or something. – Tom Bombadil Jan 31 '17 at 8:58
• Right, since it gathers things up in terms of elementary symmetric polynomials, you'll still need Newton-Girard to convert to power sums, and then handle the nonsymmetric part returned by SymmetricReduction[]. That's why I only offered it as a first step. – J. M. is in limbo Jan 31 '17 at 9:00
• @J.M. Okay, so it seems my problem is more difficult than I initially thought... At least it doesn't seem like Mathematica has some built in functionality to factor out terms. – Tom Bombadil Jan 31 '17 at 9:02
• PolynomialReduce[] might also be of interest. – J. M. is in limbo Jan 31 '17 at 9:07

I'd go with standard computational polynomial algebra methods here. For this I would assign new names to the reducing polynomials, create a Groebner basis so that the rewriting will be "canonical" in terms of these new variables, and also make replacement rules to go back to the original reducing polynomials.

reducers = {x3, (x1^2 - x2^2), (x1^2 + x2^2), (x1^2*x2^2)};
newvars = Array[a, Length[reducers]];
gb = GroebnerBasis[reducers - newvars,
Join[Variables[reducers], newvars]];


Now we work out the particular example.

p = -x1^10 x3^3 + x1^6 x2^4 x3^3 - x1^4 x2^6 x3^3 + x2^10 x3^3;
PolynomialReduce[p, gb,
Join[Variables[reducers], newvars]][] /. reprules

(* Out= 3 x1^2 x2^2 (x1^2 - x2^2) (x1^2 + x2^2)^2 x3^3 - (x1^2 -
x2^2) (x1^2 + x2^2)^4 x3^3 *)


For larger examples one might instead use a term ordering that places original variables greater than new but in other respsects is based on total degree.

• I'm still trying to understand how exactly your code is working. As I said, I'm an absolute beginner in Mathematica and this is the first time I've heard the term "Groebner Basis". However, it's working brilliantly! Thank you very much for your help! – Tom Bombadil Feb 1 '17 at 7:42
• If you are familiar with "term rewriting" this is from that family of algorithms, albeit in a math setting that offers stronger guarantees (such as termination). One can think of it as a way to get "canonicalized" polynomials modulo a given set of relations. – Daniel Lichtblau Feb 1 '17 at 16:04
• Daniel, this question reminds me of a related family of questions that come up again and again: mathematica.stackexchange.com/q/3822/121. I know you have replied to some of those already, e.g. stackoverflow.com/a/6075006, but it seems that often past solutions are difficult to apply directly. I would like to suggest that if possible a canonical answer be written to address as many of these cases in one place/function as possible, and I cannot think of anyone as well qualified as you to write it. This seems like a gap in Mathematica's functions that many would like filled. – Mr.Wizard Feb 3 '17 at 1:48
• @Mr.Wizard It's difficult to come up with a one-size-fits-all for this. What I bring to the table is I've gotten it wrong more often than anyone else. ANyway, if you can come up with a canonical form of the question, I'll give it a try (next week; I'm traveling at the moment). – Daniel Lichtblau Feb 3 '17 at 16:32
• @DanielLichtblau While your solution above works wonderfully in the given case, do you have a suggestion for handling reducers where it takes an incredibly long time to calculate the Groebner Basis? For instance, the case I'm interested in now is that I'm pretty sure my polynomials are sums of symmetric and antisymmetric polynomials in $4$ variables. So my reducers would be the elementary symmetric polynomials $s_1,s_2,s_3,s_4$ in four variables as well as the "Jacobian" $J=(z_2-z_1)(z_3-z_1)(z_4-z_1)(z_3-z_2)(z_4-z_2)(z_4-z_3)$. But the Groebner Basis calculation takes hours... – Tom Bombadil Feb 16 '17 at 7:00