freealg 0.0.3__py3-none-any.whl → 0.1.1__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/freeform.py CHANGED
@@ -13,15 +13,19 @@
13
13
 
14
14
  import numpy
15
15
  from scipy.stats import gaussian_kde
16
+ # from statsmodels.nonparametric.kde import KDEUnivariate
16
17
  from functools import partial
17
18
  from ._util import compute_eig, force_density
18
- from ._jacobi import jacobi_proj, jacobi_approx, jacobi_stieltjes
19
- from ._chebyshev import chebyshev_proj, chebyshev_approx, chebyshev_stieltjes
19
+ from ._jacobi import jacobi_sample_proj, jacobi_kernel_proj, jacobi_approx, \
20
+ jacobi_stieltjes
21
+ from ._chebyshev import chebyshev_sample_proj, chebyshev_kernel_proj, \
22
+ chebyshev_approx, chebyshev_stieltjes
20
23
  from ._damp import jackson_damping, lanczos_damping, fejer_damping, \
21
24
  exponential_damping, parzen_damping
22
25
  from ._plot_util import plot_fit, plot_density, plot_hilbert, plot_stieltjes
23
26
  from ._pade import fit_pade, eval_pade
24
27
  from ._decompress import decompress
28
+ from ._sample import qmc_sample
25
29
 
26
30
  __all__ = ['FreeForm']
27
31
 
@@ -173,8 +177,9 @@ class FreeForm(object):
173
177
  # ===
174
178
 
