freealg 0.1.11__py3-none-any.whl → 0.7.12__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.
- freealg/__init__.py +8 -2
- freealg/__version__.py +1 -1
- freealg/_algebraic_form/__init__.py +12 -0
- freealg/_algebraic_form/_branch_points.py +288 -0
- freealg/_algebraic_form/_constraints.py +139 -0
- freealg/_algebraic_form/_continuation_algebraic.py +706 -0
- freealg/_algebraic_form/_decompress.py +641 -0
- freealg/_algebraic_form/_decompress2.py +204 -0
- freealg/_algebraic_form/_edge.py +330 -0
- freealg/_algebraic_form/_homotopy.py +323 -0
- freealg/_algebraic_form/_moments.py +448 -0
- freealg/_algebraic_form/_sheets_util.py +145 -0
- freealg/_algebraic_form/_support.py +309 -0
- freealg/_algebraic_form/algebraic_form.py +1232 -0
- freealg/_free_form/__init__.py +16 -0
- freealg/{_chebyshev.py → _free_form/_chebyshev.py} +75 -43
- freealg/_free_form/_decompress.py +993 -0
- freealg/_free_form/_density_util.py +243 -0
- freealg/_free_form/_jacobi.py +359 -0
- freealg/_free_form/_linalg.py +508 -0
- freealg/{_pade.py → _free_form/_pade.py} +42 -208
- freealg/{_plot_util.py → _free_form/_plot_util.py} +37 -22
- freealg/{_sample.py → _free_form/_sample.py} +58 -22
- freealg/_free_form/_series.py +454 -0
- freealg/_free_form/_support.py +214 -0
- freealg/_free_form/free_form.py +1362 -0
- freealg/_geometric_form/__init__.py +13 -0
- freealg/_geometric_form/_continuation_genus0.py +175 -0
- freealg/_geometric_form/_continuation_genus1.py +275 -0
- freealg/_geometric_form/_elliptic_functions.py +174 -0
- freealg/_geometric_form/_sphere_maps.py +63 -0
- freealg/_geometric_form/_torus_maps.py +118 -0
- freealg/_geometric_form/geometric_form.py +1094 -0
- freealg/_util.py +56 -110
- freealg/distributions/__init__.py +7 -1
- freealg/distributions/_chiral_block.py +494 -0
- freealg/distributions/_deformed_marchenko_pastur.py +726 -0
- freealg/distributions/_deformed_wigner.py +386 -0
- freealg/distributions/_kesten_mckay.py +29 -15
- freealg/distributions/_marchenko_pastur.py +224 -95
- freealg/distributions/_meixner.py +47 -37
- freealg/distributions/_wachter.py +29 -17
- freealg/distributions/_wigner.py +27 -14
- freealg/visualization/__init__.py +12 -0
- freealg/visualization/_glue_util.py +32 -0
- freealg/visualization/_rgb_hsv.py +125 -0
- freealg-0.7.12.dist-info/METADATA +172 -0
- freealg-0.7.12.dist-info/RECORD +53 -0
- {freealg-0.1.11.dist-info → freealg-0.7.12.dist-info}/WHEEL +1 -1
- freealg/_decompress.py +0 -180
- freealg/_jacobi.py +0 -218
- freealg/_support.py +0 -85
- freealg/freeform.py +0 -967
- freealg-0.1.11.dist-info/METADATA +0 -140
- freealg-0.1.11.dist-info/RECORD +0 -24
- /freealg/{_damp.py → _free_form/_damp.py} +0 -0
- {freealg-0.1.11.dist-info → freealg-0.7.12.dist-info}/licenses/AUTHORS.txt +0 -0
- {freealg-0.1.11.dist-info → freealg-0.7.12.dist-info}/licenses/LICENSE.txt +0 -0
- {freealg-0.1.11.dist-info → freealg-0.7.12.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
# SPDX-FileType: SOURCE
|
|
3
|
+
#
|
|
4
|
+
# This program is free software: you can redistribute it and/or modify it under
|
|
5
|
+
# the terms of the license found in the LICENSE.txt file in the root directory
|
|
6
|
+
# of this source tree.
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# =======
|
|
10
|
+
# Imports
|
|
11
|
+
# =======
|
|
12
|
+
|
|
13
|
+
import numpy
|
|
14
|
+
from .._util import compute_eig
|
|
15
|
+
from .free_form import FreeForm
|
|
16
|
+
|
|
17
|
+
__all__ = ['eigvalsh', 'cond', 'norm', 'trace', 'slogdet']
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# ===============
|
|
21
|
+
# subsample apply
|
|
22
|
+
# ===============
|
|
23
|
+
|
|
24
|
+
def _subsample_apply(f, A, output_array=False, seed=None):
|
|
25
|
+
"""
|
|
26
|
+
Compute f(A_n) over subsamples A_n of A. If the output of
|
|
27
|
+
f is an array (e.g. eigvals), specify output_array to be True.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
if (A.ndim != 2) or (A.shape[0] != A.shape[1]):
|
|
31
|
+
raise RuntimeError("Only square matrices are permitted.")
|
|
32
|
+
|
|
33
|
+
n = A.shape[0]
|
|
34
|
+
|
|
35
|
+
# Size of sample matrix
|
|
36
|
+
n_s = int(80.0 * (1.0 + numpy.log(n)))
|
|
37
|
+
|
|
38
|
+
# If matrix is not large enough, return eigenvalues
|
|
39
|
+
if n < n_s:
|
|
40
|
+
return f(A), n, n
|
|
41
|
+
|
|
42
|
+
# Number of samples
|
|
43
|
+
num_samples = int(10 * (n / n_s)**0.5)
|
|
44
|
+
|
|
45
|
+
# Collect eigenvalue samples
|
|
46
|
+
samples = []
|
|
47
|
+
rng = numpy.random.default_rng(seed=seed)
|
|
48
|
+
for _ in range(num_samples):
|
|
49
|
+
indices = rng.choice(n, n_s, replace=False)
|
|
50
|
+
samples.append(f(A[numpy.ix_(indices, indices)]))
|
|
51
|
+
|
|
52
|
+
if output_array:
|
|
53
|
+
return numpy.concatenate(samples), n, n_s
|
|
54
|
+
else:
|
|
55
|
+
return numpy.array(samples), n, n_s
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# ========
|
|
59
|
+
# eigvalsh
|
|
60
|
+
# ========
|
|
61
|
+
|
|
62
|
+
def eigvalsh(A, size=None, psd=None, seed=None, plot=False, **kwargs):
|
|
63
|
+
"""
|
|
64
|
+
Estimate the eigenvalues of a matrix.
|
|
65
|
+
|
|
66
|
+
This function estimates the eigenvalues of the matrix :math:`\\mathbf{A}`
|
|
67
|
+
or a larger matrix containing :math:`\\mathbf{A}` using free decompression.
|
|
68
|
+
|
|
69
|
+
Parameters
|
|
70
|
+
----------
|
|
71
|
+
|
|
72
|
+
A : numpy.ndarray
|
|
73
|
+
The symmetric real-valued matrix :math:`\\mathbf{A}` whose eigenvalues
|
|
74
|
+
(or those of a matrix containing :math:`\\mathbf{A}`) are to be
|
|
75
|
+
computed.
|
|
76
|
+
|
|
77
|
+
size : int, default=None
|
|
78
|
+
The size of the matrix containing :math:`\\mathbf{A}` to estimate
|
|
79
|
+
eigenvalues of. If None, returns estimates of the eigenvalues of
|
|
80
|
+
:math:`\\mathbf{A}` itself.
|
|
81
|
+
|
|
82
|
+
psd : bool, default=None
|
|
83
|
+
Determines whether the matrix is positive-semidefinite (PSD; all
|
|
84
|
+
eigenvalues are non-negative). If `None`, the matrix is considered PSD
|
|
85
|
+
if all sampled eigenvalues are positive.
|
|
86
|
+
|
|
87
|
+
seed : int, default=None
|
|
88
|
+
The seed for sampling rows/columns of matirx as well as the Quasi-Monte
|
|
89
|
+
Carlo sampler for eigenvalues from density.
|
|
90
|
+
|
|
91
|
+
plot : bool, default=False
|
|
92
|
+
Print out all relevant plots for diagnosing eigenvalue accuracy.
|
|
93
|
+
|
|
94
|
+
**kwargs : dict, optional
|
|
95
|
+
Pass additional options to the underlying
|
|
96
|
+
:func:`FreeForm.decompress` function.
|
|
97
|
+
|
|
98
|
+
Returns
|
|
99
|
+
-------
|
|
100
|
+
|
|
101
|
+
eigs : numpy.array
|
|
102
|
+
Eigenvalues of decompressed matrix
|
|
103
|
+
|
|
104
|
+
See Also
|
|
105
|
+
--------
|
|
106
|
+
|
|
107
|
+
cond
|
|
108
|
+
|
|
109
|
+
Notes
|
|
110
|
+
-----
|
|
111
|
+
|
|
112
|
+
This is a convenience function for the :class:`freealg.FreeForm` class with
|
|
113
|
+
some effective defaults that work well for common random matrix ensembles.
|
|
114
|
+
For improved performance and plotting utilities, consider fine-tuning
|
|
115
|
+
parameters using the FreeForm class.
|
|
116
|
+
|
|
117
|
+
References
|
|
118
|
+
----------
|
|
119
|
+
|
|
120
|
+
.. [1] Reference.
|
|
121
|
+
|
|
122
|
+
Examples
|
|
123
|
+
--------
|
|
124
|
+
|
|
125
|
+
.. code-block:: python
|
|
126
|
+
:emphasize-lines: 6
|
|
127
|
+
|
|
128
|
+
>>> from freealg import cond
|
|
129
|
+
>>> from freealg.distributions import MarchenkoPastur
|
|
130
|
+
|
|
131
|
+
>>> mp = MarchenkoPastur(1/50)
|
|
132
|
+
>>> A = mp.matrix(3000)
|
|
133
|
+
>>> eigs = eigvalsh(A)
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
samples, n, n_s = _subsample_apply(compute_eig, A, output_array=True,
|
|
137
|
+
seed=seed)
|
|
138
|
+
|
|
139
|
+
if size is None:
|
|
140
|
+
size = n
|
|
141
|
+
|
|
142
|
+
# If all eigenvalues are positive, set PSD flag
|
|
143
|
+
if psd is None:
|
|
144
|
+
psd = samples.min() > 0
|
|
145
|
+
|
|
146
|
+
ff = FreeForm(samples)
|
|
147
|
+
|
|
148
|
+
# Since we are resampling, we need to provide the correct matrix size
|
|
149
|
+
ff.n = n_s
|
|
150
|
+
|
|
151
|
+
# Perform fit and estimate eigenvalues
|
|
152
|
+
order = 1 + int(len(samples)**0.2)
|
|
153
|
+
ff.fit(method='chebyshev', K=order, projection='sample',
|
|
154
|
+
continuation='wynn-eps', force=True, plot=False, latex=False,
|
|
155
|
+
save=False)
|
|
156
|
+
|
|
157
|
+
if plot:
|
|
158
|
+
ff.density(plot=True)
|
|
159
|
+
ff.stieltjes(plot=True)
|
|
160
|
+
|
|
161
|
+
# Sampling method using Pade seems to need a lower tolerance to properly
|
|
162
|
+
# work. Here we set defaults unless user provides otherwise. Note that the
|
|
163
|
+
# default of tolerance in ff._decompress is much larger (1e-4) for other
|
|
164
|
+
# methods (Newton, and non-sampling projections such as Gaussian and beta)
|
|
165
|
+
# to work properly.
|
|
166
|
+
kwargs.setdefault('tolerance', 1e-9)
|
|
167
|
+
kwargs.setdefault('method', 'secant')
|
|
168
|
+
|
|
169
|
+
eigs = ff.eigvalsh(size, seed=seed, plot=plot, **kwargs)
|
|
170
|
+
|
|
171
|
+
if psd:
|
|
172
|
+
eigs = numpy.abs(eigs)
|
|
173
|
+
eigs.sort()
|
|
174
|
+
|
|
175
|
+
return eigs
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
# ====
|
|
179
|
+
# cond
|
|
180
|
+
# ====
|
|
181
|
+
|
|
182
|
+
def cond(A, size=None, seed=None, **kwargs):
|
|
183
|
+
"""
|
|
184
|
+
Estimate the condition number of a Hermitian positive-definite matrix.
|
|
185
|
+
|
|
186
|
+
This function estimates the condition number of the matrix
|
|
187
|
+
:math:`\\mathbf{A}` or a larger matrix containing :math:`\\mathbf{A}`
|
|
188
|
+
using free decompression.
|
|
189
|
+
|
|
190
|
+
Parameters
|
|
191
|
+
----------
|
|
192
|
+
|
|
193
|
+
A : numpy.ndarray
|
|
194
|
+
The symmetric real-valued matrix :math:`\\mathbf{A}` whose condition
|
|
195
|
+
number (or that of a matrix containing :math:`\\mathbf{A}`) are to be
|
|
196
|
+
computed.
|
|
197
|
+
|
|
198
|
+
size : int, default=None
|
|
199
|
+
The size of the matrix containing :math:`\\mathbf{A}` to estimate
|
|
200
|
+
eigenvalues of. If None, returns estimates of the eigenvalues of
|
|
201
|
+
:math:`\\mathbf{A}` itself.
|
|
202
|
+
|
|
203
|
+
seed : int, default=None
|
|
204
|
+
The seed for the Quasi-Monte Carlo sampler.
|
|
205
|
+
|
|
206
|
+
**kwargs : dict, optional
|
|
207
|
+
Pass additional options to the underlying
|
|
208
|
+
:func:`FreeForm.decompress` function.
|
|
209
|
+
|
|
210
|
+
Returns
|
|
211
|
+
-------
|
|
212
|
+
|
|
213
|
+
c : float
|
|
214
|
+
Condition number
|
|
215
|
+
|
|
216
|
+
See Also
|
|
217
|
+
--------
|
|
218
|
+
|
|
219
|
+
eigvalsh
|
|
220
|
+
norm
|
|
221
|
+
slogdet
|
|
222
|
+
trace
|
|
223
|
+
|
|
224
|
+
Notes
|
|
225
|
+
-----
|
|
226
|
+
|
|
227
|
+
This is a convenience function using :func:`freealg.eigvalsh`.
|
|
228
|
+
|
|
229
|
+
Examples
|
|
230
|
+
--------
|
|
231
|
+
|
|
232
|
+
.. code-block:: python
|
|
233
|
+
:emphasize-lines: 6
|
|
234
|
+
|
|
235
|
+
>>> from freealg import cond
|
|
236
|
+
>>> from freealg.distributions import MarchenkoPastur
|
|
237
|
+
|
|
238
|
+
>>> mp = MarchenkoPastur(1/50)
|
|
239
|
+
>>> A = mp.matrix(3000)
|
|
240
|
+
>>> cond(A)
|
|
241
|
+
"""
|
|
242
|
+
|
|
243
|
+
eigs = eigvalsh(A, size=size, psd=True, seed=seed, **kwargs)
|
|
244
|
+
return eigs.max() / eigs.min()
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
# ====
|
|
248
|
+
# norm
|
|
249
|
+
# ====
|
|
250
|
+
|
|
251
|
+
def norm(A, size=None, order=2, seed=None, **kwargs):
|
|
252
|
+
"""
|
|
253
|
+
Estimate the Schatten norm of a Hermitian matrix.
|
|
254
|
+
|
|
255
|
+
This function estimates the norm of the matrix :math:`\\mathbf{A}` or a
|
|
256
|
+
larger matrix containing :math:`\\mathbf{A}` using free decompression.
|
|
257
|
+
|
|
258
|
+
Parameters
|
|
259
|
+
----------
|
|
260
|
+
|
|
261
|
+
A : numpy.ndarray
|
|
262
|
+
The symmetric real-valued matrix :math:`\\mathbf{A}` whose condition
|
|
263
|
+
number (or that of a matrix containing :math:`\\mathbf{A}`) are to be
|
|
264
|
+
computed.
|
|
265
|
+
|
|
266
|
+
size : int, default=None
|
|
267
|
+
The size of the matrix containing :math:`\\mathbf{A}` to estimate
|
|
268
|
+
eigenvalues of. If None, returns estimates of the eigenvalues of
|
|
269
|
+
:math:`\\mathbf{A}` itself.
|
|
270
|
+
|
|
271
|
+
order : {float, ``''inf``, ``'-inf'``, ``'fro'``, ``'nuc'``}, default=2
|
|
272
|
+
Order of the norm.
|
|
273
|
+
|
|
274
|
+
* float :math:`p`: Schatten p-norm.
|
|
275
|
+
* ``'inf'``: Largest absolute eigenvalue
|
|
276
|
+
:math:`\\max \\vert \\lambda_i \\vert)`
|
|
277
|
+
* ``'-inf'``: Smallest absolute eigenvalue
|
|
278
|
+
:math:`\\min \\vert \\lambda_i \\vert)`
|
|
279
|
+
* ``'fro'``: Frobenius norm corresponding to :math:`p=2`
|
|
280
|
+
* ``'nuc'``: Nuclear (or trace) norm corresponding to :math:`p=1`
|
|
281
|
+
|
|
282
|
+
seed : int, default=None
|
|
283
|
+
The seed for the Quasi-Monte Carlo sampler.
|
|
284
|
+
|
|
285
|
+
**kwargs : dict, optional
|
|
286
|
+
Pass additional options to the underlying
|
|
287
|
+
:func:`FreeForm.decompress` function.
|
|
288
|
+
|
|
289
|
+
Returns
|
|
290
|
+
-------
|
|
291
|
+
|
|
292
|
+
norm : float
|
|
293
|
+
matrix norm
|
|
294
|
+
|
|
295
|
+
See Also
|
|
296
|
+
--------
|
|
297
|
+
|
|
298
|
+
eigvalsh
|
|
299
|
+
cond
|
|
300
|
+
slogdet
|
|
301
|
+
trace
|
|
302
|
+
|
|
303
|
+
Notes
|
|
304
|
+
-----
|
|
305
|
+
|
|
306
|
+
Thes Schatten :math:`p`-norm is defined by
|
|
307
|
+
|
|
308
|
+
.. math::
|
|
309
|
+
|
|
310
|
+
\\Vert \\mathbf{A} \\Vert_p = \\left(
|
|
311
|
+
\\sum_{i=1}^N \\vert \\lambda_i \\vert^p \\right)^{1/p}.
|
|
312
|
+
|
|
313
|
+
Examples
|
|
314
|
+
--------
|
|
315
|
+
|
|
316
|
+
.. code-block:: python
|
|
317
|
+
:emphasize-lines: 6
|
|
318
|
+
|
|
319
|
+
>>> from freealg import norm
|
|
320
|
+
>>> from freealg.distributions import MarchenkoPastur
|
|
321
|
+
|
|
322
|
+
>>> mp = MarchenkoPastur(1/50)
|
|
323
|
+
>>> A = mp.matrix(3000)
|
|
324
|
+
>>> norm(A, 100_000, order='fro')
|
|
325
|
+
"""
|
|
326
|
+
|
|
327
|
+
eigs = eigvalsh(A, size=size, seed=seed, **kwargs)
|
|
328
|
+
|
|
329
|
+
# Check order type and convert to float
|
|
330
|
+
if order == 'nuc':
|
|
331
|
+
order = 1
|
|
332
|
+
elif order == 'fro':
|
|
333
|
+
order = 2
|
|
334
|
+
elif order == 'inf':
|
|
335
|
+
order = float('inf')
|
|
336
|
+
elif order == '-inf':
|
|
337
|
+
order = -float('inf')
|
|
338
|
+
elif not isinstance(order,
|
|
339
|
+
(int, float, numpy.integer, numpy.floating)) \
|
|
340
|
+
and not isinstance(order, (bool, numpy.bool_)):
|
|
341
|
+
raise ValueError('"order" is invalid.')
|
|
342
|
+
|
|
343
|
+
# Compute norm
|
|
344
|
+
if numpy.isinf(order) and not numpy.isneginf(order):
|
|
345
|
+
norm_ = max(numpy.abs(eigs))
|
|
346
|
+
|
|
347
|
+
elif numpy.isneginf(order):
|
|
348
|
+
norm_ = min(numpy.abs(eigs))
|
|
349
|
+
|
|
350
|
+
elif isinstance(order, (int, float, numpy.integer, numpy.floating)) \
|
|
351
|
+
and not isinstance(order, (bool, numpy.bool_)):
|
|
352
|
+
norm_q = numpy.sum(numpy.abs(eigs)**order)
|
|
353
|
+
norm_ = norm_q**(1.0 / order)
|
|
354
|
+
|
|
355
|
+
return norm_
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
# =====
|
|
359
|
+
# trace
|
|
360
|
+
# =====
|
|
361
|
+
|
|
362
|
+
def trace(A, N=None, p=1.0, seed=None, **kwargs):
|
|
363
|
+
"""
|
|
364
|
+
Estimate the trace of a power of a Hermitian matrix.
|
|
365
|
+
|
|
366
|
+
This function estimates the trace of the matrix power :math:`\\mathbf{A}^p`
|
|
367
|
+
or that of a larger matrix containing :math:`\\mathbf{A}`.
|
|
368
|
+
|
|
369
|
+
Parameters
|
|
370
|
+
----------
|
|
371
|
+
|
|
372
|
+
A : numpy.ndarray
|
|
373
|
+
The symmetric real-valued matrix :math:`\\mathbf{A}` whose trace of
|
|
374
|
+
a power (or that of a matrix containing :math:`\\mathbf{A}`) is to be
|
|
375
|
+
computed.
|
|
376
|
+
|
|
377
|
+
size : int, default=None
|
|
378
|
+
The size of the matrix containing :math:`\\mathbf{A}` to estimate
|
|
379
|
+
eigenvalues of. If None, returns estimates of the eigenvalues of
|
|
380
|
+
:math:`\\mathbf{A}` itself.
|
|
381
|
+
|
|
382
|
+
p : float, default=1.0
|
|
383
|
+
The exponent :math:`p` in :math:`\\mathbf{A}^p`.
|
|
384
|
+
|
|
385
|
+
seed : int, default=None
|
|
386
|
+
The seed for the Quasi-Monte Carlo sampler.
|
|
387
|
+
|
|
388
|
+
**kwargs : dict, optional
|
|
389
|
+
Pass additional options to the underlying
|
|
390
|
+
:func:`FreeForm.decompress` function.
|
|
391
|
+
|
|
392
|
+
Returns
|
|
393
|
+
-------
|
|
394
|
+
|
|
395
|
+
trace : float
|
|
396
|
+
matrix trace
|
|
397
|
+
|
|
398
|
+
See Also
|
|
399
|
+
--------
|
|
400
|
+
|
|
401
|
+
eigvalsh
|
|
402
|
+
cond
|
|
403
|
+
slogdet
|
|
404
|
+
norm
|
|
405
|
+
|
|
406
|
+
Notes
|
|
407
|
+
-----
|
|
408
|
+
|
|
409
|
+
The trace is highly amenable to subsampling: under free decompression
|
|
410
|
+
the average eigenvalue is assumed constant, so the trace increases
|
|
411
|
+
linearly. Traces of powers fall back to :func:`freealg.eigvalsh`.
|
|
412
|
+
|
|
413
|
+
Examples
|
|
414
|
+
--------
|
|
415
|
+
|
|
416
|
+
.. code-block:: python
|
|
417
|
+
:emphasize-lines: 6
|
|
418
|
+
|
|
419
|
+
>>> from freealg import norm
|
|
420
|
+
>>> from freealg.distributions import MarchenkoPastur
|
|
421
|
+
|
|
422
|
+
>>> mp = MarchenkoPastur(1/50)
|
|
423
|
+
>>> A = mp.matrix(3000)
|
|
424
|
+
>>> trace(A, 100_000)
|
|
425
|
+
"""
|
|
426
|
+
|
|
427
|
+
if numpy.isclose(p, 1.0):
|
|
428
|
+
samples, n, n_s = _subsample_apply(numpy.trace, A, output_array=False)
|
|
429
|
+
if N is None:
|
|
430
|
+
size = n
|
|
431
|
+
return numpy.mean(samples) * (size / n_s)
|
|
432
|
+
|
|
433
|
+
eig = eigvalsh(A, size=size, seed=seed, **kwargs)
|
|
434
|
+
return numpy.sum(eig ** p)
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
# =======
|
|
438
|
+
# slogdet
|
|
439
|
+
# =======
|
|
440
|
+
|
|
441
|
+
def slogdet(A, size=None, seed=None, **kwargs):
|
|
442
|
+
"""
|
|
443
|
+
Estimate the sign and logarithm of the determinant of a Hermitian matrix.
|
|
444
|
+
|
|
445
|
+
This function estimates the *slogdet* of the matrix :math:`\\mathbf{A}` or
|
|
446
|
+
a larger matrix containing :math:`\\mathbf{A}` using free decompression.
|
|
447
|
+
|
|
448
|
+
Parameters
|
|
449
|
+
----------
|
|
450
|
+
|
|
451
|
+
A : numpy.ndarray
|
|
452
|
+
The symmetric real-valued matrix :math:`\\mathbf{A}` whose condition
|
|
453
|
+
number (or that of a matrix containing :math:`\\mathbf{A}`) are to be
|
|
454
|
+
computed.
|
|
455
|
+
|
|
456
|
+
size : int, default=None
|
|
457
|
+
The size of the matrix containing :math:`\\mathbf{A}` to estimate
|
|
458
|
+
eigenvalues of. If None, returns estimates of the eigenvalues of
|
|
459
|
+
:math:`\\mathbf{A}` itself.
|
|
460
|
+
|
|
461
|
+
seed : int, default=None
|
|
462
|
+
The seed for the Quasi-Monte Carlo sampler.
|
|
463
|
+
|
|
464
|
+
**kwargs : dict, optional
|
|
465
|
+
Pass additional options to the underlying
|
|
466
|
+
:func:`FreeForm.decompress` function.
|
|
467
|
+
|
|
468
|
+
Returns
|
|
469
|
+
-------
|
|
470
|
+
|
|
471
|
+
sign : float
|
|
472
|
+
Sign of determinant
|
|
473
|
+
|
|
474
|
+
ld : float
|
|
475
|
+
natural logarithm of the absolute value of the determinant
|
|
476
|
+
|
|
477
|
+
See Also
|
|
478
|
+
--------
|
|
479
|
+
|
|
480
|
+
eigvalsh
|
|
481
|
+
cond
|
|
482
|
+
trace
|
|
483
|
+
norm
|
|
484
|
+
|
|
485
|
+
Notes
|
|
486
|
+
-----
|
|
487
|
+
|
|
488
|
+
This is a convenience function using :func:`freealg.eigvalsh`.
|
|
489
|
+
|
|
490
|
+
Examples
|
|
491
|
+
--------
|
|
492
|
+
|
|
493
|
+
.. code-block:: python
|
|
494
|
+
:emphasize-lines: 6
|
|
495
|
+
|
|
496
|
+
>>> from freealg import norm
|
|
497
|
+
>>> from freealg.distributions import MarchenkoPastur
|
|
498
|
+
|
|
499
|
+
>>> mp = MarchenkoPastur(1/50)
|
|
500
|
+
>>> A = mp.matrix(3000)
|
|
501
|
+
>>> sign, ld = slogdet(A, 100_000)
|
|
502
|
+
"""
|
|
503
|
+
|
|
504
|
+
eigs = eigvalsh(A, size=size, seed=seed, **kwargs)
|
|
505
|
+
sign = numpy.prod(numpy.sign(eigs))
|
|
506
|
+
ld = numpy.sum(numpy.log(numpy.abs(eigs)))
|
|
507
|
+
|
|
508
|
+
return sign, ld
|