freealg 0.7.14__py3-none-any.whl → 0.7.15__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 CHANGED
@@ -1 +1 @@
1
- __version__ = "0.7.14"
1
+ __version__ = "0.7.15"
@@ -28,32 +28,32 @@ class CompoundPoisson(object):
28
28
  Notes
29
29
  -----
30
30
 
31
- This model has atom at zero with mass :math:`\\max(1-e^{-\\lambda}, 0)`.
31
+ This model has atom at zero with mass :math:`\\max(1-\\lambda, 0)`.
32
32
 
33
33
  This model is the additive free compound Poisson law whose R-transform is
34
34
 
35
35
  .. math::
36
36
 
37
37
  R(w) = \\lambda \\left(
38
- w_1 \\frac{a_1}{1-a_1 w} + (1-w_1) \\frac{a_2}{1-a_2 w}
38
+ w_1 \\frac{t_1}{1-t_1 w} + (1-w_1) \\frac{t_2}{1-t_2 w}
39
39
  \\right),
40
40
 
41
41
  where :math:`\\lambda>0` is the total rate (intensity),
42
- :math:`a_1,a_2>0` are jump sizes, and :math:`w_1 \\in (0,1)` is the mixture
42
+ :math:`t_1,t_2>0` are jump sizes, and :math:`w_1 \\in (0,1)` is the mixture
43
43
  weight for the first jump.
44
44
 
45
45
  The Stieltjes transform :math:`m(z)` satisfies
46
46
 
47
47
  .. math::
48
48
 
49
- z = 1/m(z) + R(m(z)).
49
+ R(-m(z)) = z + 1/m(z).
50
50
 
51
51
  For two atoms, clearing denominators yields a cubic polynomial in
52
52
  :math:`m`:
53
53
 
54
54
  .. math::
55
55
 
56
- a_3(z)m^3 + a_2(z)m^2 + a_1(z)m + a_0(z) = 0.
56
+ a_3(z)m^3 + t_2(z)m^2 + t_1(z)m + a_0(z) = 0.
57
57
 
58
58
  FD-closure (free decompression):
59
59
  Under the FD rule that scales the argument of R, this family stays
@@ -66,27 +66,27 @@ class CompoundPoisson(object):
66
66
  # init
67
67
  # ====
68
68
 
69
- def __init__(self, a1, a2, w1, lam):
69
+ def __init__(self, t1, t2, w1, lam):
70
70
  """
71
71
  Parameters
72
72
  ----------
73
- a1, a2 : float
73
+ t1, t2 : float
74
74
  Jump sizes (must be > 0). For PSD-like support, keep them > 0.
75
75
 
76
76
  w1 : float
77
- Mixture weight in (0, 1) for a1. Second weight is 1-w1.
77
+ Mixture weight in (0, 1) for t1. Second weight is 1-w1.
78
78
 
79
79
  lam : float
80
80
  Total rate (intensity), must be > 0.
81
81
  """
82
82
 
83
- a1 = float(a1)
84
- a2 = float(a2)
83
+ t1 = float(t1)
84
+ t2 = float(t2)
85
85
  w1 = float(w1)
86
86
  lam = float(lam)
87
87
 
88
- if a1 <= 0.0 or a2 <= 0.0:
89
- raise ValueError("a1 and a2 must be > 0.")
88
+ if t1 <= 0.0 or t2 <= 0.0:
89
+ raise ValueError("t1 and t2 must be > 0.")
90
90
 
91
91
  if not (0.0 < w1 < 1.0):
92
92
  raise ValueError("w1 must be in (0, 1).")
@@ -94,8 +94,8 @@ class CompoundPoisson(object):
94
94
  if lam <= 0.0:
95
95
  raise ValueError("lam must be > 0.")
96
96
 
97
- self.a1 = a1
98
- self.a2 = a2
97
+ self.t1 = t1
98
+ self.t2 = t2
99
99
  self.w1 = w1
