Source code for pypesto.startpoint.latin_hypercube

"""Latin hypercube sampling."""

import numpy as np

from .base import CheckedStartpoints
from .util import rescale


[docs]def latin_hypercube( n_starts: int, lb: np.ndarray, ub: np.ndarray, smooth: bool = True, ) -> np.ndarray: """Generate latin hypercube points. Parameters ---------- n_starts: Number of points. lb: Lower bound. ub: Upper bound. smooth: Whether a (uniformly chosen) random starting point within the hypercube [i/n_starts, (i+1)/n_starts] should be chosen (True) or the midpoint of the interval (False). Returns ------- xs: Latin hypercube points, shape (n_starts, n_x). """ if not np.isfinite(ub).all() or not np.isfinite(lb).all(): raise ValueError( "Cannot use latin hypercube startpoint method with non-finite " "boundaries.", ) # parse dim = lb.size lb = lb.reshape((1, -1)) ub = ub.reshape((1, -1)) # sample xs = _latin_hypercube_unit(n_starts, dim, smooth) # re-scale xs = rescale(xs, lb, ub) return xs
def _latin_hypercube_unit( n_starts: int, dim: int, smooth: bool, ) -> np.ndarray: """Generate simple latin hypercube points in [0, 1]. Parameters are as for `latin_hypercube`. Returns ------- xs: Latin hypercube points sampled in [0, 1], shape (n_starts, dim). """ xs = np.empty((n_starts, dim)) for i_dim in range(dim): xs[:, i_dim] = np.random.permutation(np.arange(n_starts)) if smooth: xs += np.random.random((n_starts, dim)) else: xs += 0.5 xs /= n_starts return xs
[docs]class LatinHypercubeStartpoints(CheckedStartpoints): """Generate latin hypercube-sampled startpoints. See e.g. https://en.wikipedia.org/wiki/Latin_hypercube_sampling. """
[docs] def __init__( self, use_guesses: bool = True, check_fval: bool = False, check_grad: bool = False, smooth: bool = True, ): """Initialize. Parameters ---------- use_guesses, check_fval, check_grad: As in CheckedStartpoints. smooth: Whether a (uniformly chosen) random starting point within the hypercube [i/n_starts, (i+1)/n_starts] should be chosen (True) or the midpoint of the interval (False). """ super().__init__( use_guesses=use_guesses, check_fval=check_fval, check_grad=check_grad, ) self.smooth: bool = smooth
[docs] def sample( self, n_starts: int, lb: np.ndarray, ub: np.ndarray, ) -> np.ndarray: """Call function.""" return latin_hypercube( n_starts=n_starts, lb=lb, ub=ub, smooth=self.smooth, )