ฉันกำลังรู้สึกหงุดหงิดกับวิธีที่ matlab จัดการกับการรวมเชิงตัวเลขกับ Scipy ฉันสังเกตเห็นความแตกต่างต่อไปนี้ในรหัสทดสอบด้านล่าง:
- รุ่นของ Matlab ทำงานเร็วกว่างูหลามของฉันโดยเฉลี่ย24 เท่า !
- เวอร์ชันของ Matlab สามารถคำนวณอินทิกรัลโดยไม่มีการเตือนขณะที่ python คืนค่า
nan+nanj
ฉันจะทำอะไรได้บ้างเพื่อให้แน่ใจว่าฉันจะได้รับประสิทธิภาพการทำงานเหมือนกันในงูใหญ่เทียบกับสองประเด็นที่กล่าวถึง? ตามเอกสารทั้งสองวิธีควรใช้ "การปรับพื้นที่สี่เหลี่ยมจัตุรัสส่วนกลาง" เพื่อประมาณค่าอินทิกรัล
ด้านล่างเป็นรหัสในสองเวอร์ชัน (ค่อนข้างคล้ายกันแม้ว่างูใหญ่ต้องการให้มีการสร้างฟังก์ชั่นครบถ้วนเพื่อให้สามารถจัดการกับการรวมที่ซับซ้อนได้)
หลาม
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
) ลองทำการคำนวณกับอาร์เรย์ทั้งหมดในครั้งเดียว มันเป็นไปไม่ได้ลองดูที่ numba หรือ Cython แต่ฉันหวังว่ามันไม่จำเป็น
integral
ค่าเริ่มต้นของค่าเผื่อแน่นอนและค่าความสัมพันธ์สัมพัทธ์คือ1e-10
และ1e-6
ตามลำดับ ระบุเหล่านี้เป็นทั้งintegrate.quad
1.49e-8
ฉันไม่เห็นที่integrate.quad
จะอธิบายว่าเป็น "การปรับตัวระดับโลก" วิธีการและมันจะแตกต่างจากมากที่สุดอย่างแน่นอน (การปรับตัว Gauss-Kronrod ผมเชื่อว่า) integral
วิธีการใช้โดย ฉันไม่แน่ใจว่าส่วน "โลก" หมายถึงตัวฉันเอง นอกจากนี้ก็ไม่เคยมีความคิดที่ดีที่จะใช้cputime
แทนtic
/ หรือtoc
time it