Skip to content

spacefilling

SpaceFilling

Bases: Designs

A class for generating space-filling designs using Latin Hypercube Sampling.

Source code in spotpython/design/spacefilling.py
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
class SpaceFilling(Designs):
    """
    A class for generating space-filling designs using Latin Hypercube Sampling.
    """

    def __init__(
        self,
        k: int,
        scramble: bool = True,
        strength: int = 1,
        optimization: Optional[Union[None, str]] = None,
        seed: int = 123,
    ) -> None:
        """
        Initializes a SpaceFilling design class.
        Based on scipy.stats.qmc's LatinHypercube method.

        Args:
            k (int):
                Dimension of the parameter space.
            scramble (bool, optional):
                When False, center samples within cells of a multi-dimensional grid.
                Otherwise, samples are randomly placed within cells of the grid.
                Note:
                    Setting `scramble=False` does not ensure deterministic output. For that, use the `seed` parameter.
                Default is True.
            optimization (Optional[Union[None, str]]):
                Whether to use an optimization scheme to improve the quality after sampling.
                Note that this is a post-processing step that does not guarantee that all
                properties of the sample will be conserved.
                Defaults to None.
                Options:
                    - "random-cd": Random permutations of coordinates to lower the centered discrepancy. The best sample based on the centered discrepancy is constantly updated.
                    Centered discrepancy-based sampling shows better space-filling
                    robustness toward 2D and 3D subprojections compared to using other discrepancy measures.
                    - "lloyd": Perturb samples using a modified Lloyd-Max algorithm. The process converges to equally spaced samples.
            strength (Optional[int]):
                Strength of the LHS. `strength=1` produces a plain LHS while `strength=2` produces an orthogonal array based LHS of strength 2.
                In that case, only `n=p**2` points can be sampled, with `p` a prime number.
                It also constrains `d <= p + 1`.
                Defaults to 1.
            seed (int, optional):
                Seed for the random number generator. Defaults to 123.
        """
        super().__init__(k=k, seed=seed)
        self.sampler = LatinHypercube(d=self.k, scramble=scramble, strength=strength, optimization=optimization, seed=seed)

    def scipy_lhd(
        self,
        n: int,
        repeats: int = 1,
        lower: Optional[Union[int, float, np.ndarray]] = None,
        upper: Optional[Union[int, float, np.ndarray]] = None,
    ) -> np.ndarray:
        """
        Latin hypercube sampling based on scipy.

        Args:
            n (int): Number of samples.
            repeats (int): Number of repeats (replicates).
            lower (int, float, or np.ndarray, optional): Lower bound. Defaults to a zero vector.
            upper (int, float, or np.ndarray, optional): Upper bound. Defaults to a one vector.

        Returns:
            np.ndarray: Latin hypercube design with specified dimensions and boundaries.

        Examples:
            >>> from spotpython.design.spacefilling import SpaceFilling
            >>> lhd = SpaceFilling(k=2, seed=123)
            >>> lhd.scipy_lhd(n=5, repeats=2, lower=np.array([0, 0]), upper=np.array([1, 1]))
            array([[0.66352963, 0.5892358 ],
                   [0.66352963, 0.5892358 ],
                   [0.55592803, 0.96312564],
                   [0.55592803, 0.96312564],
                   [0.16481882, 0.0375811 ],
                   [0.16481882, 0.0375811 ],
                   [0.215331  , 0.34468512],
                   [0.215331  , 0.34468512],
                   [0.83604909, 0.62202146],
                   [0.83604909, 0.62202146]])
        """
        if lower is None:
            lower = np.zeros(self.k)
        if upper is None:
            upper = np.ones(self.k)

        sample = self.sampler.random(n=n)
        des = scale(sample, lower, upper)
        return np.repeat(des, repeats, axis=0)

__init__(k, scramble=True, strength=1, optimization=None, seed=123)

Initializes a SpaceFilling design class. Based on scipy.stats.qmc’s LatinHypercube method.

Parameters:

Name Type Description Default
k int

Dimension of the parameter space.

required
scramble bool

When False, center samples within cells of a multi-dimensional grid. Otherwise, samples are randomly placed within cells of the grid. Note: Setting scramble=False does not ensure deterministic output. For that, use the seed parameter. Default is True.

True
optimization Optional[Union[None, str]]

Whether to use an optimization scheme to improve the quality after sampling. Note that this is a post-processing step that does not guarantee that all properties of the sample will be conserved. Defaults to None. Options: - “random-cd”: Random permutations of coordinates to lower the centered discrepancy. The best sample based on the centered discrepancy is constantly updated. Centered discrepancy-based sampling shows better space-filling robustness toward 2D and 3D subprojections compared to using other discrepancy measures. - “lloyd”: Perturb samples using a modified Lloyd-Max algorithm. The process converges to equally spaced samples.

None
strength Optional[int]

