freealg 0.3.0__py3-none-any.whl → 0.3.2__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/__version__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.3.0"
1
+ __version__ = "0.3.2"
freealg/_support.py CHANGED
@@ -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, July). Approximate tests of correlation in
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':
freealg/eigh.py CHANGED
@@ -17,6 +17,33 @@ from .freeform import FreeForm
17
17
  __all__ = ['eigh', 'cond', 'norm', 'trace', 'slogdet']
18
18
 
19
19
 
20
+ def _subsample_apply(f, A, output_array=False):
21
+ """Compute f(A_n) over subsamples A_n of A. If the output of
22
+ f is an array (e.g. eigvals), specify output_array to be True."""
23
+
24
+ if A.ndim != 2 or A.shape[0] != A.shape[1]:
25
+ raise RuntimeError("Only square matrices are permitted.")
26
+ n = A.shape[0]
27
+
28
+ # Size of sample matrix
29
+ n_s = int(80*(1 + numpy.log(n)))
30
+ # If matrix is not large enough, return eigenvalues
31
+ if n < n_s:
32
+ return f(A), n, n
33
+ # Number of samples
34
+ num_samples = int(10 * (n / n_s)**0.5)
35
+
36
+ # Collect eigenvalue samples
37
+ samples = []
38
+ for _ in range(num_samples):
39
+ indices = numpy.random.choice(n, n_s, replace=False)
40
+ samples.append(f(A[numpy.ix_(indices, indices)]))
41
+ if output_array:
42
+ return numpy.concatenate(samples).ravel(), n, n_s
43
+
44
+ return numpy.array(samples), n, n_s
45
+
46
+
20
47
  # ====
21
48
  # eigh
22
49
  # ====
@@ -86,29 +113,11 @@ def eigh(A, N=None, psd=None, plots=False):
86
113
  >>> A = mp.matrix(3000)
87
114
  >>> eigs = eigh(A)
88
115
  """
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]
116
+ samples, n, n_s = _subsample_apply(compute_eig, A, output_array=True)
93
117
 
94
118
  if N is None:
95
119
  N = n
96
120
 
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
121
  # If all eigenvalues are positive, set PSD flag
113
122
  if psd is None:
114
123
  psd = samples.min() > 0
@@ -193,7 +202,7 @@ def cond(A, N=None):
193
202
  >>> cond(A)
194
203
  """
195
204
 
196
- eigs = eigh(A, N)
205
+ eigs = eigh(A, N, psd=True)
197
206
  return eigs.max() / eigs.min()
198
207
 
199
208
 
@@ -224,7 +233,7 @@ def norm(A, N=None, order=None):
224
233
  order : {float, ``''inf``, ``'-inf'``, ``'fro'``, ``'nuc'``}, default=2
225
234
  Order of the norm.
226
235
 
227
- * float :math:`p`: Schtten p-norm.
236
+ * float :math:`p`: Schatten p-norm.
228
237
  * ``'inf'``: Largest absolute eigenvalue
229
238
  :math:`\\max \\vert \\lambda_i \\vert)`
230
239
  * ``'-inf'``: Smallest absolute eigenvalue
@@ -300,19 +309,19 @@ def norm(A, N=None, order=None):
300
309
  # trace
301
310
  # =====
302
311
 
303
- def trace(A, N=None):
312
+ def trace(A, N=None, p=1.0):
304
313
  """
305
- Estimate the trace of a Hermitian matrix.
314
+ Estimate the trace of a power of a Hermitian matrix.
306
315
 
307
- This function estimates the trace of the matrix :math:`\\mathbf{A}` or a
308
- larger matrix containing :math:`\\mathbf{A}` using free decompression.
316
+ This function estimates the trace of the matrix power :math:`\\mathbf{A}^p`
317
+ or that of a larger matrix containing :math:`\\mathbf{A}`.
309
318
 
310
319
  Parameters
311
320
  ----------
312
321
 
313
322
  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
323
+ The symmetric real-valued matrix :math:`\\mathbf{A}` whose trace of
324
+ a power (or that of a matrix containing :math:`\\mathbf{A}`) is to be
316
325
  computed.
317
326
 
318
327
  N : int, default=None
@@ -320,6 +329,10 @@ def trace(A, N=None):
320
329
  eigenvalues of. If None, returns estimates of the eigenvalues of
321
330
  :math:`\\mathbf{A}` itself.
322
331
 
332
+ p : float, default=1.0
333
+ The exponent :math:`p` in :math:`\\mathbf{A}^p`.
334
+
335
+
323
336
  Returns
324
337
  -------
325
338
 
@@ -337,7 +350,9 @@ def trace(A, N=None):
337
350
  Notes
338
351
  -----
339
352
 
340
- This is a convenience function using :func:`freealg.eigh`.
353
+ The trace is highly amenable to subsampling: under free decompression
354
+ the average eigenvalue is assumed constant, so the trace increases
355
+ linearly. Traces of powers fall back to :func:`freealg.eigh`.
341
356
 
342
357
  Examples
343
358
  --------
@@ -352,11 +367,14 @@ def trace(A, N=None):
352
367
  >>> A = mp.matrix(3000)
353
368
  >>> trace(A, 100_000)
354
369
  """
