freealg 0.7.12__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 +1 -1
- freealg/_algebraic_form/_cusp.py +357 -0
- freealg/_algebraic_form/_cusp_wrap.py +268 -0
- freealg/_algebraic_form/_decompress2.py +2 -0
- freealg/_algebraic_form/_decompress4.py +739 -0
- freealg/_algebraic_form/_decompress5.py +738 -0
- freealg/_algebraic_form/_decompress6.py +492 -0
- freealg/_algebraic_form/_decompress7.py +355 -0
- freealg/_algebraic_form/_decompress8.py +369 -0
- freealg/_algebraic_form/_decompress9.py +363 -0
- freealg/_algebraic_form/_decompress_new.py +431 -0
- freealg/_algebraic_form/_decompress_new_2.py +1631 -0
- freealg/_algebraic_form/_decompress_util.py +172 -0
- freealg/_algebraic_form/_homotopy2.py +289 -0
- freealg/_algebraic_form/_homotopy3.py +215 -0
- freealg/_algebraic_form/_homotopy4.py +320 -0
- freealg/_algebraic_form/_homotopy5.py +185 -0
- freealg/_algebraic_form/_moments.py +0 -1
- freealg/_algebraic_form/_support.py +132 -177
- freealg/_algebraic_form/algebraic_form.py +21 -2
- freealg/distributions/_compound_poisson.py +481 -0
- freealg/distributions/_deformed_marchenko_pastur.py +6 -7
- {freealg-0.7.12.dist-info → freealg-0.7.15.dist-info}/METADATA +1 -1
- {freealg-0.7.12.dist-info → freealg-0.7.15.dist-info}/RECORD +28 -12
- {freealg-0.7.12.dist-info → freealg-0.7.15.dist-info}/WHEEL +0 -0
- {freealg-0.7.12.dist-info → freealg-0.7.15.dist-info}/licenses/AUTHORS.txt +0 -0
- {freealg-0.7.12.dist-info → freealg-0.7.15.dist-info}/licenses/LICENSE.txt +0 -0
- {freealg-0.7.12.dist-info → freealg-0.7.15.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright 2026, 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
|
+
|
|
10
|
+
# =======
|
|
11
|
+
# Imports
|
|
12
|
+
# =======
|
|
13
|
+
|
|
14
|
+
import numpy
|
|
15
|
+
from .._algebraic_form._sheets_util import _pick_physical_root_scalar
|
|
16
|
+
|
|
17
|
+
__all__ = ['CompoundPoisson']
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# ================
|
|
21
|
+
# Compound Poisson
|
|
22
|
+
# ================
|
|
23
|
+
|
|
24
|
+
class CompoundPoisson(object):
|
|
25
|
+
"""
|
|
26
|
+
Two-atom free compound Poisson model (MP-like, FD-closed).
|
|
27
|
+
|
|
28
|
+
Notes
|
|
29
|
+
-----
|
|
30
|
+
|
|
31
|
+
This model has atom at zero with mass :math:`\\max(1-\\lambda, 0)`.
|
|
32
|
+
|
|
33
|
+
This model is the additive free compound Poisson law whose R-transform is
|
|
34
|
+
|
|
35
|
+
.. math::
|
|
36
|
+
|
|
37
|
+
R(w) = \\lambda \\left(
|
|
38
|
+
w_1 \\frac{t_1}{1-t_1 w} + (1-w_1) \\frac{t_2}{1-t_2 w}
|
|
39
|
+
\\right),
|
|
40
|
+
|
|
41
|
+
where :math:`\\lambda>0` is the total rate (intensity),
|
|
42
|
+
:math:`t_1,t_2>0` are jump sizes, and :math:`w_1 \\in (0,1)` is the mixture
|
|
43
|
+
weight for the first jump.
|
|
44
|
+
|
|
45
|
+
The Stieltjes transform :math:`m(z)` satisfies
|
|
46
|
+
|
|
47
|
+
.. math::
|
|
48
|
+
|
|
49
|
+
R(-m(z)) = z + 1/m(z).
|
|
50
|
+
|
|
51
|
+
For two atoms, clearing denominators yields a cubic polynomial in
|
|
52
|
+
:math:`m`:
|
|
53
|
+
|
|
54
|
+
.. math::
|
|
55
|
+
|
|
56
|
+
a_3(z)m^3 + t_2(z)m^2 + t_1(z)m + a_0(z) = 0.
|
|
57
|
+
|
|
58
|
+
FD-closure (free decompression):
|
|
59
|
+
Under the FD rule that scales the argument of R, this family stays
|
|
60
|
+
closed by scaling the jump sizes: :math:`a_i(t) = e^{-t} a_i`
|
|
61
|
+
(keeping :math:`\\lambda,w_1` fixed). If your convention uses
|
|
62
|
+
:math:`R_t(w)=R_0(e^{+t}w)`, then use :math:`a_i(t)=e^{+t}a_i` instead.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
# ====
|
|
66
|
+
# init
|
|
67
|
+
# ====
|
|
68
|
+
|
|
69
|
+
def __init__(self, t1, t2, w1, lam):
|
|
70
|
+
"""
|
|
71
|
+
Parameters
|
|
72
|
+
----------
|
|
73
|
+
t1, t2 : float
|
|
74
|
+
Jump sizes (must be > 0). For PSD-like support, keep them > 0.
|
|
75
|
+
|
|
76
|
+
w1 : float
|
|
77
|
+
Mixture weight in (0, 1) for t1. Second weight is 1-w1.
|
|
78
|
+
|
|
79
|
+
lam : float
|
|
80
|
+
Total rate (intensity), must be > 0.
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
t1 = float(t1)
|
|
84
|
+
t2 = float(t2)
|
|
85
|
+
w1 = float(w1)
|
|
86
|
+
lam = float(lam)
|
|
87
|
+
|
|
88
|
+
if t1 <= 0.0 or t2 <= 0.0:
|
|
89
|
+
raise ValueError("t1 and t2 must be > 0.")
|
|
90
|
+
|
|
91
|
+
if not (0.0 < w1 < 1.0):
|
|
92
|
+
raise ValueError("w1 must be in (0, 1).")
|
|
93
|
+
|
|
94
|
+
if lam <= 0.0:
|
|
95
|
+
raise ValueError("lam must be > 0.")
|
|
96
|
+
|
|
97
|
+
self.t1 = t1
|
|
98
|
+
self.t2 = t2
|
|
99
|
+
self.w1 = w1
|
|
100
|
+
self.lam = lam
|
|
101
|
+
|
|
102
|
+
# ====================
|
|
103
|
+
# roots cubic m scalar
|
|
104
|
+
# ====================
|
|
105
|
+
|
|
106
|
+
def _roots_cubic_m_scalar(self, z):
|
|
107
|
+
"""
|
|
108
|
+
Return the three roots of the cubic equation in m at scalar z.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
t1 = float(self.t1)
|
|
112
|
+
t2 = float(self.t2)
|
|
113
|
+
w1 = float(self.w1)
|
|
114
|
+
lam = float(self.lam)
|
|
115
|
+
w2 = 1.0 - w1
|
|
116
|
+
|
|
117
|
+
lam1 = lam * w1
|
|
118
|
+
lam2 = lam * w2
|
|
119
|
+
|
|
120
|
+
z = complex(z)
|
|
121
|
+
|
|
122
|
+
# Coefficients for:
|
|
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
|
+
|
|
129
|
+
coeffs = numpy.array([c3, c2, c1, c0], dtype=numpy.complex128)
|
|
130
|
+
roots = numpy.roots(coeffs)
|
|
131
|
+
return roots
|
|
132
|
+
|
|
133
|
+
# =====================
|
|
134
|
+
# solve m newton scalar
|
|
135
|
+
# =====================
|
|
136
|
+
|
|
137
|
+
def _solve_m_newton(self, z, m0=None, max_iter=100, tol=1e-12):
|
|
138
|
+
"""
|
|
139
|
+
Solve R(-m) = z + 1/m for scalar z using Newton iterations.
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
t1 = float(self.t1)
|
|
143
|
+
t2 = float(self.t2)
|
|
144
|
+
w1 = float(self.w1)
|
|
145
|
+
lam = float(self.lam)
|
|
146
|
+
w2 = 1.0 - w1
|
|
147
|
+
|
|
148
|
+
lam1 = lam * w1
|
|
149
|
+
lam2 = lam * w2
|
|
150
|
+
|
|
151
|
+
z = complex(z)
|
|
152
|
+
if m0 is None:
|
|
153
|
+
m = -1.0 / z
|
|
154
|
+
else:
|
|
155
|
+
m = complex(m0)
|
|
156
|
+
|
|
157
|
+
for _ in range(int(max_iter)):
|
|
158
|
+
d1 = 1.0 + t1 * m
|
|
159
|
+
d2 = 1.0 + t2 * m
|
|
160
|
+
|
|
161
|
+
# f(m) = -1/m + R(-m) - z
|
|
162
|
+
f = (-1.0 / m) + (lam1 * t1 / d1) + (lam2 * t2 / d2) - z
|
|
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 * (t1 * t1) / (d1 * d1) +
|
|
167
|
+
lam2 * (t2 * t2) / (d2 * d2)
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
step = f / fp
|
|
171
|
+
m2 = m - step
|
|
172
|
+
|
|
173
|
+
if abs(step) < tol * (1.0 + abs(m2)):
|
|
174
|
+
return m2, True
|
|
175
|
+
|
|
176
|
+
m = m2
|
|
177
|
+
|
|
178
|
+
return m, False
|
|
179
|
+
|
|
180
|
+
# =========
|
|
181
|
+
# stieltjes
|
|
182
|
+
# =========
|
|
183
|
+
|
|
184
|
+
def stieltjes(self, z, max_iter=100, tol=1e-12):
|
|
185
|
+
"""
|
|
186
|
+
Physical/Herglotz branch of m(z) for the two-atom compound Poisson law.
|
|
187
|
+
Fast masked Newton in m, keeping z's original shape.
|
|
188
|
+
"""
|
|
189
|
+
|
|
190
|
+
# Unpack parameters
|
|
191
|
+
t1 = float(self.t1)
|
|
192
|
+
t2 = float(self.t2)
|
|
193
|
+
w1 = float(self.w1)
|
|
194
|
+
lam = float(self.lam)
|
|
195
|
+
w2 = 1.0 - w1
|
|
196
|
+
|
|
197
|
+
lam1 = lam * w1
|
|
198
|
+
lam2 = lam * w2
|
|
199
|
+
|
|
200
|
+
z = numpy.asarray(z, dtype=numpy.complex128)
|
|
201
|
+
scalar = (z.ndim == 0)
|
|
202
|
+
if scalar:
|
|
203
|
+
z = z.reshape((1,))
|
|
204
|
+
|
|
205
|
+
# m initial guess
|
|
206
|
+
m = -1.0 / z
|
|
207
|
+
active = numpy.isfinite(m)
|
|
208
|
+
|
|
209
|
+
for _ in range(int(max_iter)):
|
|
210
|
+
if not numpy.any(active):
|
|
211
|
+
break
|
|
212
|
+
|
|
213
|
+
idx = numpy.flatnonzero(active)
|
|
214
|
+
ma = m.ravel()[idx]
|
|
215
|
+
za = z.ravel()[idx]
|
|
216
|
+
|
|
217
|
+
d1 = 1.0 + t1 * ma
|
|
218
|
+
d2 = 1.0 + t2 * ma
|
|
219
|
+
|
|
220
|
+
f = (-1.0 / ma) + (lam1 * t1 / d1) + (lam2 * t2 / d2) - za
|
|
221
|
+
|
|
222
|
+
fp = (1.0 / (ma * ma)) - (
|
|
223
|
+
lam1 * (t1 * t1) / (d1 * d1) +
|
|
224
|
+
lam2 * (t2 * t2) / (d2 * d2))
|
|
225
|
+
|
|
226
|
+
step = f / fp
|
|
227
|
+
mn = ma - step
|
|
228
|
+
|
|
229
|
+
# write back m
|
|
230
|
+
m_flat = m.ravel()
|
|
231
|
+
m_flat[idx] = mn
|
|
232
|
+
|
|
233
|
+
converged = numpy.abs(step) < tol * (1.0 + numpy.abs(mn))
|
|
234
|
+
still = (~converged) & numpy.isfinite(mn)
|
|
235
|
+
|
|
236
|
+
a_flat = active.ravel()
|
|
237
|
+
a_flat[idx] = still
|
|
238
|
+
|
|
239
|
+
# Herglotz sanity: sign(Im z) == sign(Im m)
|
|
240
|
+
sign = numpy.where(numpy.imag(z) >= 0.0, 1.0, -1.0)
|
|
241
|
+
bad = (~numpy.isfinite(m)) | (sign * numpy.imag(m) <= 0.0)
|
|
242
|
+
|
|
243
|
+
if numpy.any(bad):
|
|
244
|
+
zb = z.ravel()
|
|
245
|
+
mb = m.ravel()
|
|
246
|
+
bad_idx = numpy.flatnonzero(bad)
|
|
247
|
+
for i in bad_idx:
|
|
248
|
+
zi = zb[i]
|
|
249
|
+
m_roots = self._roots_cubic_m_scalar(zi)
|
|
250
|
+
mb[i] = _pick_physical_root_scalar(zi, m_roots)
|
|
251
|
+
m = mb.reshape(z.shape)
|
|
252
|
+
|
|
253
|
+
if scalar:
|
|
254
|
+
return m.reshape(())
|
|
255
|
+
return m
|
|
256
|
+
|
|
257
|
+
# =======
|
|
258
|
+
# density
|
|
259
|
+
# =======
|
|
260
|
+
|
|
261
|
+
def density(self, x, eta=2e-4, max_iter=100, tol=1e-12, ac_only=True):
|
|
262
|
+
"""
|
|
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.
|
|
272
|
+
"""
|
|
273
|
+
|
|
274
|
+
z = numpy.asarray(x, dtype=numpy.float64) + 1j * float(eta)
|
|
275
|
+
m = self.stieltjes(z, max_iter=max_iter, tol=tol)
|
|
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
|
+
|
|
287
|
+
return rho
|
|
288
|
+
|
|
289
|
+
# =====
|
|
290
|
+
# roots
|
|
291
|
+
# =====
|
|
292
|
+
|
|
293
|
+
def roots(self, z):
|
|
294
|
+
"""
|
|
295
|
+
Return all algebraic branches (roots of the cubic) at scalar z.
|
|
296
|
+
"""
|
|
297
|
+
|
|
298
|
+
z = numpy.asarray(z, dtype=numpy.complex128)
|
|
299
|
+
if z.ndim != 0:
|
|
300
|
+
raise ValueError("roots(z) expects scalar z.")
|
|
301
|
+
return self._roots_cubic_m_scalar(z.reshape(()))
|
|
302
|
+
|
|
303
|
+
# =======
|
|
304
|
+
# support
|
|
305
|
+
# =======
|
|
306
|
+
|
|
307
|
+
def support(self, eta=2e-4, n_probe=4000, thr=5e-4, x_max=None,
|
|
308
|
+
x_pad=0.05, method='probe'):
|
|
309
|
+
"""
|
|
310
|
+
Estimate support intervals by probing rho(x) on a grid.
|
|
311
|
+
|
|
312
|
+
Parameters
|
|
313
|
+
----------
|
|
314
|
+
method : {'probe'}
|
|
315
|
+
Only probing is implemented here.
|
|
316
|
+
"""
|
|
317
|
+
|
|
318
|
+
_ = method # keep signature compatible
|
|
319
|
+
|
|
320
|
+
t1 = float(self.t1)
|
|
321
|
+
t2 = float(self.t2)
|
|
322
|
+
lam = float(self.lam)
|
|
323
|
+
|
|
324
|
+
if x_max is None:
|
|
325
|
+
# Heuristic: scale grows ~ O(lam * max(a))
|
|
326
|
+
x_max = (1.0 + lam) * max(t1, t2) * 6.0
|
|
327
|
+
x_max = float(x_max)
|
|
328
|
+
if x_max <= 0.0:
|
|
329
|
+
raise ValueError("x_max must be > 0.")
|
|
330
|
+
|
|
331
|
+
x = numpy.linspace(0.0, x_max, int(n_probe))
|
|
332
|
+
rho = self.density(x, eta=eta, ac_only=True)
|
|
333
|
+
|
|
334
|
+
mask = rho > float(thr)
|
|
335
|
+
if not numpy.any(mask):
|
|
336
|
+
return []
|
|
337
|
+
|
|
338
|
+
idx = numpy.flatnonzero(mask)
|
|
339
|
+
# split contiguous indices into intervals
|
|
340
|
+
splits = numpy.where(numpy.diff(idx) > 1)[0]
|
|
341
|
+
starts = numpy.r_[idx[0], idx[splits + 1]]
|
|
342
|
+
ends = numpy.r_[idx[splits], idx[-1]]
|
|
343
|
+
|
|
344
|
+
intervals = []
|
|
345
|
+
for s, e in zip(starts, ends):
|
|
346
|
+
xa = x[int(s)]
|
|
347
|
+
xb = x[int(e)]
|
|
348
|
+
pad = float(x_pad) * (xb - xa)
|
|
349
|
+
intervals.append((float(max(0.0, xa - pad)), float(xb + pad)))
|
|
350
|
+
|
|
351
|
+
return intervals
|
|
352
|
+
|
|
353
|
+
# ==========
|
|
354
|
+
# rho scalar
|
|
355
|
+
# ==========
|
|
356
|
+
|
|
357
|
+
def rho_scalar(self, x, eta=2e-4, max_iter=100, tol=1e-12):
|
|
358
|
+
"""
|
|
359
|
+
Scalar density helper (returns float).
|
|
360
|
+
"""
|
|
361
|
+
|
|
362
|
+
x = float(x)
|
|
363
|
+
z = x + 1j * float(eta)
|
|
364
|
+
m = self.stieltjes(z, max_iter=max_iter, tol=tol)
|
|
365
|
+
return float(numpy.imag(m) / numpy.pi)
|
|
366
|
+
|
|
367
|
+
# ======
|
|
368
|
+
# matrix
|
|
369
|
+
# ======
|
|
370
|
+
|
|
371
|
+
def matrix(self, size, seed=None):
|
|
372
|
+
"""
|
|
373
|
+
Generate a symmetric random matrix whose ESD approximates this law.
|
|
374
|
+
|
|
375
|
+
Construction
|
|
376
|
+
------------
|
|
377
|
+
Use a sum of two independent (rotationally invariant) Wishart terms,
|
|
378
|
+
which are asymptotically free:
|
|
379
|
+
|
|
380
|
+
A = s1 * (1/m1) Z1 Z1^T + s2 * (1/m2) Z2 Z2^T,
|
|
381
|
+
|
|
382
|
+
where Zi are n x mi i.i.d. N(0,1). Choose aspect ratios ci = n/mi and
|
|
383
|
+
scales si so each term has R-transform
|
|
384
|
+
|
|
385
|
+
Ri(w) = lam_i * a_i / (1 - a_i w),
|
|
386
|
+
|
|
387
|
+
with lam_1 = lam*w1, lam_2 = lam*(1-w1). This is achieved by setting
|
|
388
|
+
|
|
389
|
+
c_i = 1/lam_i,
|
|
390
|
+
s_i = a_i * lam_i.
|
|
391
|
+
|
|
392
|
+
Parameters
|
|
393
|
+
----------
|
|
394
|
+
size : int
|
|
395
|
+
Matrix size n.
|
|
396
|
+
|
|
397
|
+
seed : int, default=None
|
|
398
|
+
RNG seed.
|
|
399
|
+
|
|
400
|
+
Returns
|
|
401
|
+
-------
|
|
402
|
+
A : numpy.ndarray
|
|
403
|
+
Symmetric matrix (n x n).
|
|
404
|
+
"""
|
|
405
|
+
|
|
406
|
+
n = int(size)
|
|
407
|
+
if n <= 0:
|
|
408
|
+
raise ValueError("size must be a positive integer.")
|
|
409
|
+
|
|
410
|
+
t1 = float(self.t1)
|
|
411
|
+
t2 = float(self.t2)
|
|
412
|
+
w1 = float(self.w1)
|
|
413
|
+
lam = float(self.lam)
|
|
414
|
+
w2 = 1.0 - w1
|
|
415
|
+
|
|
416
|
+
lam1 = lam * w1
|
|
417
|
+
lam2 = lam * w2
|
|
418
|
+
|
|
419
|
+
rng = numpy.random.default_rng(seed)
|
|
420
|
+
|
|
421
|
+
A = numpy.zeros((n, n), dtype=numpy.float64)
|
|
422
|
+
|
|
423
|
+
# term 1
|
|
424
|
+
c1 = 1.0 / lam1
|
|
425
|
+
m1 = max(1, int(round(n / c1)))
|
|
426
|
+
s1 = t1 * lam1
|
|
427
|
+
Z1 = rng.standard_normal((n, m1))
|
|
428
|
+
A += s1 * (Z1 @ Z1.T) / float(m1)
|
|
429
|
+
|
|
430
|
+
# term 2
|
|
431
|
+
c2 = 1.0 / lam2
|
|
432
|
+
m2 = max(1, int(round(n / c2)))
|
|
433
|
+
s2 = t2 * lam2
|
|
434
|
+
Z2 = rng.standard_normal((n, m2))
|
|
435
|
+
A += s2 * (Z2 @ Z2.T) / float(m2)
|
|
436
|
+
|
|
437
|
+
return A
|
|
438
|
+
|
|
439
|
+
# ====
|
|
440
|
+
# poly
|
|
441
|
+
# ====
|
|
442
|
+
|
|
443
|
+
def poly(self):
|
|
444
|
+
"""
|
|
445
|
+
Return a_coeffs for the exact cubic P(z,m)=0 of the two-atom free
|
|
446
|
+
compound Poisson model.
|
|
447
|
+
|
|
448
|
+
a_coeffs[i, j] is the coefficient of z^i m^j.
|
|
449
|
+
Shape is (2, 4) since deg_z=1 and deg_m=3.
|
|
450
|
+
|
|
451
|
+
Coefficients match _roots_cubic_m_scalar.
|
|
452
|
+
"""
|
|
453
|
+
|
|
454
|
+
t1 = float(self.t1)
|
|
455
|
+
t2 = float(self.t2)
|
|
456
|
+
w1 = float(self.w1)
|
|
457
|
+
w2 = 1.0 - w1
|
|
458
|
+
lam = float(self.lam)
|
|
459
|
+
|
|
460
|
+
lam1 = lam * w1
|
|
461
|
+
lam2 = lam * w2
|
|
462
|
+
|
|
463
|
+
a = numpy.zeros((2, 4), dtype=numpy.complex128)
|
|
464
|
+
|
|
465
|
+
# c3 = z * t1 * t2
|
|
466
|
+
a[0, 3] = 0.0
|
|
467
|
+
a[1, 3] = t1 * t2
|
|
468
|
+
|
|
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)
|
|
472
|
+
|
|
473
|
+
# c1 = z + (t1+t2) - (lam1 t1 + lam2 t2)
|
|
474
|
+
a[0, 1] = (t1 + t2) - (lam1 * t1 + lam2 * t2)
|
|
475
|
+
a[1, 1] = 1.0
|
|
476
|
+
|
|
477
|
+
# c0 = 1
|
|
478
|
+
a[0, 0] = 1.0
|
|
479
|
+
a[1, 0] = 0.0
|
|
480
|
+
|
|
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 =
|
|
94
|
-
\\delta_{
|
|
95
|
-
\\delta_{
|
|
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
|
|
163
|
-
H =
|
|
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,18 +1,33 @@
|
|
|
1
1
|
freealg/__init__.py,sha256=is4de7kygj1be0S3EAcAlW_vGriWjdjHCR-J9NN6wyk,873
|
|
2
|
-
freealg/__version__.py,sha256=
|
|
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
|
|
6
6
|
freealg/_algebraic_form/_constraints.py,sha256=xBpsKAL0-Czxf9ZF9tspLpTaFJ1m2DDyqc2KH9bl5Xg,3601
|
|
7
7
|
freealg/_algebraic_form/_continuation_algebraic.py,sha256=vVHFlMJYeXm97pgwEceJB2rGJeGOVhk_Ywg6mjoIA-g,19390
|
|
8
|
+
freealg/_algebraic_form/_cusp.py,sha256=Vbk3V7pT9iyQSIGOoTMSzN7r7nfyoyXUMCIPXuHFVI4,10581
|
|
9
|
+
freealg/_algebraic_form/_cusp_wrap.py,sha256=HkpJj6HEE_Qi2eVBPJYcpKUfDOAGqpbHfF7ccC0sEKE,8309
|
|
8
10
|
freealg/_algebraic_form/_decompress.py,sha256=yCGTT3F-0NtGi3oENIS11Zcc7SVaMv_hxvzWuho5huw,22274
|
|
9
|
-
freealg/_algebraic_form/_decompress2.py,sha256=
|
|
11
|
+
freealg/_algebraic_form/_decompress2.py,sha256=2eSoIOj8R1ZuxIuDTXaKgMXY5OXfsNmaTIbE0IiUukk,6585
|
|
12
|
+
freealg/_algebraic_form/_decompress4.py,sha256=kq0KJIf_il8ed_wy66hOiwD91ixr77ru3Ovdpz-aetY,21586
|
|
13
|
+
freealg/_algebraic_form/_decompress5.py,sha256=I2y2Qvc09LjsSlW8Q1cdIdAFRTJm0cQDDBMBZ6XmuME,22618
|
|
14
|
+
freealg/_algebraic_form/_decompress6.py,sha256=Kn2TqWOjH8ifZEnfJ2UlLJZTgYZR1pWQ6nEZwNsadcQ,16774
|
|
15
|
+
freealg/_algebraic_form/_decompress7.py,sha256=hRstLXa2hD0QvDhdhsycHujjqFWWn0Z7PbKsFBH1COs,10128
|
|
16
|
+
freealg/_algebraic_form/_decompress8.py,sha256=IH05swHhA4vieOUa-4Kbapk5Q4XRggGC2c30W1QpMsY,11717
|
|
17
|
+
freealg/_algebraic_form/_decompress9.py,sha256=PR5uSo6BUZZWDyx19MA8KSQVrIxG0sUVn178lo75dq8,11445
|
|
18
|
+
freealg/_algebraic_form/_decompress_new.py,sha256=fOHtc1iTvpep3ccQPQFUTWaluv_GS1ahrGE11fJhtAw,12162
|
|
19
|
+
freealg/_algebraic_form/_decompress_new_2.py,sha256=kzjYSa4roWm8-ntCjSSG88y_82ZjSHY7jQOPSBgUrUg,54182
|
|
20
|
+
freealg/_algebraic_form/_decompress_util.py,sha256=TIaqr3tdMhsKvFskmb5-RNxKWUR-hKkHuCWqq8eWo8o,4836
|
|
10
21
|
freealg/_algebraic_form/_edge.py,sha256=X91GeX8nZZ_Lf7C3l7u-JpESDmwRqACYA_G2l1KVs2Y,9604
|
|
11
22
|
freealg/_algebraic_form/_homotopy.py,sha256=FdKQhUTjdk6Rmdd5zb8IzDJN0pteHUcgJL3eG_ySUzM,10912
|
|
12
|
-
freealg/_algebraic_form/
|
|
23
|
+
freealg/_algebraic_form/_homotopy2.py,sha256=gvfm0cabEw57zLuOMgGNJGFVqJ8ScF4Zs2FoCQSWbYs,8868
|
|
24
|
+
freealg/_algebraic_form/_homotopy3.py,sha256=OfvvX6uc_fpcPuMa53zM8o7XHrCeWeRVjDoSjUlFySE,6345
|
|
25
|
+
freealg/_algebraic_form/_homotopy4.py,sha256=dxHisWPIPdzyw1NsW1qS0EbLWtM_uyIcTrHQV3jYGis,10013
|
|
26
|
+
freealg/_algebraic_form/_homotopy5.py,sha256=lHWA5tknnZBMymcWt_KQXcI0qLrd_ftUGgd_Qp-o3fs,6306
|
|
27
|
+
freealg/_algebraic_form/_moments.py,sha256=R1-EepGsni4he-kNfiP3E3tFqR2Z27fz-ixtSVU2fSE,12427
|
|
13
28
|
freealg/_algebraic_form/_sheets_util.py,sha256=6OLzWQKu-gN8rxM2rbpbN8TjNZFmD8UJ-8t9kcZdkCo,4174
|
|
14
|
-
freealg/_algebraic_form/_support.py,sha256=
|
|
15
|
-
freealg/_algebraic_form/algebraic_form.py,sha256=
|
|
29
|
+
freealg/_algebraic_form/_support.py,sha256=Gjp4nVQJb_Syou3M_uroSl52bPTafqKk6IUSJgglKu4,6791
|
|
30
|
+
freealg/_algebraic_form/algebraic_form.py,sha256=14bKYTLdYb4F1vgIdEeFHi-PI_-AZGoAaEfzf5HAaJk,37762
|
|
16
31
|
freealg/_free_form/__init__.py,sha256=5cnSX7kHci3wKx6-BEFhmVY_NjjmQAq1JjWPTEqETTg,611
|
|
17
32
|
freealg/_free_form/_chebyshev.py,sha256=zkyVA8NLf7uUKlJdLz4ijd_SurdsqUgkA5nHGWSybaE,6916
|
|
18
33
|
freealg/_free_form/_damp.py,sha256=k2vtBtWOxQBf4qXaWu_En81lQBXbEO4QbxxWpvuVhdE,1802
|
|
@@ -35,7 +50,8 @@ freealg/_geometric_form/_torus_maps.py,sha256=7m5QsbmnXTWHJE5rWjKG3_TnErHEEQ41vW
|
|
|
35
50
|
freealg/_geometric_form/geometric_form.py,sha256=whHKYQdakqShtR-jCEugevnje72JEr9M0HSvZ2BYoKs,33379
|
|
36
51
|
freealg/distributions/__init__.py,sha256=sCx2NVcRTaHwvxXpFRU_9unN98ZED6B-xFoFZ2eU9-E,875
|
|
37
52
|
freealg/distributions/_chiral_block.py,sha256=YSC_Sk1u1UKlWVE1GGJEjX6VrWqpEEYNxBZ2j8Csc3A,13897
|
|
38
|
-
freealg/distributions/
|
|
53
|
+
freealg/distributions/_compound_poisson.py,sha256=TjeyfJod5ghPHtr-tbD8e4cbo-JhkSRvJUOFyfn8m2g,12676
|
|
54
|
+
freealg/distributions/_deformed_marchenko_pastur.py,sha256=hrA2U_LBw7eB0QBqAwZtLuAU6Tq1nQsJgX2Y1_Y3ae8,20926
|
|
39
55
|
freealg/distributions/_deformed_wigner.py,sha256=0933XQAplP3mifJKdSU7qXgrndqUs1MUpYMJHR-NId8,9086
|
|
40
56
|
freealg/distributions/_kesten_mckay.py,sha256=Uv3QuUYsfXbPMovXSO_pN3wdkc1fTKGVX7iuHDgBRqk,20089
|
|
41
57
|
freealg/distributions/_marchenko_pastur.py,sha256=eemaxDosKpV37TAn9uSiYpljIkVNoTWDJ9ZfYb8tAeY,20646
|
|
@@ -45,9 +61,9 @@ freealg/distributions/_wigner.py,sha256=epgx6ne6R_7to5j6-QsWIAVFJQFquWMmYgnZYMN4
|
|
|
45
61
|
freealg/visualization/__init__.py,sha256=NLq_zwueF7ytZ8sl8zLPqm-AODxxXNvfMozHGmmklcE,435
|
|
46
62
|
freealg/visualization/_glue_util.py,sha256=2oKnEYjUOS4OZfivmciVLauVr53kyHMwi6c2zRKilTQ,693
|
|
47
63
|
freealg/visualization/_rgb_hsv.py,sha256=rEskxXxSlKKxIrHRslVkgxHtD010L3ge9YtcVsOPl8E,3650
|
|
48
|
-
freealg-0.7.
|
|
49
|
-
freealg-0.7.
|
|
50
|
-
freealg-0.7.
|
|
51
|
-
freealg-0.7.
|
|
52
|
-
freealg-0.7.
|
|
53
|
-
freealg-0.7.
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|