Matlab'ın sayısal entegrasyonu Scipy ile karşılaştırması konusunda biraz hayal kırıklığı yaşıyorum. Aşağıdaki test kodumda aşağıdaki farklılıkları gözlemliyorum:
- Matlab'ın versiyonu python eşdeğümden ortalama 24 kat daha hızlı çalışıyor !
- Matlab'ın sürümü, integrali uyarmadan hesaplayabilirken, python döner
nan+nanj
Bahsedilen iki noktaya göre python'da aynı performansı almamı sağlamak için ne yapabilirim? Dokümantasyona göre, her iki yöntem de integrali yaklaşık olarak belirlemek için bir "global uyarlanabilir kareleme" kullanmalıdır.
Aşağıda iki versiyondaki kod bulunmaktadır (python, karmaşık integralleri işleyebilmesi için bir integral fonksiyonunun oluşturulmasını gerektirmesine rağmen oldukça benzerdir.)
piton
import numpy as np
from scipy import integrate
import time
def integral(integrand, a, b, arg):
def real_func(x,arg):
return np.real(integrand(x,arg))
def imag_func(x,arg):
return np.imag(integrand(x,arg))
real_integral = integrate.quad(real_func, a, b, args=(arg))
imag_integral = integrate.quad(imag_func, a, b, args=(arg))
return real_integral[0] + 1j*imag_integral[0]
vintegral = np.vectorize(integral)
def f_integrand(s, omega):
sigma = np.pi/(np.pi+2)
xs = np.exp(-np.pi*s/(2*sigma))
x1 = -2*sigma/np.pi*(np.log(xs/(1+np.sqrt(1-xs**2)))+np.sqrt(1-xs**2))
x2 = 1-2*sigma/np.pi*(1-xs)
zeta = x2+x1*1j
Vc = 1/(2*sigma)
theta = -1*np.arcsin(np.exp(-np.pi/(2.0*sigma)*s))
t1 = 1/np.sqrt(1+np.tan(theta)**2)
t2 = -1/np.sqrt(1+1/np.tan(theta)**2)
return np.real((t1-1j*t2)/np.sqrt(zeta**2-1))*np.exp(1j*omega*s/Vc);
t0 = time.time()
omega = 10
result = integral(f_integrand, 0, np.inf, omega)
print time.time()-t0
print result
Matlab
function [ out ] = f_integrand( s, omega )
sigma = pi/(pi+2);
xs = exp(-pi.*s./(2*sigma));
x1 = -2*sigma./pi.*(log(xs./(1+sqrt(1-xs.^2)))+sqrt(1-xs.^2));
x2 = 1-2*sigma./pi.*(1-xs);
zeta = x2+x1*1j;
Vc = 1/(2*sigma);
theta = -1*asin(exp(-pi./(2.0.*sigma).*s));
t1 = 1./sqrt(1+tan(theta).^2);
t2 = -1./sqrt(1+1./tan(theta).^2);
out = real((t1-1j.*t2)./sqrt(zeta.^2-1)).*exp(1j.*omega.*s./Vc);
end
t=cputime;
omega = 10;
result = integral(@(s) f_integrand(s,omega),0,Inf)
time_taken = cputime-t
np.vectorize
). Tüm dizide aynı anda hesaplamalar yapmayı deneyin. Bu mümkün değil, numba veya Cython'a bir göz atın, ancak umarım ikincisi gerekli değildir.
integral
'varsayılan mutlak ve bağıl toleransları vardır 1e-10
ve 1e-6
sırasıyla. integrate.quad
bunların ikisini de belirtir 1.49e-8
. Nerede integrate.quad
"küresel uyarlanabilir" bir yöntem olarak tanımlandığını görmüyorum ve kesinlikle (uyarlanabilir Gauss-Kronrod, inanıyorum) tarafından kullanılan yöntemden farklı integral
. "Küresel" kısmın ne anlama geldiğinden emin değilim, kendim. Ayrıca, / veya cputime
yerine kullanmak asla iyi bir fikir değildir . tic
toc
time it