freealg 0.1.15__tar.gz → 0.2.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 (36) hide show
  1. {freealg-0.1.15 → freealg-0.2.0}/PKG-INFO +1 -1
  2. {freealg-0.1.15 → freealg-0.2.0}/freealg/__init__.py +2 -2
  3. freealg-0.2.0/freealg/__version__.py +1 -0
  4. {freealg-0.1.15 → freealg-0.2.0}/freealg/_decompress.py +6 -4
  5. {freealg-0.1.15 → freealg-0.2.0}/freealg/_pade.py +0 -1
  6. {freealg-0.1.15 → freealg-0.2.0}/freealg/_support.py +11 -0
  7. {freealg-0.1.15 → freealg-0.2.0}/freealg/_util.py +4 -0
  8. freealg-0.1.15/freealg/eigfree.py → freealg-0.2.0/freealg/eigh.py +48 -24
  9. {freealg-0.1.15 → freealg-0.2.0}/freealg/freeform.py +4 -100
  10. {freealg-0.1.15 → freealg-0.2.0}/freealg.egg-info/PKG-INFO +1 -1
  11. {freealg-0.1.15 → freealg-0.2.0}/freealg.egg-info/SOURCES.txt +1 -1
  12. freealg-0.1.15/freealg/__version__.py +0 -1
  13. {freealg-0.1.15 → freealg-0.2.0}/AUTHORS.txt +0 -0
  14. {freealg-0.1.15 → freealg-0.2.0}/CHANGELOG.rst +0 -0
  15. {freealg-0.1.15 → freealg-0.2.0}/LICENSE.txt +0 -0
  16. {freealg-0.1.15 → freealg-0.2.0}/MANIFEST.in +0 -0
  17. {freealg-0.1.15 → freealg-0.2.0}/README.rst +0 -0
  18. {freealg-0.1.15 → freealg-0.2.0}/freealg/_chebyshev.py +0 -0
  19. {freealg-0.1.15 → freealg-0.2.0}/freealg/_damp.py +0 -0
  20. {freealg-0.1.15 → freealg-0.2.0}/freealg/_jacobi.py +0 -0
  21. {freealg-0.1.15 → freealg-0.2.0}/freealg/_plot_util.py +0 -0
  22. {freealg-0.1.15 → freealg-0.2.0}/freealg/_sample.py +0 -0
  23. {freealg-0.1.15 → freealg-0.2.0}/freealg/distributions/__init__.py +0 -0
  24. {freealg-0.1.15 → freealg-0.2.0}/freealg/distributions/_kesten_mckay.py +0 -0
  25. {freealg-0.1.15 → freealg-0.2.0}/freealg/distributions/_marchenko_pastur.py +0 -0
  26. {freealg-0.1.15 → freealg-0.2.0}/freealg/distributions/_meixner.py +0 -0
  27. {freealg-0.1.15 → freealg-0.2.0}/freealg/distributions/_wachter.py +0 -0
  28. {freealg-0.1.15 → freealg-0.2.0}/freealg/distributions/_wigner.py +0 -0
  29. {freealg-0.1.15 → freealg-0.2.0}/freealg.egg-info/dependency_links.txt +0 -0
  30. {freealg-0.1.15 → freealg-0.2.0}/freealg.egg-info/not-zip-safe +0 -0
  31. {freealg-0.1.15 → freealg-0.2.0}/freealg.egg-info/requires.txt +0 -0
  32. {freealg-0.1.15 → freealg-0.2.0}/freealg.egg-info/top_level.txt +0 -0
  33. {freealg-0.1.15 → freealg-0.2.0}/pyproject.toml +0 -0
  34. {freealg-0.1.15 → freealg-0.2.0}/requirements.txt +0 -0
  35. {freealg-0.1.15 → freealg-0.2.0}/setup.cfg +0 -0
  36. {freealg-0.1.15 → freealg-0.2.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.2.0
4
4
  Summary: Free probability for large matrices
5
5
  Keywords: leaderboard bot chat
6
6
  Platform: Linux
@@ -7,9 +7,9 @@
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
11
11
  from . import distributions
12
12
 
13
- __all__ = ['FreeForm', 'distributions', 'eigfree', 'condfree']
13
+ __all__ = ['FreeForm', 'distributions', 'eigh', 'cond']
14
14
 
15
15
  from .__version__ import __version__ # noqa: F401 E402
@@ -0,0 +1 @@
1
+ __version__ = "0.2.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
 
@@ -1,4 +1,3 @@
1
- # SPDX-FileCopyrightText: Copyright 2025, Siavash Ameli <sameli@berkeley.edu>
2
1
  # SPDX-License-Identifier: BSD-3-Clause
3
2
  # SPDX-FileType: SOURCE
4
3
  #
@@ -15,15 +14,14 @@ import numpy
15
14
  from ._util import compute_eig
16
15
  from .freeform import FreeForm
17
16
 
18
- __all__ = ['eigfree', 'condfree']
17
+ __all__ = ['eigh', 'cond']
19
18
 
20
19
 
21
- # ========
22
- # eig free
23
- # ========
20
+ # ====
21
+ # eigh
22
+ # ====
24
23
 
25
-
26
- def eigfree(A, N=None, psd=None, plots=False):
24
+ def eigh(A, N=None, psd=None, plots=False):
27
25
  """
28
26
  Estimate the eigenvalues of a matrix.
29
27
 
@@ -43,21 +41,32 @@ def eigfree(A, N=None, psd=None, plots=False):
43
41
  eigenvalues of. If None, returns estimates of the eigenvalues of
44
42
  :math:`\\mathbf{A}` itself.
45
43
 
46
- psd: bool, default=None
44
+ psd : bool, default=None
47
45
  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.
46
+ eigenvalues are non-negative). If `None`, the matrix is considered PSD
47
+ if all sampled eigenvalues are positive.
50
48
 
51
49
  plots : bool, default=False
52
50
  Print out all relevant plots for diagnosing eigenvalue accuracy.
53
51
 
52
+ Returns
53
+ -------
54
+
55
+ eigs : numpy.array
56
+ Eigenvalues of decompressed matrix
57
+
58
+ See Also
59
+ --------
60
+
61
+ cond
62
+
54
63
  Notes
55
64
  -----
56
65
 
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.
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.
61
70
 
62
71
  References
63
72
  ----------
@@ -68,12 +77,14 @@ def eigfree(A, N=None, psd=None, plots=False):
68
77
  --------
69
78
 
70
79
  .. code-block:: python
80
+ :emphasize-lines: 6
71
81
 
72
- >>> from freealg import condfree
82
+ >>> from freealg import cond
73
83
  >>> from freealg.distributions import MarchenkoPastur
84
+
74
85
  >>> mp = MarchenkoPastur(1/50)
75
86
  >>> A = mp.matrix(3000)
76
- >>> eigs = eigfree(A)
87
+ >>> eigs = eigh(A)
77
88
  """
78
89
 
79
90
  if A.ndim != 2 or A.shape[0] != A.shape[1]:
@@ -124,11 +135,11 @@ def eigfree(A, N=None, psd=None, plots=False):
124
135
  return eigs
125
136
 
126
137
 
127
- # ========
128
- # cond free
129
- # ========
138
+ # ====
139
+ # cond
140
+ # ====
130
141
 
131
- def condfree(A, N=None):
142
+ def cond(A, N=None):
132
143
  """
133
144
  Estimate the condition number of a positive-definite matrix.
134
145
 
@@ -149,22 +160,35 @@ def condfree(A, N=None):
149
160
  eigenvalues of. If None, returns estimates of the eigenvalues of
150
161
  :math:`\\mathbf{A}` itself.
151
162
 
163
+ Returns
164
+ -------
165
+
166
+ c : float
167
+ Condition number
168
+
169
+ See Also
170
+ --------
171
+
172
+ eigh
173
+
152
174
  Notes
153
175
  -----
154
176
 
155
- This is a convenience function using the eigfree procedure.
177
+ This is a convenience function using :func:`freealg.eigh`.
156
178
 
157
179
  Examples
158
180
  --------
159
181
 
160
182
  .. code-block:: python
183
+ :emphasize-lines: 6
161
184
 
162
- >>> from freealg import condfree
185
+ >>> from freealg import cond
163
186
  >>> from freealg.distributions import MarchenkoPastur
187
+
164
188
  >>> mp = MarchenkoPastur(1/50)
165
189
  >>> A = mp.matrix(3000)
166
- >>> condfree(A)
190
+ >>> cond(A)
167
191
  """
168
192
 
169
- eigs = eigfree(A, N)
193
+ eigs = eigh(A, N)
170
194
  return eigs.max() / eigs.min()
@@ -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
 
@@ -890,103 +894,3 @@ class FreeForm(object):
890
894
  return x, rho, eigs
891
895
  else:
892
896
  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.2.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"
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