13

I have the following code:

from sympy import *
init_printing()

x,y = symbols('x y')
u = Function('u')(x,y)
ux,uy,uxx,uxy,uyy = symbols("u_x u_y u_xx u_xy u_yy")

mainEvaluation = uxx - 2*sin(x)*uxy - (cos(x) ** 2) * uyy - 2*ux + (2 - cos(x) + 2*sin(x) )*uy

And when the output of print(mainExpression) is

-2*u_x + u_xx - 2*u_xy*sin(x) + u_y*(2*sin(x) - cos(x) + 2) - u_yy*cos(x)**2

The problem is: I want the original order of variables.

u_xx - 2*u_xy*sin(x)  - u_yy*cos(x)**2  - 2*u_x + u_y*(2*sin(x) - cos(x) + 2)

All this is done in IPython notebook. Is there any way to keep order?

UpmostScarab
  • 960
  • 10
  • 29

4 Answers4

8

Sadly, SymPy does not keep track of the input order (see the other question I linked in a comment on the question). You can define your own ordering function that orders expressions however you want, but there's no way to order things exactly as they were input, since that information isn't saved.

asmeurer
  • 86,894
  • 26
  • 169
  • 240
5

If you know what your arguments/terms are then you can manually create the Add with evaluate=False to keep them in order and print them with a printer initialized to not change the order:

x,y = symbols('x y')
u = Function('u')(x,y)
ux,uy,uxx,uxy,uyy = symbols("u_x u_y u_xx u_xy u_yy")
args = uxx , -2*sin(x)*uxy, -cos(x)**2*uyy, -2*ux, +(2-cos(x)+2*sin(x))*uy

expr = Add(*args, evaluate=False)
from sympy.printing.str import StrPrinter # or LatexPrinter from .latex)
StrPrinter(dict(order='none'))._print_Add(expr)

This outputs

u_xx - 2*u_xy*sin(x) - u_yy*cos(x)**2 - 2*u_x + u_y*(2 - cos(x) + 2*sin(x))
smichr
  • 16,948
  • 2
  • 27
  • 34
2

try read this http://docs.sympy.org/0.7.2/modules/utilities/misc.html, may be could help you

Note:

The key returned is useful for getting items into a canonical order that will be the same across platforms. It is not directly useful for sorting lists of expressions:

>>> a, b = x, 1/x

Since a has only 1 term, its value of sort_key is unaffected by order:

>>> a.sort_key() == a.sort_key('rev-lex')
True

If a and b are combined then the key will differ because there are terms that can be ordered:

>>> eq = a + b
>>> eq.sort_key() == eq.sort_key('rev-lex')
False
>>> eq.as_ordered_terms()
[x, 1/x]
>>> eq.as_ordered_terms('rev-lex')
[1/x, x]

But since the keys for each of these terms are independent of order‘s value, they don’t sort differently when they appear separately in a list:

>>> sorted(eq.args, key=default_sort_key)
[1/x, x]
>>> sorted(eq.args, key=lambda i: default_sort_key(i, order='rev-lex'))
[1/x, x]

The order of terms obtained when using these keys is the order that would be obtained if those terms were factors in a product.

sophros
  • 14,672
  • 11
  • 46
  • 75
Milor123
  • 537
  • 4
  • 20
  • Thank you for your answer! I'll look into that. Though I wondered if there's a flag or something for such purpose. Hope there is. – UpmostScarab Mar 30 '16 at 19:53
1

For the teaching purpose, I also don't want to simpilify or change the order of terms too early.

I'm using pytexit with jupyter notebook: https://pytexit.readthedocs.io/en/latest/

from pytexit import py2tex

def showeq(str):
    py2tex(str, print_formula=False);

eq1 = "angle = acos((side_A**2 + side_B**2 - side_C**2)/(2*side_A*side_B))"
show(eq1)

side_A = 14.8
side_B = 16.3
side_C = 13.2
exec(eq1)
Jeremy Chen
  • 1,299
  • 2
  • 11
  • 18