How to edit the order of sympy latex print? [duplicate] - python

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?

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.

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))

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.

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)

Related

Symbolic simplification of algebraic expressions composed of complex numbers

I have a question concerning the symbolic simplification of algebraic expressions composed of complex numbers. I have executed the following Python script:
from sympy import *
expr1 = 3*(2 - 11*I)**Rational(1, 3)*(2 + 11*I)**Rational(2, 3)
expr2 = 3*((2 - 11*I)*(2 + 11*I))**Rational(1, 3)*(2 + 11*I)**Rational(1, 3)
print("expr1 = {0}".format(expr1))
print("expr2 = {0}\n".format(expr2))
print("simplify(expr1) = {0}".format(simplify(expr1)))
print("simplify(expr2) = {0}\n".format(simplify(expr2)))
print("expand(expr1) = {0}".format(expand(expr1)))
print("expand(expr2) = {0}\n".format(expand(expr2)))
print("expr1.equals(expr2) = {0}".format(expr1.equals(expr2)))
The output is:
expr1 = 3*(2 - 11*I)**(1/3)*(2 + 11*I)**(2/3)
expr2 = 3*((2 - 11*I)*(2 + 11*I))**(1/3)*(2 + 11*I)**(1/3)
simplify(expr1) = 3*(2 - 11*I)**(1/3)*(2 + 11*I)**(2/3)
simplify(expr2) = 15*(2 + 11*I)**(1/3)
expand(expr1) = 3*(2 - 11*I)**(1/3)*(2 + 11*I)**(2/3)
expand(expr2) = 15*(2 + 11*I)**(1/3)
expr1.equals(expr2) = True
My questions is why the simplifications does not work for expr1 but
works for expr2 thoug the expressions are algebraically equal.
What has to be done to get the same result from simplify for expr1 as for expr2?
Thanks in advance for your replys.
Kind regards
Klaus
You can use the minimal polynomial to place algebraic numbers into a canonical representation:
In [30]: x = symbols('x')
In [31]: p1 = minpoly(expr1, x, polys=True)
In [32]: p2 = minpoly(expr2, x, polys=True)
In [33]: p1
Out[33]: Poly(x**2 - 60*x + 1125, x, domain='QQ')
In [34]: p2
Out[34]: Poly(x**2 - 60*x + 1125, x, domain='QQ')
In [35]: [r for r in p1.all_roots() if p1.same_root(r, expr1)]
Out[35]: [30 + 15⋅ⅈ]
In [36]: [r for r in p2.all_roots() if p2.same_root(r, expr2)]
Out[36]: [30 + 15⋅ⅈ]
This method should work for any two expressions representing algebraic numbers through algebraic operations: either they give the precise same result or they are distinct numbers.
It works (but nominally) for expr1 because when the product in the radical is expanded you get the cube root of 125 which is reported as 5. But SymPy tries to be careful about putting radicals together under a common exponent, an operation that is not generally valid (e.g. root(-1, 3)*root(-1,3) != root(1, 3) because the principle values are used for the roots. But if you want the bases to combine under a common exponent, you can force it to happen with powsimp:
>>> from sympy.abc import x, y
>>> from sympy import powsimp, root, solve, numer, together
>>> powsimp(root(x,3)*root(y,3), force=True)
(x*y)**(1/3)
But that only works if the exponents are the same:
>>> powsimp(root(x,3)*root(y,3)**2, force=True)
x**(1/3)*y**(2/3)
As you saw, equals was able to show that the two expressions were the same. One way this could be done is to solve for root(2 + 11*I, 3) and see if any of the resulting expression are the same:
>>> solve(expr1 - expr2, root(2 + 11*I,3))
[0, 5/(2 - 11*I)**(1/3)]
We can check the non-zero candidate:
>>> numer(together(_[1]-root(2+11*I,3)))
-(2 - 11*I)**(1/3)*(2 + 11*I)**(1/3) + 5
>>> powsimp(_, force=True)
5 - ((2 - 11*I)*(2 + 11*I))**(1/3)
>>> expand(_)
0
So we have shown (with force) that the expression was the same as that for which we solved. (And, as Oscar showed while I was writing this, minpoly is a nice candidate when it works: e.g. minpoly(expr1-expr2) -> x which means expr1 == expr2.)

How can I automatically generate an expression in Sympy using the coefficients of a 5th-order expression?

How can I automatically write a 5th order expression using a for loop using sympy in Python?
For example, let the expression be: y = 2x^5 + 3x^4 + 17x^3 + x^2 - 8x +101
I have the coefficients in the 5th order expression as a list. You can think of it like [101,-8,1,17,3,2].
I want to create a 5th order expression using the elements of this list using sympy.
I would be very grateful if you could help with this.
from sympy import *
x = symbols("x")
coeff = [101,-8,1,17,3,2]
# create a list of exponents going from 0 to 5 (included)
expon = list(range(len(coeff)))
# create a list of polynomial terms using list-comprehension syntax
# and sum up the elements
expr = sum(c * x**e for c, e in zip(coeff, expon))
Edit to satisfy comment:
from sympy import *
x = symbols("x")
coeff = [101,-8,1,17,3,2]
# create a list of exponents going from 0 to 5 (included)
expon = list(range(len(coeff)))
terms = []
for c, e in zip(coeff, expon):
terms.append(c * x**e)
expr = sum(terms)
Poly can accept a list of coefficients and the generator directly. It expects them in order from high to low. If you want an Expr, not a Poly, you can append the as_expr() call:
>>> little_endian = [101,-8,1,17,3,2]
>>> Poly(reversed(little_endian), x).as_expr()
2*x**5 + 3*x**4 + 17*x**3 + x**2 - 8*x + 101

nth derivative with sympy

I'm a bit new to sympy
I would like to compute nth derivative of an expression using sympy; however, I don't understand how the diff function works for nth derivative:
from sympy import diff, symbols
x = symbols("x")
f = ((x**2-1)**5)
# for n = 2
# from the sympy docs, I do:
d_doc = diff(f, x, x)
# using the diff two times
d_2 = diff(diff(f, x), x)
I get two different results:
>>> d_doc
10*(x**2 - 1)**3*(9*x**2 - 1)
>>> d_2
80*x**2*(x**2 - 1)**3 + 10*(x**2 - 1)**4
d_2 is the correct answer in this case.
Why is this?
is there a way to make a function that takes a n and returns the nth derivative?
The answer in an easy place, (from Pranav Hosangadi's comment):
It is the same, diff(f, x, x) simplifies the expression
>>> simplify(diff(f,x,x))
(x**2 - 1)**3*(90*x**2 - 10)
>>> simplify(diff(diff(f,x),x))
(x**2 - 1)**3*(90*x**2 - 10)

Python sympy symbols

When I use "x" and "z" as symbols, I have no problem with this code:
from sympy import *
x, z = symbols('x z')
y = -6*x**2 + 2*x*z**0.5 + 50*x - z
solve((diff(y, x), diff(y, z)))
y.subs({x: 5, z: 25})
But when I use "q" and "a", solve does not give me any solution.
q, a = symbols('q a')
y = -6*q**2 + 2*q*a**0.5 + 50*q - a
solve((diff(y, q), diff(y, a)))
y.subs({q: 5, a: 25})
As you can see I use "subs" to check that there is no typo in the objective function.
UPDATE: I used "Symbol" to set each variable individually, but again using "q" and "a" does not work.
# This works
x = Symbol('x')
z = Symbol('z')
y = -6*x**2 + 2*x*z**0.5 + 50*x - z
solve((diff(y, x), diff(y, z)))
# This does not work
q = Symbol('q')
a = Symbol('a')
y = -6*q**2 + 2*q*a**0.5 + 50*q-a
solve((diff(y, q), diff(y, a)))
Thank you.
Got it!
It all depends on an alphabetic order of your variables.
If you substitute x for z and z for x in your first example it will also stop working.
Internally solve sends the expression to the function _solve in sympy.solvers which then tries to solve your equation and fails many times.
Finally as a last effort what it does is it tries to solve -sqrt(a) + q or x - sqrt(z) by picking symbols from it through an internal function _ok_syms, with an argument that sorts those alphabetically (even without this argument it still would, but if wrapped with reversed it magically makes your examples works in the exactly opposite way).
And so it does solve x - sqrt(z) as x: sqrt(z) and -sqrt(a) + q as a: q**2.
While in the first case it ends up with an easily solvable 50 - 10*sqrt(z), in the second case it is lost on -12*q + 2*sqrt(q**2) + 50 as it is not able to simplify sqrt(q**2).
source:
a lot of testing on:
https://github.com/sympy/sympy/blob/master/sympy/solvers/solvers.py

Collecting like term of an expression in Sympy

I am currently dealing with functions of more than one variable and need to collect like terms in an attempt to simplify an expression.
Say the expression is written as follows:
x = sympy.Symbol('x')
y = sympy.Symbol('y')
k = sympy.Symbol('k')
a = sympy.Symbol('a')
z = k*(y**2*(a + x) + (a + x)**3/3) - k((2*k*y*(a + x)*(n - 1)*(-k*(y**2*(-a + x) + (-a + x)**3/3) + k*(y**2*(a + x) + (a + x)**3/3)) + y)**2*(-a + k*(n - 1)*(y**2 + (a + x)**2)*(-k*(y**2*(-a + x)))))
zEx = z.expand()
print type(z)
print type(zEx)
EDIT: Formatting to add clarity and changed the expression z to make the problem easier to understand.
Say z contains so many terms, that sifting through them by eye. and selecting the appropriate terms, would take an unsatisfactory amount of time.
I want to collect all of the terms which are ONLY a multiple of a**1. I do not care for quadratic or higher powers of a, and I do not care for terms which do not contain a.
The type of z and zEx return the following:
print type(z)
print type(zEx)
>>>
<class 'sympy.core.add.Add'>
<class 'sympy.core.mul.Mul'>
Does anyone know how I can collect the terms which are a multiple of a , not a^0 or a^2?
tl'dr
Where z(x,y) with constants a and k described by z and zEx and their type(): How can one remove all non-a terms from z AND remove all quadratic or higher terms of a from the expression? Such that what is left is only the terms which contain a unity power of a.
In addition to the other answers given, you can also use collect as a dictionary.
print(collect(zEx,a,evaluate=False)[a])
yields the expression
k*x**2 + k*y**2
In the end it is just an one-liner. #asmeurer brought me on the right track (check the comments below this post). Here is the code; explanations can be found below:
from sympy import *
from sympy.parsing.sympy_parser import parse_expr
import sys
x, y, k, a = symbols('x y k a')
# modified string: I added a few terms
z = x*(k*a**9) + (k**1)*x**2 - k*a**8 + y*x*(k**2) + y*(x**2)*k**3 + x*(k*a**1) - k*a**3 + y*a**5
zmod = Add(*[argi for argi in z.args if argi.has(a)])
Then zmod is
a**9*k*x - a**8*k + a**5*y - a**3*k + a*k*x
So let's look at this more carefully:
z.args
is just a collection of all individual terms in your expression (please note, that also the sign is parsed which makes things easier):
(k*x**2, a**5*y, -a**3*k, -a**8*k, a*k*x, a**9*k*x, k**2*x*y, k**3*x**2*y)
In the list comprehension you then select all the terms that contain an a using the function has. All these terms can then be glued back together using Add which gives you the desired output.
EDIT
The above returns all all the expressions that contain an a. If you only want to filter out the expressions that contain a with unity power, you can use collect and Mul:
from sympy import *
from sympy.parsing.sympy_parser import parse_expr
import sys
x, y, k, a = symbols('x y k a')
z2 = x**2*(k*a**1) + (k**1)*x**2 - k*a**8 + y*x*(k**2) + y*(x**2)*k**3 + x*k*a - k*a**3 + y*a**1
zc = collect(z2, a, evaluate=False)
zmod2 = Mul(zc[a], a)
then zmod2 is
a*(k*x**2 + k*x + y)
and zmod2.expand()
a*k*x**2 + a*k*x + a*y
which is correct.
With the updated z you provide I run:
z3 = k*(y**2*(a + x) + (a + x)**3/3) - k((2*k*y*(a + x)*(n - 1)*(-k*(y**2*(-a + x) + (-a + x)**3/3) + k*(y**2*(a + x) + (a + x)**3/3)) + y)**2*(-a + k*(n - 1)*(y**2 + (a + x)**2)*(-k*(y**2*(-a + x)))))
zc3 = collect(z3.expand(), a, evaluate=False)
zmod3 = Mul(zc3[a], a)
and then obtain for zmod3.expand():
a*k*x**2 + a*k*y**2
Is this the result you were looking for?
PS: Thanks to #asmeurer for all these helpful comments!
To iterate over the terms of an expression use expr.args.
I'm unclear what a is supposed to be, but the collect function may do what you want.

Categories

Resources