I'm about to tackle a problem that involves a lot of (multi-dimensional) numerical integrations and also subsequent optimizations, and so I want to make sure at least the integration step is as fast as possible.
The illustrative problem is simple. Suppose I want to compute $E[X]$ where $X \sim N(0,1)$. Of course, the analytical solution is simply $0$.
On the Mathematica side, I'll compare both the built-in NormalDistribution
function and also a hand-built Gaussian PDF.
Mathematica via NormalDistribution
rvdist = NormalDistribution[];
Expectation[ x, x \[Distributed] rvdist] // AbsoluteTiming;
(* {0.001126, 2} *)
Mathematica via handwritten PDF
testpdf[x_] := Module[ {μ, σ},
μ = 0;
σ = 1;
1/Sqrt[ 2 * Pi * σ^2] *
Exp[ - ((x - μ)^2/(2* σ^2))]
];
NIntegrate[
x * testpdf[x], {x, -Infinity, Infinity}] // AbsoluteTiming
(* {0.009001, 0.} *)
Now let's turn to the Python with Scipy side.
import numpy as np
import scipy
import scipy.integrate
import scipy.stats
import time
def intfun1():
rv = scipy.stats.norm
tic = time.time()
out = rv.expect( lambda x : x )
toc = time.time()
print(out)
print(toc - tic)
intfun1()
# 0.0
# 0.0021378993988
And also via a handwritten PDF, I have,
def intfun2():
mu = 0
sig = 1
def npdf(x):
return 1.0 / np.sqrt( 2 * np.pi * sig**2 ) * np.exp( - (x - mu)**2 / (2 * sig**2) )
tic = time.time()
out = scipy.integrate.quad( lambda x : x * npdf(x), -np.inf, np.inf)
toc = time.time()
print(out)
print(toc - tic)
intfun2()
# (0.0, 0.0)
# 0.000141859054565
Perhaps I misunderstand what exactly goes on behind Mathematica's AbsoluteTiming
and also Python's time.time()
, but otherwise, it seems like Python has a substantial speed increase over Mathematica.
Questions:
- Why is Mathematica's numerical integration slower than Python?
- If possible, how to make Mathematica faster or as fast as Python?
- If speed is really an issue (again, the application is really for a more complicated integration problem along with optimization), is it better to just write my problem in Python rather than Mathematica?
NIntegrate
has a lot of integration strategies available. Try for exampleMethod -> "ClenshawCurtisRule"
. It's faster for your integral in my machine $\endgroup$