__all__ = ["sample"]
import numpy as np
import skopt
from .. import config
[docs]
def sample(n_samples, dimension, sampler="pseudo"):
"""Generate pseudorandom or quasirandom samples in [0, 1]^dimension.
Args:
n_samples (int): The number of samples.
dimension (int): Space dimension.
sampler (string): One of the following: "pseudo" (pseudorandom), "LHS" (Latin
hypercube sampling), "Halton" (Halton sequence), "Hammersley" (Hammersley
sequence), or "Sobol" (Sobol sequence).
"""
if sampler == "pseudo":
return pseudorandom(n_samples, dimension)
if sampler in ["LHS", "Halton", "Hammersley", "Sobol"]:
return quasirandom(n_samples, dimension, sampler)
raise ValueError("f{sampler} sampling is not available.")
def pseudorandom(n_samples, dimension):
"""Pseudo random."""
# If random seed is set, then the rng based code always returns the same random
# number, which may not be what we expect.
# rng = np.random.default_rng(config.random_seed)
# return rng.random(size=(n_samples, dimension), dtype=config.real(np))
return np.random.random(size=(n_samples, dimension)).astype(config.real(np))
def quasirandom(n_samples, dimension, sampler):
# Certain points should be removed:
# - Boundary points such as [..., 0, ...]
# - Special points [0, 0, 0, ...] and [0.5, 0.5, 0.5, ...], which cause error in
# Hypersphere.random_points() and Hypersphere.random_boundary_points()
skip = 0
if sampler == "LHS":
sampler = skopt.sampler.Lhs()
elif sampler == "Halton":
# 1st point: [0, 0, ...]
sampler = skopt.sampler.Halton(min_skip=1, max_skip=1)
elif sampler == "Hammersley":
# 1st point: [0, 0, ...]
if dimension == 1:
sampler = skopt.sampler.Hammersly(min_skip=1, max_skip=1)
else:
sampler = skopt.sampler.Hammersly()
skip = 1
elif sampler == "Sobol":
# 1st point: [0, 0, ...], 2nd point: [0.5, 0.5, ...]
sampler = skopt.sampler.Sobol(randomize=False)
if dimension < 3:
skip = 1
else:
skip = 2
space = [(0.0, 1.0)] * dimension
return np.asarray(
sampler.generate(space, n_samples + skip)[skip:], dtype=config.real(np)
)