# How can I reorder the factors in the terms of a polynomial?

How can I reorder the factors in the terms of a polynomial? Consider

poly1 = \!$$\*SubsuperscriptBox[\(x$$, $$1$$, $$3$$] + \*SubsuperscriptBox[$$x$$, $$2$$, $$3$$] + \*SubsuperscriptBox[$$x$$, $$3$$, $$3$$]\  - \ $$TraditionalForm\\*SuperscriptBox[SubscriptBox[\(σ$$, $$1$$], $$3$$]\)\) /.    Subscript[σ,     1] -> (Subscript[x, 1] + Subscript[x, 2] + Subscript[x, 3]) //   Expand


\begin{align*}-3 x_2 x_1^2-3 x_3 x_1^2-3 x_2^2 x_1-3 x_3^2 x_1-6 x_2 x_3 x_1-3 x_2 x_3^2-3 x_2^2 x_3\tag{1}\end{align*}

MonomialList[poly1, {Subscript[x, 1], Subscript[x, 2], Subscript[x,   3]}, "Lexicographic"]


\begin{align*}\left\{-3 x_1^2 x_2,-3 x_1^2 x_3,-3 x_1 x_2^2,-6 x_1 x_2 x_3,-3 x_1 x_3^2,-3 x_2^2 x_3,-3 x_2 x_3^2\right\}\tag{2}\end{align*}

% /. List -> Plus


\begin{align*}-3 x_2 x_1^2-3 x_3 x_1^2-3 x_2^2 x_1-3 x_3^2 x_1-6 x_2 x_3 x_1-3 x_2 x_3^2-3 x_2^2 x_3\tag{3}\end{align*}

Question1: How can I get

\begin{align*}-3 x_1^2 x_2-3 x_1^2 x_3-3 x_1 x_2^2-6 x_1 x_2 x_3-3 x_1 x_3^2-3 x_2^2 x_3-3 x_2 x_3^2\tag{4}\end{align*}

Question2: Even better if possible, how can I get

\begin{align*}-3\left( x_1^2 x_2+x_2^2x_1+\text{...}\right)-6 x_1 x_2 x_3\tag{5}\end{align*}

My goal is to keep the order of the terms in (2) unchanged when I copy (4)/(5) into an inline formula cell.

• Does Row@MonomialList[..] work for you, or do want the TeX output? I'm not sure I'm understanding the question correctly. – Michael E2 Aug 10 '13 at 15:52
• @MichaelE2 haha, yes, question1 just can be solved by Row@%, and the result can be copied to an InlineFormula Cell. – HyperGroups Aug 10 '13 at 16:00
• Actually Row works in this case because of the negative coefficients. For positive coefficients, you'd have to insert a "+". – Michael E2 Aug 10 '13 at 20:35
• There is the undocumented PolynomialForm, but it doesn't seem to work quite right (see 9483, 15744, etc.). – Michael E2 Aug 10 '13 at 22:29

### Question 1

As I said in a comment,

Row@MonomialList[poly1,
{Subscript[x, 1], Subscript[x, 2], Subscript[x, 3]}, "Lexicographic"]


However, it works easily here because all the coefficients are negative. The following polyForm handles level 1 terms (ignores nesting). It formats the polynomial f with the monomials in a specified order. It will expand a polynomial f (via MonomialList), unless an explicit list of terms is given. It takes the same arguments as MonomialList in the case where the polynomial is passed. If the terms are passed directly in a list, they will be formatted in the same order as they occur in the list.

