22
$\begingroup$

For example,

Collect[(1 + x + Cos[s] x^2)^3, x]

gives the result

1 + 3 x + 3 x^5 Cos[s]^2 + x^6 Cos[s]^3 + x^2 (3 + 3 Cos[s]) + x^3 (1 + 6 Cos[s]) 
     + x^4 (3 Cos[s] + 3 Cos[s]^2)

Terms of the form $x^n$ are in random order. I would like the result is to be as follows:

 1 + 3 x + x^2 (3 + 3 Cos[s]) + x^3 (1 + 6 Cos[s]) +  
   x^4 (3 Cos[s] + 3 Cos[s]^2) + 3 x^5 Cos[s]^2 + x^6 Cos[s]^3

Well, First Thank you very much, Jens! Second, I found there is something wrong with your statement "the HoldForm could be left out". I have tried on my mathematica 8, it turns out that the "HoldForm" is necessary . if "HoldForm" is not there, the order is still random in the output . And I tried to understand this as well as "rule" and "ruledelayed" stuff but can't figure it out. I have tried several input, each confused me. summarized as follows

  1. Replace[cx, List[x__] -> Plus[x]]

    will give

    Sequence[1, 3 x, x^2 (3 + 3 Cos[s]), x^3 (1 + 6 Cos[s]), x^4 (3 Cos[s] + 3 Cos[s]^2), 3 x^5 Cos[s]^2, x^6 Cos[s]^3] 
    

    But I suppose it should give the Plus result because

    Replace[cx, List[x__] -> jjj[x]]
    

    gives

    jjj[1, 3 x, x^2 (3 + 3 Cos[s]), x^3 (1 + 6 Cos[s]),  x^4 (3 Cos[s] + 3 Cos[s]^2), 3 x^5 Cos[s]^2, x^6 Cos[s]^3]
    
  2. Replace[cx, List[x__] -> HoldForm@Plus[x]] gives the right result

    1 + 3 x + x^2 (3 + 3 Cos[s]) + x^3 (1 + 6 Cos[s]) +  x^4 (3 Cos[s] + 3 Cos[s]^2) + 3 x^5 Cos[s]^2 + x^6 Cos[s]^3
    
  3. Replace[cx, List[x__] :> Plus[x]] gives

    1 + 3 x + 3 x^5 Cos[s]^2 + x^6 Cos[s]^3 + x^2 (3 + 3 Cos[s]) + x^3 (1 + 6 Cos[s]) + x^4 (3 Cos[s] + 3 Cos[s]^2)
    

    Although it gives the right plus result, the order is wrong.

$\endgroup$

4 Answers 4

18
$\begingroup$

Here is an approach that doesn't rely on undocumented features or on low-level box manipulations. We're dealing with a polynomial, so we can simply collect its coefficients and arrange them any way we like as follows:

c0 = Collect[(1 + x + Cos[s] x^2)^3, x];

cx = CoefficientList[c0, x] x^Range[0, Exponent[c0, x]]

(*
==> {1, 3 x, x^2 (3 + 3 Cos[s]), x^3 (1 + 6 Cos[s]), 
 x^4 (3 Cos[s] + 3 Cos[s]^2), 3 x^5 Cos[s]^2, x^6 Cos[s]^3}
*)

Replace[cx, List[x__] :> HoldForm[Plus[x]]]

$1+3 x+x^2 (3+3 \cos (s))+x^3 (1+6 \cos (s))+x^4 \left(3 \cos (s)+3 \cos ^2(s)\right)+3 x^5 \cos ^2(s)+x^6 \cos ^3(s)$

I've just assembled the desired form of the polynomial by creating a list cx of all terms up to the maximum power Exponent[c0, x], and then turning that list into a sum by means of Replace. Here, the HoldForm was put in so that the output now can be arranged in any alternative order by permuting (or, in particular, reversing) the list cx before doing the Replace:

Replace[Reverse@cx, List[x__] :> HoldForm[Plus[x]]]

$x^6 \cos ^3(s)+3 x^5 \cos ^2(s)+x^4 \left(3 \cos (s)+3 \cos ^2(s)\right)+x^3 (1+6 \cos (s))+x^2 (3+3 \cos (s))+3 x+1$

The output is in held form, so if you apply ReleaseHold to it the order will revert back to the first version. The HoldForm could also be exploited to do further cosmetic changes on the expression, such as putting coefficients before the power of x - but you didn't ask for that.

