freealg 0.1.15__tar.gz → 0.3.0__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.
Files changed (37) hide show
  1. {freealg-0.1.15 → freealg-0.3.0}/PKG-INFO +1 -1
  2. {freealg-0.1.15 → freealg-0.3.0}/freealg/__init__.py +3 -2
  3. freealg-0.3.0/freealg/__version__.py +1 -0
  4. {freealg-0.1.15 → freealg-0.3.0}/freealg/_decompress.py +6 -4
  5. {freealg-0.1.15 → freealg-0.3.0}/freealg/_pade.py +0 -1
  6. {freealg-0.1.15 → freealg-0.3.0}/freealg/_support.py +11 -0
  7. {freealg-0.1.15 → freealg-0.3.0}/freealg/_util.py +4 -0
  8. freealg-0.3.0/freealg/eigh.py +426 -0
  9. {freealg-0.1.15 → freealg-0.3.0}/freealg/freeform.py +8 -103
  10. {freealg-0.1.15 → freealg-0.3.0}/freealg.egg-info/PKG-INFO +1 -1
  11. {freealg-0.1.15 → freealg-0.3.0}/freealg.egg-info/SOURCES.txt +1 -1
  12. freealg-0.1.15/freealg/__version__.py +0 -1
  13. freealg-0.1.15/freealg/eigfree.py +0 -170
  14. {freealg-0.1.15 → freealg-0.3.0}/AUTHORS.txt +0 -0
  15. {freealg-0.1.15 → freealg-0.3.0}/CHANGELOG.rst +0 -0
  16. {freealg-0.1.15 → freealg-0.3.0}/LICENSE.txt +0 -0
  17. {freealg-0.1.15 → freealg-0.3.0}/MANIFEST.in +0 -0
  18. {freealg-0.1.15 → freealg-0.3.0}/README.rst +0 -0
  19. {freealg-0.1.15 → freealg-0.3.0}/freealg/_chebyshev.py +0 -0
  20. {freealg-0.1.15 → freealg-0.3.0}/freealg/_damp.py +0 -0
  21. {freealg-0.1.15 → freealg-0.3.0}/freealg/_jacobi.py +0 -0
  22. {freealg-0.1.15 → freealg-0.3.0}/freealg/_plot_util.py +0 -0
  23. {freealg-0.1.15 → freealg-0.3.0}/freealg/_sample.py +0 -0
  24. {freealg-0.1.15 → freealg-0.3.0}/freealg/distributions/__init__.py +0 -0
  25. {freealg-0.1.15 → freealg-0.3.0}/freealg/distributions/_kesten_mckay.py +0 -0
  26. {freealg-0.1.15 → freealg-0.3.0}/freealg/distributions/_marchenko_pastur.py +0 -0
  27. {freealg-0.1.15 → freealg-0.3.0}/freealg/distributions/_meixner.py +0 -0
  28. {freealg-0.1.15 → freealg-0.3.0}/freealg/distributions/_wachter.py +0 -0
  29. {freealg-0.1.15 → freealg-0.3.0}/freealg/distributions/_wigner.py +0 -0
  30. {freealg-0.1.15 → freealg-0.3.0}/freealg.egg-info/dependency_links.txt +0 -0
  31. {freealg-0.1.15 → freealg-0.3.0}/freealg.egg-info/not-zip-safe +0 -0
  32. {freealg-0.1.15 → freealg-0.3.0}/freealg.egg-info/requires.txt +0 -0
  33. {freealg-0.1.15 → freealg-0.3.0}/freealg.egg-info/top_level.txt +0 -0
  34. {freealg-0.1.15 → freealg-0.3.0}/pyproject.toml +0 -0
  35. {freealg-0.1.15 → freealg-0.3.0}/requirements.txt +0 -0
  36. {freealg-0.1.15 → freealg-0.3.0}/setup.cfg +0 -0
  37. {freealg-0.1.15 → freealg-0.3.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: freealg
3
- Version: 0.1.15
3
+ Version: 0.3.0
4
4
  Summary: Free probability for large matrices
5
5
  Keywords: leaderboard bot chat
6
6
  Platform: Linux
@@ -7,9 +7,10 @@
7
7
  # directory of this source tree.
8
8
 
9
9
  from .freeform import FreeForm
10
- from .eigfree import eigfree, condfree
10
+ from .eigh import eigh, cond, norm, trace, slogdet
11
11
  from . import distributions
12
12
 
13
- __all__ = ['FreeForm', 'distributions', 'eigfree', 'condfree']
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.0"
@@ -12,6 +12,10 @@
12
12
 
13
13
  import numpy
14
14
 
15
+ # Fallback to previous API
16
+ if not hasattr(numpy, 'trapezoid'):
17
+ numpy.trapezoid = numpy.trapz
18
+
15
19
  __all__ = ['decompress', 'reverse_characteristics']
16
20
 
17
21
 
@@ -19,7 +23,6 @@ __all__ = ['decompress', 'reverse_characteristics']
19
23
  # secant method
20
24
  # =============
21
25
 
22
-
23
26
  def secant_complex(f, z0, z1, a=0+0j, tol=1e-12, max_iter=100,
24
27
  alpha=0.5, max_bt=1, eps=1e-30, step_factor=5.0,
25
28
  post_smooth=True, jump_tol=10.0, verbose=False):
@@ -200,7 +203,6 @@ def secant_complex(f, z0, z1, a=0+0j, tol=1e-12, max_iter=100,
200
203
  # decompress
201
204
  # ==========
202
205
 
203
-
204
206
  def decompress(freeform, size, x=None, delta=1e-4, max_iter=500,
205
207
  tolerance=1e-8):
206
208
  """
@@ -287,9 +289,9 @@ def decompress(freeform, size, x=None, delta=1e-4, max_iter=500,
287
289
  def _char_z(z):
288
290
  return z + (1 / m(z)) * (1 - alpha)
289
291
 
290
- z0 = numpy.full(target.shape, numpy.mean(freeform.support) + .1j,
292
+ z0 = numpy.full(target.shape, numpy.mean(freeform.support) + 0.1j,
291
293
  dtype=numpy.complex128)
292
- z1 = z0 - .2j
294
+ z1 = z0 - 0.2j
293
295
 
294
296
  roots, _, _ = secant_complex(
295
297
  _char_z, z0, z1,
@@ -299,7 +299,6 @@ def wynn_pade(coeffs, x):
299
299
  # fit pade
300
300
  # ========
301
301
 
302
-
303
302
  def fit_pade(x, f, lam_m, lam_p, p=1, q=2, odd_side='left', pade_reg=0.0,
304
303
  safety=1.0, max_outer=40, xtol=1e-12, ftol=1e-12, optimizer='ls',
305
304
  verbose=0):
@@ -14,6 +14,12 @@ import numpy
14
14
  import numba
15
15
  from scipy.stats import gaussian_kde
16
16
 
17
+ __all__ = ['support_from_density', 'detect_support']
18
+
19
+
20
+ # ====================
21
+ # support from density
22
+ # ====================
17
23
 
18
24
  @numba.njit(numba.types.UniTuple(numba.types.int64, 2)(
19
25
  numba.types.float64,
@@ -24,6 +30,7 @@ def support_from_density(dx, density):
24
30
  Estimates the support from a collection of noisy observations of a
25
31
  density over a grid of x-values with mesh spacing dx.
26
32
  """
33
+
27
34
  n = density.shape[0]
28
35
  target = 1.0 / dx
29
36
 
@@ -92,6 +99,10 @@ def support_from_density(dx, density):
92
99
  return optimal_i, optimal_j
93
100
 
94
101
 
102
+ # ==============
103
+ # detect support
104
+ # ==============
105
+
95
106
  def detect_support(eigs, method='asymp', k=None, p=0.001, **kwargs):
96
107
  """
97
108
  Estimates the support of the eigenvalue density.
@@ -16,6 +16,10 @@ import scipy
16
16
  from scipy.stats import beta
17
17
  from scipy.optimize import minimize
18
18
 
19
+ # Fallback to previous API
20
+ if not hasattr(numpy, 'trapezoid'):
21
+ numpy.trapezoid = numpy.trapz
22
+
19
23
  __all__ = ['compute_eig', 'beta_kde', 'force_density']
20
24
 
21
25
 
@@ -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)
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
@@ -28,6 +28,10 @@ from ._decompress import decompress
28
28
  from ._sample import qmc_sample
29
29
  from ._support import detect_support
30
30
 
31
+ # Fallback to previous API
32
+ if not hasattr(numpy, 'trapezoid'):
33
+ numpy.trapezoid = numpy.trapz
34
+
31
35
  __all__ = ['FreeForm']
32
36
 
33
37
 
@@ -55,13 +59,14 @@ class FreeForm(object):
55
59
  Size of perturbations into the upper half plane for Plemelj's
56
60
  formula.
57
61
 
58
- Parameters for the ``detect_support`` function can also be prescribed here
59
- when ``support=None``.
62
+ **kwargs : dict, optional
63
+ Parameters for the ``detect_support`` function can also be prescribed
64
+ here when ``support=None``.
60
65
 
61
66
  Notes
62
67
  -----
63
68
 
64
- Notes.
69
+ TBD
65
70
 
66
71
  References
67
72
  ----------
@@ -890,103 +895,3 @@ class FreeForm(object):
890
895
  return x, rho, eigs
891
896
  else:
892
897
  return x, rho
893
-
894
-
895
- def eigfree(A, N=None, psd=None, plots=False):
896
- """
897
- Estimate the eigenvalues of a matrix :math:`\\mathbf{A}` or a larger matrix
898
- containing :math:`\\mathbf{A}` using free decompression.
899
-
900
- This is a convenience function for the FreeForm class with some effective
901
- defaults that work well for common random matrix ensembles. For improved
902
- performance and plotting utilites, consider finetuning parameters using
903
- the FreeForm class.
904
-
905
- Parameters
906
- ----------
907
-
908
- A : numpy.ndarray
909
- The symmetric real-valued matrix :math:`\\mathbf{A}` whose eigenvalues
910
- (or those of a matrix containing :math:`\\mathbf{A}`) are to be
911
- computed.
912
-
913
- N : int, default=None
914
- The size of the matrix containing :math:`\\mathbf{A}` to estimate
915
- eigenvalues of. If None, returns estimates of the eigenvalues of
916
- :math:`\\mathbf{A}` itself.
917
-
918
- psd : bool, default=None
919
- Determines whether the matrix is positive-semidefinite (PSD; all
920
- eigenvalues are non-negative). If None, the matrix is considered PSD if
921
- all sampled eigenvalues are positive.
922
-
923
- plots : bool, default=False
924
- Print out all relevant plots for diagnosing eigenvalue accuracy.
925
-
926
- Notes
927
- -----
928
-
929
- Notes.
930
-
931
- References
932
- ----------
933
-
934
- .. [1] Reference.
935
-
936
- Examples
937
- --------
938
-
939
- .. code-block:: python
940
-
941
- >>> from freealg import FreeForm
942
- """
943
- if A.ndim != 2 or A.shape[0] != A.shape[1]:
944
- raise RuntimeError("Only square matrices are permitted.")
945
- n = A.shape[0]
946
-
947
- if N is None:
948
- N = n
949
-
950
- # Size of sample matrix
951
- n_s = int(80*(1 + numpy.log(n)))
952
- # If matrix is not large enough, return eigenvalues
953
- if n < n_s:
954
- return compute_eig(A)
955
- # Number of samples
956
- num_samples = int(10 * (n / n_s)**0.5)
957
- # else:
958
- # # Use the entire matrix given
959
- # n_s = n
960
- # num_samples = 1
961
-
962
- # Collect eigenvalue samples
963
- samples = []
964
- for _ in range(num_samples):
965
- indices = numpy.random.choice(n, n_s, replace=False)
966
- samples.append(compute_eig(A[numpy.ix_(indices, indices)]))
967
- samples = numpy.concatenate(samples).ravel()
968
-
969
- # If all eigenvalues are positive, set PSD flag
970
- if psd is None:
971
- psd = samples.min() > 0
972
-
973
- ff = FreeForm(samples)
974
- # Since we are resampling, we need to provide the correct matrix size
975
- ff.n = n_s
976
-
977
- # Perform fit and estimate eigenvalues
978
- order = 1 + int(len(samples)**.2)
979
- ff.fit(method='chebyshev', K=order, projection='sample',
980
- force=True, plot=False, latex=False, save=False)
981
-
982
- if plots:
983
- ff.density(plot=True)
984
- ff.stieltjes(plot=True)
985
-
986
- _, _, eigs = ff.decompress(N, plot=plots)
987
-
988
- if psd:
989
- eigs = numpy.abs(eigs)
990
- eigs.sort()
991
-
992
- return eigs
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: freealg
3
- Version: 0.1.15
3
+ Version: 0.3.0
4
4
  Summary: Free probability for large matrices
5
5
  Keywords: leaderboard bot chat
6
6
  Platform: Linux
@@ -18,7 +18,7 @@ freealg/_plot_util.py
18
18
  freealg/_sample.py
19
19
  freealg/_support.py
20
20
  freealg/_util.py
21
- freealg/eigfree.py
21
+ freealg/eigh.py
22
22
  freealg/freeform.py
23
23
  freealg.egg-info/PKG-INFO
24
24
  freealg.egg-info/SOURCES.txt
@@ -1 +0,0 @@
1
- __version__ = "0.1.15"
@@ -1,170 +0,0 @@
1
- # SPDX-FileCopyrightText: Copyright 2025, Siavash Ameli <sameli@berkeley.edu>
2
- # SPDX-License-Identifier: BSD-3-Clause
3
- # SPDX-FileType: SOURCE
4
- #
5
- # This program is free software: you can redistribute it and/or modify it under
6
- # the terms of the license found in the LICENSE.txt file in the root directory
7
- # of this source tree.
8
-
9
-
10
- # =======
11
- # Imports
12
- # =======
13
-
14
- import numpy
15
- from ._util import compute_eig
16
- from .freeform import FreeForm
17
-
18
- __all__ = ['eigfree', 'condfree']
19
-
20
-
21
- # ========
22
- # eig free
23
- # ========
24
-
25
-
26
- def eigfree(A, N=None, psd=None, plots=False):
27
- """
28
- Estimate the eigenvalues of a matrix.
29
-
30
- This function estimates the eigenvalues of the matrix :math:`\\mathbf{A}`
31
- or a larger matrix containing :math:`\\mathbf{A}` using free decompression.
32
-
33
- Parameters
34
- ----------
35
-
36
- A : numpy.ndarray
37
- The symmetric real-valued matrix :math:`\\mathbf{A}` whose eigenvalues
38
- (or those of a matrix containing :math:`\\mathbf{A}`) are to be
39
- computed.
40
-
41
- N : int, default=None
42
- The size of the matrix containing :math:`\\mathbf{A}` to estimate
43
- eigenvalues of. If None, returns estimates of the eigenvalues of
44
- :math:`\\mathbf{A}` itself.
45
-
46
- psd: bool, default=None
47
- Determines whether the matrix is positive-semidefinite (PSD; all
48
- eigenvalues are non-negative). If None, the matrix is considered PSD if
49
- all sampled eigenvalues are positive.
50
-
51
- plots : bool, default=False
52
- Print out all relevant plots for diagnosing eigenvalue accuracy.
53
-
54
- Notes
55
- -----
56
-
57
- This is a convenience function for the FreeForm class with some effective
58
- defaults that work well for common random matrix ensembles. For improved
59
- performance and plotting utilites, consider finetuning parameters using
60
- the FreeForm class.
61
-
62
- References
63
- ----------
64
-
65
- .. [1] Reference.
66
-
67
- Examples
68
- --------
69
-
70
- .. code-block:: python
71
-
72
- >>> from freealg import condfree
73
- >>> from freealg.distributions import MarchenkoPastur
74
- >>> mp = MarchenkoPastur(1/50)
75
- >>> A = mp.matrix(3000)
76
- >>> eigs = eigfree(A)
77
- """
78
-
79
- if A.ndim != 2 or A.shape[0] != A.shape[1]:
80
- raise RuntimeError("Only square matrices are permitted.")
81
- n = A.shape[0]
82
-
83
- if N is None:
84
- N = n
85
-
86
- # Size of sample matrix
87
- n_s = int(80*(1 + numpy.log(n)))
88
- # If matrix is not large enough, return eigenvalues
89
- if n < n_s:
90
- return compute_eig(A)
91
- # Number of samples
92
- num_samples = int(10 * (n / n_s)**0.5)
93
-
94
- # Collect eigenvalue samples
95
- samples = []
96
- for _ in range(num_samples):
97
- indices = numpy.random.choice(n, n_s, replace=False)
98
- samples.append(compute_eig(A[numpy.ix_(indices, indices)]))
99
- samples = numpy.concatenate(samples).ravel()
100
-
101
- # If all eigenvalues are positive, set PSD flag
102
- if psd is None:
103
- psd = samples.min() > 0
104
-
105
- ff = FreeForm(samples)
106
- # Since we are resampling, we need to provide the correct matrix size
107
- ff.n = n_s
108
-
109
- # Perform fit and estimate eigenvalues
110
- order = 1 + int(len(samples)**.2)
111
- ff.fit(method='chebyshev', K=order, projection='sample',
112
- force=True, plot=False, latex=False, save=False)
113
-
114
- if plots:
115
- ff.density(plot=True)
116
- ff.stieltjes(plot=True)
117
-
118
- _, _, eigs = ff.decompress(N, plot=plots)
119
-
120
- if psd:
121
- eigs = numpy.abs(eigs)
122
- eigs.sort()
123
-
124
- return eigs
125
-
126
-
127
- # ========
128
- # cond free
129
- # ========
130
-
131
- def condfree(A, N=None):
132
- """
133
- Estimate the condition number of a positive-definite matrix.
134
-
135
- This function estimates the condition number of the matrix
136
- :math:`\\mathbf{A}` or a larger matrix containing :math:`\\mathbf{A}`
137
- using free decompression.
138
-
139
- Parameters
140
- ----------
141
-
142
- A : numpy.ndarray
143
- The symmetric real-valued matrix :math:`\\mathbf{A}` whose condition
144
- number (or that of a matrix containing :math:`\\mathbf{A}`) are to be
145
- computed.
146
-
147
- N : int, default=None
148
- The size of the matrix containing :math:`\\mathbf{A}` to estimate
149
- eigenvalues of. If None, returns estimates of the eigenvalues of
150
- :math:`\\mathbf{A}` itself.
151
-
152
- Notes
153
- -----
154
-
155
- This is a convenience function using the eigfree procedure.
156
-
157
- Examples
158
- --------
159
-
160
- .. code-block:: python
161
-
162
- >>> from freealg import condfree
163
- >>> from freealg.distributions import MarchenkoPastur
164
- >>> mp = MarchenkoPastur(1/50)
165
- >>> A = mp.matrix(3000)
166
- >>> condfree(A)
167
- """
168
-
169
- eigs = eigfree(A, N)
170
- 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