freealg 0.1.11__py3-none-any.whl → 0.7.12__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 +8 -2
- freealg/__version__.py +1 -1
- freealg/_algebraic_form/__init__.py +12 -0
- freealg/_algebraic_form/_branch_points.py +288 -0
- freealg/_algebraic_form/_constraints.py +139 -0
- freealg/_algebraic_form/_continuation_algebraic.py +706 -0
- freealg/_algebraic_form/_decompress.py +641 -0
- freealg/_algebraic_form/_decompress2.py +204 -0
- freealg/_algebraic_form/_edge.py +330 -0
- freealg/_algebraic_form/_homotopy.py +323 -0
- freealg/_algebraic_form/_moments.py +448 -0
- freealg/_algebraic_form/_sheets_util.py +145 -0
- freealg/_algebraic_form/_support.py +309 -0
- freealg/_algebraic_form/algebraic_form.py +1232 -0
- freealg/_free_form/__init__.py +16 -0
- freealg/{_chebyshev.py → _free_form/_chebyshev.py} +75 -43
- freealg/_free_form/_decompress.py +993 -0
- freealg/_free_form/_density_util.py +243 -0
- freealg/_free_form/_jacobi.py +359 -0
- freealg/_free_form/_linalg.py +508 -0
- freealg/{_pade.py → _free_form/_pade.py} +42 -208
- freealg/{_plot_util.py → _free_form/_plot_util.py} +37 -22
- freealg/{_sample.py → _free_form/_sample.py} +58 -22
- freealg/_free_form/_series.py +454 -0
- freealg/_free_form/_support.py +214 -0
- freealg/_free_form/free_form.py +1362 -0
- freealg/_geometric_form/__init__.py +13 -0
- freealg/_geometric_form/_continuation_genus0.py +175 -0
- freealg/_geometric_form/_continuation_genus1.py +275 -0
- freealg/_geometric_form/_elliptic_functions.py +174 -0
- freealg/_geometric_form/_sphere_maps.py +63 -0
- freealg/_geometric_form/_torus_maps.py +118 -0
- freealg/_geometric_form/geometric_form.py +1094 -0
- freealg/_util.py +56 -110
- freealg/distributions/__init__.py +7 -1
- freealg/distributions/_chiral_block.py +494 -0
- freealg/distributions/_deformed_marchenko_pastur.py +726 -0
- freealg/distributions/_deformed_wigner.py +386 -0
- freealg/distributions/_kesten_mckay.py +29 -15
- freealg/distributions/_marchenko_pastur.py +224 -95
- freealg/distributions/_meixner.py +47 -37
- freealg/distributions/_wachter.py +29 -17
- freealg/distributions/_wigner.py +27 -14
- freealg/visualization/__init__.py +12 -0
- freealg/visualization/_glue_util.py +32 -0
- freealg/visualization/_rgb_hsv.py +125 -0
- freealg-0.7.12.dist-info/METADATA +172 -0
- freealg-0.7.12.dist-info/RECORD +53 -0
- {freealg-0.1.11.dist-info → freealg-0.7.12.dist-info}/WHEEL +1 -1
- freealg/_decompress.py +0 -180
- freealg/_jacobi.py +0 -218
- freealg/_support.py +0 -85
- freealg/freeform.py +0 -967
- freealg-0.1.11.dist-info/METADATA +0 -140
- freealg-0.1.11.dist-info/RECORD +0 -24
- /freealg/{_damp.py → _free_form/_damp.py} +0 -0
- {freealg-0.1.11.dist-info → freealg-0.7.12.dist-info}/licenses/AUTHORS.txt +0 -0
- {freealg-0.1.11.dist-info → freealg-0.7.12.dist-info}/licenses/LICENSE.txt +0 -0
- {freealg-0.1.11.dist-info → freealg-0.7.12.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,16 @@
|
|
|
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
|
|
6
|
+
# under the terms of the license found in the LICENSE.txt file in the root
|
|
7
|
+
# directory of this source tree.
|
|
8
|
+
|
|
9
|
+
from .free_form import FreeForm
|
|
10
|
+
from ._linalg import eigvalsh, cond, norm, trace, slogdet
|
|
11
|
+
from ._support import supp
|
|
12
|
+
from ._sample import sample
|
|
13
|
+
from ._density_util import kde
|
|
14
|
+
|
|
15
|
+
__all__ = ['FreeForm', 'eigvalsh', 'cond', 'norm', 'trace', 'slogdet', 'supp',
|
|
16
|
+
'sample', 'kde']
|
|
@@ -13,10 +13,11 @@
|
|
|
13
13
|
|
|
14
14
|
import numpy
|
|
15
15
|
from scipy.special import eval_chebyu
|
|
16
|
-
from .
|
|
16
|
+
from ._series import partial_sum, wynn_epsilon, wynn_rho, levin_u, \
|
|
17
|
+
weniger_delta, brezinski_theta
|
|
17
18
|
|
|
18
19
|
__all__ = ['chebyshev_sample_proj', 'chebyshev_kernel_proj',
|
|
19
|
-
'
|
|
20
|
+
'chebyshev_density', 'chebyshev_stieltjes']
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
# =====================
|
|
@@ -29,7 +30,7 @@ def chebyshev_sample_proj(eig, support, K=10, reg=0.0):
|
|
|
29
30
|
|
|
30
31
|
\\rho(x) = w(t) \\sum_{k=0}^K \\psi_k U_k(t),
|
|
31
32
|
|
|
32
|
-
where t = (2x
|
|
33
|
+
where t = (2x-(\\lambda_{-} + \\lambda_{+}))/ (\\lambda_{+} - \\lambda_{-})
|
|
33
34
|
in [-1, 1] and w(t) = \\sqrt{(1 - t^2}.
|
|
34
35
|
|
|
35
36
|
Parameters
|
|
@@ -42,10 +43,10 @@ def chebyshev_sample_proj(eig, support, K=10, reg=0.0):
|
|
|
42
43
|
The assumed compact support of rho.
|
|
43
44
|
|
|
44
45
|
K : int
|
|
45
|
-
Highest Chebyshev
|
|
46
|
+
Highest Chebyshev-II order.
|
|
46
47
|
|
|
47
48
|
reg : float
|
|
48
|
-
Tikhonov
|
|
49
|
+
Tikhonov-style ridge on each coefficient (defaults to 0).
|
|
49
50
|
|
|
50
51
|
Returns
|
|
51
52
|
-------
|
|
@@ -56,11 +57,10 @@ def chebyshev_sample_proj(eig, support, K=10, reg=0.0):
|
|
|
56
57
|
|
|
57
58
|
lam_m, lam_p = support
|
|
58
59
|
|
|
59
|
-
# Map to [
|
|
60
|
+
# Map to [-1,1] interval
|
|
60
61
|
t = (2 * eig - (lam_m + lam_p)) / (lam_p - lam_m)
|
|
61
|
-
N = eig.size
|
|
62
62
|
|
|
63
|
-
# Inner
|
|
63
|
+
# Inner-product norm of each U_k under w(t) = sqrt{1-t^2} is \\pi/2
|
|
64
64
|
norm = numpy.pi / 2
|
|
65
65
|
|
|
66
66
|
psi = numpy.empty(K+1)
|
|
@@ -92,19 +92,19 @@ def chebyshev_kernel_proj(xs, pdf, support, K=10, reg=0.0):
|
|
|
92
92
|
Projection of a *continuous* density given on a grid (xs, pdf)
|
|
93
93
|
onto the Chebyshev-II basis.
|
|
94
94
|
|
|
95
|
-
xs : 1-D numpy array (original x
|
|
95
|
+
xs : 1-D numpy array (original x-axis, not the t-variable)
|
|
96
96
|
pdf : same shape as xs, integrates to 1 on xs
|
|
97
97
|
"""
|
|
98
98
|
|
|
99
99
|
lam_m, lam_p = support
|
|
100
|
-
t = (2.0 * xs - (lam_m + lam_p)) / (lam_p - lam_m) # map to [
|
|
100
|
+
t = (2.0 * xs - (lam_m + lam_p)) / (lam_p - lam_m) # map to [-1,1]
|
|
101
101
|
|
|
102
102
|
norm = numpy.pi / 2.0
|
|
103
103
|
psi = numpy.empty(K + 1)
|
|
104
104
|
|
|
105
105
|
for k in range(K + 1):
|
|
106
106
|
Pk = eval_chebyu(k, t) # U_k(t) on the grid
|
|
107
|
-
moment = numpy.trapezoid(Pk * pdf, xs)
|
|
107
|
+
moment = numpy.trapezoid(Pk * pdf, xs) # \int U_k(t) \rho(x) dx
|
|
108
108
|
|
|
109
109
|
if k == 0:
|
|
110
110
|
penalty = 0
|
|
@@ -116,11 +116,11 @@ def chebyshev_kernel_proj(xs, pdf, support, K=10, reg=0.0):
|
|
|
116
116
|
return psi
|
|
117
117
|
|
|
118
118
|
|
|
119
|
-
#
|
|
120
|
-
# chebyshev
|
|
121
|
-
#
|
|
119
|
+
# =================
|
|
120
|
+
# chebyshev density
|
|
121
|
+
# =================
|
|
122
122
|
|
|
123
|
-
def
|
|
123
|
+
def chebyshev_density(x, psi, support):
|
|
124
124
|
"""
|
|
125
125
|
Given \\psi_k, evaluate the approximate density \\rho(x).
|
|
126
126
|
|
|
@@ -140,15 +140,15 @@ def chebyshev_approx(x, psi, support):
|
|
|
140
140
|
-------
|
|
141
141
|
|
|
142
142
|
rho_x : ndarray, same shape as x
|
|
143
|
-
Approximated spectral density on the original x
|
|
143
|
+
Approximated spectral density on the original x-axis.
|
|
144
144
|
"""
|
|
145
145
|
|
|
146
146
|
lam_m, lam_p = support
|
|
147
147
|
|
|
148
|
-
# Map to [
|
|
148
|
+
# Map to [-1,1] interval
|
|
149
149
|
t = (2 * numpy.asarray(x) - (lam_m + lam_p)) / (lam_p - lam_m)
|
|
150
150
|
|
|
151
|
-
# Weight sqrt{1
|
|
151
|
+
# Weight sqrt{1-t^2} (clip for numerical safety)
|
|
152
152
|
w = numpy.sqrt(numpy.clip(1 - t**2, a_min=0, a_max=None))
|
|
153
153
|
|
|
154
154
|
# Summation approximation
|
|
@@ -165,22 +165,23 @@ def chebyshev_approx(x, psi, support):
|
|
|
165
165
|
# chebushev stieltjes
|
|
166
166
|
# ===================
|
|
167
167
|
|
|
168
|
-
def chebyshev_stieltjes(z, psi, support
|
|
168
|
+
def chebyshev_stieltjes(z, psi, support, continuation='pade',
|
|
169
|
+
dtype=numpy.complex128):
|
|
169
170
|
"""
|
|
170
|
-
Compute the Stieltjes transform m(z) for a Chebyshev
|
|
171
|
+
Compute the Stieltjes transform m(z) for a Chebyshev-II expansion
|
|
171
172
|
|
|
172
|
-
rho(x) = (2/(lam_p - lam_m)) * sqrt(1
|
|
173
|
+
rho(x) = (2/(lam_p - lam_m)) * sqrt(1-t(x)^2) * sum_{k=0}^K psi_k U_k(t(x))
|
|
173
174
|
|
|
174
|
-
via the closed
|
|
175
|
+
via the closed-form
|
|
175
176
|
|
|
176
|
-
\\int_{-1}^1 U_k(t) sqrt(1
|
|
177
|
+
\\int_{-1}^1 U_k(t) sqrt(1-t^2)/(u - t) dt = \\pi J(u)^(k+1),
|
|
177
178
|
|
|
178
179
|
where
|
|
179
180
|
|
|
180
|
-
u = (2(z
|
|
181
|
+
u = (2(z-center))/span,
|
|
181
182
|
center = (lam_p + lam_m)/2,
|
|
182
183
|
span = lam_p - lam_m,
|
|
183
|
-
J(u) = u
|
|
184
|
+
J(u) = u - sqrt(u^2-1)
|
|
184
185
|
|
|
185
186
|
and then
|
|
186
187
|
|
|
@@ -193,11 +194,17 @@ def chebyshev_stieltjes(z, psi, support):
|
|
|
193
194
|
Points in the complex plane.
|
|
194
195
|
|
|
195
196
|
psi : array_like, shape (K+1,)
|
|
196
|
-
Chebyshev
|
|
197
|
+
Chebyshev-II coefficients \\psi.
|
|
197
198
|
|
|
198
199
|
support : tuple
|
|
199
200
|
The support interval of the original density.
|
|
200
201
|
|
|
202
|
+
continuation : str, default= ``'pade'``
|
|
203
|
+
Methof of analytiv continuation.
|
|
204
|
+
|
|
205
|
+
dtype : numpy.type, default=numpy.complex128
|
|
206
|
+
Data type for complex arrays. This might enhance series acceleration.
|
|
207
|
+
|
|
201
208
|
Returns
|
|
202
209
|
-------
|
|
203
210
|
|
|
@@ -205,35 +212,60 @@ def chebyshev_stieltjes(z, psi, support):
|
|
|
205
212
|
The Stieltjes transform m(z) on the same shape as z.
|
|
206
213
|
"""
|
|
207
214
|
|
|
208
|
-
z = numpy.asarray(z, dtype=
|
|
215
|
+
z = numpy.asarray(z, dtype=dtype)
|
|
216
|
+
|
|
209
217
|
lam_m, lam_p = support
|
|
210
218
|
span = lam_p - lam_m
|
|
211
219
|
center = 0.5 * (lam_m + lam_p)
|
|
212
220
|
|
|
213
|
-
#
|
|
221
|
+
# Map z to u in the standard [-1,1] domain
|
|
214
222
|
u = (2.0 * (z - center)) / span
|
|
215
223
|
|
|
216
|
-
#
|
|
217
|
-
root = numpy.sqrt(u*u - 1)
|
|
224
|
+
# Inverse-Joukowski: pick branch sqrt with +Im
|
|
225
|
+
root = numpy.sqrt(u*u - 1.0)
|
|
218
226
|
Jm = u - root
|
|
219
227
|
Jp = u + root
|
|
220
228
|
|
|
221
229
|
# Make sure J is Herglotz
|
|
222
|
-
J = numpy.zeros_like(
|
|
223
|
-
J = numpy.where(
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
230
|
+
J = numpy.zeros_like(Jp)
|
|
231
|
+
J = numpy.where(Jp.imag > 0, Jm, Jp)
|
|
232
|
+
|
|
233
|
+
# This depends on the method of analytic continuation
|
|
234
|
+
if continuation == 'pade':
|
|
235
|
+
# Horner summation for S0(J) = sum_{k=0}^K psi_k * J**k
|
|
236
|
+
K = len(psi) - 1
|
|
237
|
+
S0 = numpy.zeros_like(J)
|
|
238
|
+
for k in range(K, -1, -1):
|
|
239
|
+
S0 = psi[k] + J * S0
|
|
240
|
+
S = J * S0
|
|
241
|
+
|
|
242
|
+
else:
|
|
243
|
+
# Flatten J before passing to any of the acceleration methods.
|
|
244
|
+
psi_zero = numpy.concatenate([[0.0], psi])
|
|
245
|
+
Sn = partial_sum(psi_zero, J.ravel(), p=0)
|
|
246
|
+
|
|
247
|
+
if continuation == 'wynn-eps':
|
|
248
|
+
S = wynn_epsilon(Sn)
|
|
249
|
+
elif continuation == 'wynn-rho':
|
|
250
|
+
S = wynn_rho(Sn)
|
|
251
|
+
elif continuation == 'levin':
|
|
252
|
+
S = levin_u(Sn)
|
|
253
|
+
elif continuation == 'weniger':
|
|
254
|
+
S = weniger_delta(Sn)
|
|
255
|
+
elif continuation == 'brezinski':
|
|
256
|
+
S = brezinski_theta(Sn)
|
|
257
|
+
else:
|
|
258
|
+
raise NotImplementedError('"continuation" is invalid.')
|
|
227
259
|
|
|
228
|
-
|
|
229
|
-
#K = len(psi) - 1
|
|
230
|
-
# shape: (..., K+1)
|
|
231
|
-
#Jpow = J[..., None] ** numpy.arange(1, K+2)
|
|
260
|
+
S = S.reshape(J.shape)
|
|
232
261
|
|
|
233
|
-
#
|
|
234
|
-
|
|
262
|
+
# Assemble m(z)
|
|
263
|
+
m_z = -(2.0 / span) * numpy.pi * S
|
|
235
264
|
|
|
236
|
-
#
|
|
237
|
-
|
|
265
|
+
# Check nan or inf
|
|
266
|
+
if numpy.any(numpy.isinf(m_z)):
|
|
267
|
+
raise RuntimeError('"m" is nan.')
|
|
268
|
+
elif numpy.any(numpy.isnan(numpy.abs(m_z))):
|
|
269
|
+
raise RuntimeError('"m" is inf.')
|
|
238
270
|
|
|
239
271
|
return m_z
|