Strength of the LHS. strength=1 produces a plain LHS while strength=2 produces an orthogonal array based LHS of strength 2. In that case, only n=p**2 points can be sampled, with p a prime number. It also constrains d <= p + 1. Defaults to 1.

1
seed int

Seed for the random number generator. Defaults to 123.

123
Source code in spotpython/design/spacefilling.py
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
def __init__(
    self,
    k: int,
    scramble: bool = True,
    strength: int = 1,
    optimization: Optional[Union[None, str]] = None,
    seed: int = 123,
) -> None:
    """
    Initializes a SpaceFilling design class.
    Based on scipy.stats.qmc's LatinHypercube method.

    Args:
        k (int):
            Dimension of the parameter space.
        scramble (bool, optional):
            When False, center samples within cells of a multi-dimensional grid.
            Otherwise, samples are randomly placed within cells of the grid.
            Note:
                Setting `scramble=False` does not ensure deterministic output. For that, use the `seed` parameter.
            Default is True.
        optimization (Optional[Union[None, str]]):
            Whether to use an optimization scheme to improve the quality after sampling.
            Note that this is a post-processing step that does not guarantee that all
            properties of the sample will be conserved.
            Defaults to None.
            Options:
                - "random-cd": Random permutations of coordinates to lower the centered discrepancy. The best sample based on the centered discrepancy is constantly updated.
                Centered discrepancy-based sampling shows better space-filling
                robustness toward 2D and 3D subprojections compared to using other discrepancy measures.
                - "lloyd": Perturb samples using a modified Lloyd-Max algorithm. The process converges to equally spaced samples.
        strength (Optional[int]):
            Strength of the LHS. `strength=1` produces a plain LHS while `strength=2` produces an orthogonal array based LHS of strength 2.
            In that case, only `n=p**2` points can be sampled, with `p` a prime number.
            It also constrains `d <= p + 1`.
            Defaults to 1.
        seed (int, optional):
            Seed for the random number generator. Defaults to 123.
    """
    super().__init__(k=k, seed=seed)
    self.sampler = LatinHypercube(d=self.k, scramble=scramble, strength=strength, optimization=optimization, seed=seed)

scipy_lhd(n, repeats=1, lower=None, upper=None)

Latin hypercube sampling based on scipy.

Parameters:

Name Type Description Default
n int

Number of samples.

required
repeats int

Number of repeats (replicates).

1
lower int, float, or np.ndarray

Lower bound. Defaults to a zero vector.

None
upper int, float, or np.ndarray

Upper bound. Defaults to a one vector.

None

Returns:

Type Description
ndarray

np.ndarray: Latin hypercube design with specified dimensions and boundaries.

Examples:

>>> from spotpython.design.spacefilling import SpaceFilling
>>> lhd = SpaceFilling(k=2, seed=123)
>>> lhd.scipy_lhd(n=5, repeats=2, lower=np.array([0, 0]), upper=np.array([1, 1]))
array([[0.66352963, 0.5892358 ],
       [0.66352963, 0.5892358 ],
       [0.55592803, 0.96312564],
       [0.55592803, 0.96312564],
       [0.16481882, 0.0375811 ],
       [0.16481882, 0.0375811 ],
       [0.215331  , 0.34468512],
       [0.215331  , 0.34468512],
       [0.83604909, 0.62202146],
       [0.83604909, 0.62202146]])
Source code in spotpython/design/spacefilling.py
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
def scipy_lhd(
    self,
    n: int,
    repeats: int = 1,
    lower: Optional[Union[int, float, np.ndarray]] = None,
    upper: Optional[Union[int, float, np.ndarray]] = None,
) -> np.ndarray:
    """
    Latin hypercube sampling based on scipy.

    Args:
        n (int): Number of samples.
        repeats (int): Number of repeats (replicates).
        lower (int, float, or np.ndarray, optional): Lower bound. Defaults to a zero vector.
        upper (int, float, or np.ndarray, optional): Upper bound. Defaults to a one vector.

    Returns:
        np.ndarray: Latin hypercube design with specified dimensions and boundaries.

    Examples:
        >>> from spotpython.design.spacefilling import SpaceFilling
        >>> lhd = SpaceFilling(k=2, seed=123)
        >>> lhd.scipy_lhd(n=5, repeats=2, lower=np.array([0, 0]), upper=np.array([1, 1]))
        array([[0.66352963, 0.5892358 ],
               [0.66352963, 0.5892358 ],
               [0.55592803, 0.96312564],
               [0.55592803, 0.96312564],
               [0.16481882, 0.0375811 ],
               [0.16481882, 0.0375811 ],
               [0.215331  , 0.34468512],
               [0.215331  , 0.34468512],
               [0.83604909, 0.62202146],
               [0.83604909, 0.62202146]])
    """
    if lower is None:
        lower = np.zeros(self.k)
    if upper is None:
        upper = np.ones(self.k)

    sample = self.sampler.random(n=n)
    des = scale(sample, lower, upper)
    return np.repeat(des, repeats, axis=0)