100
100
  self.lam = lam
101
101
 
@@ -108,8 +108,8 @@ class CompoundPoisson(object):
108
108
  Return the three roots of the cubic equation in m at scalar z.
109
109
  """
110
110
 
111
- a1 = float(self.a1)
112
- a2 = float(self.a2)
111
+ t1 = float(self.t1)
112
+ t2 = float(self.t2)
113
113
  w1 = float(self.w1)
114
114
  lam = float(self.lam)
115
115
  w2 = 1.0 - w1
@@ -120,11 +120,11 @@ class CompoundPoisson(object):
120
120
  z = complex(z)
121
121
 
122
122
  # Coefficients for:
123
- # a3(z)m^3 + a2(z)m^2 + a1(z)m + a0(z) = 0
124
- c3 = z * a1 * a2
125
- c2 = (-z * (a1 + a2)) - (a1 * a2) * (1.0 - (lam1 + lam2))
126
- c1 = z + (a1 + a2) - (lam1 * a1 + lam2 * a2)
127
- c0 = -1.0
123
+ # a3(z)m^3 + t2(z)m^2 + t1(z)m + a0(z) = 0
124
+ c3 = z * t1 * t2
125
+ c2 = (z * (t1 + t2)) + (t1 * t2) * (1.0 - (lam1 + lam2))
126
+ c1 = z + (t1 + t2) - (lam1 * t1 + lam2 * t2)
127
+ c0 = 1.0
128
128
 
129
129
  coeffs = numpy.array([c3, c2, c1, c0], dtype=numpy.complex128)
130
130
  roots = numpy.roots(coeffs)
@@ -136,11 +136,11 @@ class CompoundPoisson(object):
136
136
 
137
137
  def _solve_m_newton(self, z, m0=None, max_iter=100, tol=1e-12):
138
138
  """
139
- Solve z = 1/m + R(m) for scalar z using Newton iterations.
139
+ Solve R(-m) = z + 1/m for scalar z using Newton iterations.
140
140
  """
141
141
 
142
- a1 = float(self.a1)
143
- a2 = float(self.a2)
142
+ t1 = float(self.t1)
143
+ t2 = float(self.t2)
144
144
  w1 = float(self.w1)
145
145
  lam = float(self.lam)
146
146
  w2 = 1.0 - w1
@@ -155,16 +155,16 @@ class CompoundPoisson(object):
155
155
  m = complex(m0)
156
156
 
157
157
  for _ in range(int(max_iter)):
158
- d1 = 1.0 - a1 * m
159
- d2 = 1.0 - a2 * m
158
+ d1 = 1.0 + t1 * m
159
+ d2 = 1.0 + t2 * m
160
160
 
161
- # f(m) = 1/m + R(m) - z
162
- f = (1.0 / m) + (lam1 * a1 / d1) + (lam2 * a2 / d2) - z
161
+ # f(m) = -1/m + R(-m) - z
162
+ f = (-1.0 / m) + (lam1 * t1 / d1) + (lam2 * t2 / d2) - z
163
163
 
164
- # f'(m) = -1/m^2 + sum lam_i a_i^2/(1-a_i m)^2
165
- fp = (-1.0 / (m * m)) + (
166
- lam1 * (a1 * a1) / (d1 * d1) +
167
- lam2 * (a2 * a2) / (d2 * d2)
164
+ # f'(m) = 1/m^2 - sum lam_i a_i^2/(1+a_i m)^2
165
+ fp = (1.0 / (m * m)) - (
166
+ lam1 * (t1 * t1) / (d1 * d1) +
167
+ lam2 * (t2 * t2) / (d2 * d2)
168
168
  )
169
169
 
170
170
  step = f / fp
@@ -188,8 +188,8 @@ class CompoundPoisson(object):
188
188
  """
189
189
 
190
190
  # Unpack parameters
