Skip to content

Commit 68acb0b

Browse files
committed
MAINT: stats.sobol_indices: transition to rng (SPEC 7)
1 parent 55fca04 commit 68acb0b

File tree

3 files changed

+33
-21
lines changed

3 files changed

+33
-21
lines changed

scipy/stats/_multicomp.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ def confidence_interval(
182182
return self._ci
183183

184184

185-
@_transition_to_rng('random_state')
185+
@_transition_to_rng('random_state', replace_doc=False)
186186
def dunnett(
187187
*samples: npt.ArrayLike, # noqa: D417
188188
control: npt.ArrayLike,

scipy/stats/_sensitivity_analysis.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from scipy.stats._qmc import check_random_state
1414
from scipy.stats._resampling import BootstrapResult
1515
from scipy.stats import qmc, bootstrap
16+
from scipy._lib._util import _transition_to_rng
1617

1718

1819
if TYPE_CHECKING:
@@ -61,7 +62,7 @@ def f_ishigami(x: npt.ArrayLike) -> np.ndarray:
6162
def sample_A_B(
6263
n: IntNumber,
6364
dists: list[PPFDist],
64-
random_state: SeedType = None
65+
rng: SeedType = None
6566
) -> np.ndarray:
6667
"""Sample two matrices A and B.
6768
@@ -80,7 +81,7 @@ def sample_A_B(
8081
:doi:`10.1016/j.cpc.2009.09.018`, 2010.
8182
"""
8283
d = len(dists)
83-
A_B = qmc.Sobol(d=2*d, seed=random_state, bits=64).random(n).T
84+
A_B = qmc.Sobol(d=2*d, seed=rng, bits=64).random(n).T
8485
A_B = A_B.reshape(2, d, -1)
8586
try:
8687
for d_, dist in enumerate(dists):
@@ -246,14 +247,15 @@ def ppf(self) -> Callable[..., float]:
246247
...
247248

248249

250+
@_transition_to_rng('random_state', replace_doc=False)
249251
def sobol_indices(
250252
*,
251253
func: Callable[[np.ndarray], npt.ArrayLike] |
252254
dict[Literal['f_A', 'f_B', 'f_AB'], np.ndarray],
253255
n: IntNumber,
254256
dists: list[PPFDist] | None = None,
255257
method: Callable | Literal['saltelli_2010'] = 'saltelli_2010',
256-
random_state: SeedType = None
258+
rng: SeedType = None
257259
) -> SobolResult:
258260
r"""Global sensitivity indices of Sobol'.
259261
@@ -309,11 +311,20 @@ def sobol_indices(
309311
The output is a tuple of the first and total indices with
310312
shape ``(s, d)``.
311313
This is an advanced feature and misuse can lead to wrong analysis.
312-
random_state : {None, int, `numpy.random.Generator`}, optional
313-
If `random_state` is an int or None, a new `numpy.random.Generator` is
314-
created using ``np.random.default_rng(random_state)``.
315-
If `random_state` is already a ``Generator`` instance, then the
316-
provided instance is used.
314+
rng : `numpy.random.Generator`, optional
315+
Pseudorandom number generator state. When `rng` is None, a new
316+
`numpy.random.Generator` is created using entropy from the
317+
operating system. Types other than `numpy.random.Generator` are
318+
passed to `numpy.random.default_rng` to instantiate a ``Generator``.
319+
320+
.. versionchanged:: 1.15.0
321+
322+
As part of the `SPEC-007 <https://scientific-python.org/specs/spec-0007/>`_
323+
transition from use of `numpy.random.RandomState` to
324+
`numpy.random.Generator`, this keyword was changed from `random_state` to `rng`.
325+
For an interim period, both keywords will continue to work, although only one
326+
may be specified at a time. After the interim period, function calls using the
327+
`random_state` keyword will emit warnings.
317328
318329
Returns
319330
-------
@@ -466,7 +477,7 @@ def sobol_indices(
466477
... uniform(loc=-np.pi, scale=2*np.pi),
467478
... uniform(loc=-np.pi, scale=2*np.pi)
468479
... ],
469-
... random_state=rng
480+
... rng=rng
470481
... )
471482
>>> indices.first_order
472483
array([0.31637954, 0.43781162, 0.00318825])
@@ -587,7 +598,7 @@ def sobol_indices(
587598
conclude on high-order terms. Hence the benefit of using Sobol' indices.
588599
589600
"""
590-
random_state = check_random_state(random_state)
601+
rng = check_random_state(rng)
591602

592603
n_ = int(n)
593604
if not (n_ & (n_ - 1) == 0) or n != n_:
@@ -637,7 +648,7 @@ def indices_method(f_A, f_B, f_AB):
637648
def wrapped_func(x):
638649
return np.atleast_2d(func(x))
639650

640-
A, B = sample_A_B(n=n, dists=dists, random_state=random_state)
651+
A, B = sample_A_B(n=n, dists=dists, rng=rng)
641652
AB = sample_AB(A=A, B=B)
642653

643654
f_A = wrapped_func(A)

scipy/stats/tests/test_sensitivity_analysis.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def test_ishigami(self, ishigami_ref_indices, func):
8686
res = sobol_indices(
8787
func=func, n=4096,
8888
dists=self.dists,
89-
random_state=rng
89+
rng=rng
9090
)
9191

9292
if func.__name__ == 'f_ishigami_vec':
@@ -141,7 +141,7 @@ def test_func_dict(self, ishigami_ref_indices):
141141
stats.uniform(loc=-np.pi, scale=2*np.pi)
142142
]
143143

144-
A, B = sample_A_B(n=n, dists=dists, random_state=rng)
144+
A, B = sample_A_B(n=n, dists=dists, rng=rng)
145145
AB = sample_AB(A=A, B=B)
146146

147147
func = {
@@ -150,16 +150,17 @@ def test_func_dict(self, ishigami_ref_indices):
150150
'f_AB': f_ishigami(AB).reshape((3, 1, -1))
151151
}
152152

153+
# preserve use of old random_state during SPEC 7 transition
153154
res = sobol_indices(
154155
func=func, n=n,
155156
dists=dists,
156-
random_state=rng
157+
rng=rng
157158
)
158159
assert_allclose(res.first_order, ishigami_ref_indices[0], atol=1e-2)
159160

160161
res = sobol_indices(
161162
func=func, n=n,
162-
random_state=rng
163+
rng=rng
163164
)
164165
assert_allclose(res.first_order, ishigami_ref_indices[0], atol=1e-2)
165166

@@ -180,7 +181,7 @@ def jansen_sobol(f_A, f_B, f_AB):
180181
func=f_ishigami, n=4096,
181182
dists=self.dists,
182183
method=jansen_sobol,
183-
random_state=rng
184+
rng=rng
184185
)
185186

