freealg 0.2.0__tar.gz → 0.3.1__tar.gz
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-0.2.0 → freealg-0.3.1}/PKG-INFO +4 -3
- {freealg-0.2.0 → freealg-0.3.1}/README.rst +2 -1
- {freealg-0.2.0 → freealg-0.3.1}/freealg/__init__.py +3 -2
- freealg-0.3.1/freealg/__version__.py +1 -0
- {freealg-0.2.0 → freealg-0.3.1}/freealg/_support.py +4 -2
- freealg-0.3.1/freealg/eigh.py +426 -0
- {freealg-0.2.0 → freealg-0.3.1}/freealg/freeform.py +4 -3
- {freealg-0.2.0 → freealg-0.3.1}/freealg.egg-info/PKG-INFO +4 -3
- {freealg-0.2.0 → freealg-0.3.1}/setup.py +1 -1
- freealg-0.2.0/freealg/__version__.py +0 -1
- freealg-0.2.0/freealg/eigh.py +0 -194
- {freealg-0.2.0 → freealg-0.3.1}/AUTHORS.txt +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/CHANGELOG.rst +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/LICENSE.txt +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/MANIFEST.in +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/freealg/_chebyshev.py +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/freealg/_damp.py +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/freealg/_decompress.py +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/freealg/_jacobi.py +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/freealg/_pade.py +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/freealg/_plot_util.py +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/freealg/_sample.py +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/freealg/_util.py +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/freealg/distributions/__init__.py +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/freealg/distributions/_kesten_mckay.py +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/freealg/distributions/_marchenko_pastur.py +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/freealg/distributions/_meixner.py +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/freealg/distributions/_wachter.py +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/freealg/distributions/_wigner.py +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/freealg.egg-info/SOURCES.txt +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/freealg.egg-info/dependency_links.txt +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/freealg.egg-info/not-zip-safe +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/freealg.egg-info/requires.txt +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/freealg.egg-info/top_level.txt +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/pyproject.toml +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/requirements.txt +0 -0
- {freealg-0.2.0 → freealg-0.3.1}/setup.cfg +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: freealg
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Free probability for large matrices
|
|
5
|
-
Keywords:
|
|
5
|
+
Keywords: linalg,free-probability
|
|
6
6
|
Platform: Linux
|
|
7
7
|
Platform: OSX
|
|
8
8
|
Platform: Windows
|
|
@@ -72,7 +72,8 @@ Dynamic: summary
|
|
|
72
72
|
|
|
73
73
|
`Paper <https://arxiv.org/abs/2506.11994>`__ |
|
|
74
74
|
`Slides <https://www.dropbox.com/scl/fi/03gjuyz17k9yhsqy0isoz/free_decomporession_slides.pdf?rlkey=8f82mhciyl2ju02l7hv1md5li&st=26xmhjga&dl=0>`__ |
|
|
75
|
-
`Docs <https://ameli.github.io/freealg>`__
|
|
75
|
+
`Docs <https://ameli.github.io/freealg>`__ |
|
|
76
|
+
`Live Demo <https://ameli.github.io/freealg/jlite/lab/index.html?path=quick_start.ipynb>`__
|
|
76
77
|
|
|
77
78
|
.. `Slides <https://ameli.github.io/freealg/_static/data/slides.pdf>`__ |
|
|
78
79
|
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
`Paper <https://arxiv.org/abs/2506.11994>`__ |
|
|
7
7
|
`Slides <https://www.dropbox.com/scl/fi/03gjuyz17k9yhsqy0isoz/free_decomporession_slides.pdf?rlkey=8f82mhciyl2ju02l7hv1md5li&st=26xmhjga&dl=0>`__ |
|
|
8
|
-
`Docs <https://ameli.github.io/freealg>`__
|
|
8
|
+
`Docs <https://ameli.github.io/freealg>`__ |
|
|
9
|
+
`Live Demo <https://ameli.github.io/freealg/jlite/lab/index.html?path=quick_start.ipynb>`__
|
|
9
10
|
|
|
10
11
|
.. `Slides <https://ameli.github.io/freealg/_static/data/slides.pdf>`__ |
|
|
11
12
|
|
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
# directory of this source tree.
|
|
8
8
|
|
|
9
9
|
from .freeform import FreeForm
|
|
10
|
-
from .eigh import eigh, cond
|
|
10
|
+
from .eigh import eigh, cond, norm, trace, slogdet
|
|
11
11
|
from . import distributions
|
|
12
12
|
|
|
13
|
-
__all__ = ['FreeForm', 'distributions', 'eigh', 'cond'
|
|
13
|
+
__all__ = ['FreeForm', 'distributions', 'eigh', 'cond', 'norm', 'trace',
|
|
14
|
+
'slogdet']
|
|
14
15
|
|
|
15
16
|
from .__version__ import __version__ # noqa: F401 E402
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.3.1"
|
|
@@ -127,7 +127,7 @@ def detect_support(eigs, method='asymp', k=None, p=0.001, **kwargs):
|
|
|
127
127
|
* ``'interior'``: estimates a support assuming the range overestimates;
|
|
128
128
|
uses quantiles (p, 1-p).
|
|
129
129
|
* ``'interior_smooth'``: same as ``'interior'`` but using kernel
|
|
130
|
-
density estimation.
|
|
130
|
+
density estimation, from [2].
|
|
131
131
|
|
|
132
132
|
k : int, default = None
|
|
133
133
|
Number of extreme order statistics to use for ``method='regression'``.
|
|
@@ -142,10 +142,12 @@ def detect_support(eigs, method='asymp', k=None, p=0.001, **kwargs):
|
|
|
142
142
|
References
|
|
143
143
|
----------
|
|
144
144
|
|
|
145
|
-
.. [1] Quenouille, M. H. (1949
|
|
145
|
+
.. [1] Quenouille, M. H. (1949). Approximate tests of correlation in
|
|
146
146
|
time-series. In Mathematical Proceedings of the Cambridge
|
|
147
147
|
Philosophical Society (Vol. 45, No. 3, pp. 483-484). Cambridge
|
|
148
148
|
University Press.
|
|
149
|
+
.. [2] Cuevas, A., & Fraiman, R. (1997). A plug-in approach to support
|
|
150
|
+
estimation. The Annals of Statistics, 2300-2312.
|
|
149
151
|
"""
|
|
150
152
|
|
|
151
153
|
if method == 'range':
|
|
@@ -0,0 +1,426 @@
|
|
|
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 .freeform import FreeForm
|
|
16
|
+
|
|
17
|
+
__all__ = ['eigh', 'cond', 'norm', 'trace', 'slogdet']
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# ====
|
|
21
|
+
# eigh
|
|
22
|
+
# ====
|
|
23
|
+
|
|
24
|
+
def eigh(A, N=None, psd=None, plots=False):
|
|
25
|
+
"""
|
|
26
|
+
Estimate the eigenvalues of a matrix.
|
|
27
|
+
|
|
28
|
+
This function estimates the eigenvalues of the matrix :math:`\\mathbf{A}`
|
|
29
|
+
or a larger matrix containing :math:`\\mathbf{A}` using free decompression.
|
|
30
|
+
|
|
31
|
+
Parameters
|
|
32
|
+
----------
|
|
33
|
+
|
|
34
|
+
A : numpy.ndarray
|
|
35
|
+
The symmetric real-valued matrix :math:`\\mathbf{A}` whose eigenvalues
|
|
36
|
+
(or those of a matrix containing :math:`\\mathbf{A}`) are to be
|
|
37
|
+
computed.
|
|
38
|
+
|
|
39
|
+
N : int, default=None
|
|
40
|
+
The size of the matrix containing :math:`\\mathbf{A}` to estimate
|
|
41
|
+
eigenvalues of. If None, returns estimates of the eigenvalues of
|
|
42
|
+
:math:`\\mathbf{A}` itself.
|
|
43
|
+
|
|
44
|
+
psd : bool, default=None
|
|
45
|
+
Determines whether the matrix is positive-semidefinite (PSD; all
|
|
46
|
+
eigenvalues are non-negative). If `None`, the matrix is considered PSD
|
|
47
|
+
if all sampled eigenvalues are positive.
|
|
48
|
+
|
|
49
|
+
plots : bool, default=False
|
|
50
|
+
Print out all relevant plots for diagnosing eigenvalue accuracy.
|
|
51
|
+
|
|
52
|
+
Returns
|
|
53
|
+
-------
|
|
54
|
+
|
|
55
|
+
eigs : numpy.array
|
|
56
|
+
Eigenvalues of decompressed matrix
|
|
57
|
+
|
|
58
|
+
See Also
|
|
59
|
+
--------
|
|
60
|
+
|
|
61
|
+
cond
|
|
62
|
+
|
|
63
|
+
Notes
|
|
64
|
+
-----
|
|
65
|
+
|
|
66
|
+
This is a convenience function for the :class:`freealg.FreeForm` class with
|
|
67
|
+
some effective defaults that work well for common random matrix ensembles.
|
|
68
|
+
For improved performance and plotting utilites, consider fine-tuning
|
|
69
|
+
parameters using the FreeForm class.
|
|
70
|
+
|
|
71
|
+
References
|
|
72
|
+
----------
|
|
73
|
+
|
|
74
|
+
.. [1] Reference.
|
|
75
|
+
|
|
76
|
+
Examples
|
|
77
|
+
--------
|
|
78
|
+
|
|
79
|
+
.. code-block:: python
|
|
80
|
+
:emphasize-lines: 6
|
|
81
|
+
|
|
82
|
+
>>> from freealg import cond
|
|
83
|
+
>>> from freealg.distributions import MarchenkoPastur
|
|
84
|
+
|
|
85
|
+
>>> mp = MarchenkoPastur(1/50)
|
|
86
|
+
>>> A = mp.matrix(3000)
|
|
87
|
+
>>> eigs = eigh(A)
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
if A.ndim != 2 or A.shape[0] != A.shape[1]:
|
|
91
|
+
raise RuntimeError("Only square matrices are permitted.")
|
|
92
|
+
n = A.shape[0]
|
|
93
|
+
|
|
94
|
+
if N is None:
|
|
95
|
+
N = n
|
|
96
|
+
|
|
97
|
+
# Size of sample matrix
|
|
98
|
+
n_s = int(80*(1 + numpy.log(n)))
|
|
99
|
+
# If matrix is not large enough, return eigenvalues
|
|
100
|
+
if n < n_s:
|
|
101
|
+
return compute_eig(A)
|
|
102
|
+
# Number of samples
|
|
103
|
+
num_samples = int(10 * (n / n_s)**0.5)
|
|
104
|
+
|
|
105
|
+
# Collect eigenvalue samples
|
|
106
|
+
samples = []
|
|
107
|
+
for _ in range(num_samples):
|
|
108
|
+
indices = numpy.random.choice(n, n_s, replace=False)
|
|
109
|
+
samples.append(compute_eig(A[numpy.ix_(indices, indices)]))
|
|
110
|
+
samples = numpy.concatenate(samples).ravel()
|
|
111
|
+
|
|
112
|
+
# If all eigenvalues are positive, set PSD flag
|
|
113
|
+
if psd is None:
|
|
114
|
+
psd = samples.min() > 0
|
|
115
|
+
|
|
116
|
+
ff = FreeForm(samples)
|
|
117
|
+
# Since we are resampling, we need to provide the correct matrix size
|
|
118
|
+
ff.n = n_s
|
|
119
|
+
|
|
120
|
+
# Perform fit and estimate eigenvalues
|
|
121
|
+
order = 1 + int(len(samples)**.2)
|
|
122
|
+
ff.fit(method='chebyshev', K=order, projection='sample',
|
|
123
|
+
force=True, plot=False, latex=False, save=False)
|
|
124
|
+
|
|
125
|
+
if plots:
|
|
126
|
+
ff.density(plot=True)
|
|
127
|
+
ff.stieltjes(plot=True)
|
|
128
|
+
|
|
129
|
+
_, _, eigs = ff.decompress(N, plot=plots)
|
|
130
|
+
|
|
131
|
+
if psd:
|
|
132
|
+
eigs = numpy.abs(eigs)
|
|
133
|
+
eigs.sort()
|
|
134
|
+
|
|
135
|
+
return eigs
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
# ====
|
|
139
|
+
# cond
|
|
140
|
+
# ====
|
|
141
|
+
|
|
142
|
+
def cond(A, N=None):
|
|
143
|
+
"""
|
|
144
|
+
Estimate the condition number of a Hermitian positive-definite matrix.
|
|
145
|
+
|
|
146
|
+
This function estimates the condition number of the matrix
|
|
147
|
+
:math:`\\mathbf{A}` or a larger matrix containing :math:`\\mathbf{A}`
|
|
148
|
+
using free decompression.
|
|
149
|
+
|
|
150
|
+
Parameters
|
|
151
|
+
----------
|
|
152
|
+
|
|
153
|
+
A : numpy.ndarray
|
|
154
|
+
The symmetric real-valued matrix :math:`\\mathbf{A}` whose condition
|
|
155
|
+
number (or that of a matrix containing :math:`\\mathbf{A}`) are to be
|
|
156
|
+
computed.
|
|
157
|
+
|
|
158
|
+
N : int, default=None
|
|
159
|
+
The size of the matrix containing :math:`\\mathbf{A}` to estimate
|
|
160
|
+
eigenvalues of. If None, returns estimates of the eigenvalues of
|
|
161
|
+
:math:`\\mathbf{A}` itself.
|
|
162
|
+
|
|
163
|
+
Returns
|
|
164
|
+
-------
|
|
165
|
+
|
|
166
|
+
c : float
|
|
167
|
+
Condition number
|
|
168
|
+
|
|
169
|
+
See Also
|
|
170
|
+
--------
|
|
171
|
+
|
|
172
|
+
eigh
|
|
173
|
+
norm
|
|
174
|
+
slogdet
|
|
175
|
+
trace
|
|
176
|
+
|
|
177
|
+
Notes
|
|
178
|
+
-----
|
|
179
|
+
|
|
180
|
+
This is a convenience function using :func:`freealg.eigh`.
|
|
181
|
+
|
|
182
|
+
Examples
|
|
183
|
+
--------
|
|
184
|
+
|
|
185
|
+
.. code-block:: python
|
|
186
|
+
:emphasize-lines: 6
|
|
187
|
+
|
|
188
|
+
>>> from freealg import cond
|
|
189
|
+
>>> from freealg.distributions import MarchenkoPastur
|
|
190
|
+
|
|
191
|
+
>>> mp = MarchenkoPastur(1/50)
|
|
192
|
+
>>> A = mp.matrix(3000)
|
|
193
|
+
>>> cond(A)
|
|
194
|
+
"""
|
|
195
|
+
|
|
196
|
+
eigs = eigh(A, N, psd=True)
|
|
197
|
+
return eigs.max() / eigs.min()
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
# ====
|
|
201
|
+
# norm
|
|
202
|
+
# ====
|
|
203
|
+
|
|
204
|
+
def norm(A, N=None, order=None):
|
|
205
|
+
"""
|
|
206
|
+
Estimate the Schatten norm of a Hermitian matrix.
|
|
207
|
+
|
|
208
|
+
This function estimates the norm of the matrix :math:`\\mathbf{A}` or a
|
|
209
|
+
larger matrix containing :math:`\\mathbf{A}` using free decompression.
|
|
210
|
+
|
|
211
|
+
Parameters
|
|
212
|
+
----------
|
|
213
|
+
|
|
214
|
+
A : numpy.ndarray
|
|
215
|
+
The symmetric real-valued matrix :math:`\\mathbf{A}` whose condition
|
|
216
|
+
number (or that of a matrix containing :math:`\\mathbf{A}`) are to be
|
|
217
|
+
computed.
|
|
218
|
+
|
|
219
|
+
N : int, default=None
|
|
220
|
+
The size of the matrix containing :math:`\\mathbf{A}` to estimate
|
|
221
|
+
eigenvalues of. If None, returns estimates of the eigenvalues of
|
|
222
|
+
:math:`\\mathbf{A}` itself.
|
|
223
|
+
|
|
224
|
+
order : {float, ``''inf``, ``'-inf'``, ``'fro'``, ``'nuc'``}, default=2
|
|
225
|
+
Order of the norm.
|
|
226
|
+
|
|
227
|
+
* float :math:`p`: Schtten p-norm.
|
|
228
|
+
* ``'inf'``: Largest absolute eigenvalue
|
|
229
|
+
:math:`\\max \\vert \\lambda_i \\vert)`
|
|
230
|
+
* ``'-inf'``: Smallest absolute eigenvalue
|
|
231
|
+
:math:`\\min \\vert \\lambda_i \\vert)`
|
|
232
|
+
* ``'fro'``: Frobenius norm corresponding to :math:`p=2`
|
|
233
|
+
* ``'nuc'``: Nuclear (or trace) norm corresponding to :math:`p=1`
|
|
234
|
+
|
|
235
|
+
Returns
|
|
236
|
+
-------
|
|
237
|
+
|
|
238
|
+
norm : float
|
|
239
|
+
matrix norm
|
|
240
|
+
|
|
241
|
+
See Also
|
|
242
|
+
--------
|
|
243
|
+
|
|
244
|
+
eigh
|
|
245
|
+
cond
|
|
246
|
+
slogdet
|
|
247
|
+
trace
|
|
248
|
+
|
|
249
|
+
Notes
|
|
250
|
+
-----
|
|
251
|
+
|
|
252
|
+
Thes Schatten :math:`p`-norm is defined by
|
|
253
|
+
|
|
254
|
+
.. math::
|
|
255
|
+
|
|
256
|
+
\\Vert \\mathbf{A} \\Vert_p = \\left(
|
|
257
|
+
\\sum_{i=1}^N \\vert \\lambda_i \\vert^p \\right)^{1/p}.
|
|
258
|
+
|
|
259
|
+
Examples
|
|
260
|
+
--------
|
|
261
|
+
|
|
262
|
+
.. code-block:: python
|
|
263
|
+
:emphasize-lines: 6
|
|
264
|
+
|
|
265
|
+
>>> from freealg import norm
|
|
266
|
+
>>> from freealg.distributions import MarchenkoPastur
|
|
267
|
+
|
|
268
|
+
>>> mp = MarchenkoPastur(1/50)
|
|
269
|
+
>>> A = mp.matrix(3000)
|
|
270
|
+
>>> norm(A, 100_000, order='fro')
|
|
271
|
+
"""
|
|
272
|
+
|
|
273
|
+
eigs = eigh(A, N)
|
|
274
|
+
|
|
275
|
+
if (order == 'inf') or numpy.isinf(order):
|
|
276
|
+
norm_ = max(numpy.abs(eigs))
|
|
277
|
+
|
|
278
|
+
elif (order == '-inf') or numpy.isneginf(order):
|
|
279
|
+
norm_ = min(numpy.abs(eigs))
|
|
280
|
+
|
|
281
|
+
elif (order == 'nuc') or (order == 1.0):
|
|
282
|
+
norm_ = numpy.sum(numpy.abs(eigs))
|
|
283
|
+
|
|
284
|
+
elif (order == 'fro') or (order == 2.0):
|
|
285
|
+
norm_2 = numpy.sum(numpy.abs(eigs)**2)
|
|
286
|
+
norm_ = numpy.sqrt(norm_2)
|
|
287
|
+
|
|
288
|
+
elif isinstance(order, (int, float, numpy.integer, numpy.floating)) and \
|
|
289
|
+
not isinstance(order, (bool, numpy.bool_)):
|
|
290
|
+
norm_q = numpy.sum(numpy.abs(eigs)**order)
|
|
291
|
+
norm_ = norm_q**(1.0 / order)
|
|
292
|
+
|
|
293
|
+
else:
|
|
294
|
+
raise ValueError('"order" is invalid.')
|
|
295
|
+
|
|
296
|
+
return norm_
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
# =====
|
|
300
|
+
# trace
|
|
301
|
+
# =====
|
|
302
|
+
|
|
303
|
+
def trace(A, N=None):
|
|
304
|
+
"""
|
|
305
|
+
Estimate the trace of a Hermitian matrix.
|
|
306
|
+
|
|
307
|
+
This function estimates the trace of the matrix :math:`\\mathbf{A}` or a
|
|
308
|
+
larger matrix containing :math:`\\mathbf{A}` using free decompression.
|
|
309
|
+
|
|
310
|
+
Parameters
|
|
311
|
+
----------
|
|
312
|
+
|
|
313
|
+
A : numpy.ndarray
|
|
314
|
+
The symmetric real-valued matrix :math:`\\mathbf{A}` whose condition
|
|
315
|
+
number (or that of a matrix containing :math:`\\mathbf{A}`) are to be
|
|
316
|
+
computed.
|
|
317
|
+
|
|
318
|
+
N : int, default=None
|
|
319
|
+
The size of the matrix containing :math:`\\mathbf{A}` to estimate
|
|
320
|
+
eigenvalues of. If None, returns estimates of the eigenvalues of
|
|
321
|
+
:math:`\\mathbf{A}` itself.
|
|
322
|
+
|
|
323
|
+
Returns
|
|
324
|
+
-------
|
|
325
|
+
|
|
326
|
+
trace : float
|
|
327
|
+
matrix trace
|
|
328
|
+
|
|
329
|
+
See Also
|
|
330
|
+
--------
|
|
331
|
+
|
|
332
|
+
eigh
|
|
333
|
+
cond
|
|
334
|
+
slogdet
|
|
335
|
+
norm
|
|
336
|
+
|
|
337
|
+
Notes
|
|
338
|
+
-----
|
|
339
|
+
|
|
340
|
+
This is a convenience function using :func:`freealg.eigh`.
|
|
341
|
+
|
|
342
|
+
Examples
|
|
343
|
+
--------
|
|
344
|
+
|
|
345
|
+
.. code-block:: python
|
|
346
|
+
:emphasize-lines: 6
|
|
347
|
+
|
|
348
|
+
>>> from freealg import norm
|
|
349
|
+
>>> from freealg.distributions import MarchenkoPastur
|
|
350
|
+
|
|
351
|
+
>>> mp = MarchenkoPastur(1/50)
|
|
352
|
+
>>> A = mp.matrix(3000)
|
|
353
|
+
>>> trace(A, 100_000)
|
|
354
|
+
"""
|
|
355
|
+
|
|
356
|
+
eigs = eigh(A, N)
|
|
357
|
+
trace_ = numpy.sum(eigs)
|
|
358
|
+
|
|
359
|
+
return trace_
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
# =======
|
|
363
|
+
# slogdet
|
|
364
|
+
# =======
|
|
365
|
+
|
|
366
|
+
def slogdet(A, N=None):
|
|
367
|
+
"""
|
|
368
|
+
Estimate the sign and logarithm of the determinant of a Hermitian matrix.
|
|
369
|
+
|
|
370
|
+
This function estimates the *slogdet* of the matrix :math:`\\mathbf{A}` or
|
|
371
|
+
a larger matrix containing :math:`\\mathbf{A}` using free decompression.
|
|
372
|
+
|
|
373
|
+
Parameters
|
|
374
|
+
----------
|
|
375
|
+
|
|
376
|
+
A : numpy.ndarray
|
|
377
|
+
The symmetric real-valued matrix :math:`\\mathbf{A}` whose condition
|
|
378
|
+
number (or that of a matrix containing :math:`\\mathbf{A}`) are to be
|
|
379
|
+
computed.
|
|
380
|
+
|
|
381
|
+
N : int, default=None
|
|
382
|
+
The size of the matrix containing :math:`\\mathbf{A}` to estimate
|
|
383
|
+
eigenvalues of. If None, returns estimates of the eigenvalues of
|
|
384
|
+
:math:`\\mathbf{A}` itself.
|
|
385
|
+
|
|
386
|
+
Returns
|
|
387
|
+
-------
|
|
388
|
+
|
|
389
|
+
sign : float
|
|
390
|
+
Sign of determinant
|
|
391
|
+
|
|
392
|
+
ld : float
|
|
393
|
+
natural logarithm of the absolute value of the determinant
|
|
394
|
+
|
|
395
|
+
See Also
|
|
396
|
+
--------
|
|
397
|
+
|
|
398
|
+
eigh
|
|
399
|
+
cond
|
|
400
|
+
trace
|
|
401
|
+
norm
|
|
402
|
+
|
|
403
|
+
Notes
|
|
404
|
+
-----
|
|
405
|
+
|
|
406
|
+
This is a convenience function using :func:`freealg.eigh`.
|
|
407
|
+
|
|
408
|
+
Examples
|
|
409
|
+
--------
|
|
410
|
+
|
|
411
|
+
.. code-block:: python
|
|
412
|
+
:emphasize-lines: 6
|
|
413
|
+
|
|
414
|
+
>>> from freealg import norm
|
|
415
|
+
>>> from freealg.distributions import MarchenkoPastur
|
|
416
|
+
|
|
417
|
+
>>> mp = MarchenkoPastur(1/50)
|
|
418
|
+
>>> A = mp.matrix(3000)
|
|
419
|
+
>>> sign, ld = slogdet(A, 100_000)
|
|
420
|
+
"""
|
|
421
|
+
|
|
422
|
+
eigs = eigh(A, N)
|
|
423
|
+
sign = numpy.prod(numpy.sign(eigs))
|
|
424
|
+
ld = numpy.sum(numpy.log(numpy.abs(eigs)))
|
|
425
|
+
|
|
426
|
+
return sign, ld
|
|
@@ -59,13 +59,14 @@ class FreeForm(object):
|
|
|
59
59
|
Size of perturbations into the upper half plane for Plemelj's
|
|
60
60
|
formula.
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
**kwargs : dict, optional
|
|
63
|
+
Parameters for the ``detect_support`` function can also be prescribed
|
|
64
|
+
here when ``support=None``.
|
|
64
65
|
|
|
65
66
|
Notes
|
|
66
67
|
-----
|
|
67
68
|
|
|
68
|
-
|
|
69
|
+
TBD
|
|
69
70
|
|
|
70
71
|
References
|
|
71
72
|
----------
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: freealg
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Free probability for large matrices
|
|
5
|
-
Keywords:
|
|
5
|
+
Keywords: linalg,free-probability
|
|
6
6
|
Platform: Linux
|
|
7
7
|
Platform: OSX
|
|
8
8
|
Platform: Windows
|
|
@@ -72,7 +72,8 @@ Dynamic: summary
|
|
|
72
72
|
|
|
73
73
|
`Paper <https://arxiv.org/abs/2506.11994>`__ |
|
|
74
74
|
`Slides <https://www.dropbox.com/scl/fi/03gjuyz17k9yhsqy0isoz/free_decomporession_slides.pdf?rlkey=8f82mhciyl2ju02l7hv1md5li&st=26xmhjga&dl=0>`__ |
|
|
75
|
-
`Docs <https://ameli.github.io/freealg>`__
|
|
75
|
+
`Docs <https://ameli.github.io/freealg>`__ |
|
|
76
|
+
`Live Demo <https://ameli.github.io/freealg/jlite/lab/index.html?path=quick_start.ipynb>`__
|
|
76
77
|
|
|
77
78
|
.. `Slides <https://ameli.github.io/freealg/_static/data/slides.pdf>`__ |
|
|
78
79
|
|
|
@@ -165,7 +165,7 @@ def main(argv):
|
|
|
165
165
|
description=description,
|
|
166
166
|
long_description=long_description,
|
|
167
167
|
long_description_content_type='text/x-rst',
|
|
168
|
-
keywords="""
|
|
168
|
+
keywords="""linalg, free-probability""",
|
|
169
169
|
platforms=['Linux', 'OSX', 'Windows'],
|
|
170
170
|
packages=setuptools.find_packages(exclude=[
|
|
171
171
|
'tests.*',
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.2.0"
|
freealg-0.2.0/freealg/eigh.py
DELETED
|
@@ -1,194 +0,0 @@
|
|
|
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 .freeform import FreeForm
|
|
16
|
-
|
|
17
|
-
__all__ = ['eigh', 'cond']
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
# ====
|
|
21
|
-
# eigh
|
|
22
|
-
# ====
|
|
23
|
-
|
|
24
|
-
def eigh(A, N=None, psd=None, plots=False):
|
|
25
|
-
"""
|
|
26
|
-
Estimate the eigenvalues of a matrix.
|
|
27
|
-
|
|
28
|
-
This function estimates the eigenvalues of the matrix :math:`\\mathbf{A}`
|
|
29
|
-
or a larger matrix containing :math:`\\mathbf{A}` using free decompression.
|
|
30
|
-
|
|
31
|
-
Parameters
|
|
32
|
-
----------
|
|
33
|
-
|
|
34
|
-
A : numpy.ndarray
|
|
35
|
-
The symmetric real-valued matrix :math:`\\mathbf{A}` whose eigenvalues
|
|
36
|
-
(or those of a matrix containing :math:`\\mathbf{A}`) are to be
|
|
37
|
-
computed.
|
|
38
|
-
|
|
39
|
-
N : int, default=None
|
|
40
|
-
The size of the matrix containing :math:`\\mathbf{A}` to estimate
|
|
41
|
-
eigenvalues of. If None, returns estimates of the eigenvalues of
|
|
42
|
-
:math:`\\mathbf{A}` itself.
|
|
43
|
-
|
|
44
|
-
psd : bool, default=None
|
|
45
|
-
Determines whether the matrix is positive-semidefinite (PSD; all
|
|
46
|
-
eigenvalues are non-negative). If `None`, the matrix is considered PSD
|
|
47
|
-
if all sampled eigenvalues are positive.
|
|
48
|
-
|
|
49
|
-
plots : bool, default=False
|
|
50
|
-
Print out all relevant plots for diagnosing eigenvalue accuracy.
|
|
51
|
-
|
|
52
|
-
Returns
|
|
53
|
-
-------
|
|
54
|
-
|
|
55
|
-
eigs : numpy.array
|
|
56
|
-
Eigenvalues of decompressed matrix
|
|
57
|
-
|
|
58
|
-
See Also
|
|
59
|
-
--------
|
|
60
|
-
|
|
61
|
-
cond
|
|
62
|
-
|
|
63
|
-
Notes
|
|
64
|
-
-----
|
|
65
|
-
|
|
66
|
-
This is a convenience function for the :class:`freealg.FreeForm` class with
|
|
67
|
-
some effective defaults that work well for common random matrix ensembles.
|
|
68
|
-
For improved performance and plotting utilites, consider fine-tuning
|
|
69
|
-
parameters using the FreeForm class.
|
|
70
|
-
|
|
71
|
-
References
|
|
72
|
-
----------
|
|
73
|
-
|
|
74
|
-
.. [1] Reference.
|
|
75
|
-
|
|
76
|
-
Examples
|
|
77
|
-
--------
|
|
78
|
-
|
|
79
|
-
.. code-block:: python
|
|
80
|
-
:emphasize-lines: 6
|
|
81
|
-
|
|
82
|
-
>>> from freealg import cond
|
|
83
|
-
>>> from freealg.distributions import MarchenkoPastur
|
|
84
|
-
|
|
85
|
-
>>> mp = MarchenkoPastur(1/50)
|
|
86
|
-
>>> A = mp.matrix(3000)
|
|
87
|
-
>>> eigs = eigh(A)
|
|
88
|
-
"""
|
|
89
|
-
|
|
90
|
-
if A.ndim != 2 or A.shape[0] != A.shape[1]:
|
|
91
|
-
raise RuntimeError("Only square matrices are permitted.")
|
|
92
|
-
n = A.shape[0]
|
|
93
|
-
|
|
94
|
-
if N is None:
|
|
95
|
-
N = n
|
|
96
|
-
|
|
97
|
-
# Size of sample matrix
|
|
98
|
-
n_s = int(80*(1 + numpy.log(n)))
|
|
99
|
-
# If matrix is not large enough, return eigenvalues
|
|
100
|
-
if n < n_s:
|
|
101
|
-
return compute_eig(A)
|
|
102
|
-
# Number of samples
|
|
103
|
-
num_samples = int(10 * (n / n_s)**0.5)
|
|
104
|
-
|
|
105
|
-
# Collect eigenvalue samples
|
|
106
|
-
samples = []
|
|
107
|
-
for _ in range(num_samples):
|
|
108
|
-
indices = numpy.random.choice(n, n_s, replace=False)
|
|
109
|
-
samples.append(compute_eig(A[numpy.ix_(indices, indices)]))
|
|
110
|
-
samples = numpy.concatenate(samples).ravel()
|
|
111
|
-
|
|
112
|
-
# If all eigenvalues are positive, set PSD flag
|
|
113
|
-
if psd is None:
|
|
114
|
-
psd = samples.min() > 0
|
|
115
|
-
|
|
116
|
-
ff = FreeForm(samples)
|
|
117
|
-
# Since we are resampling, we need to provide the correct matrix size
|
|
118
|
-
ff.n = n_s
|
|
119
|
-
|
|
120
|
-
# Perform fit and estimate eigenvalues
|
|
121
|
-
order = 1 + int(len(samples)**.2)
|
|
122
|
-
ff.fit(method='chebyshev', K=order, projection='sample',
|
|
123
|
-
force=True, plot=False, latex=False, save=False)
|
|
124
|
-
|
|
125
|
-
if plots:
|
|
126
|
-
ff.density(plot=True)
|
|
127
|
-
ff.stieltjes(plot=True)
|
|
128
|
-
|
|
129
|
-
_, _, eigs = ff.decompress(N, plot=plots)
|
|
130
|
-
|
|
131
|
-
if psd:
|
|
132
|
-
eigs = numpy.abs(eigs)
|
|
133
|
-
eigs.sort()
|
|
134
|
-
|
|
135
|
-
return eigs
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
# ====
|
|
139
|
-
# cond
|
|
140
|
-
# ====
|
|
141
|
-
|
|
142
|
-
def cond(A, N=None):
|
|
143
|
-
"""
|
|
144
|
-
Estimate the condition number of a positive-definite matrix.
|
|
145
|
-
|
|
146
|
-
This function estimates the condition number of the matrix
|
|
147
|
-
:math:`\\mathbf{A}` or a larger matrix containing :math:`\\mathbf{A}`
|
|
148
|
-
using free decompression.
|
|
149
|
-
|
|
150
|
-
Parameters
|
|
151
|
-
----------
|
|
152
|
-
|
|
153
|
-
A : numpy.ndarray
|
|
154
|
-
The symmetric real-valued matrix :math:`\\mathbf{A}` whose condition
|
|
155
|
-
number (or that of a matrix containing :math:`\\mathbf{A}`) are to be
|
|
156
|
-
computed.
|
|
157
|
-
|
|
158
|
-
N : int, default=None
|
|
159
|
-
The size of the matrix containing :math:`\\mathbf{A}` to estimate
|
|
160
|
-
eigenvalues of. If None, returns estimates of the eigenvalues of
|
|
161
|
-
:math:`\\mathbf{A}` itself.
|
|
162
|
-
|
|
163
|
-
Returns
|
|
164
|
-
-------
|
|
165
|
-
|
|
166
|
-
c : float
|
|
167
|
-
Condition number
|
|
168
|
-
|
|
169
|
-
See Also
|
|
170
|
-
--------
|
|
171
|
-
|
|
172
|
-
eigh
|
|
173
|
-
|
|
174
|
-
Notes
|
|
175
|
-
-----
|
|
176
|
-
|
|
177
|
-
This is a convenience function using :func:`freealg.eigh`.
|
|
178
|
-
|
|
179
|
-
Examples
|
|
180
|
-
--------
|
|
181
|
-
|
|
182
|
-
.. code-block:: python
|
|
183
|
-
:emphasize-lines: 6
|
|
184
|
-
|
|
185
|
-
>>> from freealg import cond
|
|
186
|
-
>>> from freealg.distributions import MarchenkoPastur
|
|
187
|
-
|
|
188
|
-
>>> mp = MarchenkoPastur(1/50)
|
|
189
|
-
>>> A = mp.matrix(3000)
|
|
190
|
-
>>> cond(A)
|
|
191
|
-
"""
|
|
192
|
-
|
|
193
|
-
eigs = eigh(A, N)
|
|
194
|
-
return eigs.max() / eigs.min()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|