191
- a1 = float(self.a1)
192
- a2 = float(self.a2)
191
+ t1 = float(self.t1)
192
+ t2 = float(self.t2)
193
193
  w1 = float(self.w1)
194
194
  lam = float(self.lam)
195
195
  w2 = 1.0 - w1
@@ -214,15 +214,14 @@ class CompoundPoisson(object):
214
214
  ma = m.ravel()[idx]
215
215
  za = z.ravel()[idx]
216
216
 
217
- d1 = 1.0 - a1 * ma
218
- d2 = 1.0 - a2 * ma
217
+ d1 = 1.0 + t1 * ma
218
+ d2 = 1.0 + t2 * ma
219
219
 
220
- f = (1.0 / ma) + (lam1 * a1 / d1) + (lam2 * a2 / d2) - za
220
+ f = (-1.0 / ma) + (lam1 * t1 / d1) + (lam2 * t2 / d2) - za
221
221
 
222
- fp = (-1.0 / (ma * ma)) + (
223
- lam1 * (a1 * a1) / (d1 * d1) +
224
- lam2 * (a2 * a2) / (d2 * d2)
225
- )
222
+ fp = (1.0 / (ma * ma)) - (
223
+ lam1 * (t1 * t1) / (d1 * d1) +
224
+ lam2 * (t2 * t2) / (d2 * d2))
226
225
 
227
226
  step = f / fp
228
227
  mn = ma - step
@@ -259,14 +258,32 @@ class CompoundPoisson(object):
259
258
  # density
260
259
  # =======
261
260
 
262
- def density(self, x, eta=2e-4, max_iter=100, tol=1e-12):
261
+ def density(self, x, eta=2e-4, max_iter=100, tol=1e-12, ac_only=True):
263
262
  """
264
263
  Density rho(x) from Im m(x + i eta) / pi.
264
+
265
+ ac_only: bool, default=True
266
+ If `True`, computes the absolutely-continuous (AC) part. This
267
+ matters when for :math:`\\lambda < 1`, the distribution has an
268
+ atom at zero of mass :math:`1 - \\lambda`, and for plotting, this
269
+ often shows as a spike. Setting this option to true prevents this
270
+ issue in plotting. Also, to compute support, this option allows
271
+ proper detection of the support intervals.
265
272
  """
266
273
 
267
274
  z = numpy.asarray(x, dtype=numpy.float64) + 1j * float(eta)
268
275
  m = self.stieltjes(z, max_iter=max_iter, tol=tol)
269
276
  rho = numpy.imag(m) / numpy.pi
277
+
278
+ # If it has an atom, subtract from density to get the absolutely
279
+ # continuous part before processing the support
280
+ if (ac_only is True) and (self.lam < 1.0):
281
+ zr = z.real
282
+ atom = (1.0 - self.lam) * \
283
+ (float(eta) / (numpy.pi * (zr*zr + float(eta)**2)))
284
+ rho = rho - atom
285
+ rho = numpy.maximum(rho, 0.0)
286
+
270
287
  return rho
271
288
 
272
289
  # =====
@@ -300,19 +317,19 @@ class CompoundPoisson(object):
300
317
 
301
318
  _ = method # keep signature compatible
302
319
 
303
- a1 = float(self.a1)
304
- a2 = float(self.a2)
320
+ t1 = float(self.t1)
321
+ t2 = float(self.t2)
305
322
  lam = float(self.lam)
306
323
 
307
324
  if x_max is None:
308
325
  # Heuristic: scale grows ~ O(lam * max(a))
309
- x_max = (1.0 + lam) * max(a1, a2) * 6.0
326
+ x_max = (1.0 + lam) * max(t1, t2) * 6.0
310
327
  x_max = float(x_max)
311
328
  if x_max <= 0.0:
312
329
  raise ValueError("x_max must be > 0.")
313
330
 
314
331
  x = numpy.linspace(0.0, x_max, int(n_probe))
