python - Wolfram Alpha and scipy.integrate.quad give me different answers for the same integral -


consider following function:

import numpy np scipy.special import erf  def my_func(x):     return np.exp(x ** 2) * (1 + erf(x)) 

when evaluate integral of function -14 -4 using scipy's quad function, following result:

in [3]: scipy import integrate  in [4]: integrate.quad(my_func, -14, -4) /usr/local/lib/python2.7/dist-packages/scipy/integrate/quadpack.py:289: userwarning: maximum number     of subdivisions (50) has been achieved.   if increasing limit yields no improvement advised analyze    integrand in order determine difficulties.  if position of    local difficulty can determined (singularity, discontinuity) 1    gain splitting interval , calling integrator    on subranges.  perhaps special-purpose integrator should used.   warnings.warn(msg) out[4]: (0.21896647054443383, 0.00014334175850538866) 

that is, 0.22.

however, when submit integral wolfram alpha, different result:

-5.29326 x 10 ^ 69. 

what's deal? i'm guessing has warning scipy has given me. what's best way evaluate integral in python?

note: increasing limit changes warning leaves scipy result unchanged:

in [5]: integrate.quad(my_func, -14, -4, limit=10000) /usr/local/lib/python2.7/dist-packages/scipy/integrate/quadpack.py:289: userwarning: occurrence of roundoff error detected, prevents    requested tolerance being achieved.  error may    underestimated.   warnings.warn(msg) out[5]: (0.21894780966717864, 1.989164129832358e-05) 

tl;dr: integrand equivalent erfcx(-x), , implementation of erfcx @ scipy.special.erfcx takes care of numerical issues:

in [10]: scipy.integrate import quad  in [11]: scipy.special import erfcx  in [12]: quad(lambda x: erfcx(-x), -14, -4) out[12]: (0.6990732491815446, 1.4463494884581349e-13)  in [13]: quad(lambda x: erfcx(-x), -150, -50) out[13]: (0.6197754761443759, 4.165648376274775e-14) 

you can avoid lambda expression changing sign of integration argument , limits:

in [14]: quad(erfcx, 4, 14) out[14]: (0.6990732491815446, 1.4463494884581349e-13) 

the problem numerical evaluation of 1 + erf(x) negative values of x. x decreases, erf(x) approaches -1. when add 1, catastrophic loss of precision, , sufficiently negative x (specifically x < -5.87), 1 + erf(x) numerically 0.

note default behavior @ wolfram alpha suffers same problem. had click on "more digits" twice reasonable answer.

the fix reformulate function. can express 1+erf(x) 2*ndtr(x*sqrt(2)), ndtr normal cumulative distribution function, available scipy.special.ndtr (see, example, https://en.wikipedia.org/wiki/error_function). here's alternative version of function, , result of integrating scipy.integrate.quad:

in [133]: def func2(x):    .....:     return np.exp(x**2) * 2 * ndtr(x * np.sqrt(2))    .....:   in [134]: my_func(-5) out[134]: 0.1107029852258767  in [135]: func2(-5) out[135]: 0.11070463773306743  in [136]: integrate.quad(func2, -14, -4) out[136]: (0.6990732491815298, 1.4469372263470424e-13) 

the answer @ wolfram alpha after clicking on "more digits" twice 0.6990732491815446...

this plot of function looks when use numerically stable version:

plot of integrand


to avoid overflow or underflow arguments large magnitudes, can part of computation in log-space:

from scipy.special import log_ndtr  def func3(x):     t = x**2 + np.log(2) + log_ndtr(x * np.sqrt(2))     y = np.exp(t)     return y 

e.g.

in [20]: quad(func3, -150, -50) out[20]: (0.6197754761435517, 4.6850379059597266e-14) 

(looks @ali_m beat me in new question: tricking numpy/python representing large , small numbers.)


finally, simon byrne pointed out in answer on @ tricking numpy/python representing large , small numbers, function integrated can expressed erfcx(-x), erfcx scaled complementary error function. available scipy.special.erfcx.

for example,

in [10]: scipy.integrate import quad  in [11]: scipy.special import erfcx  in [12]: quad(lambda x: erfcx(-x), -14, -4) out[12]: (0.6990732491815446, 1.4463494884581349e-13)  in [13]: quad(lambda x: erfcx(-x), -150, -50) out[13]: (0.6197754761443759, 4.165648376274775e-14) 

Comments

Popular posts from this blog

c# - Binding a comma separated list to a List<int> in asp.net web api -

Delphi 7 and decode UTF-8 base64 -

html - Is there any way to exclude a single element from the style? (Bootstrap) -