Saya mengalami beberapa frustrasi atas cara matlab menangani integrasi numerik vs Scipy. Saya mengamati perbedaan berikut dalam kode pengujian saya di bawah ini:
- Versi Matlab berjalan rata-rata 24 kali lebih cepat dari yang setara dengan python saya!
- Versi Matlab mampu menghitung integral tanpa peringatan, sementara python kembali
nan+nanj
Apa yang bisa saya lakukan untuk memastikan saya mendapatkan kinerja yang sama dalam python sehubungan dengan dua poin yang disebutkan? Menurut dokumentasi kedua metode harus menggunakan "quadrature adaptif global" untuk mendekati integral.
Di bawah ini adalah kode dalam dua versi (cukup mirip meskipun python mengharuskan fungsi integral dibuat sehingga dapat menangani integrand kompleks.)
Python
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
). Coba lakukan perhitungan pada seluruh array sekaligus. Itu tidak mungkin, lihatlah numba atau juga Cython, tapi saya harap yang terakhir tidak diperlukan.
integral
toleransi absolut dan relatif default masing-masing adalah 1e-10
dan 1e-6
. integrate.quad
menetapkan keduanya sebagai 1.49e-8
. Saya tidak melihat di mana integrate.quad
digambarkan sebagai metode "adaptasi global" dan itu pasti berbeda dari metode (adaptive Gauss-Kronrod, saya percaya) yang digunakan oleh integral
. Saya tidak yakin apa arti bagian "global" itu, saya sendiri. Juga, tidak pernah merupakan ide yang baik untuk menggunakan cputime
daripada tic
/ toc
atau time it
.