315
- rho = self.density(x, eta=eta)
332
+ rho = self.density(x, eta=eta, ac_only=True)
316
333
 
317
334
  mask = rho > float(thr)
318
335
  if not numpy.any(mask):
@@ -353,7 +370,7 @@ class CompoundPoisson(object):
353
370
 
354
371
  def matrix(self, size, seed=None):
355
372
  """
356
- Generate a PSD random matrix whose ESD approximates this law.
373
+ Generate a symmetric random matrix whose ESD approximates this law.
357
374
 
358
375
  Construction
359
376
  ------------
@@ -383,15 +400,15 @@ class CompoundPoisson(object):
383
400
  Returns
384
401
  -------
385
402
  A : numpy.ndarray
386
- Symmetric PSD matrix (n x n).
403
+ Symmetric matrix (n x n).
387
404
  """
388
405
 
389
406
  n = int(size)
390
407
  if n <= 0:
391
408
  raise ValueError("size must be a positive integer.")
392
409
 
393
- a1 = float(self.a1)
394
- a2 = float(self.a2)
410
+ t1 = float(self.t1)
411
+ t2 = float(self.t2)
395
412
  w1 = float(self.w1)
396
413
  lam = float(self.lam)
397
414
  w2 = 1.0 - w1
@@ -406,14 +423,14 @@ class CompoundPoisson(object):
406
423
  # term 1
407
424
  c1 = 1.0 / lam1
408
425
  m1 = max(1, int(round(n / c1)))
409
- s1 = a1 * lam1
426
+ s1 = t1 * lam1
410
427
  Z1 = rng.standard_normal((n, m1))
411
428
  A += s1 * (Z1 @ Z1.T) / float(m1)
412
429
 
413
430
  # term 2
414
431
  c2 = 1.0 / lam2
415
432
  m2 = max(1, int(round(n / c2)))
416
- s2 = a2 * lam2
433
+ s2 = t2 * lam2
417
434
  Z2 = rng.standard_normal((n, m2))
418
435
  A += s2 * (Z2 @ Z2.T) / float(m2)
419
436
 
@@ -434,8 +451,8 @@ class CompoundPoisson(object):
434
451
  Coefficients match _roots_cubic_m_scalar.
435
452
  """
436
453
 
437
- a1 = float(self.a1)
438
- a2 = float(self.a2)
454
+ t1 = float(self.t1)
455
+ t2 = float(self.t2)
439
456
  w1 = float(self.w1)
440
457
  w2 = 1.0 - w1
441
458
  lam = float(self.lam)
@@ -445,20 +462,20 @@ class CompoundPoisson(object):
445
462
 
446
463
  a = numpy.zeros((2, 4), dtype=numpy.complex128)
447
464
 
448
- # c3 = z * a1 * a2
465
+ # c3 = z * t1 * t2
449
466
  a[0, 3] = 0.0
450
- a[1, 3] = a1 * a2
467
+ a[1, 3] = t1 * t2
451
468
 
452
- # c2 = -z (a1+a2) - a1 a2 (1 - (lam1+lam2))
453
- a[0, 2] = -(a1 * a2) * (1.0 - (lam1 + lam2))
454
- a[1, 2] = -(a1 + a2)
469
+ # c2 = z (t1+t2) + t1 t2 (1 - (lam1+lam2))
470
+ a[0, 2] = (t1 * t2) * (1.0 - (lam1 + lam2))
471
+ a[1, 2] = (t1 + t2)
455
472
 
456
- # c1 = z + (a1+a2) - (lam1 a1 + lam2 a2)
457
- a[0, 1] = (a1 + a2) - (lam1 * a1 + lam2 * a2)
473
+ # c1 = z + (t1+t2) - (lam1 t1 + lam2 t2)
474
+ a[0, 1] = (t1 + t2) - (lam1 * t1 + lam2 * t2)
458
475
  a[1, 1] = 1.0
459
476
 
460
- # c0 = -1
461
- a[0, 0] = -1.0
477
+ # c0 = 1
478
+ a[0, 0] = 1.0
462
479
  a[1, 0] = 0.0
463
480
 
464
481
  return a
@@ -90,9 +90,9 @@ class DeformedMarchenkoPastur(object):
90
90
 
91
91
  def _roots_cubic_u_scalar(self, z):
92
92
  """
