Trajectree 0.0.0__py3-none-any.whl → 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. trajectree/__init__.py +3 -0
  2. trajectree/fock_optics/devices.py +1 -1
  3. trajectree/fock_optics/light_sources.py +2 -2
  4. trajectree/fock_optics/measurement.py +3 -3
  5. trajectree/fock_optics/utils.py +6 -6
  6. trajectree/quimb/docs/_pygments/_pygments_dark.py +118 -0
  7. trajectree/quimb/docs/_pygments/_pygments_light.py +118 -0
  8. trajectree/quimb/docs/conf.py +158 -0
  9. trajectree/quimb/docs/examples/ex_mpi_expm_evo.py +62 -0
  10. trajectree/quimb/quimb/__init__.py +507 -0
  11. trajectree/quimb/quimb/calc.py +1491 -0
  12. trajectree/quimb/quimb/core.py +2279 -0
  13. trajectree/quimb/quimb/evo.py +712 -0
  14. trajectree/quimb/quimb/experimental/__init__.py +0 -0
  15. trajectree/quimb/quimb/experimental/autojittn.py +129 -0
  16. trajectree/quimb/quimb/experimental/belief_propagation/__init__.py +109 -0
  17. trajectree/quimb/quimb/experimental/belief_propagation/bp_common.py +397 -0
  18. trajectree/quimb/quimb/experimental/belief_propagation/d1bp.py +316 -0
  19. trajectree/quimb/quimb/experimental/belief_propagation/d2bp.py +653 -0
  20. trajectree/quimb/quimb/experimental/belief_propagation/hd1bp.py +571 -0
  21. trajectree/quimb/quimb/experimental/belief_propagation/hv1bp.py +775 -0
  22. trajectree/quimb/quimb/experimental/belief_propagation/l1bp.py +316 -0
  23. trajectree/quimb/quimb/experimental/belief_propagation/l2bp.py +537 -0
  24. trajectree/quimb/quimb/experimental/belief_propagation/regions.py +194 -0
  25. trajectree/quimb/quimb/experimental/cluster_update.py +286 -0
  26. trajectree/quimb/quimb/experimental/merabuilder.py +865 -0
  27. trajectree/quimb/quimb/experimental/operatorbuilder/__init__.py +15 -0
  28. trajectree/quimb/quimb/experimental/operatorbuilder/operatorbuilder.py +1631 -0
  29. trajectree/quimb/quimb/experimental/schematic.py +7 -0
  30. trajectree/quimb/quimb/experimental/tn_marginals.py +130 -0
  31. trajectree/quimb/quimb/experimental/tnvmc.py +1483 -0
  32. trajectree/quimb/quimb/gates.py +36 -0
  33. trajectree/quimb/quimb/gen/__init__.py +2 -0
  34. trajectree/quimb/quimb/gen/operators.py +1167 -0
  35. trajectree/quimb/quimb/gen/rand.py +713 -0
  36. trajectree/quimb/quimb/gen/states.py +479 -0
  37. trajectree/quimb/quimb/linalg/__init__.py +6 -0
  38. trajectree/quimb/quimb/linalg/approx_spectral.py +1109 -0
  39. trajectree/quimb/quimb/linalg/autoblock.py +258 -0
  40. trajectree/quimb/quimb/linalg/base_linalg.py +719 -0
  41. trajectree/quimb/quimb/linalg/mpi_launcher.py +397 -0
  42. trajectree/quimb/quimb/linalg/numpy_linalg.py +244 -0
  43. trajectree/quimb/quimb/linalg/rand_linalg.py +514 -0
  44. trajectree/quimb/quimb/linalg/scipy_linalg.py +293 -0
  45. trajectree/quimb/quimb/linalg/slepc_linalg.py +892 -0
  46. trajectree/quimb/quimb/schematic.py +1518 -0
  47. trajectree/quimb/quimb/tensor/__init__.py +401 -0
  48. trajectree/quimb/quimb/tensor/array_ops.py +610 -0
  49. trajectree/quimb/quimb/tensor/circuit.py +4824 -0
  50. trajectree/quimb/quimb/tensor/circuit_gen.py +411 -0
  51. trajectree/quimb/quimb/tensor/contraction.py +336 -0
  52. trajectree/quimb/quimb/tensor/decomp.py +1255 -0
  53. trajectree/quimb/quimb/tensor/drawing.py +1646 -0
  54. trajectree/quimb/quimb/tensor/fitting.py +385 -0
  55. trajectree/quimb/quimb/tensor/geometry.py +583 -0
  56. trajectree/quimb/quimb/tensor/interface.py +114 -0
  57. trajectree/quimb/quimb/tensor/networking.py +1058 -0
  58. trajectree/quimb/quimb/tensor/optimize.py +1818 -0
  59. trajectree/quimb/quimb/tensor/tensor_1d.py +4778 -0
  60. trajectree/quimb/quimb/tensor/tensor_1d_compress.py +1854 -0
  61. trajectree/quimb/quimb/tensor/tensor_1d_tebd.py +662 -0
  62. trajectree/quimb/quimb/tensor/tensor_2d.py +5954 -0
  63. trajectree/quimb/quimb/tensor/tensor_2d_compress.py +96 -0
  64. trajectree/quimb/quimb/tensor/tensor_2d_tebd.py +1230 -0
  65. trajectree/quimb/quimb/tensor/tensor_3d.py +2869 -0
  66. trajectree/quimb/quimb/tensor/tensor_3d_tebd.py +46 -0
  67. trajectree/quimb/quimb/tensor/tensor_approx_spectral.py +60 -0
  68. trajectree/quimb/quimb/tensor/tensor_arbgeom.py +3237 -0
  69. trajectree/quimb/quimb/tensor/tensor_arbgeom_compress.py +565 -0
  70. trajectree/quimb/quimb/tensor/tensor_arbgeom_tebd.py +1138 -0
  71. trajectree/quimb/quimb/tensor/tensor_builder.py +5411 -0
  72. trajectree/quimb/quimb/tensor/tensor_core.py +11179 -0
  73. trajectree/quimb/quimb/tensor/tensor_dmrg.py +1472 -0
  74. trajectree/quimb/quimb/tensor/tensor_mera.py +204 -0
  75. trajectree/quimb/quimb/utils.py +892 -0
  76. trajectree/quimb/tests/__init__.py +0 -0
  77. trajectree/quimb/tests/test_accel.py +501 -0
  78. trajectree/quimb/tests/test_calc.py +788 -0
  79. trajectree/quimb/tests/test_core.py +847 -0
  80. trajectree/quimb/tests/test_evo.py +565 -0
  81. trajectree/quimb/tests/test_gen/__init__.py +0 -0
  82. trajectree/quimb/tests/test_gen/test_operators.py +361 -0
  83. trajectree/quimb/tests/test_gen/test_rand.py +296 -0
  84. trajectree/quimb/tests/test_gen/test_states.py +261 -0
  85. trajectree/quimb/tests/test_linalg/__init__.py +0 -0
  86. trajectree/quimb/tests/test_linalg/test_approx_spectral.py +368 -0
  87. trajectree/quimb/tests/test_linalg/test_base_linalg.py +351 -0
  88. trajectree/quimb/tests/test_linalg/test_mpi_linalg.py +127 -0
  89. trajectree/quimb/tests/test_linalg/test_numpy_linalg.py +84 -0
  90. trajectree/quimb/tests/test_linalg/test_rand_linalg.py +134 -0
  91. trajectree/quimb/tests/test_linalg/test_slepc_linalg.py +283 -0
  92. trajectree/quimb/tests/test_tensor/__init__.py +0 -0
  93. trajectree/quimb/tests/test_tensor/test_belief_propagation/__init__.py +0 -0
  94. trajectree/quimb/tests/test_tensor/test_belief_propagation/test_d1bp.py +39 -0
  95. trajectree/quimb/tests/test_tensor/test_belief_propagation/test_d2bp.py +67 -0
  96. trajectree/quimb/tests/test_tensor/test_belief_propagation/test_hd1bp.py +64 -0
  97. trajectree/quimb/tests/test_tensor/test_belief_propagation/test_hv1bp.py +51 -0
  98. trajectree/quimb/tests/test_tensor/test_belief_propagation/test_l1bp.py +142 -0
  99. trajectree/quimb/tests/test_tensor/test_belief_propagation/test_l2bp.py +101 -0
  100. trajectree/quimb/tests/test_tensor/test_circuit.py +816 -0
  101. trajectree/quimb/tests/test_tensor/test_contract.py +67 -0
  102. trajectree/quimb/tests/test_tensor/test_decomp.py +40 -0
  103. trajectree/quimb/tests/test_tensor/test_mera.py +52 -0
  104. trajectree/quimb/tests/test_tensor/test_optimizers.py +488 -0
  105. trajectree/quimb/tests/test_tensor/test_tensor_1d.py +1171 -0
  106. trajectree/quimb/tests/test_tensor/test_tensor_2d.py +606 -0
  107. trajectree/quimb/tests/test_tensor/test_tensor_2d_tebd.py +144 -0
  108. trajectree/quimb/tests/test_tensor/test_tensor_3d.py +123 -0
  109. trajectree/quimb/tests/test_tensor/test_tensor_arbgeom.py +226 -0
  110. trajectree/quimb/tests/test_tensor/test_tensor_builder.py +441 -0
  111. trajectree/quimb/tests/test_tensor/test_tensor_core.py +2066 -0
  112. trajectree/quimb/tests/test_tensor/test_tensor_dmrg.py +388 -0
  113. trajectree/quimb/tests/test_tensor/test_tensor_spectral_approx.py +63 -0
  114. trajectree/quimb/tests/test_tensor/test_tensor_tebd.py +270 -0
  115. trajectree/quimb/tests/test_utils.py +85 -0
  116. trajectree/trajectory.py +2 -2
  117. {trajectree-0.0.0.dist-info → trajectree-0.0.1.dist-info}/METADATA +2 -2
  118. trajectree-0.0.1.dist-info/RECORD +126 -0
  119. trajectree-0.0.0.dist-info/RECORD +0 -16
  120. {trajectree-0.0.0.dist-info → trajectree-0.0.1.dist-info}/WHEEL +0 -0
  121. {trajectree-0.0.0.dist-info → trajectree-0.0.1.dist-info}/licenses/LICENSE +0 -0
  122. {trajectree-0.0.0.dist-info → trajectree-0.0.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,514 @@
1
+ """Randomized iterative methods for decompositions.
2
+ """
3
+ from numbers import Integral
4
+
5
+ import numpy as np
6
+ import scipy.linalg as sla
7
+
8
+ from ..gen.rand import randn
9
+ from ..core import dag, dot, njit
10
+ from ..utils import identity
11
+
12
+
13
+ def lu_orthog(X):
14
+ return sla.lu(X, permute_l=True, overwrite_a=True, check_finite=False)[0]
15
+
16
+
17
+ def qr_orthog(X):
18
+ return sla.qr(X, mode="economic", overwrite_a=True, check_finite=False)[0]
19
+
20
+
21
+ def orthog(X, lu=False):
22
+ if lu:
23
+ return lu_orthog(X)
24
+ return qr_orthog(X)
25
+
26
+
27
+ def QB_to_svd(Q, B, compute_uv=True):
28
+ UsV = sla.svd(
29
+ B,
30
+ full_matrices=False,
31
+ compute_uv=compute_uv,
32
+ overwrite_a=True,
33
+ check_finite=False,
34
+ )
35
+
36
+ if not compute_uv:
37
+ return UsV
38
+
39
+ U, s, V = UsV
40
+ return dot(Q, U), s, V
41
+
42
+
43
+ def trim(arrays, k):
44
+ if isinstance(arrays, tuple) and len(arrays) == 3:
45
+ U, s, VH = arrays
46
+ U, s, VH = U[:, :k], s[:k], VH[:k, :]
47
+ return U, s, VH
48
+ if isinstance(arrays, tuple) and len(arrays) == 2:
49
+ # Q, B factors
50
+ Q, B = arrays
51
+ return Q[:, :k], B[:k, :]
52
+ else:
53
+ # just singular values
54
+ return arrays[:k]
55
+
56
+
57
+ def possibly_extend_randn(G, k, p, A):
58
+ # make sure we are using block of the right size by removing or adding
59
+ kG = G.shape[1]
60
+ if kG > k + p:
61
+ # have too many columns
62
+ G = G[:, : k + p]
63
+ elif kG < k + p:
64
+ # have too few columns
65
+ G_extra = randn((A.shape[1], k + p - kG), dtype=A.dtype)
66
+ G = np.concatenate((G, G_extra), axis=1)
67
+ return G
68
+
69
+
70
+ def isstring(x, s):
71
+ if not isinstance(x, str):
72
+ return False
73
+ return x == s
74
+
75
+
76
+ def rsvd_qb(A, k, q, p, state, AH=None):
77
+ if AH is None:
78
+ AH = dag(A)
79
+
80
+ # generate first block
81
+ if isstring(state, "begin-qb"):
82
+ G = randn((A.shape[1], k + p), dtype=A.dtype)
83
+ # block already supplied
84
+ elif len(state) == 1:
85
+ (G,) = state
86
+ # mid-way through adaptive algorithm in QB mode
87
+ if len(state) == 3:
88
+ Q, B, G = state
89
+ else:
90
+ Q = np.empty((A.shape[0], 0), dtype=A.dtype)
91
+ B = np.empty((0, A.shape[1]), dtype=A.dtype)
92
+
93
+ QH, BH = dag(Q), dag(B)
94
+ G = possibly_extend_randn(G, k, p, A)
95
+
96
+ Qi = orthog(dot(A, G) - dot(Q, dot(B, G)), lu=q > 0)
97
+
98
+ for i in range(1, q + 1):
99
+ Qi = orthog(dot(AH, Qi) - dot(BH, dot(QH, Qi)), lu=True)
100
+ Qi = orthog(dot(A, Qi) - dot(Q, dot(B, Qi)), lu=i != q)
101
+
102
+ Qi = orthog(Qi - dot(Q, dot(QH, Qi)))
103
+ Bi = dag(dot(AH, Qi)) - dot(dot(dag(Qi), Q), B)
104
+
105
+ if p > 0:
106
+ Qi, Bi = trim((Qi, Bi), k)
107
+
108
+ Q = np.concatenate((Q, Qi), axis=1)
109
+ B = np.concatenate((B, Bi), axis=0)
110
+
111
+ return Q, B, G
112
+
113
+
114
+ def rsvd_core(A, k, compute_uv=True, q=2, p=0, state=None, AH=None):
115
+ """Core R3SVD algorithm.
116
+
117
+ Parameters
118
+ ----------
119
+ A : linear operator, shape (m, n)
120
+ Operator to decompose, assumed m >= n.
121
+ k : int
122
+ Number of singular values to find.
123
+ compute_uv : bool, optional
124
+ Return the left and right singular vectors.
125
+ q : int, optional
126
+ Number of power iterations.
127
+ p : int, optional
128
+ Over sampling factor.
129
+ state : {None, array_like, (), (G0,), (U0, s0, VH0, G0)}, optional
130
+ Iterate based on these previous results:
131
+
132
+ - None: basic mode.
133
+ - array_like: use this as the initial subspace.
134
+ - 'begin-svd': begin block iterations, return U, s, VH, G
135
+ - (G0,) : begin block iterations with this subspace
136
+ - (U0, s0, VH0, G0): continue block iterations, return G
137
+
138
+ """
139
+ iterating = isinstance(state, (tuple, str))
140
+ maybe_project_left = maybe_project_right = identity
141
+
142
+ if AH is None:
143
+ AH = dag(A)
144
+
145
+ # generate first block
146
+ if state is None or isstring(state, "begin-svd"):
147
+ G = randn((A.shape[1], k + p), dtype=A.dtype)
148
+ # initial block supplied
149
+ elif hasattr(state, "shape"):
150
+ G = state
151
+ elif len(state) == 1:
152
+ (G,) = state
153
+ # mid-way through adaptive algorithm in SVD mode
154
+ elif len(state) == 4:
155
+ U0, s0, VH0, G = state
156
+ UH0, V0 = dag(U0), dag(VH0)
157
+
158
+ def maybe_project_left(X):
159
+ X -= dot(U0, dot(UH0, X))
160
+ return X
161
+
162
+ def maybe_project_right(X):
163
+ X -= dot(V0, dot(VH0, X))
164
+ return X
165
+
166
+ G = possibly_extend_randn(G, k, p, A)
167
+ G = maybe_project_right(G)
168
+
169
+ Q = dot(A, G)
170
+ Q = maybe_project_left(Q)
171
+ Q = orthog(Q, lu=q > 0)
172
+
173
+ # power iterations with stabilization
174
+ for i in range(1, q + 1):
175
+ Q = dot(AH, Q)
176
+ Q = maybe_project_right(Q)
177
+ Q = orthog(Q, lu=True)
178
+
179
+ Q = dot(A, Q)
180
+ Q = maybe_project_left(Q)
181
+ Q = orthog(Q, lu=i < q)
182
+
183
+ B = dag(dot(AH, Q))
184
+ UsVH = QB_to_svd(Q, B, compute_uv=compute_uv or iterating)
185
+ if p > 0:
186
+ UsVH = trim(UsVH, k)
187
+
188
+ if not iterating:
189
+ return UsVH
190
+
191
+ U, s, VH = UsVH
192
+
193
+ if isstring(state, "begin-svd") or len(state) == 1:
194
+ # first run -> don't need to project or concatenate anything
195
+ return U, s, VH, G
196
+
197
+ U = orthog(maybe_project_left(U))
198
+ VH = dag(orthog(maybe_project_right(dag(VH))))
199
+
200
+ U = np.concatenate((U0, U), axis=1)
201
+ s = np.concatenate((s0, s))
202
+ VH = np.concatenate((VH0, VH), axis=0)
203
+
204
+ return U, s, VH, G
205
+
206
+
207
+ @njit
208
+ def is_sorted(x): # pragma: no cover
209
+ for i in range(x.size - 1):
210
+ if x[i + 1] < x[i]:
211
+ return False
212
+ return True
213
+
214
+
215
+ def gen_k_steps(start, incr=1.4):
216
+ yield start
217
+ step = start
218
+ while True:
219
+ yield step
220
+ step = round(incr * step)
221
+
222
+
223
+ def rsvd_iterate(
224
+ A,
225
+ eps,
226
+ compute_uv=True,
227
+ q=2,
228
+ p=0,
229
+ G0=None,
230
+ k_max=None,
231
+ k_start=2,
232
+ k_incr=1.4,
233
+ AH=None,
234
+ use_qb=20,
235
+ ):
236
+ """Handle rank-adaptively calling ``rsvd_core``."""
237
+
238
+ if AH is None:
239
+ AH = dag(A)
240
+
241
+ # perform first iteration and set initial rank
242
+ k_steps = gen_k_steps(k_start, k_incr)
243
+ rank = next(k_steps)
244
+
245
+ if use_qb:
246
+ Q, B, G = rsvd_qb(
247
+ A, rank, q=q, p=p, AH=AH, state="begin-qb" if G0 is None else (G0,)
248
+ )
249
+ U, s, VH = QB_to_svd(Q, B)
250
+ G -= dot(dag(VH), dot(VH, G))
251
+ else:
252
+ U, s, VH, G = rsvd_core(
253
+ A,
254
+ rank,
255
+ q=q,
256
+ p=p,
257
+ AH=AH,
258
+ state="begin-svd" if G0 is None else (G0,),
259
+ )
260
+
261
+ # perform randomized SVD in small blocks
262
+ while (s[-1] > eps * s[0]) and (rank < k_max):
263
+ # only step k as far as k_max
264
+ new_k = min(next(k_steps), k_max - rank)
265
+ rank += new_k
266
+
267
+ if (rank < use_qb) or (use_qb is True):
268
+ Q, B, G = rsvd_qb(A, new_k, q=q, p=p, state=(Q, B, G), AH=AH)
269
+ U, s, VH = QB_to_svd(Q, B)
270
+ G -= dot(dag(VH), dot(VH, G))
271
+ else:
272
+ # concatenate new U, s, VH orthogonal to current U, s, VH
273
+ U, s, VH, G = rsvd_core(
274
+ A, new_k, q=q, p=p, state=(U, s, VH, G), AH=AH
275
+ )
276
+
277
+ # make sure singular values always sorted in decreasing order
278
+ if not is_sorted(s):
279
+ so = np.argsort(s)[::-1]
280
+ U, s, VH = U[:, so], s[so], VH[so, :]
281
+
282
+ return U, s, VH if compute_uv else s
283
+
284
+
285
+ @njit
286
+ def count_svdvals_needed(s, eps): # pragma: no cover
287
+ n = s.size
288
+ thresh = eps * s[0]
289
+ for i in range(n - 1, 0, -1):
290
+ if s[i - 1] < thresh:
291
+ n -= 1
292
+ else:
293
+ break
294
+ return n
295
+
296
+
297
+ def isdouble(dtype):
298
+ """Check if ``dtype`` is double precision."""
299
+ return dtype in ("float64", "complex128")
300
+
301
+
302
+ def estimate_rank(
303
+ A,
304
+ eps,
305
+ k_max=None,
306
+ use_sli=True,
307
+ k_start=2,
308
+ k_incr=1.4,
309
+ q=0,
310
+ p=0,
311
+ get_vectors=False,
312
+ G0=None,
313
+ AH=None,
314
+ use_qb=20,
315
+ ):
316
+ """Estimate the rank of an linear operator. Uses a low quality random
317
+ SVD with a resolution of ~ 10.
318
+
319
+ Parameters
320
+ ----------
321
+ A : linear operator
322
+ The operator to find rank of.
323
+ eps : float
324
+ Find rank to this relative (compared to largest singular value)
325
+ precision.
326
+ k_max : int, optional
327
+ The maximum rank to find.
328
+ use_sli : bool, optional
329
+ Whether to use :func:`scipy.linalg.interpolative.estimate_rank` if
330
+ possible (double precision and no ``k_max`` set).
331
+ k_start : int, optional
332
+ Begin the adaptive SVD with a block of this size.
333
+ k_incr : float, optional
334
+ Adaptive rank increment factor. Increase the k-step (from k_start) by
335
+ this factor each time. Set to 1 to use a constant step.
336
+ q : int, optional
337
+ Number of power iterations.
338
+ get_vectors : bool, optional
339
+ Return the right singular vectors found in the pass.
340
+ G0 : , optional
341
+
342
+ Returns
343
+ -------
344
+ rank : int
345
+ The rank.
346
+ VH : array
347
+ The (adjoint) right singular vectors if ``get_vectors=True``.
348
+ """
349
+ if k_max is None:
350
+ k_max = min(A.shape)
351
+ if eps <= 0.0:
352
+ return k_max
353
+
354
+ use_sli = (
355
+ use_sli
356
+ and (k_max == min(A.shape))
357
+ and isdouble(A.dtype)
358
+ and not get_vectors
359
+ )
360
+ if use_sli:
361
+ return sla.interpolative.estimate_rank(A, eps)
362
+
363
+ if A.shape[0] < A.shape[1]:
364
+ A = A.T
365
+ if get_vectors:
366
+ raise ValueError
367
+ if AH is None:
368
+ AH = dag(A)
369
+
370
+ _, s, VH = rsvd_iterate(
371
+ A,
372
+ eps,
373
+ q=q,
374
+ p=p,
375
+ G0=G0,
376
+ AH=AH,
377
+ use_qb=use_qb,
378
+ k_start=k_start,
379
+ k_max=k_max,
380
+ k_incr=k_incr,
381
+ )
382
+
383
+ rank = count_svdvals_needed(s, eps)
384
+
385
+ if get_vectors:
386
+ return rank, VH[:rank, :]
387
+ return rank
388
+
389
+
390
+ def maybe_flip(UsV, flipped):
391
+ # if only singular values or only tranposing do nothing
392
+ if not (isinstance(UsV, tuple) and flipped):
393
+ return UsV
394
+ U, s, V = UsV
395
+ return V.T, s, U.T
396
+
397
+
398
+ def rsvd(
399
+ A,
400
+ eps_or_k,
401
+ compute_uv=True,
402
+ mode="adapt+block",
403
+ use_qb=20,
404
+ q=2,
405
+ p=0,
406
+ k_max=None,
407
+ k_start=2,
408
+ k_incr=1.4,
409
+ G0=None,
410
+ AH=None,
411
+ ):
412
+ """Fast, randomized, iterative SVD. Adaptive variant of method due
413
+ originally to Halko. This scales as ``log(k)`` rather than ``k`` so can be
414
+ more efficient.
415
+
416
+ Parameters
417
+ ----------
418
+ A : operator, shape (m, n)
419
+ The operator to decompose.
420
+ eps_or_k : float or int
421
+ Either the relative precision or the number of singular values to
422
+ target. If precision, this is relative to the largest singular value.
423
+ compute_uv : bool, optional
424
+ Whether to return the left and right singular vectors.
425
+ mode : {'adapt+block', 'adapt', 'block'}, optional
426
+ How to perform the randomized SVD. If ``eps_or_k`` is an integer then
427
+ this is implicitly 'block' and ignored. Else:
428
+
429
+ - 'adapt+block', perform an initial low quality pass to estimate
430
+ the rank of ``A``, then use the subspace and rank from that to
431
+ perform an accurate fully blocked RSVD.
432
+ - 'adapt', just perform the adaptive randomized SVD.
433
+
434
+ q : int, optional
435
+ The number of power iterations, increase for accuracy at the expense
436
+ of runtime.
437
+ p : int, optional
438
+ Oversampling factor. Perform projections with this many extra columns
439
+ and then throw then away.
440
+ k_max : int, optional
441
+ Maximum adaptive rank. Default: ``min(A.shape)``.
442
+ k_start : int, optional
443
+ Initial k when increasing rank adaptively.
444
+ k_incr : float, optional
445
+ Adaptive rank increment factor. Increase the k-step (from k_start) by
446
+ this factor each time. Set to 1 to use a constant step.
447
+ G0 : array_like, shape (n, k), optional
448
+ Initial subspace to start iterating on. If not given a random one will
449
+ be generated.
450
+
451
+ Returns
452
+ -------
453
+ U, array, shape (m, k)
454
+ Left singular vectors, if ``compute_uv=True``.
455
+ s, array, shape (k,)
456
+ Singular values.
457
+ V, array, shape (k, n)
458
+ Right singular vectors, if ``compute_uv=True``.
459
+ """
460
+
461
+ flipped = A.shape[0] < A.shape[1]
462
+ if flipped:
463
+ A = A.T
464
+
465
+ # 'block' mode -> just perform single pass random SVD
466
+ if isinstance(eps_or_k, Integral):
467
+ UsV = rsvd_core(A, eps_or_k, q=q, p=p, state=G0, compute_uv=compute_uv)
468
+ return maybe_flip(UsV, flipped)
469
+
470
+ if k_max is None:
471
+ k_max = min(A.shape)
472
+ k_max = min(max(1, k_max), min(A.shape))
473
+
474
+ if AH is None:
475
+ AH = dag(A)
476
+
477
+ adaptive_opts = {
478
+ "k_start": k_start,
479
+ "k_max": k_max,
480
+ "k_incr": k_incr,
481
+ "use_qb": use_qb,
482
+ "AH": AH,
483
+ "G0": G0,
484
+ }
485
+
486
+ # 'adapt' mode -> rank adaptively perform SVD to low accuracy
487
+ if mode == "adapt":
488
+ UsV = rsvd_iterate(
489
+ A, eps_or_k, q=q, p=p, compute_uv=compute_uv, **adaptive_opts
490
+ )
491
+
492
+ # 'adapt+block' mode -> use first pass to find rank, then use blocking mode
493
+ elif mode == "adapt+block":
494
+ # estimate both rank and get approximate spanning vectors
495
+ k, VH = estimate_rank(A, eps_or_k, get_vectors=True, **adaptive_opts)
496
+
497
+ # reuse vectors to effectively boost number of power iterations by one
498
+ UsV = rsvd_core(
499
+ A,
500
+ k,
501
+ q=max(q - 1, 0),
502
+ p=p,
503
+ AH=AH,
504
+ state=dag(VH),
505
+ compute_uv=compute_uv,
506
+ )
507
+
508
+ else:
509
+ raise ValueError(
510
+ "``mode`` must be one of {'adapt+block', 'adapt'} or"
511
+ " ``k`` should be a integer to use 'block' mode."
512
+ )
513
+
514
+ return maybe_flip(UsV, flipped)