4
4
from .arpack import _arpack # type: ignore[attr-defined]
5
5
from . import eigsh
6
6
7
- from scipy ._lib ._util import check_random_state
7
+ from scipy ._lib ._util import check_random_state , _transition_to_rng
8
8
from scipy .sparse .linalg ._interface import LinearOperator , aslinearoperator
9
9
from scipy .sparse .linalg ._eigen .lobpcg import lobpcg # type: ignore[no-redef]
10
10
from scipy .sparse .linalg ._svdp import _svdp
@@ -19,7 +19,7 @@ def _herm(x):
19
19
20
20
21
21
def _iv (A , k , ncv , tol , which , v0 , maxiter ,
22
- return_singular , solver , random_state ):
22
+ return_singular , solver , rng ):
23
23
24
24
# input validation/standardization for `solver`
25
25
# out of order because it's needed for other parameters
@@ -90,15 +90,16 @@ def _iv(A, k, ncv, tol, which, v0, maxiter,
90
90
if return_singular not in rs_options :
91
91
raise ValueError (f"`return_singular_vectors` must be in { rs_options } ." )
92
92
93
- random_state = check_random_state (random_state )
93
+ rng = check_random_state (rng )
94
94
95
95
return (A , k , ncv , tol , which , v0 , maxiter ,
96
- return_singular , solver , random_state )
96
+ return_singular , solver , rng )
97
97
98
98
99
+ @_transition_to_rng ("random_state" , position_num = 9 )
99
100
def svds (A , k = 6 , ncv = None , tol = 0 , which = 'LM' , v0 = None ,
100
101
maxiter = None , return_singular_vectors = True ,
101
- solver = 'arpack' , random_state = None , options = None ):
102
+ solver = 'arpack' , rng = None , options = None ):
102
103
"""
103
104
Partial singular value decomposition of a sparse matrix.
104
105
@@ -158,17 +159,11 @@ def svds(A, k=6, ncv=None, tol=0, which='LM', v0=None,
158
159
:ref:`'lobpcg' <sparse.linalg.svds-lobpcg>`, and
159
160
:ref:`'propack' <sparse.linalg.svds-propack>` are supported.
160
161
Default: `'arpack'`.
161
- random_state : {None, int, `numpy.random.Generator`,
162
- `numpy.random.RandomState`}, optional
163
-
164
- Pseudorandom number generator state used to generate resamples.
165
-
166
- If `random_state` is ``None`` (or `np.random`), the
167
- `numpy.random.RandomState` singleton is used.
168
- If `random_state` is an int, a new ``RandomState`` instance is used,
169
- seeded with `random_state`.
170
- If `random_state` is already a ``Generator`` or ``RandomState``
171
- instance then that instance is used.
162
+ rng : `numpy.random.Generator`, optional
163
+ Pseudorandom number generator state. When `rng` is None, a new
164
+ `numpy.random.Generator` is created using entropy from the
165
+ operating system. Types other than `numpy.random.Generator` are
166
+ passed to `numpy.random.default_rng` to instantiate a ``Generator``.
172
167
options : dict, optional
173
168
A dictionary of solver-specific options. No solver-specific options
174
169
are currently supported; this parameter is reserved for future use.
@@ -263,7 +258,7 @@ def svds(A, k=6, ncv=None, tol=0, which='LM', v0=None,
263
258
>>> vT = v.T
264
259
>>> A = u @ np.diag(s) @ vT
265
260
>>> A = A.astype(np.float32)
266
- >>> u2, s2, vT2 = svds(A, k=2, random_state =rng)
261
+ >>> u2, s2, vT2 = svds(A, k=2, rng =rng)
267
262
>>> np.allclose(s2, s)
268
263
True
269
264
@@ -290,21 +285,21 @@ def svds(A, k=6, ncv=None, tol=0, which='LM', v0=None,
290
285
291
286
The next example follows that of 'sklearn.decomposition.TruncatedSVD'.
292
287
293
- >>> rng = np.random.RandomState (0)
288
+ >>> rng = np.random.default_rng (0)
294
289
>>> X_dense = rng.random(size=(100, 100))
295
290
>>> X_dense[:, 2 * np.arange(50)] = 0
296
291
>>> X = sparse.csr_array(X_dense)
297
- >>> _, singular_values, _ = svds(X, k=5, random_state =rng)
292
+ >>> _, singular_values, _ = svds(X, k=5, rng =rng)
298
293
>>> print(singular_values)
299
- [ 4.3293 ... 4.4491 ... 4.5420 ... 4.5987 ... 35.2410 ...]
294
+ [ 4.3221 ... 4.4043 ... 4.4907 ... 4.5858 ... 35.4549 ...]
300
295
301
296
The function can be called without the transpose of the input matrix
302
297
ever explicitly constructed.
303
298
304
299
>>> rng = np.random.default_rng(102524723947864966825913730119128190974)
305
300
>>> G = sparse.random_array((8, 9), density=0.5, random_state=rng)
306
301
>>> Glo = aslinearoperator(G)
307
- >>> _, singular_values_svds, _ = svds(Glo, k=5, random_state =rng)
302
+ >>> _, singular_values_svds, _ = svds(Glo, k=5, rng =rng)
308
303
>>> _, singular_values_svd, _ = linalg.svd(G.toarray())
309
304
>>> np.allclose(singular_values_svds, singular_values_svd[-4::-1])
310
305
True
@@ -436,9 +431,9 @@ def svds(A, k=6, ncv=None, tol=0, which='LM', v0=None,
436
431
437
432
"""
438
433
args = _iv (A , k , ncv , tol , which , v0 , maxiter , return_singular_vectors ,
439
- solver , random_state )
434
+ solver , rng )
440
435
(A , k , ncv , tol , which , v0 , maxiter ,
441
- return_singular_vectors , solver , random_state ) = args
436
+ return_singular_vectors , solver , rng ) = args
442
437
443
438
largest = (which == 'LM' )
444
439
n , m = A .shape
@@ -477,7 +472,7 @@ def matmat_XH_X(x):
477
472
if k == 1 and v0 is not None :
478
473
X = np .reshape (v0 , (- 1 , 1 ))
479
474
else :
480
- X = random_state .standard_normal (size = (min (A .shape ), k ))
475
+ X = rng .standard_normal (size = (min (A .shape ), k ))
481
476
482
477
_ , eigvec = lobpcg (XH_X , X , tol = tol ** 2 , maxiter = maxiter ,
483
478
largest = largest )
@@ -488,7 +483,7 @@ def matmat_XH_X(x):
488
483
irl_mode = (which == 'SM' )
489
484
res = _svdp (A , k = k , tol = tol ** 2 , which = which , maxiter = None ,
490
485
compute_u = jobu , compute_v = jobv , irl_mode = irl_mode ,
491
- kmax = maxiter , v0 = v0 , random_state = random_state )
486
+ kmax = maxiter , v0 = v0 , rng = rng )
492
487
493
488
u , s , vh , _ = res # but we'll ignore bnd, the last output
494
489
@@ -510,7 +505,7 @@ def matmat_XH_X(x):
510
505
511
506
elif solver == 'arpack' or solver is None :
512
507
if v0 is None :
513
- v0 = random_state .standard_normal (size = (min (A .shape ),))
508
+ v0 = rng .standard_normal (size = (min (A .shape ),))
514
509
_ , eigvec = eigsh (XH_X , k = k , tol = tol ** 2 , maxiter = maxiter ,
515
510
ncv = ncv , which = which , v0 = v0 )
516
511
# arpack do not guarantee exactly orthonormal eigenvectors
0 commit comments