Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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.

share|improve this question
1  
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
1  
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
add comment

3 Answers 3

up vote 2 down vote accepted

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[#] &]]

Mathematica graphics

Or you can use Row to keep them in the desired order (as in the question):

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

Mathematica graphics

Or use polyForm, which will yield the standard spacing around the last minus sign:

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

Mathematica graphics


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[#] &]]]

Mathematica graphics

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[##]] &)
share|improve this answer
    
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
add comment

Related questions:

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

HoldForm[+##] & @@ MonomialList[poly1]

enter image description here

(+## 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}]

enter image description here

The order of these terms appears to match your requested output whereas Michael's output does not.

share|improve this answer
    
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
add comment

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

enter image description here enter image description here

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.

share|improve this answer
    
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
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.