freealg 0.0.1__tar.gz → 0.0.3__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.
- {freealg-0.0.1/freealg.egg-info → freealg-0.0.3}/PKG-INFO +1 -1
- freealg-0.0.3/freealg/__version__.py +1 -0
- freealg-0.0.3/freealg/_decompress.py +136 -0
- {freealg-0.0.1 → freealg-0.0.3}/freealg/_jacobi.py +0 -2
- {freealg-0.0.1 → freealg-0.0.3}/freealg/_plot_util.py +86 -33
- {freealg-0.0.1 → freealg-0.0.3}/freealg/distributions/marchenko_pastur.py +71 -15
- {freealg-0.0.1 → freealg-0.0.3}/freealg/freeform.py +219 -50
- {freealg-0.0.1 → freealg-0.0.3/freealg.egg-info}/PKG-INFO +1 -1
- {freealg-0.0.1 → freealg-0.0.3}/freealg.egg-info/SOURCES.txt +1 -0
- freealg-0.0.1/freealg/__version__.py +0 -1
- {freealg-0.0.1 → freealg-0.0.3}/CHANGELOG.rst +0 -0
- {freealg-0.0.1 → freealg-0.0.3}/LICENSE.txt +0 -0
- {freealg-0.0.1 → freealg-0.0.3}/MANIFEST.in +0 -0
- {freealg-0.0.1 → freealg-0.0.3}/README.rst +0 -0
- {freealg-0.0.1 → freealg-0.0.3}/freealg/__init__.py +0 -0
- {freealg-0.0.1 → freealg-0.0.3}/freealg/_chebyshev.py +0 -0
- {freealg-0.0.1 → freealg-0.0.3}/freealg/_damp.py +0 -0
- {freealg-0.0.1 → freealg-0.0.3}/freealg/_pade.py +0 -0
- {freealg-0.0.1 → freealg-0.0.3}/freealg/_util.py +0 -0
- {freealg-0.0.1 → freealg-0.0.3}/freealg/distributions/__init__.py +0 -0
- {freealg-0.0.1 → freealg-0.0.3}/freealg.egg-info/dependency_links.txt +0 -0
- {freealg-0.0.1 → freealg-0.0.3}/freealg.egg-info/not-zip-safe +0 -0
- {freealg-0.0.1 → freealg-0.0.3}/freealg.egg-info/requires.txt +0 -0
- {freealg-0.0.1 → freealg-0.0.3}/freealg.egg-info/top_level.txt +0 -0
- {freealg-0.0.1 → freealg-0.0.3}/pyproject.toml +0 -0
- {freealg-0.0.1 → freealg-0.0.3}/requirements.txt +0 -0
- {freealg-0.0.1 → freealg-0.0.3}/setup.cfg +0 -0
- {freealg-0.0.1 → freealg-0.0.3}/setup.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.0.3"
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
# SPDX-FileType: SOURCE
|
|
3
|
+
#
|
|
4
|
+
# This program is free software: you can redistribute it and/or modify it under
|
|
5
|
+
# the terms of the license found in the LICENSE.txt file in the root directory
|
|
6
|
+
# of this source tree.
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# =======
|
|
10
|
+
# Imports
|
|
11
|
+
# =======
|
|
12
|
+
|
|
13
|
+
import numpy
|
|
14
|
+
|
|
15
|
+
__all__ = ['decompress']
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# ==========
|
|
19
|
+
# decompress
|
|
20
|
+
# ==========
|
|
21
|
+
|
|
22
|
+
def decompress(matrix, size, x=None, delta=1e-4, iterations=500, step_size=0.1,
|
|
23
|
+
tolerance=1e-4):
|
|
24
|
+
"""
|
|
25
|
+
Free decompression of spectral density.
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
|
|
30
|
+
matrix : FreeForm
|
|
31
|
+
The initial matrix to be decompressed
|
|
32
|
+
|
|
33
|
+
size : int
|
|
34
|
+
Size of the decompressed matrix.
|
|
35
|
+
|
|
36
|
+
x : numpy.array, default=None
|
|
37
|
+
Positions where density to be evaluated at. If `None`, an interval
|
|
38
|
+
slightly larger than the support interval will be used.
|
|
39
|
+
|
|
40
|
+
delta: float, default=1e-4
|
|
41
|
+
Size of the perturbation into the upper half plane for Plemelj's
|
|
42
|
+
formula.
|
|
43
|
+
|
|
44
|
+
iterations: int, default=500
|
|
45
|
+
Maximum number of Newton iterations.
|
|
46
|
+
|
|
47
|
+
step_size: float, default=0.1
|
|
48
|
+
Step size for Newton iterations.
|
|
49
|
+
|
|
50
|
+
tolerance: float, default=1e-4
|
|
51
|
+
Tolerance for the solution obtained by the Newton solver. Also
|
|
52
|
+
used for the finite difference approximation to the derivative.
|
|
53
|
+
|
|
54
|
+
Returns
|
|
55
|
+
-------
|
|
56
|
+
|
|
57
|
+
rho : numpy.array
|
|
58
|
+
Spectral density
|
|
59
|
+
|
|
60
|
+
See Also
|
|
61
|
+
--------
|
|
62
|
+
|
|
63
|
+
density
|
|
64
|
+
stieltjes
|
|
65
|
+
|
|
66
|
+
Notes
|
|
67
|
+
-----
|
|
68
|
+
|
|
69
|
+
Work in progress.
|
|
70
|
+
|
|
71
|
+
References
|
|
72
|
+
----------
|
|
73
|
+
|
|
74
|
+
.. [1] tbd
|
|
75
|
+
|
|
76
|
+
Examples
|
|
77
|
+
--------
|
|
78
|
+
|
|
79
|
+
.. code-block:: python
|
|
80
|
+
|
|
81
|
+
>>> from freealg import FreeForm
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
alpha = size / matrix.n
|
|
85
|
+
m = matrix._eval_stieltjes
|
|
86
|
+
# Lower and upper bound on new support
|
|
87
|
+
hilb_lb = (1 / m(matrix.lam_m + delta * 1j)[1]).real
|
|
88
|
+
hilb_ub = (1 / m(matrix.lam_p + delta * 1j)[1]).real
|
|
89
|
+
lb = matrix.lam_m - (alpha - 1) * hilb_lb
|
|
90
|
+
ub = matrix.lam_p - (alpha - 1) * hilb_ub
|
|
91
|
+
|
|
92
|
+
# Create x if not given
|
|
93
|
+
if x is None:
|
|
94
|
+
radius = 0.5 * (ub - lb)
|
|
95
|
+
center = 0.5 * (ub + lb)
|
|
96
|
+
scale = 1.25
|
|
97
|
+
x_min = numpy.floor(center - radius * scale)
|
|
98
|
+
x_max = numpy.ceil(center + radius * scale)
|
|
99
|
+
x = numpy.linspace(x_min, x_max, 500)
|
|
100
|
+
|
|
101
|
+
def _char_z(z):
|
|
102
|
+
return z + (1 / m(z)[1]) * (1 - alpha)
|
|
103
|
+
|
|
104
|
+
# Ensure that input is an array
|
|
105
|
+
x = numpy.asarray(x)
|
|
106
|
+
|
|
107
|
+
target = x + delta * 1j
|
|
108
|
+
|
|
109
|
+
z = numpy.full(target.shape, numpy.mean(matrix.support) - .1j,
|
|
110
|
+
dtype=numpy.complex128)
|
|
111
|
+
|
|
112
|
+
# Broken Newton steps can produce a lot of warnings. Removing them
|
|
113
|
+
# for now.
|
|
114
|
+
with numpy.errstate(all='ignore'):
|
|
115
|
+
for _ in range(iterations):
|
|
116
|
+
objective = _char_z(z) - target
|
|
117
|
+
mask = numpy.abs(objective) >= tolerance
|
|
118
|
+
if not numpy.any(mask):
|
|
119
|
+
break
|
|
120
|
+
z_m = z[mask]
|
|
121
|
+
|
|
122
|
+
# Perform finite difference approximation
|
|
123
|
+
dfdz = _char_z(z_m+tolerance) - _char_z(z_m-tolerance)
|
|
124
|
+
dfdz /= 2*tolerance
|
|
125
|
+
dfdz[dfdz == 0] = 1.0
|
|
126
|
+
|
|
127
|
+
# Perform Newton step
|
|
128
|
+
z[mask] = z_m - step_size * objective[mask] / dfdz
|
|
129
|
+
|
|
130
|
+
# Plemelj's formula
|
|
131
|
+
char_s = m(z)[1] / alpha
|
|
132
|
+
rho = numpy.maximum(0, char_s.imag / numpy.pi)
|
|
133
|
+
rho[numpy.isnan(rho) | numpy.isinf(rho)] = 0
|
|
134
|
+
rho = rho.reshape(*x.shape)
|
|
135
|
+
|
|
136
|
+
return rho, x, (lb, ub)
|
|
@@ -174,9 +174,7 @@ def jacobi_stieltjes(z, psi, support, alpha=0.0, beta=0.0, n_base=40):
|
|
|
174
174
|
integrand = w_nodes * P_k_nodes # (n_quad,)
|
|
175
175
|
|
|
176
176
|
# Broadcast over z: shape (n_quad, ...) / ...
|
|
177
|
-
# diff = u_z[None, ...] - t_nodes[:, None] # (n_quad, ...)
|
|
178
177
|
diff = u_z[None, ...] - t_nodes[:, None, None] # (n_quad, Ny, Nx)
|
|
179
|
-
# m_k = (integrand[:, None] / diff).sum(axis=0) # shape like z
|
|
180
178
|
m_k = (integrand[:, None, None] / diff).sum(axis=0)
|
|
181
179
|
|
|
182
180
|
# Accumulate with factor 2/span
|
|
@@ -19,28 +19,21 @@ import colorsys
|
|
|
19
19
|
import matplotlib.ticker as ticker
|
|
20
20
|
import matplotlib.gridspec as gridspec
|
|
21
21
|
|
|
22
|
-
__all__ = ['
|
|
23
|
-
'plot_stieltjes_on_disk'
|
|
22
|
+
__all__ = ['plot_fit', 'plot_density', 'plot_hilbert', 'plot_stieltjes',
|
|
23
|
+
'plot_stieltjes_on_disk']
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
#
|
|
27
|
-
# plot coeff
|
|
28
|
-
#
|
|
26
|
+
# ==============
|
|
27
|
+
# plot coeff fit
|
|
28
|
+
# ==============
|
|
29
29
|
|
|
30
|
-
def
|
|
30
|
+
def plot_coeff_fit(psi, latex=False, save=False):
|
|
31
31
|
"""
|
|
32
32
|
"""
|
|
33
33
|
|
|
34
34
|
with texplot.theme(use_latex=latex):
|
|
35
35
|
|
|
36
36
|
fig, ax = plt.subplots(figsize=(6, 2.7))
|
|
37
|
-
n = numpy.arange(1, 1+psi.size)
|
|
38
|
-
ax.plot(n, psi**2, '-o', markersize=3, color='black')
|
|
39
|
-
ax.set_xlim([n[0]-1e-3, n[-1]+1e-3])
|
|
40
|
-
ax.set_xlabel(r'$k$')
|
|
41
|
-
ax.set_ylabel(r'$\vert \psi_k \vert^2$')
|
|
42
|
-
ax.set_title('Spectral Energy per Mode')
|
|
43
|
-
ax.set_yscale('log')
|
|
44
37
|
|
|
45
38
|
# Save
|
|
46
39
|
if save is False:
|
|
@@ -54,7 +47,65 @@ def plot_coeff(psi, latex=False, save=False):
|
|
|
54
47
|
save_filename = 'energy.pdf'
|
|
55
48
|
|
|
56
49
|
texplot.show_or_save_plot(plt, default_filename=save_filename,
|
|
57
|
-
transparent_background=True, dpi=
|
|
50
|
+
transparent_background=True, dpi=400,
|
|
51
|
+
show_and_save=save_status, verbose=True)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# ========
|
|
55
|
+
# plot fit
|
|
56
|
+
# ========
|
|
57
|
+
|
|
58
|
+
def plot_fit(psi, x_supp, g_supp, g_supp_approx, support, latex=False,
|
|
59
|
+
save=False):
|
|
60
|
+
"""
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
with texplot.theme(use_latex=latex):
|
|
64
|
+
|
|
65
|
+
fig, ax = plt.subplots(figsize=(9, 3), ncols=2)
|
|
66
|
+
|
|
67
|
+
# Plot psi
|
|
68
|
+
n = numpy.arange(1, 1+psi.size)
|
|
69
|
+
ax[0].plot(n, psi**2, '-o', markersize=3, color='black')
|
|
70
|
+
ax[0].set_xlim([n[0]-1e-3, n[-1]+1e-3])
|
|
71
|
+
ax[0].set_xlabel(r'$k$')
|
|
72
|
+
ax[0].set_ylabel(r'$\vert \psi_k \vert^2$')
|
|
73
|
+
ax[0].set_title('Spectral Energy per Mode')
|
|
74
|
+
ax[0].set_yscale('log')
|
|
75
|
+
|
|
76
|
+
# Plot pade
|
|
77
|
+
lam_m, lam_p = support
|
|
78
|
+
g_supp_min = numpy.min(g_supp)
|
|
79
|
+
g_supp_max = numpy.max(g_supp)
|
|
80
|
+
g_supp_dif = g_supp_max - g_supp_min
|
|
81
|
+
g_min = g_supp_min - g_supp_dif * 1.1
|
|
82
|
+
g_max = g_supp_max + g_supp_dif * 1.1
|
|
83
|
+
|
|
84
|
+
ax[1].plot(x_supp, g_supp, color='firebrick',
|
|
85
|
+
label=r'$2 \pi \times $ Hilbert Transform')
|
|
86
|
+
ax[1].plot(x_supp, g_supp_approx, color='black', label='Pade estimate')
|
|
87
|
+
ax[1].legend(fontsize='small')
|
|
88
|
+
ax[1].set_xlim([lam_m, lam_p])
|
|
89
|
+
ax[1].set_ylim([g_min, g_max])
|
|
90
|
+
ax[1].set_title('Approximation of Glue Function')
|
|
91
|
+
ax[1].set_xlabel(r'$x$')
|
|
92
|
+
ax[1].set_ylabel(r'$G(x)$')
|
|
93
|
+
|
|
94
|
+
plt.tight_layout()
|
|
95
|
+
|
|
96
|
+
# Save
|
|
97
|
+
if save is False:
|
|
98
|
+
save_status = False
|
|
99
|
+
save_filename = ''
|
|
100
|
+
else:
|
|
101
|
+
save_status = True
|
|
102
|
+
if isinstance(save, str):
|
|
103
|
+
save_filename = save
|
|
104
|
+
else:
|
|
105
|
+
save_filename = 'fit.pdf'
|
|
106
|
+
|
|
107
|
+
texplot.show_or_save_plot(plt, default_filename=save_filename,
|
|
108
|
+
transparent_background=True, dpi=400,
|
|
58
109
|
show_and_save=save_status, verbose=True)
|
|
59
110
|
|
|
60
111
|
|
|
@@ -76,6 +127,8 @@ def plot_density(x, rho, eig=None, support=None, label='',
|
|
|
76
127
|
bins = numpy.linspace(lam_m, lam_p, 250)
|
|
77
128
|
_ = ax.hist(eig, bins, density=True, color='silver',
|
|
78
129
|
edgecolor='none', label='Histogram')
|
|
130
|
+
else:
|
|
131
|
+
plt.fill_between(x, y1=rho, y2=0, color='silver', zorder=-1)
|
|
79
132
|
|
|
80
133
|
ax.plot(x, rho, color='black', label=label, zorder=3)
|
|
81
134
|
ax.set_xlabel(r'$\lambda$')
|
|
@@ -99,7 +152,7 @@ def plot_density(x, rho, eig=None, support=None, label='',
|
|
|
99
152
|
save_filename = 'density.pdf'
|
|
100
153
|
|
|
101
154
|
texplot.show_or_save_plot(plt, default_filename=save_filename,
|
|
102
|
-
transparent_background=True, dpi=
|
|
155
|
+
transparent_background=True, dpi=400,
|
|
103
156
|
show_and_save=save_status, verbose=True)
|
|
104
157
|
|
|
105
158
|
|
|
@@ -149,7 +202,7 @@ def plot_hilbert(x, hilb, support=None, latex=False, save=False):
|
|
|
149
202
|
save_filename = 'hilbert.pdf'
|
|
150
203
|
|
|
151
204
|
texplot.show_or_save_plot(plt, default_filename=save_filename,
|
|
152
|
-
transparent_background=True, dpi=
|
|
205
|
+
transparent_background=True, dpi=400,
|
|
153
206
|
show_and_save=save_status, verbose=True)
|
|
154
207
|
|
|
155
208
|
|
|
@@ -327,7 +380,7 @@ def plot_stieltjes(x, y, m1, m2, support, latex=False, save=False):
|
|
|
327
380
|
save_filename = 'stieltjes.pdf'
|
|
328
381
|
|
|
329
382
|
texplot.show_or_save_plot(plt, default_filename=save_filename,
|
|
330
|
-
transparent_background=True, dpi=
|
|
383
|
+
transparent_background=True, dpi=400,
|
|
331
384
|
show_and_save=save_status, verbose=True)
|
|
332
385
|
|
|
333
386
|
|
|
@@ -456,16 +509,15 @@ def plot_stieltjes_on_disk(r, t, m1_D, m2_D, support, latex=False, save=False):
|
|
|
456
509
|
save_filename = 'stieltjes_disk.pdf'
|
|
457
510
|
|
|
458
511
|
texplot.show_or_save_plot(plt, default_filename=save_filename,
|
|
459
|
-
transparent_background=True, dpi=
|
|
512
|
+
transparent_background=True, dpi=400,
|
|
460
513
|
show_and_save=save_status, verbose=True)
|
|
461
514
|
|
|
462
515
|
|
|
463
|
-
#
|
|
464
|
-
# plot
|
|
465
|
-
#
|
|
516
|
+
# ============
|
|
517
|
+
# plot samples
|
|
518
|
+
# ============
|
|
466
519
|
|
|
467
|
-
def
|
|
468
|
-
save=False):
|
|
520
|
+
def plot_samples(x, rho, x_min, x_max, samples, latex=False, save=False):
|
|
469
521
|
"""
|
|
470
522
|
"""
|
|
471
523
|
|
|
@@ -473,15 +525,16 @@ def plot_glue_fit(x_supp, g_supp, g_supp_approx, support, latex=False,
|
|
|
473
525
|
|
|
474
526
|
fig, ax = plt.subplots(figsize=(6, 3))
|
|
475
527
|
|
|
476
|
-
|
|
477
|
-
ax.
|
|
478
|
-
|
|
479
|
-
|
|
528
|
+
bins = numpy.linspace(x_min, x_max, samples.size // 10)
|
|
529
|
+
_ = ax.hist(samples, bins, density=True, color='silver',
|
|
530
|
+
label='Samples histogram')
|
|
531
|
+
ax.plot(x, rho, color='black', label='Exact density')
|
|
480
532
|
ax.legend(fontsize='small')
|
|
481
|
-
ax.
|
|
482
|
-
ax.
|
|
483
|
-
ax.set_xlabel(r'$
|
|
484
|
-
ax.set_ylabel(r'
|
|
533
|
+
ax.set_ylim(bottom=0)
|
|
534
|
+
ax.set_xlim([x[0], x[-1]])
|
|
535
|
+
ax.set_xlabel(r'$\lambda$')
|
|
536
|
+
ax.set_ylabel(r'$\rho(\lambda)$''')
|
|
537
|
+
ax.set_title('Histogram of Samples from Distribution')
|
|
485
538
|
|
|
486
539
|
# Save
|
|
487
540
|
if save is False:
|
|
@@ -492,8 +545,8 @@ def plot_glue_fit(x_supp, g_supp, g_supp_approx, support, latex=False,
|
|
|
492
545
|
if isinstance(save, str):
|
|
493
546
|
save_filename = save
|
|
494
547
|
else:
|
|
495
|
-
save_filename = '
|
|
548
|
+
save_filename = 'samples.pdf'
|
|
496
549
|
|
|
497
550
|
texplot.show_or_save_plot(plt, default_filename=save_filename,
|
|
498
|
-
transparent_background=True, dpi=
|
|
551
|
+
transparent_background=True, dpi=400,
|
|
499
552
|
show_and_save=save_status, verbose=True)
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import numpy
|
|
15
15
|
from scipy.interpolate import interp1d
|
|
16
16
|
from .._plot_util import plot_density, plot_hilbert, plot_stieltjes, \
|
|
17
|
-
plot_stieltjes_on_disk
|
|
17
|
+
plot_stieltjes_on_disk, plot_samples
|
|
18
18
|
|
|
19
19
|
try:
|
|
20
20
|
from scipy.integrate import cumtrapz
|
|
@@ -77,9 +77,7 @@ class MarchenkoPastur(object):
|
|
|
77
77
|
|
|
78
78
|
.. [1] Marcenko, V. A., Pastur, L. A. (1967). Distribution of eigenvalues
|
|
79
79
|
for some sets of random matrices. Mathematics of the USSR-Sbornik,
|
|
80
|
-
1(4), 457
|
|
81
|
-
https://iopscience.iop.org/article/10.1070/SM1967v001n04ABEH001994
|
|
82
|
-
>`__)
|
|
80
|
+
1(4), 457
|
|
83
81
|
|
|
84
82
|
Examples
|
|
85
83
|
--------
|
|
@@ -149,6 +147,10 @@ class MarchenkoPastur(object):
|
|
|
149
147
|
>>> from freealg.distributions import MarchenkoPastur
|
|
150
148
|
>>> mp = MarchenkoPastur(1/50)
|
|
151
149
|
>>> rho = mp.density(plot=True)
|
|
150
|
+
|
|
151
|
+
.. image:: ../_static/images/plots/mp_density.png
|
|
152
|
+
:align: center
|
|
153
|
+
:class: custom-dark
|
|
152
154
|
"""
|
|
153
155
|
|
|
154
156
|
# Create x if not given
|
|
@@ -167,8 +169,7 @@ class MarchenkoPastur(object):
|
|
|
167
169
|
numpy.sqrt((self.lam_p - x[mask]) * (x[mask] - self.lam_m))
|
|
168
170
|
|
|
169
171
|
if plot:
|
|
170
|
-
plot_density(x, rho,
|
|
171
|
-
save=save)
|
|
172
|
+
plot_density(x, rho, label='', latex=latex, save=save)
|
|
172
173
|
|
|
173
174
|
return rho
|
|
174
175
|
|
|
@@ -189,7 +190,7 @@ class MarchenkoPastur(object):
|
|
|
189
190
|
spectral density is used.
|
|
190
191
|
|
|
191
192
|
plot : bool, default=False
|
|
192
|
-
If `True`,
|
|
193
|
+
If `True`, Hilbert transform is plotted.
|
|
193
194
|
|
|
194
195
|
latex : bool, default=False
|
|
195
196
|
If `True`, the plot is rendered using LaTeX. This option is
|
|
@@ -214,6 +215,10 @@ class MarchenkoPastur(object):
|
|
|
214
215
|
>>> from freealg.distributions import MarchenkoPastur
|
|
215
216
|
>>> mp = MarchenkoPastur(1/50)
|
|
216
217
|
>>> hilb = mp.hilbert(plot=True)
|
|
218
|
+
|
|
219
|
+
.. image:: ../_static/images/plots/mp_hilbert.png
|
|
220
|
+
:align: center
|
|
221
|
+
:class: custom-dark
|
|
217
222
|
"""
|
|
218
223
|
|
|
219
224
|
# Create x if not given
|
|
@@ -225,9 +230,18 @@ class MarchenkoPastur(object):
|
|
|
225
230
|
x_max = numpy.ceil(center + radius * scale)
|
|
226
231
|
x = numpy.linspace(x_min, x_max, 500)
|
|
227
232
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
233
|
+
def _P(x):
|
|
234
|
+
return x - 1 + self.lam
|
|
235
|
+
|
|
236
|
+
def _Q(x):
|
|
237
|
+
return self.lam * x
|
|
238
|
+
|
|
239
|
+
P = _P(x)
|
|
240
|
+
Q = _Q(x)
|
|
241
|
+
Delta2 = P**2 - 4.0 * Q
|
|
242
|
+
Delta = numpy.sqrt(numpy.maximum(Delta2, 0))
|
|
243
|
+
sign = numpy.sign(P)
|
|
244
|
+
hilb = (P - sign * Delta) / (2.0 * Q)
|
|
231
245
|
|
|
232
246
|
# using negative sign convention
|
|
233
247
|
hilb = -hilb
|
|
@@ -319,7 +333,7 @@ class MarchenkoPastur(object):
|
|
|
319
333
|
If `None`, a grid on the interval ``[-1, 1]`` is used.
|
|
320
334
|
|
|
321
335
|
plot : bool, default=False
|
|
322
|
-
If `True`,
|
|
336
|
+
If `True`, Stieltjes transform is plotted.
|
|
323
337
|
|
|
324
338
|
on_disk : bool, default=False
|
|
325
339
|
If `True`, the Stieltjes transform is mapped on unit disk. This
|
|
@@ -346,12 +360,25 @@ class MarchenkoPastur(object):
|
|
|
346
360
|
Examples
|
|
347
361
|
--------
|
|
348
362
|
|
|
349
|
-
.. code-block::python
|
|
363
|
+
.. code-block:: python
|
|
350
364
|
|
|
351
365
|
>>> from freealg.distributions import MarchenkoPastur
|
|
352
366
|
>>> mp = MarchenkoPastur(1/50)
|
|
353
367
|
>>> m1, m2 = mp.stieltjes(plot=True)
|
|
354
368
|
|
|
369
|
+
.. image:: ../_static/images/plots/mp_stieltjes.png
|
|
370
|
+
:align: center
|
|
371
|
+
:class: custom-dark
|
|
372
|
+
|
|
373
|
+
Plot on unit disk using Cayley transform:
|
|
374
|
+
|
|
375
|
+
.. code-block:: python
|
|
376
|
+
|
|
377
|
+
>>> m1, m2 = mp.stieltjes(plot=True, on_disk=True)
|
|
378
|
+
|
|
379
|
+
.. image:: ../_static/images/plots/mp_stieltjes_disk.png
|
|
380
|
+
:align: center
|
|
381
|
+
:class: custom-dark
|
|
355
382
|
"""
|
|
356
383
|
|
|
357
384
|
if (plot is True) and (on_disk is True):
|
|
@@ -407,7 +434,8 @@ class MarchenkoPastur(object):
|
|
|
407
434
|
# sample
|
|
408
435
|
# ======
|
|
409
436
|
|
|
410
|
-
def sample(self, size, x_min=None, x_max=None
|
|
437
|
+
def sample(self, size, x_min=None, x_max=None, plot=False, latex=False,
|
|
438
|
+
save=False):
|
|
411
439
|
"""
|
|
412
440
|
Sample from distribution.
|
|
413
441
|
|
|
@@ -425,6 +453,18 @@ class MarchenkoPastur(object):
|
|
|
425
453
|
Maximum of sample values. If `None`, the right edge of the support
|
|
426
454
|
is used.
|
|
427
455
|
|
|
456
|
+
plot : bool, default=False
|
|
457
|
+
If `True`, samples histogram is plotted.
|
|
458
|
+
|
|
459
|
+
latex : bool, default=False
|
|
460
|
+
If `True`, the plot is rendered using LaTeX. This option is
|
|
461
|
+
relevant only if ``plot=True``.
|
|
462
|
+
|
|
463
|
+
save : bool, default=False
|
|
464
|
+
If not `False`, the plot is saved. If a string is given, it is
|
|
465
|
+
assumed to the save filename (with the file extension). This option
|
|
466
|
+
is relevant only if ``plot=True``.
|
|
467
|
+
|
|
428
468
|
Returns
|
|
429
469
|
-------
|
|
430
470
|
|
|
@@ -443,7 +483,11 @@ class MarchenkoPastur(object):
|
|
|
443
483
|
|
|
444
484
|
>>> from freealg.distributions import MarchenkoPastur
|
|
445
485
|
>>> mp = MarchenkoPastur(1/50)
|
|
446
|
-
|
|
486
|
+
|
|
487
|
+
>>> s = mp.sample(2000)
|
|
488
|
+
.. image:: ../_static/images/plots/mp_samples.png
|
|
489
|
+
:align: center
|
|
490
|
+
:class: custom-dark
|
|
447
491
|
"""
|
|
448
492
|
|
|
449
493
|
if x_min is None:
|
|
@@ -466,7 +510,19 @@ class MarchenkoPastur(object):
|
|
|
466
510
|
|
|
467
511
|
# Sample and map
|
|
468
512
|
u = numpy.random.rand(size)
|
|
469
|
-
|
|
513
|
+
samples = inv_cdf(u)
|
|
514
|
+
|
|
515
|
+
if plot:
|
|
516
|
+
radius = 0.5 * (self.lam_p - self.lam_m)
|
|
517
|
+
center = 0.5 * (self.lam_p + self.lam_m)
|
|
518
|
+
scale = 1.25
|
|
519
|
+
x_min = numpy.floor(center - radius * scale)
|
|
520
|
+
x_max = numpy.ceil(center + radius * scale)
|
|
521
|
+
x = numpy.linspace(x_min, x_max, 500)
|
|
522
|
+
rho = self.density(x)
|
|
523
|
+
plot_samples(x, rho, x_min, x_max, samples, latex=latex, save=save)
|
|
524
|
+
|
|
525
|
+
return samples
|
|
470
526
|
|
|
471
527
|
# ======
|
|
472
528
|
# matrix
|
|
@@ -12,15 +12,16 @@
|
|
|
12
12
|
# =======
|
|
13
13
|
|
|
14
14
|
import numpy
|
|
15
|
+
from scipy.stats import gaussian_kde
|
|
15
16
|
from functools import partial
|
|
16
17
|
from ._util import compute_eig, force_density
|
|
17
18
|
from ._jacobi import jacobi_proj, jacobi_approx, jacobi_stieltjes
|
|
18
19
|
from ._chebyshev import chebyshev_proj, chebyshev_approx, chebyshev_stieltjes
|
|
19
20
|
from ._damp import jackson_damping, lanczos_damping, fejer_damping, \
|
|
20
21
|
exponential_damping, parzen_damping
|
|
21
|
-
from ._plot_util import
|
|
22
|
-
plot_stieltjes, plot_glue_fit
|
|
22
|
+
from ._plot_util import plot_fit, plot_density, plot_hilbert, plot_stieltjes
|
|
23
23
|
from ._pade import fit_pade, eval_pade
|
|
24
|
+
from ._decompress import decompress
|
|
24
25
|
|
|
25
26
|
__all__ = ['FreeForm']
|
|
26
27
|
|
|
@@ -45,6 +46,13 @@ class FreeForm(object):
|
|
|
45
46
|
The support of the density of :math:`\\mathbf{A}`. If `None`, it is
|
|
46
47
|
estimated from the minimum and maximum of the eigenvalues.
|
|
47
48
|
|
|
49
|
+
p : float, default=0.001
|
|
50
|
+
The edges of the support of the distribution is detected by the
|
|
51
|
+
:math:`p`-quantile on the left and :math:`(1-p)`-quantile on the right.
|
|
52
|
+
If the argument ``support`` is directly provided, this option is
|
|
53
|
+
ignored. This value should be between 0 and 1, ideally a small
|
|
54
|
+
number close to zero.
|
|
55
|
+
|
|
48
56
|
Notes
|
|
49
57
|
-----
|
|
50
58
|
|
|
@@ -64,6 +72,10 @@ class FreeForm(object):
|
|
|
64
72
|
psi : numpy.array
|
|
65
73
|
Jacobi coefficients.
|
|
66
74
|
|
|
75
|
+
n : int
|
|
76
|
+
Initial array size (assuming a square matrix when :math:`\\mathbf{A}`
|
|
77
|
+
is 2D)
|
|
78
|
+
|
|
67
79
|
Methods
|
|
68
80
|
-------
|
|
69
81
|
|
|
@@ -94,7 +106,7 @@ class FreeForm(object):
|
|
|
94
106
|
# init
|
|
95
107
|
# ====
|
|
96
108
|
|
|
97
|
-
def __init__(self, A, support=None):
|
|
109
|
+
def __init__(self, A, support=None, p=0.001):
|
|
98
110
|
"""
|
|
99
111
|
Initialization.
|
|
100
112
|
"""
|
|
@@ -106,16 +118,20 @@ class FreeForm(object):
|
|
|
106
118
|
if A.ndim == 1:
|
|
107
119
|
# When A is a 1D array, it is assumed A is the eigenvalue array.
|
|
108
120
|
self.eig = A
|
|
121
|
+
self.n = len(A)
|
|
109
122
|
elif A.ndim == 2:
|
|
110
123
|
# When A is a 2D array, it is assumed A is the actual array,
|
|
111
124
|
# and its eigenvalues will be computed.
|
|
112
125
|
self.A = A
|
|
126
|
+
self.n = A.shape[0]
|
|
127
|
+
assert A.shape[0] == A.shape[1], \
|
|
128
|
+
'Only square matrices are permitted.'
|
|
113
129
|
self.eig = compute_eig(A)
|
|
114
130
|
|
|
115
131
|
# Support
|
|
116
132
|
if support is None:
|
|
117
|
-
self.lam_m = self.eig
|
|
118
|
-
|
|
133
|
+
self.lam_m, self.lam_p = self._detect_support(self.eig, p,
|
|
134
|
+
smoothen=True)
|
|
119
135
|
else:
|
|
120
136
|
self.lam_m = support[0]
|
|
121
137
|
self.lam_p = support[1]
|
|
@@ -126,20 +142,46 @@ class FreeForm(object):
|
|
|
126
142
|
self.psi = None
|
|
127
143
|
self.alpha = None
|
|
128
144
|
self.beta = None
|
|
145
|
+
self._pade_sol = None
|
|
146
|
+
|
|
147
|
+
# ==============
|
|
148
|
+
# detect support
|
|
149
|
+
# ==============
|
|
150
|
+
|
|
151
|
+
def _detect_support(self, eig, p, smoothen=True):
|
|
152
|
+
"""
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
# Using quantile directly.
|
|
156
|
+
if smoothen:
|
|
157
|
+
kde = gaussian_kde(eig)
|
|
158
|
+
xs = numpy.linspace(eig.min(), eig.max(), 1000)
|
|
159
|
+
fs = kde(xs)
|
|
160
|
+
|
|
161
|
+
cdf = numpy.cumsum(fs)
|
|
162
|
+
cdf /= cdf[-1]
|
|
163
|
+
|
|
164
|
+
lam_m = numpy.interp(p, cdf, xs)
|
|
165
|
+
lam_p = numpy.interp(1-p, cdf, xs)
|
|
166
|
+
else:
|
|
167
|
+
lam_m, lam_p = numpy.quantile(eig, [p, 1-p])
|
|
168
|
+
|
|
169
|
+
return lam_m, lam_p
|
|
129
170
|
|
|
130
171
|
# ===
|
|
131
172
|
# fit
|
|
132
173
|
# ===
|
|
133
174
|
|
|
134
175
|
def fit(self, method='jacobi', K=10, alpha=0.0, beta=0.0, reg=0.0,
|
|
135
|
-
damp=None, force=False,
|
|
176
|
+
damp=None, force=False, pade_p=1, pade_q=1, plot=False,
|
|
177
|
+
latex=False, save=False):
|
|
136
178
|
"""
|
|
137
179
|
Fit model to eigenvalues.
|
|
138
180
|
|
|
139
181
|
Parameters
|
|
140
182
|
----------
|
|
141
183
|
|
|
142
|
-
method : {``'jacobi'``, ``'chebyshev'``}, default
|
|
184
|
+
method : {``'jacobi'``, ``'chebyshev'``}, default= ``'jacobi'``
|
|
143
185
|
Method of approximation, either by Jacobi polynomials or Chebyshev
|
|
144
186
|
polynomials of the second kind.
|
|
145
187
|
|
|
@@ -167,8 +209,15 @@ class FreeForm(object):
|
|
|
167
209
|
If `True`, it forces the density to have unit mass and to be
|
|
168
210
|
strictly positive.
|
|
169
211
|
|
|
212
|
+
pade_p : int, default=1
|
|
213
|
+
Degree of polynomial :math:`P(z)`. See notes below.
|
|
214
|
+
|
|
215
|
+
pade_q : int, default=1
|
|
216
|
+
Degree of polynomial :math:`Q(z)`. See notes below.
|
|
217
|
+
|
|
170
218
|
plot : bool, default=False
|
|
171
|
-
If `True`,
|
|
219
|
+
If `True`, the approximation coefficients and pade approximaton to
|
|
220
|
+
the Hilbert traosnform are plotted.
|
|
172
221
|
|
|
173
222
|
latex : bool, default=False
|
|
174
223
|
If `True`, the plot is rendered using LaTeX. This option is
|
|
@@ -245,8 +294,24 @@ class FreeForm(object):
|
|
|
245
294
|
self.alpha = alpha
|
|
246
295
|
self.beta = beta
|
|
247
296
|
|
|
297
|
+
# For holomorphic continuation for the lower half-plane
|
|
298
|
+
x_supp = numpy.linspace(self.lam_m, self.lam_p, 1000)
|
|
299
|
+
g_supp = 2.0 * numpy.pi * self.hilbert(x_supp)
|
|
300
|
+
|
|
301
|
+
# Fit a pade approximation
|
|
302
|
+
self._pade_sol = fit_pade(x_supp, g_supp, self.lam_m,
|
|
303
|
+
self.lam_p, pade_p, pade_q, delta=1e-8,
|
|
304
|
+
B=numpy.inf, S=numpy.inf)
|
|
305
|
+
|
|
248
306
|
if plot:
|
|
249
|
-
|
|
307
|
+
# Unpack optimized parameters
|
|
308
|
+
s = self._pade_sol['s']
|
|
309
|
+
a = self._pade_sol['a']
|
|
310
|
+
b = self._pade_sol['b']
|
|
311
|
+
|
|
312
|
+
g_supp_approx = eval_pade(x_supp[None, :], s, a, b)[0, :]
|
|
313
|
+
plot_fit(psi, x_supp, g_supp, g_supp_approx, support=self.support,
|
|
314
|
+
latex=latex, save=save)
|
|
250
315
|
|
|
251
316
|
return self.psi
|
|
252
317
|
|
|
@@ -444,41 +509,28 @@ class FreeForm(object):
|
|
|
444
509
|
# glue
|
|
445
510
|
# ====
|
|
446
511
|
|
|
447
|
-
def _glue(self, z
|
|
512
|
+
def _glue(self, z):
|
|
448
513
|
"""
|
|
449
514
|
"""
|
|
450
515
|
|
|
451
|
-
# Holomorphic continuation for the lower half-plane
|
|
452
|
-
x_supp = numpy.linspace(self.lam_m, self.lam_p, 1000)
|
|
453
|
-
g_supp = 2.0 * numpy.pi * self.hilbert(x_supp)
|
|
454
|
-
|
|
455
|
-
# Fit a pade approximation
|
|
456
|
-
sol = fit_pade(x_supp, g_supp, self.lam_m, self.lam_p, p, q,
|
|
457
|
-
delta=1e-8, B=numpy.inf, S=numpy.inf)
|
|
458
|
-
|
|
459
516
|
# Unpack optimized parameters
|
|
460
|
-
s =
|
|
461
|
-
a =
|
|
462
|
-
b =
|
|
517
|
+
s = self._pade_sol['s']
|
|
518
|
+
a = self._pade_sol['a']
|
|
519
|
+
b = self._pade_sol['b']
|
|
463
520
|
|
|
464
521
|
# Glue function
|
|
465
522
|
g = eval_pade(z, s, a, b)
|
|
466
523
|
|
|
467
|
-
if plot_glue:
|
|
468
|
-
g_supp_approx = eval_pade(x_supp[None, :], s, a, b)[0, :]
|
|
469
|
-
plot_glue_fit(x_supp, g_supp, g_supp_approx, support=self.support,
|
|
470
|
-
latex=latex, save=save)
|
|
471
|
-
|
|
472
524
|
return g
|
|
473
525
|
|
|
474
526
|
# =========
|
|
475
527
|
# stieltjes
|
|
476
528
|
# =========
|
|
477
529
|
|
|
478
|
-
def stieltjes(self, x, y,
|
|
479
|
-
latex=False, save=False):
|
|
530
|
+
def stieltjes(self, x, y, plot=False, latex=False, save=False):
|
|
480
531
|
"""
|
|
481
|
-
Compute Stieltjes transform of the spectral density
|
|
532
|
+
Compute Stieltjes transform of the spectral density over a 2D Cartesian
|
|
533
|
+
grid on the complex plane.
|
|
482
534
|
|
|
483
535
|
Parameters
|
|
484
536
|
----------
|
|
@@ -492,19 +544,9 @@ class FreeForm(object):
|
|
|
492
544
|
The y axis of the grid where the Stieltjes transform is evaluated.
|
|
493
545
|
If `None`, a grid on the interval ``[-1, 1]`` is used.
|
|
494
546
|
|
|
495
|
-
p : int, default=1
|
|
496
|
-
Degree of polynomial :math:`P(z)`. See notes below.
|
|
497
|
-
|
|
498
|
-
q : int, default=1
|
|
499
|
-
Degree of polynomial :math:`Q(z)`. See notes below.
|
|
500
|
-
|
|
501
547
|
plot : bool, default=False
|
|
502
548
|
If `True`, density is plotted.
|
|
503
549
|
|
|
504
|
-
plot_glue : bool, default=False
|
|
505
|
-
If `True`, the fit of glue function to Hilbert transform is
|
|
506
|
-
plotted.
|
|
507
|
-
|
|
508
550
|
latex : bool, default=False
|
|
509
551
|
If `True`, the plot is rendered using LaTeX. This option is
|
|
510
552
|
relevant only if ``plot=True``.
|
|
@@ -536,7 +578,7 @@ class FreeForm(object):
|
|
|
536
578
|
References
|
|
537
579
|
----------
|
|
538
580
|
|
|
539
|
-
.. [1]
|
|
581
|
+
.. [1] tbd
|
|
540
582
|
|
|
541
583
|
Examples
|
|
542
584
|
--------
|
|
@@ -591,46 +633,165 @@ class FreeForm(object):
|
|
|
591
633
|
m1[mask_m, :] = numpy.conjugate(
|
|
592
634
|
stieltjes(numpy.conjugate(z[mask_m, :])))
|
|
593
635
|
|
|
636
|
+
# Second Reimann sheet
|
|
594
637
|
m2[mask_p, :] = m1[mask_p, :]
|
|
595
|
-
m2[mask_m, :] = -m1[mask_m, :] + self._glue(
|
|
596
|
-
z[mask_m, :], p, q, plot_glue=plot_glue, latex=latex,
|
|
597
|
-
save=save)
|
|
638
|
+
m2[mask_m, :] = -m1[mask_m, :] + self._glue(z[mask_m, :])
|
|
598
639
|
|
|
599
640
|
if plot:
|
|
600
641
|
plot_stieltjes(x, y, m1, m2, self.support, latex=latex, save=save)
|
|
601
642
|
|
|
602
643
|
return m1, m2
|
|
603
644
|
|
|
645
|
+
# ==============
|
|
646
|
+
# eval stieltjes
|
|
647
|
+
# ==============
|
|
648
|
+
|
|
649
|
+
def _eval_stieltjes(self, z):
|
|
650
|
+
"""
|
|
651
|
+
Compute Stieltjes transform of the spectral density.
|
|
652
|
+
|
|
653
|
+
Parameters
|
|
654
|
+
----------
|
|
655
|
+
|
|
656
|
+
z : numpy.array
|
|
657
|
+
The z values in the complex plan where the Stieltjes transform is
|
|
658
|
+
evaluated.
|
|
659
|
+
|
|
660
|
+
|
|
661
|
+
Returns
|
|
662
|
+
-------
|
|
663
|
+
|
|
664
|
+
m_p : numpy.ndarray
|
|
665
|
+
The Stieltjes transform on the principal branch.
|
|
666
|
+
|
|
667
|
+
m_m : numpy.ndarray
|
|
668
|
+
The Stieltjes transform continued to the secondary branch.
|
|
669
|
+
|
|
670
|
+
See Also
|
|
671
|
+
--------
|
|
672
|
+
density
|
|
673
|
+
hilbert
|
|
674
|
+
|
|
675
|
+
Notes
|
|
676
|
+
-----
|
|
677
|
+
|
|
678
|
+
Notes.
|
|
679
|
+
|
|
680
|
+
References
|
|
681
|
+
----------
|
|
682
|
+
|
|
683
|
+
.. [1] tbd
|
|
684
|
+
|
|
685
|
+
Examples
|
|
686
|
+
--------
|
|
687
|
+
|
|
688
|
+
.. code-block:: python
|
|
689
|
+
|
|
690
|
+
>>> from freealg import FreeForm
|
|
691
|
+
"""
|
|
692
|
+
|
|
693
|
+
if self.psi is None:
|
|
694
|
+
raise RuntimeError('"fit" the model first.')
|
|
695
|
+
|
|
696
|
+
z = numpy.asarray(z)
|
|
697
|
+
shape = z.shape
|
|
698
|
+
if len(shape) == 0:
|
|
699
|
+
shape = (1,)
|
|
700
|
+
z = z.reshape(-1, 1)
|
|
701
|
+
|
|
702
|
+
# Stieltjes function
|
|
703
|
+
if self.method == 'jacobi':
|
|
704
|
+
stieltjes = partial(jacobi_stieltjes, psi=self.psi,
|
|
705
|
+
support=self.support, alpha=self.alpha,
|
|
706
|
+
beta=self.beta)
|
|
707
|
+
elif self.method == 'chebyshev':
|
|
708
|
+
stieltjes = partial(chebyshev_stieltjes, psi=self.psi,
|
|
709
|
+
support=self.support)
|
|
710
|
+
|
|
711
|
+
mask_p = z.imag >= 0.0
|
|
712
|
+
mask_m = z.imag < 0.0
|
|
713
|
+
|
|
714
|
+
m1 = numpy.zeros_like(z)
|
|
715
|
+
m2 = numpy.zeros_like(z)
|
|
716
|
+
|
|
717
|
+
# Upper half-plane
|
|
718
|
+
m1[mask_p] = stieltjes(z[mask_p].reshape(-1, 1)).reshape(-1)
|
|
719
|
+
|
|
720
|
+
# Lower half-plane, use Schwarz reflection
|
|
721
|
+
m1[mask_m] = numpy.conjugate(
|
|
722
|
+
stieltjes(numpy.conjugate(z[mask_m].reshape(-1, 1)))).reshape(-1)
|
|
723
|
+
|
|
724
|
+
# Second Reimann sheet
|
|
725
|
+
m2[mask_p] = m1[mask_p]
|
|
726
|
+
m2[mask_m] = -m1[mask_m] + self._glue(
|
|
727
|
+
z[mask_m].reshape(-1, 1)).reshape(-1)
|
|
728
|
+
|
|
729
|
+
m1, m2 = m1.reshape(*shape), m2.reshape(*shape)
|
|
730
|
+
|
|
731
|
+
return m1, m2
|
|
732
|
+
|
|
604
733
|
# ==========
|
|
605
734
|
# decompress
|
|
606
735
|
# ==========
|
|
607
736
|
|
|
608
|
-
def decompress(self,
|
|
737
|
+
def decompress(self, size, x=None, delta=1e-4, iterations=500,
|
|
738
|
+
step_size=0.1, tolerance=1e-4, plot=False, latex=False,
|
|
739
|
+
save=False):
|
|
609
740
|
"""
|
|
610
741
|
Free decompression of spectral density.
|
|
611
742
|
|
|
612
743
|
Parameters
|
|
613
744
|
----------
|
|
614
745
|
|
|
615
|
-
|
|
616
|
-
Size of the matrix.
|
|
746
|
+
size : int
|
|
747
|
+
Size of the decompressed matrix.
|
|
748
|
+
|
|
749
|
+
x : numpy.array, default=None
|
|
750
|
+
Positions where density to be evaluated at. If `None`, an interval
|
|
751
|
+
slightly larger than the support interval will be used.
|
|
752
|
+
|
|
753
|
+
delta: float, default=1e-4
|
|
754
|
+
Size of the perturbation into the upper half plane for Plemelj's
|
|
755
|
+
formula.
|
|
756
|
+
|
|
757
|
+
iterations: int, default=500
|
|
758
|
+
Maximum number of Newton iterations.
|
|
759
|
+
|
|
760
|
+
step_size: float, default=0.1
|
|
761
|
+
Step size for Newton iterations.
|
|
762
|
+
|
|
763
|
+
tolerance: float, default=1e-4
|
|
764
|
+
Tolerance for the solution obtained by the Newton solver. Also
|
|
765
|
+
used for the finite difference approximation to the derivative.
|
|
766
|
+
|
|
767
|
+
plot : bool, default=False
|
|
768
|
+
If `True`, density is plotted.
|
|
769
|
+
|
|
770
|
+
latex : bool, default=False
|
|
771
|
+
If `True`, the plot is rendered using LaTeX. This option is
|
|
772
|
+
relevant only if ``plot=True``.
|
|
773
|
+
|
|
774
|
+
save : bool, default=False
|
|
775
|
+
If not `False`, the plot is saved. If a string is given, it is
|
|
776
|
+
assumed to the save filename (with the file extension). This option
|
|
777
|
+
is relevant only if ``plot=True``.
|
|
617
778
|
|
|
618
779
|
Returns
|
|
619
780
|
-------
|
|
620
781
|
|
|
621
782
|
rho : numpy.array
|
|
622
|
-
|
|
783
|
+
Spectral density
|
|
623
784
|
|
|
624
785
|
See Also
|
|
625
786
|
--------
|
|
626
787
|
|
|
627
788
|
density
|
|
628
|
-
|
|
789
|
+
stieltjes
|
|
629
790
|
|
|
630
791
|
Notes
|
|
631
792
|
-----
|
|
632
793
|
|
|
633
|
-
|
|
794
|
+
Work in progress.
|
|
634
795
|
|
|
635
796
|
References
|
|
636
797
|
----------
|
|
@@ -645,4 +806,12 @@ class FreeForm(object):
|
|
|
645
806
|
>>> from freealg import FreeForm
|
|
646
807
|
"""
|
|
647
808
|
|
|
648
|
-
|
|
809
|
+
rho, x, (lb, ub) = decompress(self, size, x=x, delta=delta,
|
|
810
|
+
iterations=iterations,
|
|
811
|
+
step_size=step_size, tolerance=tolerance)
|
|
812
|
+
|
|
813
|
+
if plot:
|
|
814
|
+
plot_density(x.reshape(-1), rho.reshape(-1), support=(lb, ub),
|
|
815
|
+
label='Decompression', latex=latex, save=save)
|
|
816
|
+
|
|
817
|
+
return rho
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.0.1"
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|