175
179
  def fit(self, method='jacobi', K=10, alpha=0.0, beta=0.0, reg=0.0,
176
- damp=None, force=False, pade_p=1, pade_q=1, plot=False,
177
- latex=False, save=False):
180
+ projection='kernel', kernel_bw=None, damp=None, force=False,
181
+ pade_p=0, pade_q=1, odd_side='left', pade_reg=0.0, optimizer='ls',
182
+ plot=False, latex=False, save=False):
178
183
  """
179
184
  Fit model to eigenvalues.
180
185
 
@@ -201,6 +206,19 @@ class FreeForm(object):
201
206
  reg : float, default=0.0
202
207
  Tikhonov regularization coefficient.
203
208
 
209
+ projection : {``'sample'``, ``'kernel'``}, default= ``'kernel'``
210
+ The method of Galerkin projection:
211
+
212
+ * ``'sample'``: directly project samples (eigenvalues) to the
213
+ orthogonal polynomials. This method is highly unstable as it
214
+ treats each sample as a delta Dirac function.
215
+ * ``'kernel'``: computes KDE from the samples and project a
216
+ smooth KDE to the orthogonal polynomials. This method is stable.
217
+
218
+ kernel_bw : float, default=None
219
+ Kernel band-wdth. See scipy.stats.gaussian_kde. This argument is
220
+ relevant if ``projection='kernel'`` is set.
221
+
204
222
  damp : {``'jackson'``, ``'lanczos'``, ``'fejer``, ``'exponential'``,\
205
223
  ``'parzen'``}, default=None
206
224
  Damping method to eliminate Gibbs oscillation.
@@ -209,15 +227,33 @@ class FreeForm(object):
209
227
  If `True`, it forces the density to have unit mass and to be
210
228
  strictly positive.
211
229
 
212
- pade_p : int, default=1
213
- Degree of polynomial :math:`P(z)`. See notes below.
230
+ pade_p : int, default=0
231
+ Degree of polynomial :math:`P(z)` is :math:`q+p` where :math:`p`
232
+ can only be ``-1``, ``0``, or ``1``. See notes below.
214
233
 
215
234
  pade_q : int, default=1
216
- Degree of polynomial :math:`Q(z)`. See notes below.
235
+ Degree of polynomial :math:`Q(z)` is :math:`q`. See notes below.
236
+
237
+ odd_side : {``'left'``, ``'right'``}, default= ``'left'``
238
+ In case of odd number of poles (when :math:`q` is odd), the extra
239
+ pole is set to the left or right side of the support interval,
240
+ while all other poles are split in half to the left and right. Note
241
+ that this is only for the initialization of the poles. The
242
+ optimizer will decide best location by moving them to the left or
243
+ right of the support.
244
+
245
+ pade_reg : float, default=0.0
246
+ Regularization for Pade approximation.
247
+
248
+ optimizer : {``'ls'``, ``'de'``}, default= ``'ls'``
249
+ Optimizer for Pade approximation, including:
250
+
251
+ * ``'ls'``: least square (local, fast)
252
+ * ``'de'``: differential evolution (global, slow)
217
253
 
218
254
  plot : bool, default=False
219
- If `True`, the approximation coefficients and pade approximaton to
220
- the Hilbert traosnform are plotted.
255
+ If `True`, the approximation coefficients and Pade approximation to
256
+ the Hilbert transform are plotted.
221
257
 
222
258
  latex : bool, default=False
223
259
  If `True`, the plot is rendered using LaTeX. This option is
@@ -234,6 +270,20 @@ class FreeForm(object):
234
270
  psi : (K+1, ) numpy.ndarray
235
271
  Coefficients of fitting Jacobi polynomials
236
272
 
273
+ Notes
274
+ -----
275
+
276
+ The Pade approximation for the glue function :math:`G(z)` is
277
+
278
+ .. math::
279
+
280
+ G(z) = \\frac{P(z)}{Q(z)},
281
+
282
+ where :math:`P(z)` and :math:`Q(z)` are polynomials of order
283
+ :math:`p+q` and :math:`q` respectively. Note that :math:`p` can only
284
+ be -1, 0, or 1, effectively making Pade approximation of order
285
+ :math:`q-1:q`, :math:`q:q`, or :math:`q-1:q`.
286
+
237
287
  Examples
238
288
  --------
239
289
 
@@ -248,12 +298,50 @@ class FreeForm(object):
248
298
  if beta <= -1:
249
299
  raise ValueError('"beta" should be greater then "-1".')
250
300
 
301
+ if not (method in ['jacobi', 'chebyshev']):
302
+ raise ValueError('"method" is invalid.')
303
+
304
+ if not (projection in ['sample', 'kernel']):
305
+ raise ValueError('"projection" is invalid.')
306
+
251
307
  # Project eigenvalues to Jacobi polynomials basis
252
308
  if method == 'jacobi':
253
- psi = jacobi_proj(self.eig, support=self.support, K=K, alpha=alpha,
254
- beta=beta, reg=reg)
309
+
310
+ if projection == 'sample':
311
+ psi = jacobi_sample_proj(self.eig, support=self.support, K=K,
312
+ alpha=alpha, beta=beta, reg=reg)
313
+ else:
314
+ # smooth KDE on a fixed grid
315
+ xs = numpy.linspace(self.lam_m, self.lam_p, 2000)
316
+ pdf = gaussian_kde(self.eig, bw_method=kernel_bw)(xs)
317
+
318
+ # Adaptive KDE
319
+ # k = KDEUnivariate(self.eig)
320
+ # k.fit(bw="silverman", fft=False, weights=None, gridsize=1024,
321
+ # adaptive=True)
322
+ # pdf = k.evaluate(xs)
323
+
324
+ psi = jacobi_kernel_proj(xs, pdf, support=self.support, K=K,
325
+ alpha=alpha, beta=beta, reg=reg)
326
+
255
327
  elif method == 'chebyshev':
256
- psi = chebyshev_proj(self.eig, support=self.support, K=K, reg=reg)
328
+
329
+ if projection == 'sample':
330
+ psi = chebyshev_sample_proj(self.eig, support=self.support,
331
+ K=K, reg=reg)
332
+ else:
333
+ # smooth KDE on a fixed grid
334
+ xs = numpy.linspace(self.lam_m, self.lam_p, 2000)
335
+ pdf = gaussian_kde(self.eig, bw_method=kernel_bw)(xs)
336
+
337
+ # Adaptive KDE
338
+ # k = KDEUnivariate(self.eig)
339
+ # k.fit(bw="silverman", fft=False, weights=None, gridsize=1024,
340
+ # adaptive=True)
341
+ # pdf = k.evaluate(xs)
342
+
343
+ psi = chebyshev_kernel_proj(xs, pdf, support=self.support,
344
+ K=K, reg=reg)
257
345
  else:
258
346
  raise ValueError('"method" is invalid.')
259
347
 
@@ -299,17 +387,17 @@ class FreeForm(object):
299
387
  g_supp = 2.0 * numpy.pi * self.hilbert(x_supp)
300
388
 
301
389
  # 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)
390
+ # self._pade_sol = fit_pade(x_supp, g_supp, self.lam_m,
391
+ # self.lam_p, pade_p, pade_q, delta=1e-8,
392
+ # B=numpy.inf, S=numpy.inf)
393
+ self._pade_sol = fit_pade(x_supp, g_supp, self.lam_m, self.lam_p,
394
+ p=pade_p, q=pade_q, odd_side=odd_side,
395
+ pade_reg=pade_reg, safety=1.0, max_outer=40,
396
+ xtol=1e-12, ftol=1e-12, optimizer=optimizer,
397
+ verbose=0)
305
398
 
306
399
  if plot:
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, :]
400
+ g_supp_approx = eval_pade(x_supp[None, :], self._pade_sol)[0, :]
313
401
  plot_fit(psi, x_supp, g_supp, g_supp_approx, support=self.support,
314
402
  latex=latex, save=save)
315
403
 
@@ -513,13 +601,8 @@ class FreeForm(object):
513
601
  """