186187
assert_allclose(res.first_order, ishigami_ref_indices[0], atol=1e-2)
@@ -195,15 +196,15 @@ def jansen_sobol_typed(
195196
func=f_ishigami, n=8,
196197
dists=self.dists,
197198
method=jansen_sobol_typed,
198-
random_state=rng
199+
rng=rng
199200
)
200201

201202
def test_normalization(self, ishigami_ref_indices):
202203
rng = np.random.default_rng(28631265345463262246170309650372465332)
203204
res = sobol_indices(
204205
func=lambda x: f_ishigami(x) + 1000, n=4096,
205206
dists=self.dists,
206-
random_state=rng
207+
rng=rng
207208
)
208209

209210
assert_allclose(res.first_order, ishigami_ref_indices[0], atol=1e-2)
@@ -220,7 +221,7 @@ def f_ishigami_vec_const(x):
220221
res = sobol_indices(
221222
func=f_ishigami_vec_const, n=4096,
222223
dists=self.dists,
223-
random_state=rng
224+
rng=rng
224225
)
225226

226227
ishigami_vec_indices = [
@@ -237,7 +238,7 @@ def test_more_converged(self, ishigami_ref_indices):
237238
res = sobol_indices(
238239
func=f_ishigami, n=2**19, # 524288
239240
dists=self.dists,
240-
random_state=rng
241+
rng=rng
241242
)
242243

243244
assert_allclose(res.first_order, ishigami_ref_indices[0], atol=1e-4)

0 commit comments

Comments
 (0)