Tôi đang trải qua một số thất vọng về cách MATLAB xử lý tích hợp số so với Scipy. Tôi quan sát sự khác biệt sau đây trong mã kiểm tra của tôi dưới đây:
- Phiên bản của Matlab chạy nhanh hơn trung bình 24 lần so với con trăn của tôi!
- Phiên bản của Matlab có thể tính toán tích phân mà không cần cảnh báo, trong khi python trả về
nan+nanj
Tôi có thể làm gì để đảm bảo tôi có được hiệu suất tương tự trong python đối với hai điểm được đề cập? Theo tài liệu, cả hai phương pháp nên sử dụng "phương pháp thích nghi toàn cầu" để tính gần đúng tích phân.
Dưới đây là mã trong hai phiên bản (khá giống nhau mặc dù python yêu cầu một hàm tách rời được tạo để nó có thể xử lý các tích phân phức tạp.)
Con trăn
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
). Hãy thử làm các phép tính trên toàn bộ mảng cùng một lúc. Điều đó là không thể, hãy xem numba hoặc Cython, nhưng tôi hy vọng điều này là không cần thiết.
integral
dung sai tuyệt đối và tương đối mặc định tương ứng là 1e-10
và 1e-6
. integrate.quad
chỉ định cả hai như 1.49e-8
. Tôi không thấy nơi nào integrate.quad
được mô tả là phương pháp "thích ứng toàn cầu" và nó chắc chắn khác với phương pháp (Gauss-Kronrod thích nghi, tôi tin) được sử dụng bởi integral
. Bản thân tôi không chắc phần "toàn cầu" nghĩa là gì. Ngoài ra, không bao giờ nên sử dụng cputime
thay vì tic
/ toc
hoặc time it
.