514
602
  """
515
603
 
516
- # Unpack optimized parameters
517
- s = self._pade_sol['s']
518
- a = self._pade_sol['a']
519
- b = self._pade_sol['b']
520
-
521
604
  # Glue function
522
- g = eval_pade(z, s, a, b)
605
+ g = eval_pade(z, self._pade_sol)
523
606
 
524
607
  return g
525
608
 
@@ -633,7 +716,7 @@ class FreeForm(object):
633
716
  m1[mask_m, :] = numpy.conjugate(
634
717
  stieltjes(numpy.conjugate(z[mask_m, :])))
635
718
 
636
- # Second Reimann sheet
719
+ # Second Riemann sheet
637
720
  m2[mask_p, :] = m1[mask_p, :]
638
721
  m2[mask_m, :] = -m1[mask_m, :] + self._glue(z[mask_m, :])
639
722
 
@@ -721,7 +804,7 @@ class FreeForm(object):
721
804
  m1[mask_m] = numpy.conjugate(
722
805
  stieltjes(numpy.conjugate(z[mask_m].reshape(-1, 1)))).reshape(-1)
723
806
 
724
- # Second Reimann sheet
807
+ # Second Riemann sheet
725
808
  m2[mask_p] = m1[mask_p]
726
809
  m2[mask_m] = -m1[mask_m] + self._glue(
727
810
  z[mask_m].reshape(-1, 1)).reshape(-1)
@@ -734,7 +817,7 @@ class FreeForm(object):
734
817
  # decompress
735
818
  # ==========
736
819
 
737
- def decompress(self, size, x=None, delta=1e-4, iterations=500,
820
+ def decompress(self, size, x=None, delta=1e-6, iterations=500,
738
821
  step_size=0.1, tolerance=1e-4, plot=False, latex=False,
739
822
  save=False):
740
823
  """
@@ -782,6 +865,10 @@ class FreeForm(object):
782
865
  rho : numpy.array
783
866
  Spectral density
784
867
 
868
+ eigs : numpy.array
869
+ Estimated eigenvalues as low-discrepancy samples of the estimated
870
+ spectral density.
871
+
785
872
  See Also
786
873
  --------
787
874
 
@@ -809,9 +896,12 @@ class FreeForm(object):
809
896
  rho, x, (lb, ub) = decompress(self, size, x=x, delta=delta,
810
897
  iterations=iterations,
811
898
  step_size=step_size, tolerance=tolerance)
899
+ x, rho = x.ravel(), rho.ravel()
812
900
 
813
901
  if plot:
