freealg 0.4.1__py3-none-any.whl → 0.5.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/__version__.py +1 -1
- freealg/_chebyshev.py +36 -14
- freealg/_decompress.py +706 -66
- freealg/_linalg.py +24 -10
- freealg/_pade.py +3 -59
- freealg/_plot_util.py +30 -18
- freealg/_sample.py +13 -6
- freealg/_series.py +123 -0
- freealg/_support.py +2 -0
- freealg/_util.py +1 -1
- freealg/distributions/_kesten_mckay.py +6 -6
- freealg/distributions/_marchenko_pastur.py +9 -11
- freealg/distributions/_meixner.py +6 -6
- freealg/distributions/_wachter.py +9 -11
- freealg/distributions/_wigner.py +8 -9
- freealg/freeform.py +199 -82
- {freealg-0.4.1.dist-info → freealg-0.5.0.dist-info}/METADATA +1 -1
- freealg-0.5.0.dist-info/RECORD +26 -0
- freealg-0.4.1.dist-info/RECORD +0 -25
- {freealg-0.4.1.dist-info → freealg-0.5.0.dist-info}/WHEEL +0 -0
- {freealg-0.4.1.dist-info → freealg-0.5.0.dist-info}/licenses/AUTHORS.txt +0 -0
- {freealg-0.4.1.dist-info → freealg-0.5.0.dist-info}/licenses/LICENSE.txt +0 -0
- {freealg-0.4.1.dist-info → freealg-0.5.0.dist-info}/top_level.txt +0 -0
freealg/freeform.py
CHANGED
|
@@ -28,7 +28,7 @@ from ._decompress import decompress
|
|
|
28
28
|
from ._sample import qmc_sample
|
|
29
29
|
from ._support import detect_support
|
|
30
30
|
|
|
31
|
-
# Fallback to previous API
|
|
31
|
+
# Fallback to previous numpy API
|
|
32
32
|
if not hasattr(numpy, 'trapezoid'):
|
|
33
33
|
numpy.trapezoid = numpy.trapz
|
|
34
34
|
|
|
@@ -142,7 +142,7 @@ class FreeForm(object):
|
|
|
142
142
|
|
|
143
143
|
self.A = None
|
|
144
144
|
self.eig = None
|
|
145
|
-
self.delta = delta
|
|
145
|
+
self.delta = delta # Offset above real axis to apply Plemelj formula
|
|
146
146
|
|
|
147
147
|
# Eigenvalues
|
|
148
148
|
if A.ndim == 1:
|
|
@@ -167,20 +167,21 @@ class FreeForm(object):
|
|
|
167
167
|
self.support = (self.lam_m, self.lam_p)
|
|
168
168
|
|
|
169
169
|
# Initialize
|
|
170
|
-
self.method = None
|
|
171
|
-
self.
|
|
172
|
-
self.
|
|
173
|
-
self.
|
|
174
|
-
self.
|
|
170
|
+
self.method = None # fitting rho: jacobi, chebyshev
|
|
171
|
+
self.continuation = None # analytic continuation: pade, wynn
|
|
172
|
+
self._pade_sol = None # result of pade approximation
|
|
173
|
+
self.psi = None # coefficients of estimating rho
|
|
174
|
+
self.alpha = None # Jacobi polynomials alpha parameter
|
|
175
|
+
self.beta = None # Jacobi polynomials beta parameter
|
|
175
176
|
|
|
176
177
|
# ===
|
|
177
178
|
# fit
|
|
178
179
|
# ===
|
|
179
180
|
|
|
180
181
|
def fit(self, method='jacobi', K=10, alpha=0.0, beta=0.0, reg=0.0,
|
|
181
|
-
projection='gaussian', kernel_bw=
|
|
182
|
-
pade_p=0, pade_q=1, odd_side='left',
|
|
183
|
-
plot=False, latex=False, save=False):
|
|
182
|
+
projection='gaussian', kernel_bw=0.001, damp=None, force=False,
|
|
183
|
+
continuation='pade', pade_p=0, pade_q=1, odd_side='left',
|
|
184
|
+
pade_reg=0.0, optimizer='ls', plot=False, latex=False, save=False):
|
|
184
185
|
"""
|
|
185
186
|
Fit model to eigenvalues.
|
|
186
187
|
|
|
@@ -233,12 +234,22 @@ class FreeForm(object):
|
|
|
233
234
|
If `True`, it forces the density to have unit mass and to be
|
|
234
235
|
strictly positive.
|
|
235
236
|
|
|
237
|
+
continuation : {``'pade'``, ``wynn``}, default= ``'pade'``
|
|
238
|
+
Method of analytic continuation to construct the second branch of
|
|
239
|
+
Steltjes transform in the lower-half complex plane:
|
|
240
|
+
|
|
241
|
+
* ``'pade'``: using Reimann-Hilbert problem witth Pade
|
|
242
|
+
approximation.
|
|
243
|
+
* ``'wynn'``: Wynn's epsilon algorithm.
|
|
244
|
+
|
|
236
245
|
pade_p : int, default=0
|
|
237
246
|
Degree of polynomial :math:`P(z)` is :math:`q+p` where :math:`p`
|
|
238
|
-
can only be ``-1``, ``0``, or ``1``. See notes below.
|
|
247
|
+
can only be ``-1``, ``0``, or ``1``. See notes below. This option
|
|
248
|
+
is applicable if ``continuation='pade'``.
|
|
239
249
|
|
|
240
250
|
pade_q : int, default=1
|
|
241
251
|
Degree of polynomial :math:`Q(z)` is :math:`q`. See notes below.
|
|
252
|
+
This option is applicable if ``continuation='pade'``.
|
|
242
253
|
|
|
243
254
|
odd_side : {``'left'``, ``'right'``}, default= ``'left'``
|
|
244
255
|
In case of odd number of poles (when :math:`q` is odd), the extra
|
|
@@ -246,10 +257,12 @@ class FreeForm(object):
|
|
|
246
257
|
while all other poles are split in half to the left and right. Note
|
|
247
258
|
that this is only for the initialization of the poles. The
|
|
248
259
|
optimizer will decide best location by moving them to the left or
|
|
249
|
-
right of the support.
|
|
260
|
+
right of the support. This option is applicable if
|
|
261
|
+
``continuation='pade'``.
|
|
250
262
|
|
|
251
263
|
pade_reg : float, default=0.0
|
|
252
|
-
Regularization for Pade approximation.
|
|
264
|
+
Regularization for Pade approximation. This option is applicable if
|
|
265
|
+
``continuation='pade'``.
|
|
253
266
|
|
|
254
267
|
optimizer : {``'ls'``, ``'de'``}, default= ``'ls'``
|
|
255
268
|
Optimizer for Pade approximation, including:
|
|
@@ -257,9 +270,11 @@ class FreeForm(object):
|
|
|
257
270
|
* ``'ls'``: least square (local, fast)
|
|
258
271
|
* ``'de'``: differential evolution (global, slow)
|
|
259
272
|
|
|
273
|
+
This option is applicable if ``continuation='pade'``.
|
|
274
|
+
|
|
260
275
|
plot : bool, default=False
|
|
261
276
|
If `True`, the approximation coefficients and Pade approximation to
|
|
262
|
-
the Hilbert transform are plotted.
|
|
277
|
+
the Hilbert transform (if applicable) are plotted.
|
|
263
278
|
|
|
264
279
|
latex : bool, default=False
|
|
265
280
|
If `True`, the plot is rendered using LaTeX. This option is
|
|
@@ -332,7 +347,6 @@ class FreeForm(object):
|
|
|
332
347
|
# adaptive=True)
|
|
333
348
|
# pdf = k.evaluate(xs)
|
|
334
349
|
|
|
335
|
-
# TEST
|
|
336
350
|
# import matplotlib.pyplot as plt
|
|
337
351
|
# plt.plot(xs, pdf)
|
|
338
352
|
# plt.grid(True)
|
|
@@ -365,7 +379,7 @@ class FreeForm(object):
|
|
|
365
379
|
psi = chebyshev_kernel_proj(xs, pdf, support=self.support,
|
|
366
380
|
K=K, reg=reg)
|
|
367
381
|
else:
|
|
368
|
-
raise
|
|
382
|
+
raise NotImplementedError('"method" is invalid.')
|
|
369
383
|
|
|
370
384
|
# Damping
|
|
371
385
|
if damp is not None:
|
|
@@ -404,8 +418,14 @@ class FreeForm(object):
|
|
|
404
418
|
self.alpha = alpha
|
|
405
419
|
self.beta = beta
|
|
406
420
|
|
|
407
|
-
#
|
|
408
|
-
if
|
|
421
|
+
# Analytic continuation
|
|
422
|
+
if continuation not in ['pade', 'wynn']:
|
|
423
|
+
raise NotImplementedError('"continuation" method is invalid.')
|
|
424
|
+
|
|
425
|
+
self.continuation = continuation
|
|
426
|
+
|
|
427
|
+
if self.continuation == 'pade':
|
|
428
|
+
|
|
409
429
|
# For holomorphic continuation for the lower half-plane
|
|
410
430
|
x_supp = numpy.linspace(self.lam_m, self.lam_p, 1000)
|
|
411
431
|
g_supp = 2.0 * numpy.pi * self.hilbert(x_supp)
|
|
@@ -414,21 +434,36 @@ class FreeForm(object):
|
|
|
414
434
|
pade_reg=pade_reg, safety=1.0,
|
|
415
435
|
max_outer=40, xtol=1e-12, ftol=1e-12,
|
|
416
436
|
optimizer=optimizer, verbose=0)
|
|
437
|
+
else:
|
|
438
|
+
# Do nothing. Make sure _pade_sol is still None
|
|
439
|
+
self._pade_sol = None
|
|
440
|
+
|
|
441
|
+
if method != 'chebyshev':
|
|
442
|
+
raise NotImplementedError(
|
|
443
|
+
'Up to the current version, the analytic continuation ' +
|
|
444
|
+
'using "wynn" is only implemented for "chebyshev" ' +
|
|
445
|
+
'estimation method.')
|
|
417
446
|
|
|
418
447
|
if plot:
|
|
419
|
-
|
|
448
|
+
if self._pade_sol is not None:
|
|
449
|
+
g_supp_approx = eval_pade(x_supp[None, :],
|
|
450
|
+
self._pade_sol)[0, :]
|
|
451
|
+
else:
|
|
452
|
+
x_supp = None
|
|
453
|
+
g_supp = None
|
|
454
|
+
g_supp_approx = None
|
|
420
455
|
plot_fit(psi, x_supp, g_supp, g_supp_approx, support=self.support,
|
|
421
456
|
latex=latex, save=save)
|
|
422
457
|
|
|
423
458
|
return self.psi
|
|
424
459
|
|
|
425
|
-
#
|
|
426
|
-
#
|
|
427
|
-
#
|
|
460
|
+
# =============
|
|
461
|
+
# generate grid
|
|
462
|
+
# =============
|
|
428
463
|
|
|
429
|
-
def
|
|
464
|
+
def _generate_grid(self, scale, extend=1.0, N=500):
|
|
430
465
|
"""
|
|
431
|
-
|
|
466
|
+
Generate a grid of points to evaluate density / Hilbert / Stieltjes
|
|
432
467
|
transforms.
|
|
433
468
|
"""
|
|
434
469
|
|
|
@@ -490,12 +525,12 @@ class FreeForm(object):
|
|
|
490
525
|
"""
|
|
491
526
|
|
|
492
527
|
if self.psi is None:
|
|
493
|
-
raise RuntimeError('The
|
|
494
|
-
'
|
|
528
|
+
raise RuntimeError('The model needs to be fit using the .fit() ' +
|
|
529
|
+
'function.')
|
|
495
530
|
|
|
496
531
|
# Create x if not given
|
|
497
532
|
if x is None:
|
|
498
|
-
x = self.
|
|
533
|
+
x = self._generate_grid(1.25)
|
|
499
534
|
|
|
500
535
|
# Preallocate density to zero
|
|
501
536
|
rho = numpy.zeros_like(x)
|
|
@@ -580,12 +615,12 @@ class FreeForm(object):
|
|
|
580
615
|
"""
|
|
581
616
|
|
|
582
617
|
if self.psi is None:
|
|
583
|
-
raise RuntimeError('The
|
|
584
|
-
'
|
|
618
|
+
raise RuntimeError('The model needs to be fit using the .fit() ' +
|
|
619
|
+
'function.')
|
|
585
620
|
|
|
586
621
|
# Create x if not given
|
|
587
622
|
if x is None:
|
|
588
|
-
x = self.
|
|
623
|
+
x = self._generate_grid(1.25)
|
|
589
624
|
|
|
590
625
|
# if (numpy.min(x) > self.lam_m) or (numpy.max(x) < self.lam_p):
|
|
591
626
|
# raise ValueError('"x" does not encompass support interval.')
|
|
@@ -626,10 +661,23 @@ class FreeForm(object):
|
|
|
626
661
|
# ====
|
|
627
662
|
|
|
628
663
|
def _glue(self, z):
|
|
629
|
-
|
|
664
|
+
"""
|
|
665
|
+
Glue function.
|
|
666
|
+
|
|
667
|
+
Notes
|
|
668
|
+
-----
|
|
669
|
+
|
|
670
|
+
This function needs self._pade_sol to be initialized in .fit()
|
|
671
|
+
function. This only works when continuation method is set to "pade".
|
|
672
|
+
"""
|
|
673
|
+
|
|
630
674
|
if self._pade_sol is None:
|
|
631
|
-
|
|
675
|
+
raise RuntimeError('"_glue" is called but "_pade_sol" is not' +
|
|
676
|
+
'initialized. This is likely a ' +
|
|
677
|
+
'development bug.')
|
|
678
|
+
|
|
632
679
|
g = eval_pade(z, self._pade_sol)
|
|
680
|
+
|
|
633
681
|
return g
|
|
634
682
|
|
|
635
683
|
# =========
|
|
@@ -700,30 +748,25 @@ class FreeForm(object):
|
|
|
700
748
|
"""
|
|
701
749
|
|
|
702
750
|
if self.psi is None:
|
|
703
|
-
raise RuntimeError('The
|
|
704
|
-
'
|
|
705
|
-
|
|
706
|
-
# Determine whether the Stieltjes transform is to be computed on a
|
|
707
|
-
# Cartesian grid
|
|
708
|
-
cartesian = plot | (y is not None)
|
|
751
|
+
raise RuntimeError('The model needs to be fit using the .fit() ' +
|
|
752
|
+
'function.')
|
|
709
753
|
|
|
710
754
|
# Create x if not given
|
|
711
755
|
if x is None:
|
|
712
|
-
x = self.
|
|
713
|
-
|
|
714
|
-
if not cartesian:
|
|
715
|
-
# Evaluate slightly above the real line
|
|
716
|
-
x = x.astype(complex)
|
|
717
|
-
x += self.delta * 1j
|
|
756
|
+
x = self._generate_grid(2.0, extend=2.0)
|
|
718
757
|
|
|
719
758
|
# Create y if not given
|
|
720
|
-
if
|
|
759
|
+
if (plot is False) and (y is None):
|
|
760
|
+
# Do no tuse a Cartesian grid. Create a 1D array z slightly above
|
|
761
|
+
# the real line.
|
|
762
|
+
y = self.delta * 1j
|
|
763
|
+
z = x.astype(complex) + y # shape (Nx,)
|
|
764
|
+
else:
|
|
765
|
+
# Use a Cartesian grid
|
|
721
766
|
if y is None:
|
|
722
767
|
y = numpy.linspace(-1, 1, 400)
|
|
723
768
|
x_grid, y_grid = numpy.meshgrid(x.real, y.real)
|
|
724
769
|
z = x_grid + 1j * y_grid # shape (Ny, Nx)
|
|
725
|
-
else:
|
|
726
|
-
z = x
|
|
727
770
|
|
|
728
771
|
m1, m2 = self._eval_stieltjes(z, branches=True)
|
|
729
772
|
|
|
@@ -752,7 +795,6 @@ class FreeForm(object):
|
|
|
752
795
|
transform. The default ``branches=False`` will return only
|
|
753
796
|
the secondary branch.
|
|
754
797
|
|
|
755
|
-
|
|
756
798
|
Returns
|
|
757
799
|
-------
|
|
758
800
|
|
|
@@ -764,7 +806,8 @@ class FreeForm(object):
|
|
|
764
806
|
The Stieltjes transform continued to the secondary branch.
|
|
765
807
|
"""
|
|
766
808
|
|
|
767
|
-
|
|
809
|
+
if self.psi is None:
|
|
810
|
+
raise RuntimeError('"fit" the model first.')
|
|
768
811
|
|
|
769
812
|
# Allow for arbitrary input shapes
|
|
770
813
|
z = numpy.asarray(z)
|
|
@@ -783,9 +826,17 @@ class FreeForm(object):
|
|
|
783
826
|
stieltjes = partial(jacobi_stieltjes, psi=self.psi,
|
|
784
827
|
support=self.support, alpha=self.alpha,
|
|
785
828
|
beta=self.beta) # n_base = n_base
|
|
829
|
+
|
|
786
830
|
elif self.method == 'chebyshev':
|
|
831
|
+
|
|
832
|
+
if self.continuation == 'wynn':
|
|
833
|
+
use_wynn_epsilon = True
|
|
834
|
+
else:
|
|
835
|
+
use_wynn_epsilon = False
|
|
836
|
+
|
|
787
837
|
stieltjes = partial(chebyshev_stieltjes, psi=self.psi,
|
|
788
|
-
support=self.support
|
|
838
|
+
support=self.support,
|
|
839
|
+
use_wynn_epsilon=use_wynn_epsilon)
|
|
789
840
|
|
|
790
841
|
mask_p = z.imag >= 0.0
|
|
791
842
|
mask_m = z.imag < 0.0
|
|
@@ -793,7 +844,7 @@ class FreeForm(object):
|
|
|
793
844
|
m1 = numpy.zeros_like(z)
|
|
794
845
|
m2 = numpy.zeros_like(z)
|
|
795
846
|
|
|
796
|
-
if self.
|
|
847
|
+
if self.continuation == 'pade':
|
|
797
848
|
# Upper half-plane
|
|
798
849
|
m1[mask_p] = stieltjes(z[mask_p].reshape(-1, 1)).ravel()
|
|
799
850
|
|
|
@@ -806,47 +857,55 @@ class FreeForm(object):
|
|
|
806
857
|
m2[mask_m] = -m1[mask_m] + self._glue(
|
|
807
858
|
z[mask_m].reshape(-1, 1)).ravel()
|
|
808
859
|
|
|
809
|
-
|
|
860
|
+
elif self.continuation == 'wynn':
|
|
810
861
|
m2[:] = stieltjes(z.reshape(-1, 1)).reshape(*m2.shape)
|
|
811
862
|
if branches:
|
|
812
863
|
m1[mask_p] = m2[mask_p]
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
864
|
+
z_conj = numpy.conjugate(z[mask_m].reshape(-1, 1))
|
|
865
|
+
m1[mask_m] = numpy.conjugate(stieltjes(z_conj)).ravel()
|
|
866
|
+
|
|
867
|
+
else:
|
|
868
|
+
raise NotImplementedError('Invalid continuation method.')
|
|
816
869
|
|
|
817
870
|
if not branches:
|
|
818
871
|
return m2.reshape(*shape)
|
|
819
872
|
else:
|
|
820
|
-
m1
|
|
873
|
+
m1 = m1.reshape(*shape)
|
|
874
|
+
m2 = m2.reshape(*shape)
|
|
821
875
|
return m1, m2
|
|
822
876
|
|
|
823
877
|
# ==========
|
|
824
878
|
# decompress
|
|
825
879
|
# ==========
|
|
826
880
|
|
|
827
|
-
def decompress(self, size, x=None,
|
|
828
|
-
tolerance=1e-
|
|
829
|
-
|
|
881
|
+
def decompress(self, size, x=None, method='newton', max_iter=500,
|
|
882
|
+
step_size=0.1, tolerance=1e-4, plot=False, latex=False,
|
|
883
|
+
save=False, plot_diagnostics=False):
|
|
830
884
|
"""
|
|
831
885
|
Free decompression of spectral density.
|
|
832
886
|
|
|
833
887
|
Parameters
|
|
834
888
|
----------
|
|
835
889
|
|
|
836
|
-
size : int
|
|
837
|
-
Size of the decompressed matrix.
|
|
890
|
+
size : int or array_like
|
|
891
|
+
Size(s) of the decompressed matrix. This can be a scalar or an
|
|
892
|
+
array of sizes. For each matrix size in ``size`` array, a density
|
|
893
|
+
is produced.
|
|
838
894
|
|
|
839
895
|
x : numpy.array, default=None
|
|
840
896
|
Positions where density to be evaluated at. If `None`, an interval
|
|
841
897
|
slightly larger than the support interval will be used.
|
|
842
898
|
|
|
899
|
+
method : {``'newton'``, ``'secant'``}, default= ``'newton'``
|
|
900
|
+
Root-finding method.
|
|
901
|
+
|
|
843
902
|
max_iter: int, default=500
|
|
844
|
-
Maximum number of
|
|
903
|
+
Maximum number of root-finding method iterations.
|
|
845
904
|
|
|
846
|
-
|
|
847
|
-
|
|
905
|
+
step_size: float, default=0.1
|
|
906
|
+
Step size for Newton iterations.
|
|
848
907
|
|
|
849
|
-
tolerance: float, default=1e-
|
|
908
|
+
tolerance: float, default=1e-4
|
|
850
909
|
Tolerance for the solution obtained by the Newton solver. Also
|
|
851
910
|
used for the finite difference approximation to the derivative.
|
|
852
911
|
|
|
@@ -862,18 +921,25 @@ class FreeForm(object):
|
|
|
862
921
|
assumed to the save filename (with the file extension). This option
|
|
863
922
|
is relevant only if ``plot=True``.
|
|
864
923
|
|
|
924
|
+
plot_diagnostics : bool, default=False
|
|
925
|
+
Plots diagnostics including convergence and number of iterations
|
|
926
|
+
of root finding method.
|
|
927
|
+
|
|
865
928
|
Returns
|
|
866
929
|
-------
|
|
867
930
|
|
|
868
|
-
|
|
869
|
-
|
|
931
|
+
rho : numpy.array or numpy.ndarray
|
|
932
|
+
Estimated spectral density at locations x. ``rho`` can be a 1D or
|
|
933
|
+
2D array output:
|
|
870
934
|
|
|
871
|
-
|
|
872
|
-
|
|
935
|
+
* If ``size`` is a scalar, ``rho`` is a 1D array od the same size
|
|
936
|
+
as ``x``.
|
|
937
|
+
* If ``size`` is an array of size `n`, ``rho`` is a 2D array with
|
|
938
|
+
`n` rows, where each row corresponds to decompression to a size.
|
|
939
|
+
Number of columns of ``rho`` is the same as the size of ``x``.
|
|
873
940
|
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
spectral density. Only returns if ``eigvals=True``.
|
|
941
|
+
x : numpy.array
|
|
942
|
+
Locations where the spectral density is estimated
|
|
877
943
|
|
|
878
944
|
See Also
|
|
879
945
|
--------
|
|
@@ -899,17 +965,69 @@ class FreeForm(object):
|
|
|
899
965
|
>>> from freealg import FreeForm
|
|
900
966
|
"""
|
|
901
967
|
|
|
902
|
-
|
|
968
|
+
# Check size argument
|
|
969
|
+
if numpy.isscalar(size):
|
|
970
|
+
size = int(size)
|
|
971
|
+
else:
|
|
972
|
+
# Check monotonic increment (either all increasing or decreasing)
|
|
973
|
+
diff = numpy.diff(size)
|
|
974
|
+
if not (numpy.all(diff >= 0) or numpy.all(diff <= 0)):
|
|
975
|
+
raise ValueError('"size" increment should be monotonic.')
|
|
976
|
+
|
|
977
|
+
# Decompression ratio equal to e^{t}.
|
|
978
|
+
alpha = numpy.atleast_1d(size) / self.n
|
|
903
979
|
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
980
|
+
# Lower and upper bound on new support
|
|
981
|
+
m = self._eval_stieltjes
|
|
982
|
+
hilb_lb = (1.0 / m(self.lam_m + self.delta * 1j).item()).real
|
|
983
|
+
hilb_ub = (1.0 / m(self.lam_p + self.delta * 1j).item()).real
|
|
984
|
+
lb = self.lam_m - (numpy.max(alpha) - 1) * hilb_lb
|
|
985
|
+
ub = self.lam_p - (numpy.max(alpha) - 1) * hilb_ub
|
|
907
986
|
|
|
987
|
+
# Create x if not given
|
|
988
|
+
if x is None:
|
|
989
|
+
radius = 0.5 * (ub - lb)
|
|
990
|
+
center = 0.5 * (ub + lb)
|
|
991
|
+
scale = 1.25
|
|
992
|
+
x_min = numpy.floor(center - radius * scale)
|
|
993
|
+
x_max = numpy.ceil(center + radius * scale)
|
|
994
|
+
x = numpy.linspace(x_min, x_max, 500)
|
|
995
|
+
else:
|
|
996
|
+
x = numpy.asarray(x)
|
|
997
|
+
|
|
998
|
+
if (alpha.size > 8) and plot_diagnostics:
|
|
999
|
+
raise RuntimeError(
|
|
1000
|
+
'Too many diagnostic plots for %d sizes.' % alpha.size)
|
|
1001
|
+
|
|
1002
|
+
# Decompress to each alpha
|
|
1003
|
+
rho = numpy.zeros((alpha.size, x.size), dtype=float)
|
|
1004
|
+
for i in range(alpha.size):
|
|
1005
|
+
|
|
1006
|
+
# Initial guess for roots (only for the first iteration)
|
|
1007
|
+
# if i == 0:
|
|
1008
|
+
# roots = numpy.full(x.shape, numpy.mean(self.support) - 0.1j,
|
|
1009
|
+
# dtype=numpy.complex128)
|
|
1010
|
+
roots = None
|
|
1011
|
+
|
|
1012
|
+
rho[i, :], roots = decompress(
|
|
1013
|
+
self, alpha[i], x, roots_init=roots, method=method,
|
|
1014
|
+
delta=self.delta, max_iter=max_iter, step_size=step_size,
|
|
1015
|
+
tolerance=tolerance, plot_diagnostics=plot_diagnostics)
|
|
1016
|
+
|
|
1017
|
+
# If the input size was only a scalar, return a 1D rho, otherwise 2D.
|
|
1018
|
+
if numpy.isscalar(size):
|
|
1019
|
+
rho = numpy.squeeze(rho)
|
|
1020
|
+
|
|
1021
|
+
# Plot only the last size
|
|
908
1022
|
if plot:
|
|
909
|
-
|
|
1023
|
+
if numpy.isscalar(size):
|
|
1024
|
+
rho_last = rho
|
|
1025
|
+
else:
|
|
1026
|
+
rho_last = rho[-1, :]
|
|
1027
|
+
plot_density(x, rho_last, support=(lb, ub),
|
|
910
1028
|
label='Decompression', latex=latex, save=save)
|
|
911
1029
|
|
|
912
|
-
return
|
|
1030
|
+
return rho, x
|
|
913
1031
|
|
|
914
1032
|
# ========
|
|
915
1033
|
# eigvalsh
|
|
@@ -964,12 +1082,11 @@ class FreeForm(object):
|
|
|
964
1082
|
"""
|
|
965
1083
|
|
|
966
1084
|
if size is None:
|
|
967
|
-
x = self._grid(1.25)
|
|
968
|
-
rho = self.density(x)
|
|
969
1085
|
size = self.n
|
|
970
|
-
|
|
971
|
-
|
|
1086
|
+
|
|
1087
|
+
rho, x = self.decompress(size, **kwargs)
|
|
972
1088
|
eigs = numpy.sort(qmc_sample(x, rho, size, seed=seed))
|
|
1089
|
+
|
|
973
1090
|
return eigs
|
|
974
1091
|
|
|
975
1092
|
# ====
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
freealg/__init__.py,sha256=KfzqG7qig6ZZCKqgHcC2ApTg4rTLkrbJsvVoJd8UFG8,625
|
|
2
|
+
freealg/__version__.py,sha256=LBK46heutvn3KmsCrKIYu8RQikbfnjZaj2xFrXaeCzQ,22
|
|
3
|
+
freealg/_chebyshev.py,sha256=-XiMKPra9pjkvMLjLusPo8n4NfjcJd9K0tAm5TF8PdA,6311
|
|
4
|
+
freealg/_damp.py,sha256=k2vtBtWOxQBf4qXaWu_En81lQBXbEO4QbxxWpvuVhdE,1802
|
|
5
|
+
freealg/_decompress.py,sha256=RKYnuLKMx1V6-XrFjYX1UkGMRbUD9Gmf9XTyS4ffPSc,31970
|
|
6
|
+
freealg/_jacobi.py,sha256=AT4ONSHGGDxVKE3MGMLyMR8uDFiO-e9u3x5udYfdJJk,5635
|
|
7
|
+
freealg/_linalg.py,sha256=khfRwdQIDtf45aOIq3QSeihAEtUCL-HgwEYtEs0YELc,13137
|
|
8
|
+
freealg/_pade.py,sha256=Ecm373RvBWznAaf8a5D9qtjcRA8O_8NQsePwto-dsP4,13656
|
|
9
|
+
freealg/_plot_util.py,sha256=mkvOZJDXCxIo8jUZoS8gsSDgieMCL8oZNZEo_-mYreQ,20052
|
|
10
|
+
freealg/_sample.py,sha256=MUY9ZkJbdhbC5thoy5_JMRWOHz_OfqMfaH0g2VhKPhg,2550
|
|
11
|
+
freealg/_series.py,sha256=x0_NNaNjv-_FSAnZzlp8BO5XI5q8ELF_kwnGlAUBZZg,2603
|
|
12
|
+
freealg/_support.py,sha256=ZfU0T7CCDaTXMdEHSbwOL-rMnCPvJWsRb6JtqUMsrzY,6441
|
|
13
|
+
freealg/_util.py,sha256=yerqBCedkglc9soWmRgxcm7HTnJGKeiDq9xxfKcE9WY,3780
|
|
14
|
+
freealg/freeform.py,sha256=zkjkkMkvCTn25k8QvefrvNBaGYQhIkPLBiV_Ij01l04,42286
|
|
15
|
+
freealg/distributions/__init__.py,sha256=t_yZyEkW_W_tSV9IvgYXtVASxD2BEdiNVXcV2ebMy8M,579
|
|
16
|
+
freealg/distributions/_kesten_mckay.py,sha256=4EvW0seBZUv-cZjuLzfVCredmrCiOJcQ_hJM0mJDl6g,19899
|
|
17
|
+
freealg/distributions/_marchenko_pastur.py,sha256=r-jmz8Wq5vG0-x7rB0qvVemqvu0Oq6S-BN67pqH0uiw,16992
|
|
18
|
+
freealg/distributions/_meixner.py,sha256=bZv-x4mwS4yjisKoYSZAffHXtvDEKEis-74BeAjK4_s,17530
|
|
19
|
+
freealg/distributions/_wachter.py,sha256=rkAmrBLqD2zvpBh0F32aQBscjXv8earXDH9_BITgFF0,16900
|
|
20
|
+
freealg/distributions/_wigner.py,sha256=w8OlZL9pSfGnXVSSB6A4KBiImr0Zz4iH2PDLCHFfpaY,15877
|
|
21
|
+
freealg-0.5.0.dist-info/licenses/AUTHORS.txt,sha256=0b67Nz4_JgIzUupHJTAZxu5QdSUM_HRM_X_w4xCb17o,30
|
|
22
|
+
freealg-0.5.0.dist-info/licenses/LICENSE.txt,sha256=J-EEYEtxb3VVf_Bn1TYfWnpY5lMFIM15iLDDcnaDTPA,1443
|
|
23
|
+
freealg-0.5.0.dist-info/METADATA,sha256=rKSfjasqwCCzpGbqmdfjs4y0jezvH6ylKDv_tEL4xZM,5529
|
|
24
|
+
freealg-0.5.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
25
|
+
freealg-0.5.0.dist-info/top_level.txt,sha256=eR2wrgYwDdnnJ9Zf5PruPqe4kQav0GMvRsqct6y00Q8,8
|
|
26
|
+
freealg-0.5.0.dist-info/RECORD,,
|
freealg-0.4.1.dist-info/RECORD
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
freealg/__init__.py,sha256=KfzqG7qig6ZZCKqgHcC2ApTg4rTLkrbJsvVoJd8UFG8,625
|
|
2
|
-
freealg/__version__.py,sha256=pMtTmSUht-XtbR_7Doz6bsQqopJJd8rZ8I8zy2HwwoA,22
|
|
3
|
-
freealg/_chebyshev.py,sha256=dsAj3YEpmkzB65smluZ0Fi5IZSdpnQXBSIuKMg19grA,5523
|
|
4
|
-
freealg/_damp.py,sha256=k2vtBtWOxQBf4qXaWu_En81lQBXbEO4QbxxWpvuVhdE,1802
|
|
5
|
-
freealg/_decompress.py,sha256=0MYoO3lqwMgNYlVriaRNUqUwY3XYyZZsDAtNRBq6rhE,10470
|
|
6
|
-
freealg/_jacobi.py,sha256=AT4ONSHGGDxVKE3MGMLyMR8uDFiO-e9u3x5udYfdJJk,5635
|
|
7
|
-
freealg/_linalg.py,sha256=Vl1iB0rG-PVjEqoUbCXNxk6BmeujEbBucG2ZdBJoFjA,12490
|
|
8
|
-
freealg/_pade.py,sha256=Diw850oH2OLQeUrBR-q19TmjSBoBvXl6ogp4o1s2UIo,15184
|
|
9
|
-
freealg/_plot_util.py,sha256=U4alp7Pzg315_7jJdu1UB0tIUcxUovQgHDHsUYoa2Z0,19728
|
|
10
|
-
freealg/_sample.py,sha256=ckC75eqv-mRP1F5BnhvsjfLTaoAzHK8bebl9bCRZYDo,2561
|
|
11
|
-
freealg/_support.py,sha256=mYlrsdLbniqFgFofbHrZIiYSyJudPqtyMQQTPBD9Y6M,6439
|
|
12
|
-
freealg/_util.py,sha256=8Tvz-XODtKYoU76ODmF1TBaIYLlr6-AXiyoMDwDSxVg,3779
|
|
13
|
-
freealg/freeform.py,sha256=3_zAlmLbhwrmJrLqsghTUQQbJ9H0u7DI1fjdF84Sk_M,37145
|
|
14
|
-
freealg/distributions/__init__.py,sha256=t_yZyEkW_W_tSV9IvgYXtVASxD2BEdiNVXcV2ebMy8M,579
|
|
15
|
-
freealg/distributions/_kesten_mckay.py,sha256=210RF2OQEYLZBeLB6wmbdHnZPs_9ldDNHm_FMlg5tis,19881
|
|
16
|
-
freealg/distributions/_marchenko_pastur.py,sha256=kchFccRMuVF2Cus_99vdEwuRimkHzEUV8xt5kZFg7ZI,16994
|
|
17
|
-
freealg/distributions/_meixner.py,sha256=ws7t_EUa7V0s97dgMQIJLv1b6qMLqf9fLLbTJQudf_8,17512
|
|
18
|
-
freealg/distributions/_wachter.py,sha256=Hna_MXqAPjuRkeilLPMf4Xg_3C6tTu5oZLEQnA-RuE4,16897
|
|
19
|
-
freealg/distributions/_wigner.py,sha256=SxgPLtvIVBi9m4De-oBD0x6-2Je_eBqpDrpDYcoLuis,15871
|
|
20
|
-
freealg-0.4.1.dist-info/licenses/AUTHORS.txt,sha256=0b67Nz4_JgIzUupHJTAZxu5QdSUM_HRM_X_w4xCb17o,30
|
|
21
|
-
freealg-0.4.1.dist-info/licenses/LICENSE.txt,sha256=J-EEYEtxb3VVf_Bn1TYfWnpY5lMFIM15iLDDcnaDTPA,1443
|
|
22
|
-
freealg-0.4.1.dist-info/METADATA,sha256=wN2_XUZz2mEfjMROOLmGY8-0xtflEKY40gL5RZBTElQ,5529
|
|
23
|
-
freealg-0.4.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
24
|
-
freealg-0.4.1.dist-info/top_level.txt,sha256=eR2wrgYwDdnnJ9Zf5PruPqe4kQav0GMvRsqct6y00Q8,8
|
|
25
|
-
freealg-0.4.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|