355
-
356
- eigs = eigh(A, N)
357
- trace_ = numpy.sum(eigs)
358
-
359
- return trace_
370
+ if numpy.isclose(p, 1.0):
371
+ samples, n, n_s = _subsample_apply(numpy.trace, A, output_array=False)
372
+ if N is None:
373
+ N = n
374
+ return numpy.mean(samples) * (N / n_s)
375
+
376
+ eig = eigh(A, N)
377
+ return numpy.sum(eig ** p)
360
378
 
361
379
 
362
380
  # =======
@@ -1,8 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: freealg
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: Free probability for large matrices
5
- Keywords: leaderboard bot chat
5
+ Home-page: https://github.com/ameli/freealg
6
+ Download-URL: https://github.com/ameli/freealg/archive/main.zip
7
+ Project-URL: Documentation, https://github.com/ameli/freealg/blob/main/README.rst
8
+ Project-URL: Source, https://github.com/ameli/freealg
9
+ Project-URL: Tracker, https://github.com/ameli/freealg/issues
10
+ Keywords: linalg,free-probability
6
11
  Platform: Linux
7
12
  Platform: OSX
8
13
  Platform: Windows
@@ -37,9 +42,12 @@ Provides-Extra: docs
37
42
  Dynamic: classifier
38
43
  Dynamic: description
39
44
  Dynamic: description-content-type
45
+ Dynamic: download-url
46
+ Dynamic: home-page
40
47
  Dynamic: keywords
41
48
  Dynamic: license-file
42
49
  Dynamic: platform
50
+ Dynamic: project-url
43
51
  Dynamic: provides-extra
44
52
  Dynamic: requires-dist
45
53
  Dynamic: requires-python
@@ -52,7 +60,8 @@ Dynamic: summary
52
60
 
53
61
  `Paper <https://arxiv.org/abs/2506.11994>`__ |
54
62
  `Slides <https://www.dropbox.com/scl/fi/03gjuyz17k9yhsqy0isoz/free_decomporession_slides.pdf?rlkey=8f82mhciyl2ju02l7hv1md5li&st=26xmhjga&dl=0>`__ |
55
- `Docs <https://ameli.github.io/freealg>`__
63
+ `Docs <https://ameli.github.io/freealg>`__ |
64
+ `Live Demo <https://colab.research.google.com/github/ameli/freealg/blob/main/notebooks/quick_start.ipynb>`__
56
65
 
57
66
  .. `Slides <https://ameli.github.io/freealg/_static/data/slides.pdf>`__ |
58
67
 
@@ -126,7 +135,7 @@ requests and bug reports.
126
135
  How to Cite
127
136
  ===========
128
137
 
129
- If you use this work, please cite the `arXiv paper <https://arxiv.org/abs/2506.11994>`__.
138
+ If you use this work, please cite our `arXiv paper <https://arxiv.org/abs/2506.11994>`__.
130
139
 
131
140
  .. code::
132
141
 
@@ -1,5 +1,5 @@
1
1
  freealg/__init__.py,sha256=AM0G2tX7sBgzCTcOVbWynA9NFkQZKyphL9IR1tKOoK4,614
2
- freealg/__version__.py,sha256=VrXpHDu3erkzwl_WXrqINBm9xWkcyUy53IQOj042dOs,22
2
+ freealg/__version__.py,sha256=vNiWJ14r_cw5t_7UDqDQIVZvladKFGyHH2avsLpN7Vg,22
3
3
  freealg/_chebyshev.py,sha256=dsAj3YEpmkzB65smluZ0Fi5IZSdpnQXBSIuKMg19grA,5523
4
4
  freealg/_damp.py,sha256=k2vtBtWOxQBf4qXaWu_En81lQBXbEO4QbxxWpvuVhdE,1802