polyForm[f_Plus, vars_: Automatic, order_: "Lexicographic"] :=
polyForm[MonomialList[f, vars /. Automatic :> Variables[f], order]];
polyForm[terms_List] := Module[{signs},
signs =
First[Cases[#, c_?NumericQ :> Sign[c]] /. {} -> {1}] & /@
Rest@terms;
PrecedenceForm[Row[Riffle[{1}~Join~signs terms,
signs /. {1 -> "\[MediumSpace]+\[MediumSpace]", -1 ->
"\[MediumSpace]-\[MediumSpace]"}]], 10]
];

polyForm[x_, ___] := x; (* leave other stuff alone *)


### Question 2

In this case you can gather the terms by the number of variables each contains:

Total[Factor /@ Plus @@@ GatherBy[List @@ poly1, Length@Variables[#] &]] Or you can use Row to keep them in the desired order (as in the question):

Row[Factor /@ Plus @@@ GatherBy[List @@ poly1, Length@Variables[#] &]] Or use polyForm, which will yield the standard spacing around the last minus sign:

polyForm[Factor /@ Plus @@@ GatherBy[List @@ poly1, Length@Variables[#] &]] Mr.Wizard pointed out that my order is not the same as the desired order in the OP, something I overlooked. Here is a fix:

Factor /@ Plus @@@ GatherBy[MonomialList[poly1, Variables[poly1], "Lexicographic"],
Length@Variables[#] &] /. poly_Plus :> polyForm[poly] // polyForm


Here is another:

MapAll[# /. poly_Plus :> polyForm[poly] &,
Total[Factor /@ Plus @@@ GatherBy[MonomialList[poly1, Variables[poly1], "Lexicographic"],
Length @ Variables[#] &]]] For the curious, I'll share the following. Using ReplaceAll with poly_Plus :> polyForm[poly] does not work on the Total in the preceding example because is it applies the replacement at the top level first and polyForm expands the polynomial. Here is a way around that, but it does reverse the order at the top level:

Total[Factor /@ Plus @@@
GatherBy[MonomialList[poly1, Variables[poly1], "Lexicographic"],
Length@Variables[#] &]] /. Plus -> (polyForm[List[##]] &)

• Michael, I don't think this is quite right yet; for example, shouldn't the term −3 x1 x3^3 be the third from the right, not the second as shown above? – Mr.Wizard Aug 11 '13 at 7:45
• @Mr.Wizard Oops, that's right (assuming you mean -3 x1 x3^2) - I blithely thought the point was just to separate the kinds of terms. – Michael E2 Aug 11 '13 at 11:37
• Oops.. yes, that's what I meant. – Mr.Wizard Aug 11 '13 at 11:38
• polyForm[...]//TeXForm complains withTeXForm::unspt: TeXForm of TemplateSlotSequence[1,] is not supported.. Is it possible to change polyForm so that the output can be given to TeXForm? – Hotschke Aug 10 '19 at 15:34
• @Hotschke This works on the OP's example: RowBox@First@MakeBoxes[#, StandardForm] &@ First@polyForm[ Factor /@ Plus @@@ GatherBy[List @@ poly1, Length@Variables[#] &]] /. "\"\[MediumSpace]-\[MediumSpace]\"" -> "-" // RawBoxes // TeXForm -- Might also need the substitution "\[MediumSpace]+\[MediumSpace]" -> "+", but it doesn't come up in this case. – Michael E2 Aug 10 '19 at 16:32

Related questions:

As shown in answer to the third question above you could use:

HoldForm[+##] & @@ MonomialList[poly1] (+## is shorthand for Plus[##])

As already noted above and in that answer Row is not sufficient as it will not handle the signs of terms correctly.

For the second question I am borrowing part of Michael's answer, but my result is different and I believe correct:

format = HoldForm[+##] & @@ MonomialList@ # &;

Factor /@ Plus @@@ GatherBy[List @@ poly1, Length@Variables[#] &];

Plus @@ MapAt[format, %, {1, 2}] The order of these terms appears to match your requested output whereas Michael's output does not.

• Interesting___, HoldForm[+##] – HyperGroups Aug 11 '13 at 11:47
• @HyperGroups I fixed mine, but I must admit Mr.Wizard's is much more elegant! – Michael E2 Aug 11 '13 at 12:14

This can easily be done by straight manipulation with the Presentations Application, which I sell.

<< Presentations

step1 = poly1 // MapLevelParts[FactorOut[-3], {{1, 2, 3, 5, 6, 7}}]
step2 = MapAt[HoldOrderForm[{1, 3, 2, 5, 4, 6}], step1, {{2, 2}}]  FactorOut will factor an arbitrary expression out of an existing expression - even if it is not initially in the expression. MapLevelParts will map a function to a set of level parts in an expression (usually a sum or product or sometimes a list). It applies as a whole to the sub sum, product or list. In your example the level parts are at level 1 but it is also possible to specify a set of level parts at a deeper position.

• This also doesn't seem to match the requested order. Compare your result to mine. – Mr.Wizard Aug 11 '13 at 8:44
• @ Mr. Wizard. Well that is easy to fix with another Presentations routine, HoldOrderForm, which allows the permutation of terms or factors. However, the first form does have the advantage of being a normal non-held Mathematica expression. – David Park Aug 11 '13 at 16:28