I am trying to perform Monte Carlo integration of a function, but sample non-uniformly. I need this method to work for both logarithmic scale and for integration in polar coordinates since I will then combine the two and use polar with log-scale sampling in radius.
I wrote a testing script that tries to
integrate a 2D gaussian in polar coordinates (which should equal to pi)
integrate y(x) = x in log-scale from 10**-2 to 10**7 (which should equal to ~0.5*10 ** 14)
For testing purposes, I complement the calculation with a uniform cartesian coordinate-based Monte Carlo that works. It is the non-uniformity of the sample that shifts my results.
import numpy as np
def function_to_integrate(x, y):
return np.exp(-x**2 - y**2)
def polar_MC(polar):
size = 100000
integral = 0.
integration_radius = 4.
if polar:
for _ in range(size):
r = np.random.random()*integration_radius
phi = np.random.random()*2.*np.pi
x = r*np.cos(phi)
y = r*np.sin(phi)
jacobian_MC_polar = 1.
integral += function_to_integrate(x, y) * jacobian_MC_polar
integral = integral * np.pi * integration_radius**2 / size
else:
for _ in range(size):
length = 2. * integration_radius
x = np.random.random()*length - length/2.
y = np.random.random()*length - length/2.
integral += function_to_integrate(x, y)
integral = integral * length**2 / size
print('POLAR: True integral should be pi ', '; MC:', integral, polar)
def log_MC(log):
size = 10000
integral = 0.
if log:
for _ in range(size):
x = np.random.uniform(-2, 7.)
jacobian_MC_log = 1.
integral += 10**x * jacobian_MC_log
else:
for _ in range(size):
x = np.random.uniform(10**-2, 10**7)
integral += x
integral = integral*10**7 / size
print('LOG: True integral should be 0.5*10**7*10**7 = 5*10**13; MC:', integral/10**13, '* 10**13', log)
polar_MC(polar=True)
polar_MC(polar=False)
log_MC(log=True)
log_MC(log=False)
I am unable to get the correct result from the polar and log-scale Monte Carlo, how should I set the jacobian_MC in order for this to work? Or am I doing something else wrong?
I have tried using the standard Jacobians (r for polar and r*np.log(10) for logarithmic) and that did not help.
With the Jacobians set to 1, I am getting
POLAR: True integral should be pi ; MC: 11.041032315593327 True
POLAR: True integral should be pi ; MC: 3.108344559871783 False
LOG: True integral should be 0.5*10**7*10**7 = 5*10**13; MC: 0.48366198481209793 * 10**13 True
LOG: True integral should be 0.5*10**7*10**7 = 5*10**13; MC: 5.003437412553992 * 10**13 False
Increasing sampling does not help, the results is close to being converged.
What probability distribution should I divide the sampled points with?