问题
I want to write a custom function to integrate an expression (python or lambda function) numerically with a specific tolerance. I know with scipy.integrate.quad
one can simply change the epsabs
but I want to write the function myself using numpy.
From this blogpost I know the function:
def integrate(f, a, b, N):
x = np.linspace(a+(b-a)/(2*N), b-(b-a)/(2*N), N)
fx = f(x)
area = np.sum(fx)*(b-a)/N
return area
gives me the numerical integration with N segments. How can I write another function or extend this to take a tol
input and increase N until the difference between the two subsequent calculations is smaller than the given tolerance?
回答1:
Using the function you have, one can start with a reasonable N, for example 5, and keep doubling the number until the required precision is reached.
def integrate_tol(f, a, b, tol):
N = 5
old_integral = integrate(f, a, b, N)
while True:
N *= 2
new_integral = integrate(f, a, b, N)
if np.abs(old_integral - new_integral) < tol:
return (4*new_integral - old_integral)/3
old_integral = new_integral
A simple test:
f = lambda x: np.exp(x)
print(integrate_tol(f, -1, 1, 1e-9))
print(np.exp(1)-np.exp(-1)) # exact value for comparison
prints
2.3504023872876028
2.3504023872876028
There is no guarantee that the error is indeed less than tol
(but then again, scipy.quad
does not guarantee that either). In practice, the error will be much smaller than tol, because of the trick I used, called Richardson extrapolation: the return value (4*new_integral - old_integral)/3
is in general much more accurate than either new or old approximations themselves. (Explanation: since integrate
uses the midpoint rule, each doubling of N reduces the error by the factor of about 4. So, taking the combination 4*new_integral - old_integral
nearly cancels out the residual error in both of those results.)
(Remark: in the while loop it's unadvisable to start with N=1; it probably will not be enough, and there's higher risk of stopping too early because of some numerical coincidence, e.g., the function being zero in a bunch of places.)
来源:https://stackoverflow.com/questions/50033275/write-a-function-with-numpy-to-calculate-integral-with-a-specific-tolerance