I'ld like my SymPy results to be displayed as precise results and not as decimal results. I looked through the SymPy documentation, but couldn't find anything helpful.
To illustrate the problem, here is some example code:
from sympy import *
u = symbols("u")
integrate((1+u)**(1/2), (u, 0, 1))
Output:
1.21895141649746
Expected result:
(4/3)*sqrt(2)-(2/3)
The problem is that SymPy will simplify expressions containing floats and so removes those symbolic expressions. Although the expression doesn't look like a float, the division 1/2 is done with standard Python, internally represented as 0.5.
The solution is to first convert one of the parts of the fraction to a SymPy object. The easiest way is with the function S, as in:
from sympy import *
u = symbols("u")
print(integrate((1+u)**(S(1)/2), (u, 0, 1)))
which outputs the desired -2/3 + 4*sqrt(2)/3.
The gotcha section of the documentation tries to explain this behavior.
Related
I had some trouble adding complex numbers in polar form in sympy.
The following code
from sympy import I, exp, pi, re, im
a = exp(2*pi/3*I)
b = exp(-2*pi/3*I)
c = a+b
print(c)
print(c.simplify())
print(c.as_real_imag())
print(re(c)+im(c)*I)
print(int(c))
print(complex(c))
gives
exp(-2*I*pi/3) + exp(2*I*pi/3)
-(-1)**(1/3) + (-1)**(2/3)
(-1, 0)
-1
-1
(-1+6.776263578034403e-21j)
What I want, is to get the simplest answer to a+b, which is -1. I can obtain this, by manually rebuilding c=a+b with re(c)+im(c)*I. Why is this necessary? And is there a better way to do this?
Simply printing c retains the polar forms, obfuscating the answer, c.simplify() leaves the polar form, but is not really helpful, and c.as_real_imag() returns a tuple. int(c) does the job, but requires the knowledge, that c is real (otherwise it throws an error) and integer (otherwise, this is not the answer I want). complex(c) kind of works, but I don't want to leave symbolic calculation. Note, that float(c) does not work, since complex(c) has a non-zero imaginary part.
https://stackoverflow.com/users/9450991/oscar-benjamin has given you the solution. If you are in polar coordinates, your expression may have exponential functions. If you don't want these you have to rewrite into trigonometric functions where special values are known for many values. For example, consider a's 2*pi/3 angle:
>>> cos(2*pi/3)
-1/2
>>> sin(2*pi/3)
sqrt(3)/2
When you rewrite a in terms of cos (or sin) it becomes the sum of those two values (with I on the sin value):
>>> a.rewrite(cos)
-1/2 + sqrt(3)*I/2
When you rewrite a more complex expression, you will get the whole expression rewritten in that way and any terms that cancel/combine will do so (or might need some simplification):
>>> c.rewrite(cos)
-1
Hello I have this sympy expression 0.5*c**2*m*(v/c)**2.0 and I want to bring it automatically to this form: 0.5*m*v**2. I tried the sympy simplify function but that doesn't seem to work. What can I do? Thank you!
These two expressions are not equivalent, only equivalent if c is not equal to 0. So if you want to get 0.5*m*v**2, you need set c as a positive number:``
>>> import sympy
>>> c= sympy.symbols('c',positive=True)
>>> m,v = sympy.symbols('m v')
>>> sympy.powsimp(0.5*c**2*m*(v/c)**2.0)
0.5*m*v**2.0
Besides, although sympy.simplify will give you what you want, I think sympy.powsimp is better. Because actually we want to reduce expression by combining powers with similar bases and exponents.
I recently started learning IPython. I have a problem with Sympy library. It only prints the function instead of exact value.
import matplotlib.pyplot as plt
import numpy as nm
from sympy import *
x,y = symbols("x y")
expr = cos(x)
a = expr.subs(x,1)
print(a)
The output of above program is cos(1). But I want to print the exact value of cos(1).
First of all some nitpicking: “cos(1)” is the most concise way to represent the exact value of cos(1). Numerical representations like “0.54”, “0.540302”, or “0.54030230587” are not exact but are only accurate within the respective number of digits. The fact that cos(1) is not simply translated to one of those numerical approximations is one of the features of SymPy, as it ensures that something like simplify(acos(cos(1))) actually yields 1 and not 0.99999999.
That being said, there are of course purposes where you really need a numerical representation. In this case, you can use the class function n of SymPy expressions or the function N from SymPy, for example:
from sympy import cos, N
expr = cos(1)
print(expr.n()) # 0.540302305868140
print(N(expr)) # 0.540302305868140
I find myself wanting to use approxmations provided as part of the mpmath package, but getting confused on exactly what they are supposed to be doing:
http://docs.sympy.org/dev/modules/mpmath/calculus/approximation.html
What exactly is the difference between a sympy expression and a sympy.mpmath expression ?
If I want a taylor approximation to a symbolic expression without understanding what mpmath package is doing I can do the following:
#Imports
import sympy
import sympy.parsing
import sympy.parsing.sympy_parser
import Library_TaylorApproximation
#Create a sympy expression to approximate
ExampleStringExpression = 'sin(x)'
ExampleSympyExpression = sympy.parsing.sympy_parser.parse_expr(ExampleStringExpression)
#Create a taylor expantion sympy expression around the point x=0
SympyTaylorApproximation = sympy.series(
ExampleSympyExpression,
sympy.Symbol('x'),
1,
4,
).removeO()
#Cast the sympy expressions to python functions which can be evaluated:
VariableNames = [str(var) for var in SympyTaylorApproximation.free_symbols]
PythonFunctionOriginal = sympy.lambdify(VariableNames, ExampleSympyExpression)
PythonFunctionApproximation = sympy.lambdify(VariableNames, SympyTaylorApproximation)
#Evaluate the approximation and the original at a point:
print PythonFunctionOriginal(2)
print PythonFunctionApproximation(2)
#>>> 0.909297426826
#>>> 0.870987413961
However, if I try to do the same thing with mpmath based on the documentation:
TaylorCoefficients = sympy.mpmath.taylor(ExampleSympyExpression, 1, 4 )
print 'TaylorCoefficients', TaylorCoefficients
#>>> TypeError: 'sin' object is not callable
I can try to cram the python function in there (which is callable):
TaylorCoefficients = sympy.mpmath.taylor(PythonFunctionOriginal, 1, 4 )
print 'TaylorCoefficients', TaylorCoefficients
#>>> TaylorCoefficients [mpf('0.8414709848078965'), mpf('0.0'), mpf('0.0'), mpf('0.0'), mpf('-8.3694689805155739e+57')]
But the above does not make any sense, because I know that derivatives cannot be taken of a python function.
I can call the mpmath function sin:
TaylorCoefficients = sympy.mpmath.taylor(sympy.mpmath.sin, 1, 4 )
print 'TaylorCoefficients', TaylorCoefficients
#>>> TaylorCoefficients [mpf('0.8414709848078965'), mpf('0.54030230586813977'), mpf('-0.42073549240394825'), mpf('-0.090050384311356632'), mpf('0.035061291033662352')]
But then I cannot do manipulations on it the way I would want too -> like If I want
SinTimesCos = sympy.mpmath.sin*sympy.mpmath.cos
TaylorCoefficients = sympy.mpmath.taylor(SinTimesCos, 1, 4 )
print 'TaylorCoefficients', TaylorCoefficients
#>>> TypeError: unsupported operand type(s) for *: 'function' and 'function'
Exactly WHAT is an mpmath function ?
It is not a sympy expression, and it is also not a python function. How do I do manipulations on arbitrary expressions?
It would appear that I cannot take approximations of arbitrary sympy expressions in the documentation.
http://docs.sympy.org/dev/modules/mpmath/calculus/approximation.html
How do I take arbitrary approximations ( Pade / Cheby Chev / Fourier )
to arbitrary sympy expressions?
EDIT:
So an example of what I am looking for is the following approximation:
#Start with a sympy expression of (a, b, x)
expressionString = 'cos(a*x)*sin(b*x)*(x**2)'
expressionSympy = sympy.parsing.sympy_parser.parse_expr(expressionString)
#Do not want to decide on value of `a or b` in advance.
#Do want approximation with respect to x:
wantedSympyExpression = SympyChebyChev( expressionSympy, sympy.Symbol('x') )
Result could either be a list of coefficient expressions that are functions of a, and b:
wantedSympyExpressionCoefficients = [ Coef0Expression(a,b), Coef1Expression(a,b), ... , CoefNExpression(a,b)]
OR the result could be the entire sympy expression itself (which is itself a function of a, b):
wantedSympyExpression = Coef0Expression(a,b) + Coef1Expression(a,b) *(x**2) + ... + CoefNExpression(a,b) (x**N)
Note that a and b are not chosen in advance of performing the approximation.
mpmath functions are ordinary Python functions. They simply do their math in arbitrary-precision arithmetic.
But the above does not make any sense, because I know that derivatives cannot be taken of a python function.
You can't take the derivative symbolically, but you can compute an approximation of the derivative by evaluating the function several times and using numerical differentiation techniques. This is what sympy.mpmath.taylor does. Quoting the docs:
The coefficients are computed using high-order numerical differentiation. The function must be possible to evaluate to arbitrary precision.
If you have a SymPy expression and want to evaluate it to arbitrary precision, use evalf, like
sympy.sin(1).evalf(100)
You can use sin(x).evalf(100, subs={x:1}) to replace the x with 1 before evaluating. evalf uses mpmath under the hood, so this will give you the same result that mpmath would, but without having to use mpmath directly.
Why doesn't -(-1)**(1/3) + (-1)**(2/3) reduce to -1?
wolfram alpha knows it's -1 but sympy gamma only does a float approximation
re(_) + I*im(_) produces a NegativeOne object, but none of the other simplification functions I tried did anything to it.
I'm assuming you really mean -(-1)**Rational(1, 3) + (-1)**Rational(2, 3), as literally -(-1)**(1/3) + (-1)**(2/3) is all Python (no SymPy), and evaluates numerically.
Most SymPy objects do not do any kind of nontrivial simplification automatically. The reason is that sometimes you might want to represent -(-1)**(1/3) + (-1)**(2/3) without it simplifying. Also, simplification in general is an expensive operation, and doing so at operation creation time would be very inefficient, as often you create intermediate expressions that don't need to be simplified at the intermediate stage.
re(expr) + I*im(expr) is fine. A more automated way to do that is to use expand_complex():
In [19]: expand_complex(-(-1)**Rational(1, 3) + (-1)**Rational(2, 3))
Out[19]: -1
Ideally simplify() would call expand_complex(), and there is an open issue for this (https://github.com/sympy/sympy/issues/7569).
And a note that SymPy Gamma provides a lot of automation on top of SymPy directly. For instance, it converts -(-1)**(1/3) + (-1)**(2/3) to SymPy types and performs various functions to the expression, like numerical evaluation, simplification, differentiation, etc.