Edit In response to a follow-up question: the Replace command has RuleDelayed (:>) instead of -> in it because the pattern indicated by x__ has to be fed into the Plus only at the time when there is actually a list of terms present. E.g., if you use List[x__] -> Plus[x] then the right-hand side is immediately evaluated to give you x as the result of Plus[x] (assuming that x hasn't been defined globally). And when you then later encounter the Replace statement it will say to feed the pattern inside List into the right-hand side that now has the form x instead of Plus[x]. That will yield something with the head Sequence corresponding to the sequence of arguments inside the given List.

$\endgroup$
4
  • $\begingroup$ I admit that's better. +1 $\endgroup$
    – Mr.Wizard
    Dec 5, 2012 at 7:45
  • $\begingroup$ Hello! Jens! I have some more questions, and post it as an "answer" below, would you please help me figure them out? $\endgroup$
    – matheorem
    Dec 6, 2012 at 6:46
  • $\begingroup$ @user15964 Yes, I think my statement about HoldForm is confusing. I think I wanted to say that it's not needed if you want to replace a list by a sum, but of course it's needed to preserve the desired order as I tried to say afterwards. I'll edit this, but you should delete your answer because you're not supposed to write follow-up questions that way. $\endgroup$
    – Jens
    Dec 6, 2012 at 7:27
  • $\begingroup$ Thank you! finally, All is clear. $\endgroup$
    – matheorem
    Dec 6, 2012 at 8:03
23
$\begingroup$

You can use PolynomialForm :

Collect[(1 + x + Cos[s] x^2)^3, x] // PolynomialForm[#, TraditionalOrder -> True] &
Cos[s]^3 x^6 + 3 Cos[s]^2 x^5 + (3 Cos[s]^2 + 3 Cos[s]) x^4 + (6 Cos[s] + 1) x^3
 + (3 Cos[s] + 3) x^2 + 3 x + 1
$\endgroup$
5
  • $\begingroup$ Thank you! it's really worked! But why I can't find the "polynomialForm" entry in mathematica document centre?? And is there any other order except traditional order? How about keep order from low to high instead of high to low? $\endgroup$
    – matheorem
    Dec 5, 2012 at 5:48
  • 3
    $\begingroup$ @user15964 PolynomialForm is undocumented. You can evaluate e.g. Options[PolynomialForm] which yields only {TraditionalOrder -> Automatic}. More on useful undocumented functions you can find here : mathematica.stackexchange.com/questions/805/…. On the other hand you can get almost the same result with documented TraditionalForm : e.g. expr // TraditionalForm. $\endgroup$
    – Artes
    Dec 5, 2012 at 12:07
  • $\begingroup$ @Artes Is there any undocumented MultivariatePolynomialForm function like PolynomialForm? $\endgroup$ Jan 29, 2020 at 3:55
  • 1
    $\begingroup$ @PleaseCorrectGrammarMistakes PolynomialForm works for multi-variable polynomials as well. $\endgroup$
    – Artes
    Jan 29, 2020 at 21:49
  • $\begingroup$ @Artes PolynomialForm[b*x*y^3 + x^2 + a*x + y + y^2, {x, y}] How to get the sorting result of the binary polynomials according to the sum of index of the specified variables:a*x + y + x^2 + y^2 + b*x*y^3. $\endgroup$ Jan 30, 2020 at 0:55
6
$\begingroup$

Artes shows how to use TraditionalOrder, but user15964 asks "How about keep order from low to high instead of high to low?" This can be done by manipulating the Box structure output of PolynomialForm. First a look at that box structure:

tradOrder = PolynomialForm[#, TraditionalOrder -> True] &;
boxes = Collect[(1 + x + Cos[s] x^2)^3, x] // tradOrder // ToBoxes;
boxes // Shallow
TagBox[RowBox[{<<13>>}], <<2>>&]

The row of terms is held as the elements skeletonized as <<13>>. This list is at part {1, 1} of the boxes expression, so if we MapAt Reverse onto this position, and then show the boxes with DisplayForm we get:

MapAt[Reverse, boxes, {1, 1}] // DisplayForm
 1 + 3 x + (3 Cos[s] + 3) x^2 + (6 Cos[s] + 1) x^3 + (3 Cos[s]^2 + 3 Cos[s]) x^4 
  + 3 Cos[s]^2 x^5 + Cos[s]^3 x^6
$\endgroup$
5
$\begingroup$

It seems that a clean yet undocumented method has existed since v5.2 or earlier that could be applied here. Please reference Undocumented fourth parameter of Collect; how long has it been there? and then observe:

Collect[(1 + x + Cos[s] x^2)^3, x, # &, Defer[+##] &]
1 + 3 x + x^2 (3 + 3 Cos[s]) + x^3 (1 + 6 Cos[s]) + x^4 (3 Cos[s] + 3 Cos[s]^2) + 
 3 x^5 Cos[s]^2 + x^6 Cos[s]^3

Or in reverse:

Collect[(1 + x + Cos[s] x^2)^3, x, # &, Defer[+##] ~Reverse~ 2 &]
x^6 Cos[s]^3 + 3 x^5 Cos[s]^2 + x^4 (3 Cos[s] + 3 Cos[s]^2) + x^3 (1 + 6 Cos[s]) + 
 x^2 (3 + 3 Cos[s]) + 3 x + 1
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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