814
- plot_density(x.reshape(-1), rho.reshape(-1), support=(lb, ub),
902
+ plot_density(x, rho, support=(lb, ub),
815
903
  label='Decompression', latex=latex, save=save)
816
904
 
817
- return rho
905
+ eigs = numpy.sort(qmc_sample(x, rho, size))
906
+
907
+ return rho, eigs
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: freealg
3
- Version: 0.0.3
3
+ Version: 0.1.1
4
4
  Summary: Free probability for large matrices
5
5
  Keywords: leaderboard bot chat
6
6
  Platform: Linux
@@ -29,6 +29,8 @@ Requires-Dist: scipy
29
29
  Requires-Dist: texplot
30
30
  Requires-Dist: matplotlib
31
31
  Requires-Dist: colorcet
32
+ Requires-Dist: networkx
33
+ Requires-Dist: statsmodels
32
34
  Provides-Extra: test
33
35
  Provides-Extra: docs
34
36
  Dynamic: classifier
@@ -0,0 +1,21 @@
1
+ freealg/__init__.py,sha256=K92neXJZ9VE1U_j_pj28Qyq1MzlMXhOuYK2ZihgwCaU,463
2
+ freealg/__version__.py,sha256=rnObPjuBcEStqSO0S6gsdS_ot8ITOQjVj_-P1LUUYpg,22
3
+ freealg/_chebyshev.py,sha256=X6u5pKjR1HPZ-KbCfr7zT6HRwB6pZMADvVS3sT5LTkA,5638
4
+ freealg/_damp.py,sha256=k2vtBtWOxQBf4qXaWu_En81lQBXbEO4QbxxWpvuVhdE,1802
5
+ freealg/_decompress.py,sha256=H7ocq09gQnCY-q_8xHi6qyYj3qp239MCgj406hn0yeE,3344
6
+ freealg/_jacobi.py,sha256=AT4ONSHGGDxVKE3MGMLyMR8uDFiO-e9u3x5udYfdJJk,5635
7
+ freealg/_pade.py,sha256=mP96wEPfIzHLZ6PDB5OyhmSA8N1uVPVUkmJa3ebXXiU,13623
8
+ freealg/_plot_util.py,sha256=aL0u7FHdCwLTj4dZ4SSGA00wab0Voem2nBAsBVvo6XY,18400
9
+ freealg/_sample.py,sha256=K1ZxKoiuPbEKyh-swL5X7gz1kYcQno6Mof0o1xF38tg,2323
10
+ freealg/_util.py,sha256=wJ-t8LMZZFEr2PsZEVqTJP_jQTQ3rHUf0dO27F6L7YQ,2310
11
+ freealg/freeform.py,sha256=MintRRVsEwIrur7KC4tvYa8nBVpNeaajphIqUCmGnLs,27910
12
+ freealg/distributions/__init__.py,sha256=Hnk9bJi4Wy8I_1uuskRyrT2DUpPN1YmBY5uK7XI3U_o,644
13
+ freealg/distributions/kesten_mckay.py,sha256=SFYg2_6_MEX9NGfOIW_rRfM9kgF-bdjQiVS0ENJBemQ,15379
14
+ freealg/distributions/marchenko_pastur.py,sha256=0XHhjw1ZDkigGfjU9lmPRgmwecM1-n6VBkGjRJbxpeY,15869
15
+ freealg/distributions/wachter.py,sha256=cG-3XTP5CHSK5o6SQfa3lqQR__ZibeWZ9AoeMxr3Nnk,15602
16
+ freealg/distributions/wigner.py,sha256=gj3XWK4X7wLsB-inoVpn4pHUUM7NOQdgMGw01LEqkcw,14914
17
+ freealg-0.1.1.dist-info/licenses/LICENSE.txt,sha256=J-EEYEtxb3VVf_Bn1TYfWnpY5lMFIM15iLDDcnaDTPA,1443
18
+ freealg-0.1.1.dist-info/METADATA,sha256=WMUZ2N2ZDfTLNuByAjNyP3e7QpCOF-tyV3ImcwUAZY4,2939
19
+ freealg-0.1.1.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
20
+ freealg-0.1.1.dist-info/top_level.txt,sha256=eR2wrgYwDdnnJ9Zf5PruPqe4kQav0GMvRsqct6y00Q8,8
21
+ freealg-0.1.1.dist-info/RECORD,,
@@ -1,17 +0,0 @@
1
- freealg/__init__.py,sha256=K92neXJZ9VE1U_j_pj28Qyq1MzlMXhOuYK2ZihgwCaU,463
2
- freealg/__version__.py,sha256=4GZKi13lDTD25YBkGakhZyEQZWTER_OWQMNPoH_UM2c,22
3
- freealg/_chebyshev.py,sha256=Cw48gXF6kd3IAQuLTEWadySeKGnY9TynzX9MNmycMUU,4697
4
- freealg/_damp.py,sha256=k2vtBtWOxQBf4qXaWu_En81lQBXbEO4QbxxWpvuVhdE,1802
5
- freealg/_decompress.py,sha256=H7ocq09gQnCY-q_8xHi6qyYj3qp239MCgj406hn0yeE,3344
6
- freealg/_jacobi.py,sha256=HVnaujwAcaILVFGEgxk26UyIaLdP2FZMY44C8TG3Qcc,4763
7
- freealg/_pade.py,sha256=rWILLpEL910YdixC2c5Cw77HqogAYoxi2YZgRVXEELM,4022
8
- freealg/_plot_util.py,sha256=Q_LWLbqJefjympbcF2ylpeiYupbj5YAvTLwnpjEDeC4,19009
9
- freealg/_util.py,sha256=wJ-t8LMZZFEr2PsZEVqTJP_jQTQ3rHUf0dO27F6L7YQ,2310
10
- freealg/freeform.py,sha256=PsI0cnN38J-97jXDMSqERxgJZw-Tr13pPbIGmpgnRcc,23846
11
- freealg/distributions/__init__.py,sha256=7t4HbP_EofiFDYLH6jbD94AIumOdcHn1y_Qo54mpLFM,614
12
- freealg/distributions/marchenko_pastur.py,sha256=k8SoEgB2DFXLqGF-Hyqm8Sfh1DlF3khMssuxak5Uaqw,15827
13
- freealg-0.0.3.dist-info/licenses/LICENSE.txt,sha256=J-EEYEtxb3VVf_Bn1TYfWnpY5lMFIM15iLDDcnaDTPA,1443
14
- freealg-0.0.3.dist-info/METADATA,sha256=Z1wF6CU_RomE2Q9ICEuYyNr6R3vQgrW0eZ3HIuEkRs8,2888
15
- freealg-0.0.3.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
16
- freealg-0.0.3.dist-info/top_level.txt,sha256=eR2wrgYwDdnnJ9Zf5PruPqe4kQav0GMvRsqct6y00Q8,8
17
- freealg-0.0.3.dist-info/RECORD,,