5
5
  freealg/_decompress.py,sha256=0MYoO3lqwMgNYlVriaRNUqUwY3XYyZZsDAtNRBq6rhE,10470
@@ -7,9 +7,9 @@ freealg/_jacobi.py,sha256=AT4ONSHGGDxVKE3MGMLyMR8uDFiO-e9u3x5udYfdJJk,5635
7
7
  freealg/_pade.py,sha256=Diw850oH2OLQeUrBR-q19TmjSBoBvXl6ogp4o1s2UIo,15184
8
8
  freealg/_plot_util.py,sha256=U4alp7Pzg315_7jJdu1UB0tIUcxUovQgHDHsUYoa2Z0,19728
9
9
  freealg/_sample.py,sha256=ckC75eqv-mRP1F5BnhvsjfLTaoAzHK8bebl9bCRZYDo,2561
10
- freealg/_support.py,sha256=sxp867DxfmvYqyQNOyla3zlcVyxm7KL0M-fxZaRIw8E,6299
10
+ freealg/_support.py,sha256=mYlrsdLbniqFgFofbHrZIiYSyJudPqtyMQQTPBD9Y6M,6439
11
11
  freealg/_util.py,sha256=8Tvz-XODtKYoU76ODmF1TBaIYLlr6-AXiyoMDwDSxVg,3779
12
- freealg/eigh.py,sha256=Vm9kLiksmOhsbsxUH7vBtAAKEtwR_RHeEDJCH4Qkr28,10109
12
+ freealg/eigh.py,sha256=5SFixxpXiVBsf5R9S0neg1lqWgmPoqGwVx4jwunh0xg,10856
13
13
  freealg/freeform.py,sha256=8emyCQ6AUjp_HB1gWQ-ecddlDgfxHGr3PqXSyoPxeMo,28593
14
14
  freealg/distributions/__init__.py,sha256=t_yZyEkW_W_tSV9IvgYXtVASxD2BEdiNVXcV2ebMy8M,579
15
15
  freealg/distributions/_kesten_mckay.py,sha256=210RF2OQEYLZBeLB6wmbdHnZPs_9ldDNHm_FMlg5tis,19881
@@ -17,9 +17,9 @@ freealg/distributions/_marchenko_pastur.py,sha256=kchFccRMuVF2Cus_99vdEwuRimkHzE
17
17
  freealg/distributions/_meixner.py,sha256=ws7t_EUa7V0s97dgMQIJLv1b6qMLqf9fLLbTJQudf_8,17512
18
18
  freealg/distributions/_wachter.py,sha256=Hna_MXqAPjuRkeilLPMf4Xg_3C6tTu5oZLEQnA-RuE4,16897
19
19
  freealg/distributions/_wigner.py,sha256=SxgPLtvIVBi9m4De-oBD0x6-2Je_eBqpDrpDYcoLuis,15871
20
- freealg-0.3.0.dist-info/licenses/AUTHORS.txt,sha256=0b67Nz4_JgIzUupHJTAZxu5QdSUM_HRM_X_w4xCb17o,30
21
- freealg-0.3.0.dist-info/licenses/LICENSE.txt,sha256=J-EEYEtxb3VVf_Bn1TYfWnpY5lMFIM15iLDDcnaDTPA,1443
22
- freealg-0.3.0.dist-info/METADATA,sha256=Z9HFCclNCRzFORlR2dQ6pzvPmAJfa5-Dxpee67QxqdM,4496
23
- freealg-0.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
24
- freealg-0.3.0.dist-info/top_level.txt,sha256=eR2wrgYwDdnnJ9Zf5PruPqe4kQav0GMvRsqct6y00Q8,8
25
- freealg-0.3.0.dist-info/RECORD,,
20
+ freealg-0.3.2.dist-info/licenses/AUTHORS.txt,sha256=0b67Nz4_JgIzUupHJTAZxu5QdSUM_HRM_X_w4xCb17o,30
21
+ freealg-0.3.2.dist-info/licenses/LICENSE.txt,sha256=J-EEYEtxb3VVf_Bn1TYfWnpY5lMFIM15iLDDcnaDTPA,1443
22
+ freealg-0.3.2.dist-info/METADATA,sha256=uRwMJGay5-IuqPSOWqpoMeaSqbNC1dq47moA2MxkGlo,4978
23
+ freealg-0.3.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
24
+ freealg-0.3.2.dist-info/top_level.txt,sha256=eR2wrgYwDdnnJ9Zf5PruPqe4kQav0GMvRsqct6y00Q8,8
25
+ freealg-0.3.2.dist-info/RECORD,,