93
- Solve the cubic for u = \\underline{m}(z) for H = w1
94
- \\delta_{t1} + (1-w1)
95
- \\delta_{t2}.
93
+ Solve the cubic for u = \\underline{m}(z) for H = w_1
94
+ \\delta_{t_1} + (1-w_1)
95
+ \\delta_{t_2}.
96
96
  """
97
97
 
98
98
  # Unpack parameters
@@ -159,8 +159,8 @@ class DeformedMarchenkoPastur(object):
159
159
 
160
160
  def stieltjes(self, z, max_iter=100, tol=1e-12):
161
161
  """
162
- Physical/Herglotz branch of m(z) for μ = H \\boxtimes MP_c with
163
- H = w1 \\delta_{t1} + (1-w1) \\delta_{t2}.
162
+ Physical/Herglotz branch of m(z) for \\mu = H \\boxtimes MP_c with
163
+ H = w_1 \\delta_{t_1} + (1-w_1) \\delta_{t_2}.
164
164
  Fast masked Newton in u (companion Stieltjes), keeping z's original
165
165
  shape.
166
166
  """
@@ -206,8 +206,7 @@ class DeformedMarchenkoPastur(object):
206
206
  f = (-1.0 / ua) + c * (w1 * t1 / d1 + w2 * t2 / d2) - za
207
207
  fp = (1.0 / (ua * ua)) - c * (
208
208
  w1 * (t1 * t1) / (d1 * d1) +
209
- w2 * (t2 * t2) / (d2 * d2)
210
- )
209
+ w2 * (t2 * t2) / (d2 * d2))
211
210
 
212
211
  step = f / fp
213
212
  un = ua - step
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: freealg
3
- Version: 0.7.14
3
+ Version: 0.7.15
4
4
  Summary: Free probability for large matrices
5
5
  Home-page: https://github.com/ameli/freealg
6
6
  Download-URL: https://github.com/ameli/freealg/archive/main.zip
@@ -1,5 +1,5 @@
1
1
  freealg/__init__.py,sha256=is4de7kygj1be0S3EAcAlW_vGriWjdjHCR-J9NN6wyk,873
2
- freealg/__version__.py,sha256=7BOggTpADa3sz2Lo7K_EuX10-Jk_mW3PS3k2rLh8AF8,23
2
+ freealg/__version__.py,sha256=7TV8ktpkocjy2CbaPP0e82unkG7763a7BOPYX37gato,23
3
3
  freealg/_util.py,sha256=RzccUCORgzrI9NdNqwMVugiHU0uDKkJFcIyjFMUOnv8,2518
4
4
  freealg/_algebraic_form/__init__.py,sha256=etgaRiuipcmxtwHzMVxZwO_qbX8R7m9j39mKvgRyTZg,463
5
5
  freealg/_algebraic_form/_branch_points.py,sha256=jzvHszw7xFe9B15a5RZV3pGfCGtndvrKJ4GIX6F3qhc,7814
@@ -50,8 +50,8 @@ freealg/_geometric_form/_torus_maps.py,sha256=7m5QsbmnXTWHJE5rWjKG3_TnErHEEQ41vW
50
50
  freealg/_geometric_form/geometric_form.py,sha256=whHKYQdakqShtR-jCEugevnje72JEr9M0HSvZ2BYoKs,33379
51
51
  freealg/distributions/__init__.py,sha256=sCx2NVcRTaHwvxXpFRU_9unN98ZED6B-xFoFZ2eU9-E,875
52
52
  freealg/distributions/_chiral_block.py,sha256=YSC_Sk1u1UKlWVE1GGJEjX6VrWqpEEYNxBZ2j8Csc3A,13897
53
- freealg/distributions/_compound_poisson.py,sha256=weckLA0ix0gHLnacPPOxs0WhqAtlvVVxcUuRZQUWuJM,11810
54
- freealg/distributions/_deformed_marchenko_pastur.py,sha256=iZixcZiXUKpe9Vi4I1_x_p_lIVqJeo7Tlb8ENqbZa94,20929
53
+ freealg/distributions/_compound_poisson.py,sha256=TjeyfJod5ghPHtr-tbD8e4cbo-JhkSRvJUOFyfn8m2g,12676
54
+ freealg/distributions/_deformed_marchenko_pastur.py,sha256=hrA2U_LBw7eB0QBqAwZtLuAU6Tq1nQsJgX2Y1_Y3ae8,20926
55
55
  freealg/distributions/_deformed_wigner.py,sha256=0933XQAplP3mifJKdSU7qXgrndqUs1MUpYMJHR-NId8,9086
56
56
  freealg/distributions/_kesten_mckay.py,sha256=Uv3QuUYsfXbPMovXSO_pN3wdkc1fTKGVX7iuHDgBRqk,20089
57
57
  freealg/distributions/_marchenko_pastur.py,sha256=eemaxDosKpV37TAn9uSiYpljIkVNoTWDJ9ZfYb8tAeY,20646
@@ -61,9 +61,9 @@ freealg/distributions/_wigner.py,sha256=epgx6ne6R_7to5j6-QsWIAVFJQFquWMmYgnZYMN4
61
61
  freealg/visualization/__init__.py,sha256=NLq_zwueF7ytZ8sl8zLPqm-AODxxXNvfMozHGmmklcE,435
62
62
  freealg/visualization/_glue_util.py,sha256=2oKnEYjUOS4OZfivmciVLauVr53kyHMwi6c2zRKilTQ,693
63
63
  freealg/visualization/_rgb_hsv.py,sha256=rEskxXxSlKKxIrHRslVkgxHtD010L3ge9YtcVsOPl8E,3650
64
- freealg-0.7.14.dist-info/licenses/AUTHORS.txt,sha256=0b67Nz4_JgIzUupHJTAZxu5QdSUM_HRM_X_w4xCb17o,30
65
- freealg-0.7.14.dist-info/licenses/LICENSE.txt,sha256=J-EEYEtxb3VVf_Bn1TYfWnpY5lMFIM15iLDDcnaDTPA,1443
66
- freealg-0.7.14.dist-info/METADATA,sha256=9QtOauh9E-xiAUPG5Dg9-H7f9ldRLg6buhnkBapCoik,5537
67
- freealg-0.7.14.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
68
- freealg-0.7.14.dist-info/top_level.txt,sha256=eR2wrgYwDdnnJ9Zf5PruPqe4kQav0GMvRsqct6y00Q8,8
69
- freealg-0.7.14.dist-info/RECORD,,
64
+ freealg-0.7.15.dist-info/licenses/AUTHORS.txt,sha256=0b67Nz4_JgIzUupHJTAZxu5QdSUM_HRM_X_w4xCb17o,30
65
+ freealg-0.7.15.dist-info/licenses/LICENSE.txt,sha256=J-EEYEtxb3VVf_Bn1TYfWnpY5lMFIM15iLDDcnaDTPA,1443
66
+ freealg-0.7.15.dist-info/METADATA,sha256=NRK-E0Ni96OuonpfAX_PAGCZIbHZ_A_kVRzQ4TmfTRQ,5537
67
+ freealg-0.7.15.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
68
+ freealg-0.7.15.dist-info/top_level.txt,sha256=eR2wrgYwDdnnJ9Zf5PruPqe4kQav0GMvRsqct6y00Q8,8
69
+ freealg-0.7.15.dist-info/RECORD,,