-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #71 from kjs73/uniform_sampling
Uniform sampling
- Loading branch information
Showing
8 changed files
with
271 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
""" | ||
This example computes the numerical value of Pi by Monte Carlo. | ||
Points are sampled uniformly at random from an n-dimensional cube of | ||
side length 2R. By measuring the fraction of points contained within | ||
a ball of radius R contained in the cube, we determine Pi. | ||
""" | ||
from __future__ import division | ||
import numpy as np | ||
import copy | ||
from scipy.special import gamma | ||
from mcpele.monte_carlo import _BaseMCRunner | ||
from mcpele.monte_carlo import NullPotential | ||
from mcpele.monte_carlo import UniformCubicSampling | ||
from mcpele.monte_carlo import CheckSphericalContainerConfig | ||
|
||
def volume_nball(radius, n): | ||
return np.power(np.pi, n / 2) * np.power(radius, n) / gamma(n / 2 + 1) | ||
|
||
def get_pi(accepted_fraction, ndim): | ||
return np.power(2 ** ndim * accepted_fraction * gamma(ndim / 2 + 1), 2 / ndim) | ||
|
||
class MC(_BaseMCRunner): | ||
def set_control(self, temp): | ||
self.set_temperature(temp) | ||
|
||
class ComputePi(object): | ||
def __init__(self, ndim=2, nsamples=1e4): | ||
# | ||
self.ndim = ndim | ||
self.nsamples = nsamples | ||
# | ||
self.radius = 44 | ||
self.potential = NullPotential() | ||
self.mc = MC(self.potential, np.ones(self.ndim), 1, self.nsamples) | ||
self.step = UniformCubicSampling(42, self.radius) | ||
self.mc.set_takestep(self.step) | ||
self.mc.set_report_steps(0) | ||
self.conftest_check_spherical_container = CheckSphericalContainerConfig(self.radius) | ||
self.mc.add_conf_test(self.conftest_check_spherical_container) | ||
self.mc.set_print_progress() | ||
self.mc.run() | ||
self.p = self.mc.get_accepted_fraction() | ||
self.pi = get_pi(self.p, self.ndim) | ||
|
||
if __name__ == "__main__": | ||
nsamples = 1e5 | ||
ndim_ = [] | ||
res = [] | ||
for ndim in xrange(2, 16): | ||
print("computing pi in {} dimensions".format(ndim)) | ||
c = ComputePi(ndim=ndim, nsamples=nsamples) | ||
res.append(c.pi) | ||
ndim_.append(ndim) | ||
for (i, p) in zip(ndim_, res): | ||
print("dimension", i) | ||
print("pi", p) | ||
print("pi / np.pi", p / np.pi) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#ifndef _MCPELE_UNIFORM_CUBIC_SAMPLING_H__ | ||
#define _MCPELE_UNIFORM_CUBIC_SAMPLING_H__ | ||
|
||
namespace mcpele { | ||
|
||
class UniformCubicSampling : public TakeStep { | ||
protected: | ||
std::mt19937_64 m_gen; | ||
std::uniform_real_distribution<double> m_dist; | ||
public: | ||
virtual ~UniformCubicSampling() {} | ||
UniformCubicSampling(const size_t seed=42, const double delta=1) | ||
: m_gen(seed), | ||
m_dist(-delta, delta) | ||
{} | ||
void set_generator_seed(const size_t inp) { m_gen.seed(inp); } | ||
virtual void displace(pele::Array<double>& coords, MC* mc) | ||
{ | ||
for (size_t i = 0; i < coords.size(); ++i) { | ||
coords[i] = m_dist(m_gen); | ||
} | ||
} | ||
}; | ||
|
||
} // namespace mcpele | ||
|
||
#endif // #ifndef _MCPELE_UNIFORM_CUBIC_SAMPLING_H__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
#ifndef _MCPELE_UNIFORM_SPHERICAL_SAMPLING_H__ | ||
#define _MCPELE_UNIFORM_SPHERICAL_SAMPLING_H__ | ||
|
||
namespace mcpele { | ||
|
||
/** | ||
* Sample points uniformly at random within an N-ball. | ||
* See also: http://math.stackexchange.com/questions/87230/picking-random-points-in-the-volume-of-sphere-with-uniform-probability | ||
*/ | ||
|
||
class UniformSphericalSampling : public TakeStep { | ||
protected: | ||
std::mt19937_64 m_gen; | ||
const double m_radius; | ||
std::normal_distribution<double> m_dist_normal; | ||
std::uniform_real_distribution<double> m_dist_uniform; | ||
public: | ||
virtual ~UniformSphericalSampling() {} | ||
UniformSphericalSampling(const size_t seed=42, const double radius=1) | ||
: m_gen(seed), | ||
m_radius(radius), | ||
m_dist_normal(0, 1), | ||
m_dist_uniform(0, 1) | ||
{} | ||
void set_generator_seed(const size_t inp) { m_gen.seed(inp); } | ||
virtual void displace(pele::Array<double>& coords, MC* mc) | ||
{ | ||
for (size_t i = 0; i < coords.size(); ++i) { | ||
coords[i] = m_dist_normal(m_gen); | ||
} | ||
/** | ||
* From Numerical Recipes: | ||
* Picking a random point on a sphere: | ||
* 1) generate n independent, identically distributed, normal random numbers, y_0, ..., y_{n-1} | ||
* 2) get point {x} on unit sphere in n dimensions by {x} = {y} / norm({y}) | ||
* Picking a random point inside a sphere: | ||
* 3) generate an additional uniform random number u in [0,1] | ||
* 4) compute point x_i = y_i * u^{1/n} / norm({y}) | ||
*/ | ||
// This computes 1 / norm({y}). | ||
double tmp = 1.0 / norm(coords); | ||
// This computes u^{1/n} / norm({y}) and rescales to a sphere of radius m_radius. | ||
tmp *= m_radius * std::pow(m_dist_uniform(m_gen), 1.0 / coords.size()); | ||
// This computes the sampled random point in the sphere. | ||
coords *= tmp; | ||
} | ||
}; | ||
|
||
} // namespace mcpele | ||
|
||
#endif // #ifndef _MCPELE_UNIFORM_SPHERICAL_SAMPLING_H__ |