Sympy - not converting `solve()` correctly - python

I apologize if this has been asked already.
I am just learning about SymPy and I'm wondering why it won't spit out a correct answer for what seems to be a simple equation.
from sympy.solvers import solve
from sympy import Symbol, simplify
from sympy.abc import x, alpha, sigma
alpha = Symbol('alpha')
x = Symbol('x')
sigma = Symbol('sigma')
solve((alpha - 0.5*(sigma**2))*((alpha + 0.5*(sigma**2)))**(-1)+ (1/7),sigma**2, simplify = True)
It spits out [2.0* alpha], which I know is incorrect. In fact, the answer should be [2.6666*alpha] or something like that. I'm assuming that SymPy is for some reason converting the number 2.666 to an integer string.
How can I fix this problem? Also, is there any way I could get the fractional form of the solution?

You're probably using Python 2.7, so 1/7 is giving you integer division:
>>> 1/7
0
>>> 1./7
0.14285714285714285
>>> solve((alpha - 0.5*(sigma**2))*((alpha + 0.5*(sigma**2)))**(-1)+ (1/7),sigma**2, simplify = True)
[2.0*alpha]
>>> solve((alpha - 0.5*(sigma**2))*((alpha + 0.5*(sigma**2)))**(-1)+ (1./7),sigma**2, simplify = True)
[2.66666666666667*alpha]
If you want the fractional answer, maybe something like
>>> from sympy import Rational
>>> solve((alpha - (sigma**2)/2)*((alpha + (sigma**2)/2))**(-1)+ Rational(1,7),sigma**2, simplify = True)
[8*alpha/3]

You can also use help(solve) to read the docstring of solve that tells how to use the rational keyword:
>>> solve(x-.3)
[0.300000000000000]
>>> solve(x-.3, rational=True)
[3/10]

Related

How to simplify a sympy expression

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.

SymPy outputs a numerical result when a symbolic expression is expected

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.

How to apart Exponential function in python

I am trying to apart Exponential function in python.
import sympy as sym
from sympy.abc import t
from sympy import exp
u = (3*(exp(4*t) - 1)*exp(-4*t))/4
apart = sym.apart(u, t)
print(apart)
But i get the error:
exp(4*t) contains an element of the set of generators
it looks like exp() is confusing it. For a workaround
import sympy as sym
from sympy.abc import t,z
from sympy import exp
u = (3*(exp(4*t) - 1)*exp(-4*t))/4
expr = sym.apart(u.subs(exp(t),z), z)
expr = expr.subs(z,exp(t))
Which gives
Out[3]: 3/4 - 3*exp(-4*t)/4
Using 3.7 on conda
Your expression is a univariate, rational function in terms of exp(t):
>>> u.subs(exp(t),y)
3*(y**4 - 1)/(4*y**4)
>>> apart(_)
3/4 - 3/(4*y**4)
>>> _.subs(y, exp(t))
3/4 - 3*exp(-4*t)/4
But SymPy can handle such non-symbol generators so for such an expression sym.apart(u) would have given the same result as shown above. When you said the generator was t it detected the exp(t) and raised the error since an expression like t + exp(t) has two generators that depend on t.

How to correctly deal with floating point arithmetic in Python?

How to correctly add or subtract using floats?
For example how to perform:
2.4e-07 - 1e-8
so that it returns 2.3e-7 instead of 2.2999999999999997e-07.
Converting to int first yields unexpected results, the below returns 2.2e-07:
int(2.4e-07 * 1e8 - 1) * 1e-8
Similarly,
(2.4e-07 * 1e8 - 1) * 1e-8
returns 2.2999999999999997e-07.
How to perform subtraction and addition of numbers with 8 decimal point precision?
2.2999999999999997e-07 is not sufficient as the number is used as a lookup in a dictionary, and the key is 2.3e-7. This means that any value other than 2.3e-7 results in an incorrect lookup.
I suggest using the decimal data type (it is present in the stardard installation of Python), because it uses fixed precision to avoid just the differences you are talking about.
>>> from decimal import Decimal
>>> x = Decimal('2.4e-7')
>>> x
Decimal('2.4E-7')
>>> y = Decimal('1e-8')
>>> y
Decimal('1E-8')
>>> x - y
Decimal('2.3E-7')
It's really just a way of skirting around the issue of floating point arithmetic, but I suggest using the decimal package from the standard library. It lets you do exact floating point math.
Using your example,
$ from decimal import Decimal
$ x = Decimal('2.4e-7')
$ y = Decimal('1e-8')
$ x-y
Decimal('2.3E-7')
It's worth noting that Decimal objects are different than the float built-in, but they are mostly interchangeable.
I do not know if it is what you are looking for but you can try that kind of thing:
a = 0.555555555
a = float("{0:.2f}".format(a))
>>> 0.56
I hope it will help you!
Adrien

Getting a better answer from sympy inverse laplace transform

Trying to compute the following lines I'm getting a realy complex result.
from sympy import *
s = symbols("s")
t = symbols("t")
h = 1/(s**3 + s**2/5 + s)
inverse_laplace_transform(h,s,t)
The result is the following:
(-(I*exp(-t/10)*sin(3*sqrt(11)*t/10) - exp(-t/10)*cos(3*sqrt(11)*t/10))*gamma(-3*sqrt(11)*I/5)*gamma(-1/10 - 3*sqrt(11)*I/10)/(gamma(9/10 - 3*sqrt(11)*I/10)*gamma(1 - 3*sqrt(11)*I/5)) + (I*exp(-t/10)*sin(3*sqrt(11)*t/10) + exp(-t/10)*cos(3*sqrt(11)*t/10))*gamma(3*sqrt(11)*I/5)*gamma(-1/10 + 3*sqrt(11)*I/10)/(gamma(9/10 + 3*sqrt(11)*I/10)*gamma(1 + 3*sqrt(11)*I/5)) + gamma(1/10 - 3*sqrt(11)*I/10)*gamma(1/10 + 3*sqrt(11)*I/10)/(gamma(11/10 - 3*sqrt(11)*I/10)*gamma(11/10 + 3*sqrt(11)*I/10)))*Heaviside(t)
However the answer should be simpler, Wolframalpha proves it.
Is there any way to simplify this result?
I tried a bit with this one and the way I could find a simpler solution is using something like:
from sympy import *
s = symbols("s")
t = symbols("t", positive=True)
h = 1/(s**3 + s**2/5 + s)
inverse_laplace_transform(h,s,t).evalf().simplify()
Notice that I define t as a positive variable, otherwise the sympy function returns a large term followed by the Heaviaside function. The result still contains many gamma functions that I could not reduce to the expression returned by Wolfram. Using evalf() some of those are converted to their numeric value and then after simplification you get a expression similar like the one in Wolfram but with floating numbers.
Unfortunately this part of Sympy is not quite mature. I also tried with Maxima and the result is quite close to the one in Wolfram. So it seems that Wolfram is not doing anything really special there.

Categories

Resources