freealg 0.7.16__py3-none-any.whl → 0.7.18__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.
Files changed (52) hide show
  1. freealg/__init__.py +8 -6
  2. freealg/__version__.py +1 -1
  3. freealg/_algebraic_form/_branch_points.py +18 -18
  4. freealg/_algebraic_form/_continuation_algebraic.py +13 -13
  5. freealg/_algebraic_form/_cusp.py +15 -15
  6. freealg/_algebraic_form/_cusp_wrap.py +6 -6
  7. freealg/_algebraic_form/_decompress.py +16 -16
  8. freealg/_algebraic_form/_decompress4.py +31 -31
  9. freealg/_algebraic_form/_decompress5.py +23 -23
  10. freealg/_algebraic_form/_decompress6.py +13 -13
  11. freealg/_algebraic_form/_decompress7.py +15 -15
  12. freealg/_algebraic_form/_decompress8.py +17 -17
  13. freealg/_algebraic_form/_decompress9.py +18 -18
  14. freealg/_algebraic_form/_decompress_new.py +17 -17
  15. freealg/_algebraic_form/_decompress_new_2.py +57 -57
  16. freealg/_algebraic_form/_decompress_util.py +10 -10
  17. freealg/_algebraic_form/_decompressible.py +292 -0
  18. freealg/_algebraic_form/_edge.py +10 -10
  19. freealg/_algebraic_form/_homotopy4.py +9 -9
  20. freealg/_algebraic_form/_homotopy5.py +9 -9
  21. freealg/_algebraic_form/_support.py +19 -19
  22. freealg/_algebraic_form/algebraic_form.py +262 -468
  23. freealg/_base_form.py +401 -0
  24. freealg/_free_form/__init__.py +1 -4
  25. freealg/_free_form/_density_util.py +1 -1
  26. freealg/_free_form/_plot_util.py +3 -511
  27. freealg/_free_form/free_form.py +8 -367
  28. freealg/_util.py +59 -11
  29. freealg/distributions/__init__.py +2 -1
  30. freealg/distributions/_base_distribution.py +163 -0
  31. freealg/distributions/_chiral_block.py +137 -11
  32. freealg/distributions/_compound_poisson.py +168 -64
  33. freealg/distributions/_deformed_marchenko_pastur.py +137 -88
  34. freealg/distributions/_deformed_wigner.py +92 -40
  35. freealg/distributions/_fuss_catalan.py +269 -0
  36. freealg/distributions/_kesten_mckay.py +4 -130
  37. freealg/distributions/_marchenko_pastur.py +8 -196
  38. freealg/distributions/_meixner.py +4 -130
  39. freealg/distributions/_wachter.py +4 -130
  40. freealg/distributions/_wigner.py +10 -127
  41. freealg/visualization/__init__.py +2 -2
  42. freealg/visualization/{_rgb_hsv.py → _domain_coloring.py} +37 -29
  43. freealg/visualization/_plot_util.py +513 -0
  44. {freealg-0.7.16.dist-info → freealg-0.7.18.dist-info}/METADATA +1 -1
  45. freealg-0.7.18.dist-info/RECORD +74 -0
  46. freealg-0.7.16.dist-info/RECORD +0 -69
  47. /freealg/{_free_form/_sample.py → _sample.py} +0 -0
  48. /freealg/{_free_form/_support.py → _support.py} +0 -0
  49. {freealg-0.7.16.dist-info → freealg-0.7.18.dist-info}/WHEEL +0 -0
  50. {freealg-0.7.16.dist-info → freealg-0.7.18.dist-info}/licenses/AUTHORS.txt +0 -0
  51. {freealg-0.7.16.dist-info → freealg-0.7.18.dist-info}/licenses/LICENSE.txt +0 -0
  52. {freealg-0.7.16.dist-info → freealg-0.7.18.dist-info}/top_level.txt +0 -0
