Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 38 additions & 3 deletions pyDOE3/doe_lhs.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
from scipy import linalg
from numpy import ma

from warnings import warn

__all__ = ["lhs"]


Expand All @@ -29,6 +31,7 @@ def lhs(
iterations=None,
random_state=None,
correlation_matrix=None,
seed=None,
):
"""
Generate a latin-hypercube design
Expand All @@ -50,9 +53,12 @@ def lhs(
The number of iterations in the maximin and correlations algorithms
(Default: 5).
randomstate : np.random.RandomState, int
DEPRECATED! It will be removed in a future release. Use seed parameter instead.
Random state (or seed-number) which controls the seed and random draws
correlation_matrix : ndarray
Enforce correlation between factors (only used in lhsmu)
seed : int or np.random.Generator
Seed or np.random.Generator which controls random draws

Returns
-------
Expand Down Expand Up @@ -111,10 +117,31 @@ def lhs(
H = None

if random_state is None:
random_state = np.random.RandomState()
random_state = np.random.default_rng()
elif isinstance(random_state, np.random.RandomState):
warn(
"Using random_state is deprecated "
"and will raise an error in a future version. Please "
"use seed parameter and pass a np.random.Generator",
DeprecationWarning,
stacklevel=2,
)
elif not isinstance(random_state, np.random.RandomState):
warn(
"Passing a seed or integer to random_state is deprecated "
"and will raise an error in a future version. Please "
"use seed parameter",
DeprecationWarning,
stacklevel=2,
)
random_state = np.random.RandomState(random_state)

if seed is not None:
if isinstance(seed, np.random.Generator):
random_state = seed
else:
random_state = np.random.default_rng(seed)

if samples is None:
samples = n

Expand Down Expand Up @@ -164,7 +191,11 @@ def _lhsclassic(n, samples, randomstate):
cut = np.linspace(0, 1, samples + 1)

# Fill points uniformly in each interval
u = randomstate.rand(samples, n)
u = (
randomstate.rand(samples, n)
if isinstance(randomstate, np.random.RandomState)
else randomstate.random((samples, n))
)
a = cut[:samples]
b = cut[1 : samples + 1]
rdpoints = np.zeros_like(u)
Expand All @@ -188,7 +219,11 @@ def _lhscentered(n, samples, randomstate):
cut = np.linspace(0, 1, samples + 1)

# Fill points uniformly in each interval
u = randomstate.rand(samples, n)
u = (
randomstate.rand(samples, n)
if isinstance(randomstate, np.random.RandomState)
else randomstate.random((samples, n))
)
a = cut[:samples]
b = cut[1 : samples + 1]
_center = (a + b) / 2
Expand Down
86 changes: 70 additions & 16 deletions tests/test_lhs.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@


class TestLhs(unittest.TestCase):
def test_lhs1(self):
def test_lhs1_deprecated(self):
expected = [
[0.12484671, 0.95539205, 0.24399798],
[0.53288616, 0.38533955, 0.86703834],
[0.68602787, 0.31690477, 0.38533151],
]
actual = lhs(3, random_state=42)
np.testing.assert_allclose(actual, expected)
with self.assertWarns(DeprecationWarning):
actual = lhs(3, random_state=42)
np.testing.assert_allclose(actual, expected)

def test_lhs2(self):
def test_lhs2_deprecated(self):
expected = [
[0.06242335, 0.19266575, 0.88202411, 0.89439364],
[0.19266977, 0.53538985, 0.53030416, 0.49498498],
Expand All @@ -22,33 +23,86 @@ def test_lhs2(self):
[0.43351917, 0.45134543, 0.12199899, 0.53056742],
[0.93530882, 0.15845238, 0.7386575, 0.09977641],
]
actual = lhs(4, samples=6, random_state=42)
np.testing.assert_allclose(actual, expected)
with self.assertWarns(DeprecationWarning):
actual = lhs(4, samples=6, random_state=42)
np.testing.assert_allclose(actual, expected)

def test_lhs3(self):
def test_lhs3_deprecated(self):
expected = [[0.1, 0.9], [0.5, 0.5], [0.7, 0.1], [0.3, 0.7], [0.9, 0.3]]
actual = lhs(2, samples=5, criterion="center", random_state=42)
np.testing.assert_allclose(actual, expected)
with self.assertWarns(DeprecationWarning):
actual = lhs(2, samples=5, criterion="center", random_state=42)
np.testing.assert_allclose(actual, expected)

def test_lhs4(self):
def test_lhs4_deprecated(self):
expected = [
[0.69754389, 0.2997106, 0.96250964],
[0.10585037, 0.09872038, 0.73157522],
[0.25351996, 0.65148999, 0.07337204],
[0.91276926, 0.97873992, 0.42783549],
]
actual = lhs(3, samples=4, criterion="maximin", random_state=42)
np.testing.assert_allclose(actual, expected)
with self.assertWarns(DeprecationWarning):
actual = lhs(3, samples=4, criterion="maximin", random_state=42)
np.testing.assert_allclose(actual, expected)

def test_lhs5(self):
def test_lhs5_deprecated(self):
expected = [
[0.4846803, 0.74226839, 0.23305339, 0.97000772],
[0.98526018, 0.11735023, 0.75803511, 0.20312728],
[0.10793843, 0.2592547, 0.98299194, 0.72119199],
[0.25519984, 0.4789763, 0.19305106, 0.12140685],
[0.63976848, 0.93021541, 0.45869763, 0.40281596],
]
actual = lhs(
4, samples=5, criterion="correlation", iterations=10, random_state=42
)
with self.assertWarns(DeprecationWarning):
actual = lhs(
4, samples=5, criterion="correlation", iterations=10, random_state=42
)
np.testing.assert_allclose(actual, expected)

def test_lhs1(self):
expected = [
[0.25798535, 0.14629281, 0.65854078],
[0.56578934, 0.9286881, 0.28619931],
[0.9203799, 0.36472578, 0.70937121],
]
actual = lhs(3, seed=42)
np.testing.assert_allclose(actual, expected, atol=1e-6)

def test_lhs2(self):
expected = [
[0.60731085, 0.32927039, 0.8046052, 0.98218685],
[0.35468561, 0.67730288, 0.14309965, 0.77194407],
[0.18236289, 0.89242099, 0.29352328, 0.53787312],
[0.75909746, 0.63712694, 0.395133, 0.48779416],
[0.95968129, 0.40839766, 0.99511634, 0.116228],
[0.12899267, 0.07314641, 0.57390237, 0.29767738],
]
actual = lhs(4, samples=6, seed=42)
np.testing.assert_allclose(actual, expected, atol=1e-6)

def test_lhs3(self):
expected = [[0.9, 0.1], [0.1, 0.7], [0.5, 0.9], [0.7, 0.5], [0.3, 0.3]]
actual = lhs(2, samples=5, criterion="center", seed=42)
print(actual)
np.testing.assert_allclose(actual, expected)

def test_lhs4(self):
expected = [
[0.91547913, 0.46335077, 0.05364617],
[0.51457569, 0.10917935, 0.94597455],
[0.35213216, 0.57034597, 0.30848487],
[0.00770446, 0.88925804, 0.57339844],
]
actual = lhs(3, samples=4, criterion="maximin", seed=42)
print(actual)
np.testing.assert_allclose(actual, expected, atol=1e-6)

def test_lhs5(self):
expected = [
[0.15479121, 0.49007719, 0.68868284, 0.35721286],
[0.21883547, 0.39512447, 0.4741596, 0.64544774],
[0.42562273, 0.08777569, 0.35222794, 0.92633288],
[0.91091696, 0.76455232, 0.96552623, 0.585353],
[0.72877302, 0.81276345, 0.17171958, 0.13947361],
]
actual = lhs(4, samples=5, criterion="correlation", iterations=10, seed=42)
np.testing.assert_allclose(actual, expected)