I am trying to integrate the following expression symbolically (final expression will be in terms of x):
from sympy import *
x, y = symbols('x, y')
expr = 0.25*sqrt(15/(2*pi)) * exp(2j*y) * (sin(x))**2 * sin(x) * sqrt(cos(x))
int_expr = simplify(integrate(expr, x,(y,0,2*pi)))
print(int_expr)
Point to be noted, when I am integrating 0.25*sqrt(15/(2*pi)) * exp(2j*y) * (sin(x))**2 * sin(x)
the program works a little faster. Joining the sqrt(cos(x))
to it makes it very slow and it takes like an eternity to implement the code.
I have reached to this mathematical expression after doing much simplification and it has made the program 'start working'
Is there any way to speed up this code? Any suggestion is very much appreciated.
Firstly I advise against using floats especially in the exponent (i.e. 2j
). You should use sympy's exact rationals and also I
for sqrt(-1)
.
That gives us this:
In [11]: expr = sqrt(15/(2*pi))/4 * exp(2*I*y) * (sin(x))**2 * sin(x) * sqrt(cos(x))
In [12]: int_expr = Integral(expr, (x, 0, 2*pi))
In [13]: int_expr
Out[13]:
2⋅π
⌠
⎮ 2⋅ⅈ⋅y 3 ________
⎮ √30⋅ℯ ⋅sin (x)⋅╲╱ cos(x)
⎮ ───────────────────────────── dx
⎮ 8⋅√π
⌡
0
Now I notice that actually the extraneous factor can be pulled out of this integral. We can use factor_terms
to do that:
In [14]: factor_terms(int_expr)
Out[14]:
2⋅π
⌠
2⋅ⅈ⋅y ⎮ 3 ________
√30⋅ℯ ⋅ ⎮ sin (x)⋅╲╱ cos(x) dx
⌡
0
────────────────────────────────────
8⋅√π
Seeing the integral that remains it's worth knowing that when you have an integral with no free symbols in it (the only symbol in the integrand is the dummy integration symbol) then you can often get a faster approximate result by evaluating the integral numerically:
In [15]: Integral(sin(x)**3 * sqrt(cos(x)), (x, 0, 2*pi))
Out[15]:
2⋅π
⌠
⎮ 3 ________
⎮ sin (x)⋅╲╱ cos(x) dx
⌡
0
In [16]: _.n()
Out[16]: -0.e-103 + 0.e-103⋅ⅈ
This is showing that the integral is basically zero.
The algorithms used for symbolic integration can be extremely slow for some cases. This is a general problem with many integration algorithms and they are often quite sensitive to the exact form of the input. You shouldn't be surprised that an additional factor of sqrt(cos(x))
changes things: it would make the integral significantly harder by hand as well as there is no "product rule" for integrals. In this example it is slow in the "heurisch" algorithm so you can set heurisch=False
to disable that but then none of the other algorithms can evaluate the integral so you won't get a result.
Often a substitution will make the integral a lot easier and you can ask sympy to do the substitution explicitly. In this case we can use the substitution z = cos(x)
but we need to split the integral into two parts from 0
to pi
and from pi
to 2*pi
so that the substitution is monotonic in each part:
In [30]: Integral(expr, (x, 0, pi))
Out[30]:
π
⌠
⎮ 2⋅ⅈ⋅y 3 ________
⎮ √30⋅ℯ ⋅sin (x)⋅╲╱ cos(x)
⎮ ───────────────────────────── dx
⎮ 8⋅√π
⌡
0
In [31]: Integral(expr, (x, 0, pi)).transform(cos(x), z)
Out[31]:
1
⌠
⎮ ⎛ 2⎞ 2⋅ⅈ⋅y
⎮ √30⋅√z⋅⎝1 - z ⎠⋅ℯ
⎮ ────────────────────── dz
⎮ 8⋅√π
⌡
-1
In [32]: Integral(expr, (x, 0, pi)).transform(cos(x), z).doit()
Out[32]:
2⋅ⅈ⋅y 2⋅ⅈ⋅y
√30⋅ℯ √30⋅ⅈ⋅ℯ
────────── + ────────────
21⋅√π 21⋅√π
In [33]: _ + Integral(expr, (x, pi, 2*pi)).transform(cos(x), z).doit()
Out[33]: 0