freealg/_base_form.py ADDED
@@ -0,0 +1,401 @@
1
+ # SPDX-FileCopyrightText: Copyright 2026, 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 resolve_complex_dtype
16
+ from ._sample import sample
17
+
18
+ __all__ = ['BaseForm']
19
+
20
+
21
+ # =========
22
+ # Base Form
23
+ # =========
24
+
25
+ class BaseForm(object):
26
+ """
27
+ Base for other "Form" classes. This class itself not a part of API, but the
28
+ inheritted member methods are exposed to the API.
29
+ """
30
+
31
+ # ====
32
+ # init
33
+ # ====
34
+
35
+ def __init__(self, delta, dtype='complex128'):
36
+
37
+ self.A = None
38
+ self.eig = None
39
+ self.delta = delta # Offset above real axis to apply Plemelj formula
40
+ self.n = None
41
+ self.lam_m = None
42
+ self.lam_p = None
43
+
44
+ # Data type for complex arrays
45
+ self.dtype = resolve_complex_dtype(dtype)
46
+
47
+ # =============
48
+ # generate grid
49
+ # =============
50
+
51
+ def _generate_grid(self, scale, extend=1.0, N=500):
52
+ """
53
+ Generate a grid of points to evaluate density / Hilbert / Stieltjes
54
+ transforms.
55
+ """
56
+
57
+ radius = 0.5 * (self.lam_p - self.lam_m)
58
+ center = 0.5 * (self.lam_p + self.lam_m)
59
+
60
+ x_min = numpy.floor(extend * (center - extend * radius * scale))
61
+ x_max = numpy.ceil(extend * (center + extend * radius * scale))
62
+
63
+ x_min /= extend
64
+ x_max /= extend
65
+
66
+ return numpy.linspace(x_min, x_max, N)
67
+
68
+ # ========
69
+ # eigvalsh
70
+ # ========
71
+
72
+ def eigvalsh(self, size=None, seed=None, **kwargs):
73
+ """
74
+ Estimate the eigenvalues.
75
+
76
+ This function estimates the eigenvalues of the freeform matrix
77
+ or a larger matrix containing it using free decompression.
78
+
79
+ Parameters
80
+ ----------
81
+
82
+ size : int, default=None
83
+ The size of the matrix containing :math:`\\mathbf{A}` to estimate
84
+ eigenvalues of. If None, returns estimates of the eigenvalues of
85
+ :math:`\\mathbf{A}` itself.
86
+
87
+ seed : int, default=None
88
+ The seed for the Quasi-Monte Carlo sampler.
89
+
90
+ **kwargs : dict, optional
91
+ Pass additional options to the underlying
92
+ :func:`FreeForm.decompress` function.
93
+
94
+ Returns
95
+ -------
96
+
97
+ eigs : numpy.array
98
+ Eigenvalues of decompressed matrix
99
+
100
+ See Also
101
+ --------
102
+
103
+ FreeForm.decompress
104
+ FreeForm.cond
105
+
106
+ Notes
107
+ -----
108
+
109
+ All arguments to the :func:`decompress` procedure can be provided.
110
+
111
+ Examples
112
+ --------
113
+
114
+ .. code-block:: python
115
+ :emphasize-lines: 1
116
+
117
+ >>> from freealg import FreeForm
118
+ """
119
+
120
+ if size is None:
121
+ size = self.n
122
+
123
+ rho, x = self.decompress(size, **kwargs)
124
+ eigs = numpy.sort(sample(x, rho, size, method='qmc', seed=seed))
125
+
126
+ return eigs
127
+
128
+ # ====
129
+ # cond
130
+ # ====
131
+
132
+ def cond(self, size=None, seed=None, **kwargs):
133
+ """
134
+ Estimate the condition number.
135
+
136
+ This function estimates the condition number of the matrix
137
+ :math:`\\mathbf{A}` or a larger matrix containing :math:`\\mathbf{A}`
138
+ using free decompression.
139
+
140
+ Parameters
141
+ ----------
142
+
143
+ size : int, default=None
144
+ The size of the matrix containing :math:`\\mathbf{A}` to estimate
145
+ eigenvalues of. If None, returns estimates of the eigenvalues of
146
+ :math:`\\mathbf{A}` itself.
147
+
148
+ **kwargs : dict, optional
149
+ Pass additional options to the underlying
150
+ :func:`FreeForm.decompress` function.
151
+
152
+ Returns
153
+ -------
154
+
155
+ c : float
156
+ Condition number
157
+
158
+ See Also
159
+ --------
160
+
161
+ FreeForm.eigvalsh
162
+ FreeForm.norm
163
+ FreeForm.slogdet
164
+ FreeForm.trace
165
+
166
+ Examples
167
+ --------
168
+
169
+ .. code-block:: python
170
+ :emphasize-lines: 1
171
+
172
+ >>> from freealg import FreeForm
173
+ """
174
+
175
+ eigs = self.eigvalsh(size=size, **kwargs)
176
+ return eigs.max() / eigs.min()
177
+
178
+ # =====
179
+ # trace
180
+ # =====
181
+
182
+ def trace(self, size=None, p=1.0, seed=None, **kwargs):
183
+ """
184
+ Estimate the trace of a power.
185
+
186
+ This function estimates the trace of the matrix power
187
+ :math:`\\mathbf{A}^p` of the freeform or that of a larger matrix
188
+ containing it.
189
+
190
+ Parameters
191
+ ----------
192
+
193
+ size : int, default=None
194
+ The size of the matrix containing :math:`\\mathbf{A}` to estimate
195
+ eigenvalues of. If None, returns estimates of the eigenvalues of
196
+ :math:`\\mathbf{A}` itself.
197
+
198
+ p : float, default=1.0
199
+ The exponent :math:`p` in :math:`\\mathbf{A}^p`.
200
+
201
+ seed : int, default=None
202
+ The seed for the Quasi-Monte Carlo sampler.
203
+
204
+ **kwargs : dict, optional
205
+ Pass additional options to the underlying
206
+ :func:`FreeForm.decompress` function.
207
+
208
+ Returns
209
+ -------
210
+
211
+ trace : float
212
+ matrix trace
213
+
214
+ See Also
215
+ --------
216
+
217
+ FreeForm.eigvalsh
218
+ FreeForm.cond
219
+ FreeForm.slogdet
220
+ FreeForm.norm
221
+
222
+ Notes
223
+ -----
224
+
225
+ The trace is highly amenable to subsampling: under free decompression
226
+ the average eigenvalue is assumed constant, so the trace increases
227
+ linearly. Traces of powers fall back to :func:`eigvalsh`.
228
+ All arguments to the `.decompress()` procedure can be provided.
229
+
230
+ Examples
231
+ --------
232
+
233
+ .. code-block:: python
234
+ :emphasize-lines: 1
235
+
236
+ >>> from freealg import FreeForm
237
+ """
238
+
239
+ if numpy.isclose(p, 1.0):
240
+ return numpy.mean(self.eig) * (size / self.n)
241
+
242
+ eig = self.eigvalsh(size=size, seed=seed, **kwargs)
243
+ return numpy.sum(eig ** p)
244
+
245
+ # =======
246
+ # slogdet
247
+ # =======
248
+
249
+ def slogdet(self, size=None, seed=None, **kwargs):
250
+ """
251
+ Estimate the sign and logarithm of the determinant.
252
+
253
+ This function estimates the *slogdet* of the freeform or that of
254
+ a larger matrix containing it using free decompression.
255
+
256
+ Parameters
257
+ ----------
258
+
259
+ size : int, default=None
260
+ The size of the matrix containing :math:`\\mathbf{A}` to estimate
261
+ eigenvalues of. If None, returns estimates of the eigenvalues of
262
+ :math:`\\mathbf{A}` itself.
263
+
264
+ seed : int, default=None
265
+ The seed for the Quasi-Monte Carlo sampler.
266
+
267
+ Returns
268
+ -------
269
+
270
+ sign : float
271
+ Sign of determinant
272
+
273
+ ld : float
274
+ natural logarithm of the absolute value of the determinant
275
+
276
+ See Also
277
+ --------
278
+
279
+ FreeForm.eigvalsh
280
+ FreeForm.cond
281
+ FreeForm.trace
282
+ FreeForm.norm
283
+
284
+ Notes
285
+ -----
286
+
287
+ All arguments to the `.decompress()` procedure can be provided.
288
+
289
+ Examples
290
+ --------
291
+
292
+ .. code-block:: python
293
+ :emphasize-lines: 1
294
+
295
+ >>> from freealg import FreeForm
296
+ """
297
+
298
+ eigs = self.eigvalsh(size=size, seed=seed, **kwargs)
299
+ sign = numpy.prod(numpy.sign(eigs))
300
+ ld = numpy.sum(numpy.log(numpy.abs(eigs)))
301
+ return sign, ld
302
+
303
+ # ====
304
+ # norm
305
+ # ====
306
+
307
+ def norm(self, size=None, order=2, seed=None, **kwargs):
308
+ """
309
+ Estimate the Schatten norm.
310
+
311
+ This function estimates the norm of the freeform or a larger
312
+ matrix containing it using free decompression.
313
+
314
+ Parameters
315
+ ----------
316
+
317
+ size : int, default=None
318
+ The size of the matrix containing :math:`\\mathbf{A}` to estimate
319
+ eigenvalues of. If None, returns estimates of the eigenvalues of
320
+ :math:`\\mathbf{A}` itself.
321
+
322
+ order : {float, ``''inf``, ``'-inf'``, ``'fro'``, ``'nuc'``}, default=2
323
+ Order of the norm.
324
+
325
+ * float :math:`p`: Schatten p-norm.
326
+ * ``'inf'``: Largest absolute eigenvalue
327
+ :math:`\\max \\vert \\lambda_i \\vert)`
328
+ * ``'-inf'``: Smallest absolute eigenvalue
329
+ :math:`\\min \\vert \\lambda_i \\vert)`
330
+ * ``'fro'``: Frobenius norm corresponding to :math:`p=2`
331
+ * ``'nuc'``: Nuclear (or trace) norm corresponding to :math:`p=1`
332
+
333
+ seed : int, default=None
334
+ The seed for the Quasi-Monte Carlo sampler.
335
+
336
+ **kwargs : dict, optional
337
+ Pass additional options to the underlying
338
+ :func:`FreeForm.decompress` function.
339
+
340
+ Returns
341
+ -------
342
+
343
+ norm : float
344
+ matrix norm
345
+
346
+ See Also
347
+ --------
348
+
349
+ FreeForm.eigvalsh
350
+ FreeForm.cond
351
+ FreeForm.slogdet
352
+ FreeForm.trace
353
+
354
+ Notes
355
+ -----
356
+
357
+ Thes Schatten :math:`p`-norm is defined by
358
+
359
+ .. math::
360
+
361
+ \\Vert \\mathbf{A} \\Vert_p = \\left(
362
+ \\sum_{i=1}^N \\vert \\lambda_i \\vert^p \\right)^{1/p}.
363
+
364
+ Examples
365
+ --------
366
+
367
+ .. code-block:: python
368
+ :emphasize-lines: 1
369
+
370
+ >>> from freealg import FreeForm
371
+ """
372
+
373
+ eigs = self.eigvalsh(size, seed=seed, **kwargs)
374
+
375
+ # Check order type and convert to float
376
+ if order == 'nuc':
377
+ order = 1
378
+ elif order == 'fro':
379
+ order = 2
380
+ elif order == 'inf':
381
+ order = float('inf')
382
+ elif order == '-inf':
383
+ order = -float('inf')
384
+ elif not isinstance(order,
385
+ (int, float, numpy.integer, numpy.floating)) \
386
+ and not isinstance(order, (bool, numpy.bool_)):
387
+ raise ValueError('"order" is invalid.')
388
+
389
+ # Compute norm
390
+ if numpy.isinf(order) and not numpy.isneginf(order):
391
+ norm_ = max(numpy.abs(eigs))
392
+
393
+ elif numpy.isneginf(order):
394
+ norm_ = min(numpy.abs(eigs))
395
+
396
+ elif isinstance(order, (int, float, numpy.integer, numpy.floating)) \
397
+ and not isinstance(order, (bool, numpy.bool_)):
398
+ norm_q = numpy.sum(numpy.abs(eigs)**order)
399
+ norm_ = norm_q**(1.0 / order)
400
+
401
+ return norm_
@@ -8,9 +8,6 @@
8
8
 
9
9
  from .free_form import FreeForm
10
10
  from ._linalg import eigvalsh, cond, norm, trace, slogdet
11
- from ._support import supp
12
- from ._sample import sample
13
11
  from ._density_util import kde
14
12
 
15
- __all__ = ['FreeForm', 'eigvalsh', 'cond', 'norm', 'trace', 'slogdet', 'supp',
16
- 'sample', 'kde']
13
+ __all__ = ['FreeForm', 'eigvalsh', 'cond', 'norm', 'trace', 'slogdet', 'kde']
@@ -18,7 +18,7 @@ from scipy.stats import beta
18
18
  from scipy.optimize import minimize
19
19
  import matplotlib.pyplot as plt
20
20
  import texplot
21
- from ._plot_util import _auto_bins
21
+ from ..visualization._plot_util import _auto_bins
22
22
 
23
23
  # Fallback to previous API
24
24
  if not hasattr(numpy, 'trapezoid'):