freealg 0.3.5__py3-none-any.whl → 0.4.0__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 CHANGED
@@ -7,10 +7,10 @@
7
7
  # directory of this source tree.
8
8
 
9
9
  from .freeform import FreeForm
10
- from .eigh import eigh, cond, norm, trace, slogdet
10
+ from ._linalg import eigvalsh, cond, norm, trace, slogdet
11
11
  from . import distributions
12
12
 
13
- __all__ = ['FreeForm', 'distributions', 'eigh', 'cond', 'norm', 'trace',
13
+ __all__ = ['FreeForm', 'distributions', 'eigvalsh', 'cond', 'norm', 'trace',
14
14
  'slogdet']
15
15
 
16
16
  from .__version__ import __version__ # noqa: F401 E402
freealg/__version__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.3.5"
1
+ __version__ = "0.4.0"
@@ -14,7 +14,7 @@ import numpy
14
14
  from ._util import compute_eig
15
15
  from .freeform import FreeForm
16
16
 
17
- __all__ = ['eigh', 'cond', 'norm', 'trace', 'slogdet']
17
+ __all__ = ['eigvalsh', 'cond', 'norm', 'trace', 'slogdet']
18
18
 
19
19
 
20
20
  # ===============
@@ -53,11 +53,11 @@ def _subsample_apply(f, A, output_array=False):
53
53
  return numpy.array(samples), n, n_s
54
54
 
55
55
 
56
- # ====
57
- # eigh
58
- # ====
56
+ # ========
57
+ # eigvalsh
58
+ # ========
59
59
 
60
- def eigh(A, N=None, psd=None, plots=False):
60
+ def eigvalsh(A, size=None, psd=None, seed=None, plot=False, **kwargs):
61
61
  """
62
62
  Estimate the eigenvalues of a matrix.
63
63
 
@@ -72,7 +72,7 @@ def eigh(A, N=None, psd=None, plots=False):
72
72
  (or those of a matrix containing :math:`\\mathbf{A}`) are to be
73
73
  computed.
74
74
 
75
- N : int, default=None
75
+ size : int, default=None
76
76
  The size of the matrix containing :math:`\\mathbf{A}` to estimate
77
77
  eigenvalues of. If None, returns estimates of the eigenvalues of
78
78
  :math:`\\mathbf{A}` itself.
@@ -82,9 +82,16 @@ def eigh(A, N=None, psd=None, plots=False):
82
82
  eigenvalues are non-negative). If `None`, the matrix is considered PSD
83
83
  if all sampled eigenvalues are positive.
84
84
 
85
- plots : bool, default=False
85
+ seed : int, default=None
86
+ The seed for the Quasi-Monte Carlo sampler.
87
+
88
+ plot : bool, default=False
86
89
  Print out all relevant plots for diagnosing eigenvalue accuracy.
87
90
 
91
+ **kwargs : dict, optional
92
+ Pass additional options to the underlying
93
+ :func:`FreeForm.decompress` function.
94
+
88
95
  Returns
89
96
  -------
90
97
 
@@ -101,7 +108,7 @@ def eigh(A, N=None, psd=None, plots=False):
101
108
 
102
109
  This is a convenience function for the :class:`freealg.FreeForm` class with
103
110
  some effective defaults that work well for common random matrix ensembles.
104
- For improved performance and plotting utilites, consider fine-tuning
111
+ For improved performance and plotting utilities, consider fine-tuning
105
112
  parameters using the FreeForm class.
106
113
 
107
114
  References
@@ -120,13 +127,13 @@ def eigh(A, N=None, psd=None, plots=False):
120
127
 
121
128
  >>> mp = MarchenkoPastur(1/50)
122
129
  >>> A = mp.matrix(3000)
123
- >>> eigs = eigh(A)
130
+ >>> eigs = eigvalsh(A)
124
131
  """
125
132
 
126
133
  samples, n, n_s = _subsample_apply(compute_eig, A, output_array=True)
127
134
 
128
- if N is None:
129
- N = n
135
+ if size is None:
136
+ size = n
130
137
 
131
138
  # If all eigenvalues are positive, set PSD flag
132
139
  if psd is None:
@@ -137,15 +144,15 @@ def eigh(A, N=None, psd=None, plots=False):
137
144
  ff.n = n_s
138
145
 
139
146
  # Perform fit and estimate eigenvalues
140
- order = 1 + int(len(samples)**.2)
147
+ order = 1 + int(len(samples)**0.2)
141
148
  ff.fit(method='chebyshev', K=order, projection='sample',
142
149
  force=True, plot=False, latex=False, save=False)
143
150
 
144
- if plots:
151
+ if plot:
145
152
  ff.density(plot=True)
146
153
  ff.stieltjes(plot=True)
147
154
 
148
- _, _, eigs = ff.decompress(N, plot=plots)
155
+ eigs = ff.eigvalsh(size, seed=seed, plot=plot, **kwargs)
149
156
 
150
157
  if psd:
151
158
  eigs = numpy.abs(eigs)
@@ -158,7 +165,7 @@ def eigh(A, N=None, psd=None, plots=False):
158
165
  # cond
159
166
  # ====
160
167
 
161
- def cond(A, N=None):
168
+ def cond(A, size=None, seed=None, **kwargs):
162
169
  """
163
170
  Estimate the condition number of a Hermitian positive-definite matrix.
164
171
 
@@ -174,11 +181,18 @@ def cond(A, N=None):
174
181
  number (or that of a matrix containing :math:`\\mathbf{A}`) are to be
175
182
  computed.
176
183
 
177
- N : int, default=None
184
+ size : int, default=None
178
185
  The size of the matrix containing :math:`\\mathbf{A}` to estimate
179
186
  eigenvalues of. If None, returns estimates of the eigenvalues of
180
187
  :math:`\\mathbf{A}` itself.
181
188
 
189
+ seed : int, default=None
190
+ The seed for the Quasi-Monte Carlo sampler.
191
+
192
+ **kwargs : dict, optional
193
+ Pass additional options to the underlying
194
+ :func:`FreeForm.decompress` function.
195
+
182
196
  Returns
183
197
  -------
184
198
 
@@ -188,7 +202,7 @@ def cond(A, N=None):
188
202
  See Also
189
203
  --------
190
204
 
191
- eigh
205
+ eigvalsh
192
206
  norm
193
207
  slogdet
194
208
  trace
@@ -196,7 +210,7 @@ def cond(A, N=None):
196
210
  Notes
197
211
  -----
198
212
 
199
- This is a convenience function using :func:`freealg.eigh`.
213
+ This is a convenience function using :func:`freealg.eigvalsh`.
200
214
 
201
215
  Examples
202
216
  --------
@@ -212,7 +226,7 @@ def cond(A, N=None):
212
226
  >>> cond(A)
213
227
  """
214
228
 
215
- eigs = eigh(A, N, psd=True)
229
+ eigs = eigvalsh(A, size=size, psd=True, seed=seed, **kwargs)
216
230
  return eigs.max() / eigs.min()
217
231
 
218
232
 
@@ -220,7 +234,7 @@ def cond(A, N=None):
220
234
  # norm
221
235
  # ====
222
236
 
223
- def norm(A, N=None, order=None):
237
+ def norm(A, size=None, order=2, seed=None, **kwargs):
224
238
  """
225
239
  Estimate the Schatten norm of a Hermitian matrix.
226
240
 
@@ -235,7 +249,7 @@ def norm(A, N=None, order=None):
235
249
  number (or that of a matrix containing :math:`\\mathbf{A}`) are to be
236
250
  computed.
237
251
 
238
- N : int, default=None
252
+ size : int, default=None
239
253
  The size of the matrix containing :math:`\\mathbf{A}` to estimate
240
254
  eigenvalues of. If None, returns estimates of the eigenvalues of
241
255
  :math:`\\mathbf{A}` itself.
@@ -251,6 +265,13 @@ def norm(A, N=None, order=None):
251
265
  * ``'fro'``: Frobenius norm corresponding to :math:`p=2`
252
266
  * ``'nuc'``: Nuclear (or trace) norm corresponding to :math:`p=1`
253
267
 
268
+ seed : int, default=None
269
+ The seed for the Quasi-Monte Carlo sampler.
270
+
271
+ **kwargs : dict, optional
272
+ Pass additional options to the underlying
273
+ :func:`FreeForm.decompress` function.
274
+
254
275
  Returns
255
276
  -------
256
277
 
@@ -260,7 +281,7 @@ def norm(A, N=None, order=None):
260
281
  See Also
261
282
  --------
262
283
 
263
- eigh
284
+ eigvalsh
264
285
  cond
265
286
  slogdet
266
287
  trace
@@ -289,29 +310,34 @@ def norm(A, N=None, order=None):
289
310
  >>> norm(A, 100_000, order='fro')
290
311
  """
291
312
 
292
- eigs = eigh(A, N)
313
+ eigs = eigvalsh(A, size=size, seed=seed, **kwargs)
314
+
315
+ # Check order type and convert to float
316
+ if order == 'nuc':
317
+ order = 1
318
+ elif order == 'fro':
319
+ order = 2
320
+ elif order == 'inf':
321
+ order = float('inf')
322
+ elif order == '-inf':
323
+ order = -float('inf')
324
+ elif not isinstance(order,
325
+ (int, float, numpy.integer, numpy.floating)) \
326
+ and not isinstance(order, (bool, numpy.bool_)):
327
+ raise ValueError('"order" is invalid.')
293
328
 
294
- if (order == 'inf') or numpy.isinf(order):
329
+ # Compute norm
330
+ if numpy.isinf(order) and not numpy.isneginf(order):
295
331
  norm_ = max(numpy.abs(eigs))
296
332
 
297
- elif (order == '-inf') or numpy.isneginf(order):
333
+ elif numpy.isneginf(order):
298
334
  norm_ = min(numpy.abs(eigs))
299
335
 
300
- elif (order == 'nuc') or (order == 1.0):
301
- norm_ = numpy.sum(numpy.abs(eigs))
302
-
303
- elif (order == 'fro') or (order == 2.0):
304
- norm_2 = numpy.sum(numpy.abs(eigs)**2)
305
- norm_ = numpy.sqrt(norm_2)
306
-
307
- elif isinstance(order, (int, float, numpy.integer, numpy.floating)) and \
308
- not isinstance(order, (bool, numpy.bool_)):
336
+ elif isinstance(order, (int, float, numpy.integer, numpy.floating)) \
337
+ and not isinstance(order, (bool, numpy.bool_)):
309
338
  norm_q = numpy.sum(numpy.abs(eigs)**order)
310
339
  norm_ = norm_q**(1.0 / order)
311
340
 
312
- else:
313
- raise ValueError('"order" is invalid.')
314
-
315
341
  return norm_
316
342
 
317
343
 
@@ -319,7 +345,7 @@ def norm(A, N=None, order=None):
319
345
  # trace
320
346
  # =====
321
347
 
322
- def trace(A, N=None, p=1.0):
348
+ def trace(A, N=None, p=1.0, seed=None, **kwargs):
323
349
  """
324
350
  Estimate the trace of a power of a Hermitian matrix.
325
351
 
@@ -334,7 +360,7 @@ def trace(A, N=None, p=1.0):
334
360
  a power (or that of a matrix containing :math:`\\mathbf{A}`) is to be
335
361
  computed.
336
362
 
337
- N : int, default=None
363
+ size : int, default=None
338
364
  The size of the matrix containing :math:`\\mathbf{A}` to estimate
339
365
  eigenvalues of. If None, returns estimates of the eigenvalues of
340
366
  :math:`\\mathbf{A}` itself.
@@ -342,6 +368,12 @@ def trace(A, N=None, p=1.0):
342
368
  p : float, default=1.0
343
369
  The exponent :math:`p` in :math:`\\mathbf{A}^p`.
344
370
 
371
+ seed : int, default=None
372
+ The seed for the Quasi-Monte Carlo sampler.
373
+
374
+ **kwargs : dict, optional
375
+ Pass additional options to the underlying
376
+ :func:`FreeForm.decompress` function.
345
377
 
346
378
  Returns
347
379
  -------
@@ -352,7 +384,7 @@ def trace(A, N=None, p=1.0):
352
384
  See Also
353
385
  --------
354
386
 
355
- eigh
387
+ eigvalsh
356
388
  cond
357
389
  slogdet
358
390
  norm
@@ -362,7 +394,7 @@ def trace(A, N=None, p=1.0):
362
394
 
363
395
  The trace is highly amenable to subsampling: under free decompression
364
396
  the average eigenvalue is assumed constant, so the trace increases
365
- linearly. Traces of powers fall back to :func:`freealg.eigh`.
397
+ linearly. Traces of powers fall back to :func:`freealg.eigvalsh`.
366
398
 
367
399
  Examples
368
400
  --------
@@ -381,10 +413,10 @@ def trace(A, N=None, p=1.0):
381
413
  if numpy.isclose(p, 1.0):
382
414
  samples, n, n_s = _subsample_apply(numpy.trace, A, output_array=False)
383
415
  if N is None:
384
- N = n
385
- return numpy.mean(samples) * (N / n_s)
416
+ size = n
417
+ return numpy.mean(samples) * (size / n_s)
386
418
 
387
- eig = eigh(A, N)
419
+ eig = eigvalsh(A, size=size, seed=seed, **kwargs)
388
420
  return numpy.sum(eig ** p)
389
421
 
390
422
 
@@ -392,7 +424,7 @@ def trace(A, N=None, p=1.0):
392
424
  # slogdet
393
425
  # =======
394
426
 
395
- def slogdet(A, N=None):
427
+ def slogdet(A, size=None, seed=None, **kwargs):
396
428
  """
397
429
  Estimate the sign and logarithm of the determinant of a Hermitian matrix.
398
430
 
@@ -407,11 +439,18 @@ def slogdet(A, N=None):
407
439
  number (or that of a matrix containing :math:`\\mathbf{A}`) are to be
408
440
  computed.
409
441
 
410
- N : int, default=None
442
+ size : int, default=None
411
443
  The size of the matrix containing :math:`\\mathbf{A}` to estimate
412
444
  eigenvalues of. If None, returns estimates of the eigenvalues of
413
445
  :math:`\\mathbf{A}` itself.
414
446
 
447
+ seed : int, default=None
448
+ The seed for the Quasi-Monte Carlo sampler.
449
+
450
+ **kwargs : dict, optional
451
+ Pass additional options to the underlying
452
+ :func:`FreeForm.decompress` function.
453
+
415
454
  Returns
416
455
  -------
417
456
 
@@ -424,7 +463,7 @@ def slogdet(A, N=None):
424
463
  See Also
425
464
  --------
426
465
 
427
- eigh
466
+ eigvalsh
428
467
  cond
429
468
  trace
430
469
  norm
@@ -432,7 +471,7 @@ def slogdet(A, N=None):
432
471
  Notes
433
472
  -----
434
473
 
435
- This is a convenience function using :func:`freealg.eigh`.
474
+ This is a convenience function using :func:`freealg.eigvalsh`.
436
475
 
437
476
  Examples
438
477
  --------
@@ -448,7 +487,7 @@ def slogdet(A, N=None):
448
487
  >>> sign, ld = slogdet(A, 100_000)
449
488
  """
450
489
 
451
- eigs = eigh(A, N)
490
+ eigs = eigvalsh(A, size=size, seed=seed, **kwargs)
452
491
  sign = numpy.prod(numpy.sign(eigs))
453
492
  ld = numpy.sum(numpy.log(numpy.abs(eigs)))
454
493
 
freealg/freeform.py CHANGED
@@ -108,6 +108,21 @@ class FreeForm(object):
108
108
  decompress
109
109
  Free decompression of spectral density
110
110
 
111
+ eigvalsh
112
+ Estimate the eigenvalues
113
+
114
+ cond
115
+ Estimate the condition number
116
+
117
+ trace
118
+ Estimate the trace of a matrix power
119
+
120
+ slogdet
121
+ Estimate the sign and logarithm of the determinant
122
+
123
+ norm
124
+ Estimate the Schatten norm
125
+
111
126
  Examples
112
127
  --------
113
128
 
@@ -411,9 +426,30 @@ class FreeForm(object):
411
426
  # density
412
427
  # =======
413
428
 
429
+ def _grid(self, scale, extend=1.0, N=500):
430
+ """
431
+ Return a grid of points to evaluate density / Hilbert / Stieltjes
432
+ transforms.
433
+ """
434
+
435
+ radius = 0.5 * (self.lam_p - self.lam_m)
436
+ center = 0.5 * (self.lam_p + self.lam_m)
437
+
438
+ x_min = numpy.floor(extend * (center - extend * radius * scale))
439
+ x_max = numpy.ceil(extend * (center + extend * radius * scale))
440
+
441
+ x_min /= extend
442
+ x_max /= extend
443
+
444
+ return numpy.linspace(x_min, x_max, N)
445
+
446
+ # =======
447
+ # density
448
+ # =======
449
+
414
450
  def density(self, x=None, plot=False, latex=False, save=False):
415
451
  """
416
- Evaluate density.
452
+ Evaluate spectral density.
417
453
 
418
454
  Parameters
419
455
  ----------
@@ -459,12 +495,7 @@ class FreeForm(object):
459
495
 
460
496
  # Create x if not given
461
497
  if x is None:
462
- radius = 0.5 * (self.lam_p - self.lam_m)
463
- center = 0.5 * (self.lam_p + self.lam_m)
464
- scale = 1.25
465
- x_min = numpy.floor(center - radius * scale)
466
- x_max = numpy.ceil(center + radius * scale)
467
- x = numpy.linspace(x_min, x_max, 500)
498
+ x = self._grid(1.25)
468
499
 
469
500
  # Preallocate density to zero
470
501
  rho = numpy.zeros_like(x)
@@ -554,12 +585,7 @@ class FreeForm(object):
554
585
 
555
586
  # Create x if not given
556
587
  if x is None:
557
- radius = 0.5 * (self.lam_p - self.lam_m)
558
- center = 0.5 * (self.lam_p + self.lam_m)
559
- scale = 1.25
560
- x_min = numpy.floor(center - radius * scale)
561
- x_max = numpy.ceil(center + radius * scale)
562
- x = numpy.linspace(x_min, x_max, 500)
588
+ x = self._grid(1.25)
563
589
 
564
590
  # if (numpy.min(x) > self.lam_m) or (numpy.max(x) < self.lam_p):
565
591
  # raise ValueError('"x" does not encompass support interval.')
@@ -683,12 +709,8 @@ class FreeForm(object):
683
709
 
684
710
  # Create x if not given
685
711
  if x is None:
686
- radius = 0.5 * (self.lam_p - self.lam_m)
687
- center = 0.5 * (self.lam_p + self.lam_m)
688
- scale = 2.0
689
- x_min = numpy.floor(2.0 * (center - 2.0 * radius * scale)) / 2.0
690
- x_max = numpy.ceil(2.0 * (center + 2.0 * radius * scale)) / 2.0
691
- x = numpy.linspace(x_min, x_max, 500)
712
+ x = self._grid(2.0, extend=2.0)
713
+
692
714
  if not cartesian:
693
715
  # Evaluate slightly above the real line
694
716
  x = x.astype(complex)
@@ -803,7 +825,7 @@ class FreeForm(object):
803
825
  # ==========
804
826
 
805
827
  def decompress(self, size, x=None, max_iter=500, eigvals=True,
806
- tolerance=1e-9, seed=None, plot=False,
828
+ tolerance=1e-9, plot=False,
807
829
  latex=False, save=False):
808
830
  """
809
831
  Free decompression of spectral density.
@@ -828,9 +850,6 @@ class FreeForm(object):
828
850
  Tolerance for the solution obtained by the Newton solver. Also
829
851
  used for the finite difference approximation to the derivative.
830
852
 
831
- seed : int, default=None
832
- Seed for random number generator. Used for QMC sampling.
833
-
834
853
  plot : bool, default=False
835
854
  If `True`, density is plotted.
836
855
 
@@ -890,8 +909,339 @@ class FreeForm(object):
890
909
  plot_density(x, rho, support=(lb, ub),
891
910
  label='Decompression', latex=latex, save=save)
892
911
 
893
- if eigvals:
894
- eigs = numpy.sort(qmc_sample(x, rho, size, seed=seed))
895
- return x, rho, eigs
912
+ return x, rho
913
+
914
+ # ========
915
+ # eigvalsh
916
+ # ========
917
+
918
+ def eigvalsh(self, size=None, seed=None, **kwargs):
919
+ """
920
+ Estimate the eigenvalues.
921
+
922
+ This function estimates the eigenvalues of the freeform matrix
923
+ or a larger matrix containing it using free decompression.
924
+
925
+ Parameters
926
+ ----------
927
+
928
+ size : int, default=None
929
+ The size of the matrix containing :math:`\\mathbf{A}` to estimate
930
+ eigenvalues of. If None, returns estimates of the eigenvalues of
931
+ :math:`\\mathbf{A}` itself.
932
+
933
+ seed : int, default=None
934
+ The seed for the Quasi-Monte Carlo sampler.
935
+
936
+ **kwargs : dict, optional
937
+ Pass additional options to the underlying
938
+ :func:`FreeForm.decompress` function.
939
+
940
+ Returns
941
+ -------
942
+
943
+ eigs : numpy.array
944
+ Eigenvalues of decompressed matrix
945
+
946
+ See Also
947
+ --------
948
+
949
+ FreeForm.decompress
950
+ FreeForm.cond
951
+
952
+ Notes
953
+ -----
954
+
955
+ All arguments to the `.decompress()` procedure can be provided.
956
+
957
+ Examples
958
+ --------
959
+
960
+ .. code-block:: python
961
+ :emphasize-lines: 1
962
+
963
+ >>> from freealg import FreeForm
964
+ """
965
+
966
+ if size is None:
967
+ x = self._grid(1.25)
968
+ rho = self.density(x)
969
+ size = self.n
896
970
  else:
897
- return x, rho
971
+ x, rho = self.decompress(size, **kwargs)
972
+ eigs = numpy.sort(qmc_sample(x, rho, size, seed=seed))
973
+ return eigs
974
+
975
+ # ====
976
+ # cond
977
+ # ====
978
+
979
+ def cond(self, size=None, seed=None, **kwargs):
980
+ """
981
+ Estimate the condition number.
982
+
983
+ This function estimates the condition number of the matrix
984
+ :math:`\\mathbf{A}` or a larger matrix containing :math:`\\mathbf{A}`
985
+ using free decompression.
986
+
987
+ Parameters
988
+ ----------
989
+
990
+ size : int, default=None
991
+ The size of the matrix containing :math:`\\mathbf{A}` to estimate
992
+ eigenvalues of. If None, returns estimates of the eigenvalues of
993
+ :math:`\\mathbf{A}` itself.
994
+
995
+ **kwargs : dict, optional
996
+ Pass additional options to the underlying
997
+ :func:`FreeForm.decompress` function.
998
+
999
+ Returns
1000
+ -------
1001
+
1002
+ c : float
1003
+ Condition number
1004
+
1005
+ See Also
1006
+ --------
1007
+
1008
+ FreeForm.eigvalsh
1009
+ FreeForm.norm
1010
+ FreeForm.slogdet
1011
+ FreeForm.trace
1012
+
1013
+ Examples
1014
+ --------
1015
+
1016
+ .. code-block:: python
1017
+ :emphasize-lines: 1
1018
+
1019
+ >>> from freealg import FreeForm
1020
+ """
1021
+
1022
+ eigs = self.eigvalsh(size=size, **kwargs)
1023
+ return eigs.max() / eigs.min()
1024
+
1025
+ # =====
1026
+ # trace
1027
+ # =====
1028
+
1029
+ def trace(self, size=None, p=1.0, seed=None, **kwargs):
1030
+ """
1031
+ Estimate the trace of a power.
1032
+
1033
+ This function estimates the trace of the matrix power
1034
+ :math:`\\mathbf{A}^p` of the freeform or that of a larger matrix
1035
+ containing it.
1036
+
1037
+ Parameters
1038
+ ----------
1039
+
1040
+ size : int, default=None
1041
+ The size of the matrix containing :math:`\\mathbf{A}` to estimate
1042
+ eigenvalues of. If None, returns estimates of the eigenvalues of
1043
+ :math:`\\mathbf{A}` itself.
1044
+
1045
+ p : float, default=1.0
1046
+ The exponent :math:`p` in :math:`\\mathbf{A}^p`.
1047
+
1048
+ seed : int, default=None
1049
+ The seed for the Quasi-Monte Carlo sampler.
1050
+
1051
+ **kwargs : dict, optional
1052
+ Pass additional options to the underlying
1053
+ :func:`FreeForm.decompress` function.
1054
+
1055
+ Returns
1056
+ -------
1057
+
1058
+ trace : float
1059
+ matrix trace
1060
+
1061
+ See Also
1062
+ --------
1063
+
1064
+ FreeForm.eigvalsh
1065
+ FreeForm.cond
1066
+ FreeForm.slogdet
1067
+ FreeForm.norm
1068
+
1069
+ Notes
1070
+ -----
1071
+
1072
+ The trace is highly amenable to subsampling: under free decompression
1073
+ the average eigenvalue is assumed constant, so the trace increases
1074
+ linearly. Traces of powers fall back to :func:`eigvalsh`.
1075
+ All arguments to the `.decompress()` procedure can be provided.
1076
+
1077
+ Examples
1078
+ --------
1079
+
1080
+ .. code-block:: python
1081
+ :emphasize-lines: 6
1082
+
1083
+ >>> ...
1084
+ """
1085
+ if numpy.isclose(p, 1.0):
1086
+ return numpy.mean(self.eig) * (size / self.n)
1087
+
1088
+ eig = self.eigvalsh(size=size, seed=seed, **kwargs)
1089
+ return numpy.sum(eig ** p)
1090
+
1091
+ # =======
1092
+ # slogdet
1093
+ # =======
1094
+
1095
+ def slogdet(self, size=None, seed=None, **kwargs):
1096
+ """
1097
+ Estimate the sign and logarithm of the determinant.
1098
+
1099
+ This function estimates the *slogdet* of the freeform or that of
1100
+ a larger matrix containing it using free decompression.
1101
+
1102
+ Parameters
1103
+ ----------
1104
+
1105
+ size : int, default=None
1106
+ The size of the matrix containing :math:`\\mathbf{A}` to estimate
1107
+ eigenvalues of. If None, returns estimates of the eigenvalues of
1108
+ :math:`\\mathbf{A}` itself.
1109
+
1110
+ seed : int, default=None
1111
+ The seed for the Quasi-Monte Carlo sampler.
1112
+
1113
+ Returns
1114
+ -------
1115
+
1116
+ sign : float
1117
+ Sign of determinant
1118
+
1119
+ ld : float
1120
+ natural logarithm of the absolute value of the determinant
1121
+
1122
+ See Also
1123
+ --------
1124
+
1125
+ FreeForm.eigvalsh
1126
+ FreeForm.cond
1127
+ FreeForm.trace
1128
+ FreeForm.norm
1129
+
1130
+ Notes
1131
+ -----
1132
+
1133
+ All arguments to the `.decompress()` procedure can be provided.
1134
+
1135
+ Examples
1136
+ --------
1137
+
1138
+ .. code-block:: python
1139
+ :emphasize-lines: 6
1140
+
1141
+ >>> ...
1142
+ """
1143
+
1144
+ eigs = self.eigvalsh(size=size, seed=seed, **kwargs)
1145
+ sign = numpy.prod(numpy.sign(eigs))
1146
+ ld = numpy.sum(numpy.log(numpy.abs(eigs)))
1147
+ return sign, ld
1148
+
1149
+ # ====
1150
+ # norm
1151
+ # ====
1152
+
1153
+ def norm(self, size=None, order=2, seed=None, **kwargs):
1154
+ """
1155
+ Estimate the Schatten norm.
1156
+
1157
+ This function estimates the norm of the freeform or a larger
1158
+ matrix containing it using free decompression.
1159
+
1160
+ Parameters
1161
+ ----------
1162
+
1163
+ size : int, default=None
1164
+ The size of the matrix containing :math:`\\mathbf{A}` to estimate
1165
+ eigenvalues of. If None, returns estimates of the eigenvalues of
1166
+ :math:`\\mathbf{A}` itself.
1167
+
1168
+ order : {float, ``''inf``, ``'-inf'``, ``'fro'``, ``'nuc'``}, default=2
1169
+ Order of the norm.
1170
+
1171
+ * float :math:`p`: Schatten p-norm.
1172
+ * ``'inf'``: Largest absolute eigenvalue
1173
+ :math:`\\max \\vert \\lambda_i \\vert)`
1174
+ * ``'-inf'``: Smallest absolute eigenvalue
1175
+ :math:`\\min \\vert \\lambda_i \\vert)`
1176
+ * ``'fro'``: Frobenius norm corresponding to :math:`p=2`
1177
+ * ``'nuc'``: Nuclear (or trace) norm corresponding to :math:`p=1`
1178
+
1179
+ seed : int, default=None
1180
+ The seed for the Quasi-Monte Carlo sampler.
1181
+
1182
+ **kwargs : dict, optional
1183
+ Pass additional options to the underlying
1184
+ :func:`FreeForm.decompress` function.
1185
+
1186
+ Returns
1187
+ -------
1188
+
1189
+ norm : float
1190
+ matrix norm
1191
+
1192
+ See Also
1193
+ --------
1194
+
1195
+ FreeForm.eigvalsh
1196
+ FreeForm.cond
1197
+ FreeForm.slogdet
1198
+ FreeForm.trace
1199
+
1200
+ Notes
1201
+ -----
1202
+
1203
+ Thes Schatten :math:`p`-norm is defined by
1204
+
1205
+ .. math::
1206
+
1207
+ \\Vert \\mathbf{A} \\Vert_p = \\left(
1208
+ \\sum_{i=1}^N \\vert \\lambda_i \\vert^p \\right)^{1/p}.
1209
+
1210
+ Examples
1211
+ --------
1212
+
1213
+ .. code-block:: python
1214
+ :emphasize-lines: 6
1215
+
1216
+ >>> ...
1217
+ """
1218
+
1219
+ eigs = self.eigvalsh(size, seed=seed, **kwargs)
1220
+
1221
+ # Check order type and convert to float
1222
+ if order == 'nuc':
1223
+ order = 1
1224
+ elif order == 'fro':
1225
+ order = 2
1226
+ elif order == 'inf':
1227
+ order = float('inf')
1228
+ elif order == '-inf':
1229
+ order = -float('inf')
1230
+ elif not isinstance(order,
1231
+ (int, float, numpy.integer, numpy.floating)) \
1232
+ and not isinstance(order, (bool, numpy.bool_)):
1233
+ raise ValueError('"order" is invalid.')
1234
+
1235
+ # Compute norm
1236
+ if numpy.isinf(order) and not numpy.isneginf(order):
1237
+ norm_ = max(numpy.abs(eigs))
1238
+
1239
+ elif numpy.isneginf(order):
1240
+ norm_ = min(numpy.abs(eigs))
1241
+
1242
+ elif isinstance(order, (int, float, numpy.integer, numpy.floating)) \
1243
+ and not isinstance(order, (bool, numpy.bool_)):
1244
+ norm_q = numpy.sum(numpy.abs(eigs)**order)
1245
+ norm_ = norm_q**(1.0 / order)
1246
+
1247
+ return norm_
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: freealg
3
- Version: 0.3.5
3
+ Version: 0.4.0
4
4
  Summary: Free probability for large matrices
5
5
  Home-page: https://github.com/ameli/freealg
6
6
  Download-URL: https://github.com/ameli/freealg/archive/main.zip
@@ -102,10 +102,10 @@ using a much smaller Wishart matrix.
102
102
  >>> import freealg as fa
103
103
  >>> mp = fa.distributions.MarchenkoPastur(1/50) # Wishart matrices with aspect ratio 1/50
104
104
  >>> A = mp.matrix(1000) # Sample a 1000 x 1000 Wishart matrix
105
- >>> eigs = fa.eigfree(A, 100_000) # Estimate the eigenvalues of 100000 x 100000
105
+ >>> eigs = fa.eigvalsh(A, 100_000) # Estimate the eigenvalues of 100000 x 100000
106
106
 
107
107
  For more details on how to interface with *freealg* check out the
108
- `Quick Start Guide <https://github.com/ameli/freealg/blob/main/notebooks/quick_start.ipynb>`__.
108
+ `Live Demo <https://colab.research.google.com/github/ameli/freealg/blob/main/notebooks/quick_start.ipynb>`__.
109
109
 
110
110
 
111
111
  Test
@@ -129,7 +129,7 @@ How to Contribute
129
129
  =================
130
130
 
131
131
  We welcome contributions via GitHub's pull request. Developers should review
132
- our [Contributing Guidelines](https://github.com/ameli/freealg/blob/main/CONTRIBUTING.rst)
132
+ our `Contributing Guidelines <https://github.com/ameli/freealg/blob/main/CONTRIBUTING.rst>`__
133
133
  before submitting their code. If you do not feel comfortable modifying the
134
134
  code, we also welcome feature requests and bug reports.
135
135
 
@@ -1,25 +1,25 @@
1
- freealg/__init__.py,sha256=AM0G2tX7sBgzCTcOVbWynA9NFkQZKyphL9IR1tKOoK4,614
2
- freealg/__version__.py,sha256=ThnCuF3X7rsQSd5PAea_jfYA70ZmhLvkFcLBxBPwZnY,22
1
+ freealg/__init__.py,sha256=KfzqG7qig6ZZCKqgHcC2ApTg4rTLkrbJsvVoJd8UFG8,625
2
+ freealg/__version__.py,sha256=42STGor_9nKYXumfeV5tiyD_M8VdcddX7CEexmibPBk,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
6
6
  freealg/_jacobi.py,sha256=AT4ONSHGGDxVKE3MGMLyMR8uDFiO-e9u3x5udYfdJJk,5635
7
+ freealg/_linalg.py,sha256=Vl1iB0rG-PVjEqoUbCXNxk6BmeujEbBucG2ZdBJoFjA,12490
7
8
  freealg/_pade.py,sha256=Diw850oH2OLQeUrBR-q19TmjSBoBvXl6ogp4o1s2UIo,15184
8
9
  freealg/_plot_util.py,sha256=U4alp7Pzg315_7jJdu1UB0tIUcxUovQgHDHsUYoa2Z0,19728
9
10
  freealg/_sample.py,sha256=ckC75eqv-mRP1F5BnhvsjfLTaoAzHK8bebl9bCRZYDo,2561
10
11
  freealg/_support.py,sha256=mYlrsdLbniqFgFofbHrZIiYSyJudPqtyMQQTPBD9Y6M,6439
11
12
  freealg/_util.py,sha256=8Tvz-XODtKYoU76ODmF1TBaIYLlr6-AXiyoMDwDSxVg,3779
12
- freealg/eigh.py,sha256=ybUCE8Qi-H8r-QxDvbeSP9Ow-q8xTuq5o-LNhPvBvIE,10926
13
- freealg/freeform.py,sha256=8emyCQ6AUjp_HB1gWQ-ecddlDgfxHGr3PqXSyoPxeMo,28593
13
+ freealg/freeform.py,sha256=8yW7dwuUeQ52ewovhnpGbXZrpEZssuUj4djVoD5K2Iw,37065
14
14
  freealg/distributions/__init__.py,sha256=t_yZyEkW_W_tSV9IvgYXtVASxD2BEdiNVXcV2ebMy8M,579
15
15
  freealg/distributions/_kesten_mckay.py,sha256=210RF2OQEYLZBeLB6wmbdHnZPs_9ldDNHm_FMlg5tis,19881
16
16
  freealg/distributions/_marchenko_pastur.py,sha256=kchFccRMuVF2Cus_99vdEwuRimkHzEUV8xt5kZFg7ZI,16994
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.5.dist-info/licenses/AUTHORS.txt,sha256=0b67Nz4_JgIzUupHJTAZxu5QdSUM_HRM_X_w4xCb17o,30
21
- freealg-0.3.5.dist-info/licenses/LICENSE.txt,sha256=J-EEYEtxb3VVf_Bn1TYfWnpY5lMFIM15iLDDcnaDTPA,1443
22
- freealg-0.3.5.dist-info/METADATA,sha256=8RiG0kyAzVeL0pvXV-xAZ8LMlYNFPzwqOg5kHlZeGno,4977
23
- freealg-0.3.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
24
- freealg-0.3.5.dist-info/top_level.txt,sha256=eR2wrgYwDdnnJ9Zf5PruPqe4kQav0GMvRsqct6y00Q8,8
25
- freealg-0.3.5.dist-info/RECORD,,
20
+ freealg-0.4.0.dist-info/licenses/AUTHORS.txt,sha256=0b67Nz4_JgIzUupHJTAZxu5QdSUM_HRM_X_w4xCb17o,30
21
+ freealg-0.4.0.dist-info/licenses/LICENSE.txt,sha256=J-EEYEtxb3VVf_Bn1TYfWnpY5lMFIM15iLDDcnaDTPA,1443
22
+ freealg-0.4.0.dist-info/METADATA,sha256=6R-LP2gEEp1C7RvoSg1Nc_tMiGUSPEoHH-HpxR1gNM4,4994
23
+ freealg-0.4.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
24
+ freealg-0.4.0.dist-info/top_level.txt,sha256=eR2wrgYwDdnnJ9Zf5PruPqe4kQav0GMvRsqct6y00Q8,8
25
+ freealg-0.4.0.dist-info/RECORD,,