Order of terms in polynomial with symbolic coefficients?

208 views
Skip to first unread message

Matthias Geier

unread,
Feb 22, 2018, 2:02:20 PM2/22/18
to sy...@googlegroups.com
Dear SymPy list.

I'm playing around with polynomials in the context of spline curves.

I want to use a cubic polynomial with yet unknown coefficients like this:

>>> import sympy as sp
>>> t, a0, a1, a2, a3 = sp.symbols('t, a:4', real=True)
>>> a3 * t**3 + a2 * t**2 + a1 * t + a0
a0 + a1*t + a2*t**2 + a3*t**3

The problem here is that the displayed order of terms is reversed,
normally the highest power of t should come first.
I guess this is because SymPy doesn't know that the coefficients a0
etc. are constants and shouldn't be treated like variables.
So in fact this polynomial isn't sorted by powers of t but instead by
the coefficients.

Is there a way to get around this?

At some later point, I have expressions like this (without t):

a1 + 2*a2 + 3*a3

It would make sense in my case to also display them reversed like this:

3*a3 + 2*a2 + a1

Is it possible to create a new type of symbol with non-default ordering?
Is it possible to define that this order is "ascending": a3, a2, a1, a0?
It doesn't have to be a generic solution, I'm OK with having those 4
special symbols.

Or is there an entirely different and much better way to do this?

I know that I could just use a, b, c, d instead of a3, a2, a1, a0 and
it would work, but I would really like to see the connection between a
coefficient and its power of t.

For the record, I also quickly tried to use IndexedBase to get a3, a2,
a1 and a0, and it turns out that although the LaTeX display of the
symbols looks the same (in text mode it's different), they are sorted
differently.

>>> b = sp.IndexedBase('b')
>>> b[3] * t**3 + b[2] * t**2 + b[1] * t + b[0]
t**3*b[3] + t**2*b[2] + t*b[1] + b[0]

They are sorted after the powers of t, which isn't what I want, either.

cheers,
Matthias

Leonid Kovalev

unread,
Feb 22, 2018, 5:38:53 PM2/22/18
to sympy
In SymPy, polynomials have extra structure that distinguishes them from generic expressions. a3 * t**3 + a2 * t**2 + a1 * t + a0 is an expression. 
If you create a polynomial in t, it will print with the order of terms being from highest to lowest. 

>>> p = sp.Poly([a3, a2, a1, a0], t)
>>> print(p)
Poly(a3*t**3 + a2*t**2 + a1*t + a0, t, domain='ZZ[a0,a1,a2,a3]')



Also, the order can be specified in the print command

>>> pprint(a3 * t**3 + a2 * t**2 + a1 * t + a0, order='grevlex')
   
3       2            
a
₃⋅t  + a₂⋅t  + a₁⋅t + a


or, staying with str format,


>>> sstrrepr(a3 * t**3 + a2 * t**2 + a1 * t + a0, order='grevlex')
'a3*t**3 + a2*t**2 + a1*t + a0'


The printing module has a number of printers which support a number of settings.  

Matthias Geier

unread,
Feb 23, 2018, 5:54:16 AM2/23/18
to sy...@googlegroups.com
Thanks Leonid for this quick and helpful answer!

I just have a few follow-up questions:

On Thu, Feb 22, 2018 at 11:38 PM, Leonid Kovalev wrote:
> In SymPy, polynomials have extra structure that distinguishes them from
> generic expressions. a3 * t**3 + a2 * t**2 + a1 * t + a0 is an expression.
> If you create a polynomial in t, it will print with the order of terms being
> from highest to lowest.
>
> >>> p = sp.Poly([a3, a2, a1, a0], t)
> >>> print(p)
> Poly(a3*t**3 + a2*t**2 + a1*t + a0, t, domain='ZZ[a0,a1,a2,a3]')

Ah, that's interesting!

I was actually using a Jupyter notebook with MathJax output most of
the time, and there this is not true!

Same for the raw LaTeX output:

>>> sp.latex(p)
'\\operatorname{Poly}{\\left( a_{0} + a_{1} t + a_{2} t^{2} +
a_{3} t^{3}, t, domain=\\mathbb{Z}\\left[a_{0}, a_{1}, a_{2},
a_{3}\\right] \\right)}'

Is this a bug?

> Also, the order can be specified in the print command
>
> >>> pprint(a3 * t**3 + a2 * t**2 + a1 * t + a0, order='grevlex')
> 3 2
> a₃⋅t + a₂⋅t + a₁⋅t + a₀
>
>
> or, staying with str format,
>
>
> >>> sstrrepr(a3 * t**3 + a2 * t**2 + a1 * t + a0, order='grevlex')
> 'a3*t**3 + a2*t**2 + a1*t + a0'

That's great, I think 'grevlex' is what I want!

I was actually already playing around with 'lex', 'revlex' and
'grevlex', but I got confused at some point.
It looks like this doesn't work if the highest power doesn't have a
symbolic coefficient, e.g.:

>>> sp.sstrrepr(t**2 + a1 * t, order='grevlex')
'a1*t + t**2'

I assume there is a perfectly reasonable explanation for that, and in
my case such expressions didn't actually appear yet, so that's fine
for me.

I think I will mainly use 'grevlex' with:

sp.init_printing(order='grevlex')

But when I'm dealing with expressions that have only the coefficients
and no powers of t in them, e.g.:

3*a3 + 2*a2 + a1

... then I'll temporarily switch:

sp.init_printing(order='rev-lex')

Or is this a bad idea?
Or is there a better way to temporarily change the order?

Is there a way to specify the order for a single Jupyter output cell?

> The printing module has a number of printers which support a number of
> settings.

Thanks for the reference to
http://docs.sympy.org/latest/modules/printing.html, that's a very
helpful page.

cheers,
Matthias

Aaron Meurer

unread,
Feb 23, 2018, 5:09:08 PM2/23/18
to sy...@googlegroups.com
It is possible to create a custom order, however the documentation is
pretty sparse. The place to start is here if you want to look into it
https://github.com/sympy/sympy/blob/fb536869fb7aa28b2695ad7a3b70949926b291c4/sympy/polys/orderings.py#L199.
The printers (including the latex printer) have an order setting which
ends up getting passed to that function.

Aaron Meurer
> --
> You received this message because you are subscribed to the Google Groups "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
> To post to this group, send email to sy...@googlegroups.com.
> Visit this group at https://groups.google.com/group/sympy.
> To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/CAFesC-cN3_h-dVm854PeU%3Dkr3J%2Bhywyvkk0JBMbDrqQiRcbinA%40mail.gmail.com.
> For more options, visit https://groups.google.com/d/optout.

Leonid Kovalev

unread,
Feb 25, 2018, 7:35:10 PM2/25/18
to sympy
The LaTeX printing of Poly was indeed buggy. Corrected in the current development version of SymPy: 

>>> latex(Poly([a3, a2, a1, a0], t))
'\\operatorname{Poly}{\\left( a_{3} t^{3} + a_{2} t^{2} + a_{1} t + a_{0}, t, domain=\\mathbb{Z}\\left[a_{0}, a_{1}, a_{2}, a_{3}\\right] \\right)}'


Reply all
Reply to author
Forward
0 new messages