In [1]:
# Import modules
import time
import math
import numpy as np
import scipy
import matplotlib.pyplot as plt
In [2]:
def linear_congruential_generator(x, a, b, m):
x = (a * x + b) % m
u = x / m
return u, x, a, b, m
def stdrand(x):
return linear_congruential_generator(x, pow(7, 5), 0, pow(2, 31) - 1)[:2]
def halton(p, n):
b = np.zeros(math.ceil(math.log(n + 1) / math.log(p)))
u = np.zeros(n)
for j in range(n):
i = 0
b[0] = b[0] + 1
while b[i] > p - 1 + np.finfo(float).eps:
b[i] = 0
i += 1
b[i] += 1
u[j] = 0
for k in range(1, b.size + 1):
u[j] = u[j] + b[k-1] * pow(p, -k)
return u
In [3]:
def monte_carlo_process_std(toss):
x = time.time()
hit = 0
for i in range(toss):
u1, x = stdrand(x)
u2, x = stdrand(x)
if pow(u1, 2) + pow(u2, 2) < 1.0:
hit += 1
return hit * 4.0 / toss
pi = monte_carlo_process_std(2000000)
print('pi = %.10f, err = %.10f' %(pi, abs(pi - np.pi)))
In [4]:
def monte_carlo_process_customized(toss):
x0 = time.time()
args = (x0, 13, 0, 31)
hit = 0
for i in range(toss):
u1, *args = linear_congruential_generator(*args)
u2, *args = linear_congruential_generator(*args)
if pow(u1, 2) + pow(u2, 2) < 1.0:
hit += 1
return hit * 4.0 / toss
pi = monte_carlo_process_customized(2000000)
print('pi = %.10f, err = %.10f' %(pi, abs(pi - np.pi)))
In [5]:
def monte_carlo_process_quasi(toss):
hit = 0
px = halton(2, toss)
py = halton(3, toss)
for i in range(toss):
u1 = px[i]
u2 = py[i]
if pow(u1, 2) + pow(u2, 2) < 1.0:
hit += 1
return hit * 4.0 / toss
pi = monte_carlo_process_quasi(2000000)
print('pi = %.10f, err = %.10f' %(pi, abs(pi - np.pi)))