I am trying to speed up a specific (numerical) integral in Python. I have evaluated in Mathematica and it takes 14s. In python it takes 15.6 minutes!
The integral I want to evaluate is of the form:
The python code is the following:
from mpmath import hermite
def light_nm( dipol, n, m, t):
mat_elem = light_amp(n)*light_amp_conj(m)*coef_ground( dipol, n,t)*np.conj(coef_ground( dipol, m,t)) + \
light_amp(n+1)*light_amp_conj(m+1)*coef_excit( dipol, n+1,t)*np.conj(coef_excit( dipol, m+1,t))
return mat_elem
def light_nm_dmu( dipol, n, m, t):
mat_elem = light_amp(n)*light_amp_conj(m)*(coef_ground_dmu( dipol, n,t)*conj(coef_ground( dipol, m,t)) + coef_ground( dipol, n,t)*conj(coef_ground_dmu( dipol, m,t)) )+ \
light_amp(n+1)*light_amp_conj(m+1)*(coef_excit_dmu( dipol, n+1,t)*np.conj(coef_excit( dipol, m+1,t)) + coef_excit( dipol, n+1,t)*conj(coef_excit_dmu( dipol, m+1,t)))
return mat_elem
def prob(dipol, t, x, thlo, cutoff, n, m):
temp = complex( light_nm(dipol, n, m, t)* cmath.exp(1j*thlo*(n-m)-x**2)*\
hermite(n,x)*hermite(m,x)/math.sqrt(2**(n+m)*math.factorial(m)*math.factorial(n)*math.pi))
return np.real(temp)
def derprob(dipol, t, x, thlo, cutoff, n, m):
temp = complex( light_nm_dmu(dipol, n, m, t)* cmath.exp(1j*thlo*(n-m)-x**2)*\
hermite(n,x)*hermite(m,x)/math.sqrt(2**(n+m)*math.factorial(m)*math.factorial(n)*math.pi))
if np.imag(temp)>10**(-6):
print(t)
return np.real(temp)
def integrand(dipol, t, thlo, cutoff,x):
return 1/np.sum(np.array([ prob(dipol,t,x,thlo,cutoff,n,m) for n,m in product(range(cutoff),range(cutoff))]))*\
np.sum(np.array([ derprob(dipol,t,x,thlo,cutoff,n,m) for n,m in product(range(cutoff),range(cutoff))]))**2
def cfi(dipol, t, thlo, cutoff, a):
global alpha
alpha = a
temp_func_real = lambda x: np.real(integrand(dipol,t, thlo, cutoff, x))
temp_real = integ.quad(temp_func_real, -8, 8)
return temp_real[0]
The hermite functions are called from the mpmath library. Is there any way to make this code work faster?
Thank you!
UPDATED: I added the whole code. (I'm sorry for the delay) The functions "light_nm_dmu" are similiar to the "light_nm". I tried the answer, but I get an error "TypeError: only size-1 arrays can be converted to Python scalars" in the light_amp function, so I vectorised prob and derprob.
New time is 886.7085871696472 = 14.8 min for the same evaluation (cfi(0.1,1,0,40,1))