freealg 0.7.16__tar.gz → 0.7.18__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.
Files changed (85) hide show
  1. {freealg-0.7.16 → freealg-0.7.18}/PKG-INFO +1 -1
  2. {freealg-0.7.16 → freealg-0.7.18}/freealg/__init__.py +8 -6
  3. freealg-0.7.18/freealg/__version__.py +1 -0
  4. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_branch_points.py +18 -18
  5. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_continuation_algebraic.py +13 -13
  6. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_cusp.py +15 -15
  7. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_cusp_wrap.py +6 -6
  8. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_decompress.py +16 -16
  9. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_decompress4.py +31 -31
  10. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_decompress5.py +23 -23
  11. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_decompress6.py +13 -13
  12. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_decompress7.py +15 -15
  13. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_decompress8.py +17 -17
  14. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_decompress9.py +18 -18
  15. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_decompress_new.py +17 -17
  16. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_decompress_new_2.py +57 -57
  17. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_decompress_util.py +10 -10
  18. freealg-0.7.18/freealg/_algebraic_form/_decompressible.py +292 -0
  19. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_edge.py +10 -10
  20. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_homotopy4.py +9 -9
  21. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_homotopy5.py +9 -9
  22. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_support.py +19 -19
  23. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/algebraic_form.py +262 -468
  24. freealg-0.7.18/freealg/_base_form.py +401 -0
  25. {freealg-0.7.16 → freealg-0.7.18}/freealg/_free_form/__init__.py +1 -4
  26. {freealg-0.7.16 → freealg-0.7.18}/freealg/_free_form/_density_util.py +1 -1
  27. freealg-0.7.18/freealg/_free_form/_plot_util.py +90 -0
  28. {freealg-0.7.16 → freealg-0.7.18}/freealg/_free_form/free_form.py +8 -367
  29. {freealg-0.7.16 → freealg-0.7.18}/freealg/_util.py +59 -11
  30. {freealg-0.7.16 → freealg-0.7.18}/freealg/distributions/__init__.py +2 -1
  31. freealg-0.7.18/freealg/distributions/_base_distribution.py +163 -0
  32. {freealg-0.7.16 → freealg-0.7.18}/freealg/distributions/_chiral_block.py +137 -11
  33. {freealg-0.7.16 → freealg-0.7.18}/freealg/distributions/_compound_poisson.py +168 -64
  34. {freealg-0.7.16 → freealg-0.7.18}/freealg/distributions/_deformed_marchenko_pastur.py +137 -88
  35. {freealg-0.7.16 → freealg-0.7.18}/freealg/distributions/_deformed_wigner.py +92 -40
  36. freealg-0.7.18/freealg/distributions/_fuss_catalan.py +269 -0
  37. {freealg-0.7.16 → freealg-0.7.18}/freealg/distributions/_kesten_mckay.py +4 -130
  38. {freealg-0.7.16 → freealg-0.7.18}/freealg/distributions/_marchenko_pastur.py +8 -196
  39. {freealg-0.7.16 → freealg-0.7.18}/freealg/distributions/_meixner.py +4 -130
  40. {freealg-0.7.16 → freealg-0.7.18}/freealg/distributions/_wachter.py +4 -130
  41. {freealg-0.7.16 → freealg-0.7.18}/freealg/distributions/_wigner.py +10 -127
  42. {freealg-0.7.16 → freealg-0.7.18}/freealg/visualization/__init__.py +2 -2
  43. freealg-0.7.16/freealg/visualization/_rgb_hsv.py → freealg-0.7.18/freealg/visualization/_domain_coloring.py +37 -29
  44. {freealg-0.7.16/freealg/_free_form → freealg-0.7.18/freealg/visualization}/_plot_util.py +42 -127
  45. {freealg-0.7.16 → freealg-0.7.18}/freealg.egg-info/PKG-INFO +1 -1
  46. {freealg-0.7.16 → freealg-0.7.18}/freealg.egg-info/SOURCES.txt +8 -3
  47. freealg-0.7.16/freealg/__version__.py +0 -1
  48. {freealg-0.7.16 → freealg-0.7.18}/AUTHORS.txt +0 -0
  49. {freealg-0.7.16 → freealg-0.7.18}/CHANGELOG.rst +0 -0
  50. {freealg-0.7.16 → freealg-0.7.18}/LICENSE.txt +0 -0
  51. {freealg-0.7.16 → freealg-0.7.18}/MANIFEST.in +0 -0
  52. {freealg-0.7.16 → freealg-0.7.18}/README.rst +0 -0
  53. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/__init__.py +0 -0
  54. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_constraints.py +0 -0
  55. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_decompress2.py +0 -0
  56. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_homotopy.py +0 -0
  57. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_homotopy2.py +0 -0
  58. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_homotopy3.py +0 -0
  59. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_moments.py +0 -0
  60. {freealg-0.7.16 → freealg-0.7.18}/freealg/_algebraic_form/_sheets_util.py +0 -0
  61. {freealg-0.7.16 → freealg-0.7.18}/freealg/_free_form/_chebyshev.py +0 -0
  62. {freealg-0.7.16 → freealg-0.7.18}/freealg/_free_form/_damp.py +0 -0
  63. {freealg-0.7.16 → freealg-0.7.18}/freealg/_free_form/_decompress.py +0 -0
  64. {freealg-0.7.16 → freealg-0.7.18}/freealg/_free_form/_jacobi.py +0 -0
  65. {freealg-0.7.16 → freealg-0.7.18}/freealg/_free_form/_linalg.py +0 -0
  66. {freealg-0.7.16 → freealg-0.7.18}/freealg/_free_form/_pade.py +0 -0
  67. {freealg-0.7.16 → freealg-0.7.18}/freealg/_free_form/_series.py +0 -0
  68. {freealg-0.7.16 → freealg-0.7.18}/freealg/_geometric_form/__init__.py +0 -0
  69. {freealg-0.7.16 → freealg-0.7.18}/freealg/_geometric_form/_continuation_genus0.py +0 -0
  70. {freealg-0.7.16 → freealg-0.7.18}/freealg/_geometric_form/_continuation_genus1.py +0 -0
  71. {freealg-0.7.16 → freealg-0.7.18}/freealg/_geometric_form/_elliptic_functions.py +0 -0
  72. {freealg-0.7.16 → freealg-0.7.18}/freealg/_geometric_form/_sphere_maps.py +0 -0
  73. {freealg-0.7.16 → freealg-0.7.18}/freealg/_geometric_form/_torus_maps.py +0 -0
  74. {freealg-0.7.16 → freealg-0.7.18}/freealg/_geometric_form/geometric_form.py +0 -0
  75. {freealg-0.7.16/freealg/_free_form → freealg-0.7.18/freealg}/_sample.py +0 -0
  76. {freealg-0.7.16/freealg/_free_form → freealg-0.7.18/freealg}/_support.py +0 -0
  77. {freealg-0.7.16 → freealg-0.7.18}/freealg/visualization/_glue_util.py +0 -0
  78. {freealg-0.7.16 → freealg-0.7.18}/freealg.egg-info/dependency_links.txt +0 -0
  79. {freealg-0.7.16 → freealg-0.7.18}/freealg.egg-info/not-zip-safe +0 -0
  80. {freealg-0.7.16 → freealg-0.7.18}/freealg.egg-info/requires.txt +0 -0
  81. {freealg-0.7.16 → freealg-0.7.18}/freealg.egg-info/top_level.txt +0 -0
  82. {freealg-0.7.16 → freealg-0.7.18}/pyproject.toml +0 -0
  83. {freealg-0.7.16 → freealg-0.7.18}/requirements.txt +0 -0
  84. {freealg-0.7.16 → freealg-0.7.18}/setup.cfg +0 -0
  85. {freealg-0.7.16 → freealg-0.7.18}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: freealg
3
- Version: 0.7.16
3
+ Version: 0.7.18
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
@@ -6,15 +6,17 @@
6
6
  # under the terms of the license found in the LICENSE.txt file in the root
7
7
  # directory of this source tree.
8
8
 
9
- from ._free_form import FreeForm, eigvalsh, cond, norm, trace, slogdet, supp, \
10
- sample, kde
11
- from ._algebraic_form import AlgebraicForm, decompress_newton
9
+ from ._free_form import FreeForm, eigvalsh, cond, norm, trace, slogdet, kde
10
+ from ._algebraic_form import AlgebraicForm
12
11
  from ._geometric_form import GeometricForm
13
12
  from . import visualization
14
13
  from . import distributions
14
+ from ._sample import sample
15
+ from ._support import supp
16
+ from ._util import submatrix
15
17
 
16
- __all__ = ['FreeForm', 'distributions', 'visualization', 'eigvalsh', 'cond',
17
- 'norm', 'trace', 'slogdet', 'supp', 'sample', 'kde',
18
- 'AlgebraicForm', 'GeometricForm', 'decompress_newton']
18
+ __all__ = ['FreeForm', 'AlgebraicForm', 'GeometricForm', 'distributions',
19
+ 'visualization', 'eigvalsh', 'cond', 'norm', 'trace', 'slogdet',
20
+ 'supp', 'sample', 'submatrix', 'kde']
19
21
 
20
22
  from .__version__ import __version__ # noqa: F401 E402
@@ -0,0 +1 @@
1
+ __version__ = "0.7.18"
@@ -13,7 +13,7 @@
13
13
 
14
14
  import numpy
15
15
 
16
- __all__ = ['compute_branch_points']
16
+ __all__ = ['estimate_branch_points']
17
17
 
18
18
 
19
19
  # =========
@@ -154,19 +154,19 @@ def _det_bareiss_poly(M, tol):
154
154
  # resultant discriminant
155
155
  # ======================
156
156
 
157
- def _resultant_discriminant(a_coeffs, tol):
157
+ def _resultant_discriminant(coeffs, tol):
158
158
  """
159
159
  Numerically compute Disc_m(P)(z) as a polynomial in z (ascending coeffs),
160
160
  via Sylvester determinant evaluation on a circle + interpolation.
161
161
 
162
- a_coeffs[i,j] is coeff of z^i m^j, shape (deg_z+1, s+1).
162
+ coeffs[i,j] is coeff of z^i m^j, shape (deg_z+1, s+1).
163
163
  """
164
164
 
165
165
  import numpy
166
166
 
167
- a_coeffs = numpy.asarray(a_coeffs, dtype=numpy.complex128)
168
- deg_z = a_coeffs.shape[0] - 1
169
- s = a_coeffs.shape[1] - 1
167
+ coeffs = numpy.asarray(coeffs, dtype=numpy.complex128)
168
+ deg_z = coeffs.shape[0] - 1
169
+ s = coeffs.shape[1] - 1
170
170
  if s < 1 or deg_z < 0:
171
171
  return numpy.zeros(1, dtype=numpy.complex128)
172
172
 
@@ -180,7 +180,7 @@ def _resultant_discriminant(a_coeffs, tol):
180
180
  # m^(s-k)
181
181
  p_asc = numpy.zeros(s + 1, dtype=numpy.complex128)
182
182
  for j in range(s + 1):
183
- p_asc[j] = numpy.polyval(a_coeffs[:, j][::-1], z) # a_j(z)
183
+ p_asc[j] = numpy.polyval(coeffs[:, j][::-1], z) # a_j(z)
184
184
  p_desc = p_asc[::-1]
185
185
 
186
186
  # Q(m) = dP/dm, descending
@@ -207,8 +207,8 @@ def _resultant_discriminant(a_coeffs, tol):
207
207
  # Sample points on a circle; scale radius using coefficient magnitude
208
208
  # (simple heuristic) (This only affects conditioning of interpolation, not
209
209
  # correctness.)
210
- scale = float(numpy.max(numpy.abs(a_coeffs))) \
211
- if numpy.max(numpy.abs(a_coeffs)) > 0 else 1.0
210
+ scale = float(numpy.max(numpy.abs(coeffs))) \
211
+ if numpy.max(numpy.abs(coeffs)) > 0 else 1.0
212
212
  R = 1.0 + 0.1 * scale
213
213
 
214
214
  N = D + 1
@@ -228,7 +228,7 @@ def _resultant_discriminant(a_coeffs, tol):
228
228
  c = numpy.zeros(1, dtype=numpy.complex128)
229
229
 
230
230
  # If numerics leave small imag, kill it (disc should be real-coeff if
231
- # a_coeffs real)
231
+ # coeffs real)
232
232
  if numpy.linalg.norm(c.imag) <= \
233
233
  1e3 * tol * max(1.0, numpy.linalg.norm(c.real)):
234
234
  c = c.real.astype(numpy.float64)
@@ -236,11 +236,11 @@ def _resultant_discriminant(a_coeffs, tol):
236
236
  return c
237
237
 
238
238
 
239
- # =====================
240
- # compute branch points
241
- # =====================
239
+ # ======================
240
+ # estimate branch points
241
+ # ======================
242
242
 
243
- def compute_branch_points(a_coeffs, tol=1e-12, real_tol=None):
243
+ def estimate_branch_points(coeffs, tol=1e-12, real_tol=None):
244
244
  """
245
245
  Compute global branch points of the affine curve P(z,m)=0 by
246
246
  z-roots of Disc_m(P)(z) = Res_m(P, dP/dm).
@@ -252,8 +252,8 @@ def compute_branch_points(a_coeffs, tol=1e-12, real_tol=None):
252
252
  info : dict
253
253
  """
254
254
 
255
- a_coeffs = numpy.asarray(a_coeffs, dtype=float)
256
- s = a_coeffs.shape[1] - 1
255
+ coeffs = numpy.asarray(coeffs, dtype=float)
256
+ s = coeffs.shape[1] - 1
257
257
  if s < 1:
258
258
  if real_tol is None:
259
259
  real_tol = 1e3 * tol
@@ -269,11 +269,11 @@ def compute_branch_points(a_coeffs, tol=1e-12, real_tol=None):
269
269
  if real_tol is None:
270
270
  real_tol = 1e3 * tol
271
271
 
272
- a_s = _poly_trim(a_coeffs[:, s], tol)
272
+ a_s = _poly_trim(coeffs[:, s], tol)
273
273
  a_s_zero = numpy.roots(a_s[::-1]) if a_s.size > 1 else \
274
274
  numpy.array([], dtype=complex)
275
275
 
276
- disc = _resultant_discriminant(a_coeffs, tol)
276
+ disc = _resultant_discriminant(coeffs, tol)
277
277
  if disc.size <= 1:
278
278
  z_bp = numpy.array([], dtype=complex)
279
279
  else:
@@ -301,7 +301,7 @@ def fit_polynomial_relation(z, m, s, deg_z, ridge_lambda=0.0, weights=None,
301
301
  # sanity check stieltjes branch
302
302
  # =============================
303
303
 
304
- def sanity_check_stieltjes_branch(a_coeffs, x_min, x_max, eta=0.1,
304
+ def sanity_check_stieltjes_branch(coeffs, x_min, x_max, eta=0.1,
305
305
  n_x=64, y0=None, max_bad_frac=0.05):
306
306
  """
307
307
  Quick sanity check: does P(z,m)=0 admit a continuously trackable root with
@@ -322,7 +322,7 @@ def sanity_check_stieltjes_branch(a_coeffs, x_min, x_max, eta=0.1,
322
322
  z0 = 1j * y0
323
323
  m0_target = -1.0 / z0
324
324
 
325
- c0 = _poly_coef_in_m(numpy.array([z0]), a_coeffs)[0]
325
+ c0 = _poly_coef_in_m(numpy.array([z0]), coeffs)[0]
326
326
  r0 = numpy.roots(c0[::-1])
327
327
  if r0.size == 0:
328
328
  return {'ok': False, 'frac_bad': 1.0, 'n_test': 0, 'n_bad': 0}
@@ -337,7 +337,7 @@ def sanity_check_stieltjes_branch(a_coeffs, x_min, x_max, eta=0.1,
337
337
  n_ok = 0
338
338
 
339
339
  for z in zs:
340
- c = _poly_coef_in_m(numpy.array([z]), a_coeffs)[0]
340
+ c = _poly_coef_in_m(numpy.array([z]), coeffs)[0]
341
341
  r = numpy.roots(c[::-1])
342
342
  if r.size == 0 or not numpy.all(numpy.isfinite(r)):
343
343
  n_bad += 1
@@ -372,12 +372,12 @@ def sanity_check_stieltjes_branch(a_coeffs, x_min, x_max, eta=0.1,
372
372
  # eval P
373
373
  # ======
374
374
 
375
- def eval_P(z, m, a_coeffs):
375
+ def eval_P(z, m, coeffs):
376
376
 
377
377
  z = numpy.asarray(z, dtype=complex)
378
378
  m = numpy.asarray(m, dtype=complex)
379
- deg_z = int(a_coeffs.shape[0] - 1)
380
- s = int(a_coeffs.shape[1] - 1)
379
+ deg_z = int(coeffs.shape[0] - 1)
380
+ s = int(coeffs.shape[1] - 1)
381
381
 
382
382
  shp = numpy.broadcast(z, m).shape
383
383
  zz = numpy.broadcast_to(z, shp).ravel()
@@ -388,7 +388,7 @@ def eval_P(z, m, a_coeffs):
388
388
 
389
389
  P = numpy.zeros(zz.size, dtype=complex)
390
390
  for j in range(s + 1):
391
- aj = zp @ a_coeffs[:, j]
391
+ aj = zp @ coeffs[:, j]
392
392
  P = P + aj * mp[:, j]
393
393
 
394
394
  return P.reshape(shp)
@@ -398,16 +398,16 @@ def eval_P(z, m, a_coeffs):
398
398
  # poly coef in m
399
399
  # ==============
400
400
 
401
- def _poly_coef_in_m(z, a_coeffs):
401
+ def _poly_coef_in_m(z, coeffs):
402
402
 
403
403
  z = numpy.asarray(z, dtype=complex).ravel()
404
- deg_z = int(a_coeffs.shape[0] - 1)
405
- s = int(a_coeffs.shape[1] - 1)
404
+ deg_z = int(coeffs.shape[0] - 1)
405
+ s = int(coeffs.shape[1] - 1)
406
406
  zp = powers(z, deg_z)
407
407
 
408
408
  c = numpy.empty((z.size, s + 1), dtype=complex)
409
409
  for j in range(s + 1):
410
- c[:, j] = zp @ a_coeffs[:, j]
410
+ c[:, j] = zp @ coeffs[:, j]
411
411
  return c
412
412
 
413
413
 
@@ -489,10 +489,10 @@ def _roots_cubic(c0, c1, c2, c3):
489
489
  # eval roots
490
490
  # ==========
491
491
 
492
- def eval_roots(z, a_coeffs):
492
+ def eval_roots(z, coeffs):
493
493
 
494
494
  z = numpy.asarray(z, dtype=complex).ravel()
495
- c = _poly_coef_in_m(z, a_coeffs)
495
+ c = _poly_coef_in_m(z, coeffs)
496
496
 
497
497
  s = int(c.shape[1] - 1)
498
498
  if s == 1:
@@ -95,7 +95,7 @@ def _newton_3x3(F, x0, max_iter=60, tol=1e-12, bounds=None, max_step=None):
95
95
  __all__ = ["solve_cusp"]
96
96
 
97
97
 
98
- def _second_partials_fd(zeta, y, a_coeffs, eps_z=None, eps_y=None):
98
+ def _second_partials_fd(zeta, y, coeffs, eps_z=None, eps_y=None):
99
99
  zeta = float(zeta)
100
100
  y = float(y)
101
101
 
@@ -104,13 +104,13 @@ def _second_partials_fd(zeta, y, a_coeffs, eps_z=None, eps_y=None):
104
104
  if eps_y is None:
105
105
  eps_y = 1e-7 * (1.0 + abs(y))
106
106
 
107
- _, Pz_p, Py_p = eval_P_partials(zeta + eps_z, y, a_coeffs)
108
- _, Pz_m, Py_m = eval_P_partials(zeta - eps_z, y, a_coeffs)
107
+ _, Pz_p, Py_p = eval_P_partials(zeta + eps_z, y, coeffs)
108
+ _, Pz_m, Py_m = eval_P_partials(zeta - eps_z, y, coeffs)
109
109
  Pzz = (Pz_p - Pz_m) / (2.0 * eps_z)
110
110
  Pzy1 = (Py_p - Py_m) / (2.0 * eps_z)
111
111
 
112
- _, Pz_p, Py_p = eval_P_partials(zeta, y + eps_y, a_coeffs)
113
- _, Pz_m, Py_m = eval_P_partials(zeta, y - eps_y, a_coeffs)
112
+ _, Pz_p, Py_p = eval_P_partials(zeta, y + eps_y, coeffs)
113
+ _, Pz_m, Py_m = eval_P_partials(zeta, y - eps_y, coeffs)
114
114
  Pzy2 = (Pz_p - Pz_m) / (2.0 * eps_y)
115
115
  Pyy = (Py_p - Py_m) / (2.0 * eps_y)
116
116
 
@@ -118,11 +118,11 @@ def _second_partials_fd(zeta, y, a_coeffs, eps_z=None, eps_y=None):
118
118
  return float(Pzz), float(Pzy), float(Pyy)
119
119
 
120
120
 
121
- def _cusp_F_real(zeta, y, s, a_coeffs):
121
+ def _cusp_F_real(zeta, y, s, coeffs):
122
122
  # tau = 1 + exp(s) => c = tau-1 = exp(s) > 0
123
123
  c = float(numpy.exp(float(s)))
124
124
 
125
- P, Pz, Py = eval_P_partials(float(zeta), float(y), a_coeffs)
125
+ P, Pz, Py = eval_P_partials(float(zeta), float(y), coeffs)
126
126
  P = float(numpy.real(P))
127
127
  Pz = float(numpy.real(Pz))
128
128
  Py = float(numpy.real(Py))
@@ -130,7 +130,7 @@ def _cusp_F_real(zeta, y, s, a_coeffs):
130
130
  F1 = P
131
131
  F2 = (y * y) * Py - c * Pz
132
132
 
133
- Pzz, Pzy, Pyy = _second_partials_fd(zeta, y, a_coeffs)
133
+ Pzz, Pzy, Pyy = _second_partials_fd(zeta, y, coeffs)
134
134
  F3 = y * (Pzz * (Py * Py) - 2.0 * Pzy * Pz * Py + Pyy * (Pz * Pz)) + \
135
135
  2.0 * (Pz * Pz) * Py
136
136
 
@@ -141,8 +141,8 @@ def _cusp_F_real(zeta, y, s, a_coeffs):
141
141
  # poly coeffs in y
142
142
  # ================
143
143
 
144
- def _poly_coeffs_in_y(a_coeffs, zeta):
145
- a = numpy.asarray(a_coeffs)
144
+ def _poly_coeffs_in_y(coeffs, zeta):
145
+ a = numpy.asarray(coeffs)
146
146
  deg_z = a.shape[0] - 1
147
147
  deg_y = a.shape[1] - 1
148
148
  z_pows = numpy.power(zeta, numpy.arange(deg_z + 1, dtype=numpy.int64))
@@ -156,9 +156,9 @@ def _poly_coeffs_in_y(a_coeffs, zeta):
156
156
  # pick realish root y
157
157
  # ===================
158
158
 
159
- def _pick_realish_root_y(a_coeffs, zeta):
159
+ def _pick_realish_root_y(coeffs, zeta):
160
160
 
161
- c_asc = _poly_coeffs_in_y(a_coeffs, zeta)
161
+ c_asc = _poly_coeffs_in_y(coeffs, zeta)
162
162
  c_desc = c_asc[::-1] # descending for numpy.roots
163
163
 
164
164
  k = 0
@@ -179,7 +179,7 @@ def _pick_realish_root_y(a_coeffs, zeta):
179
179
  # ==========
180
180
 
181
181
  def solve_cusp(
182
- a_coeffs,
182
+ coeffs,
183
183
  t_init,
184
184
  zeta_init,
185
185
  y_init=None,
@@ -191,11 +191,11 @@ def solve_cusp(
191
191
  Exact-derivative cusp solve for (zeta, y, t) with unknowns (zeta, y, s),
192
192
  where tau = 1 + exp(s), t = log(tau), x = zeta - (tau-1)/y.
193
193
 
194
- a_coeffs: array shape (deg_z+1, deg_y+1), P(zeta,y)=
194
+ coeffs: array shape (deg_z+1, deg_y+1), P(zeta,y)=
195
195
  sum_{i,j} a[i,j]*zeta^i*y^j
196
196
  """
197
197
 
198
- a = numpy.asarray(a_coeffs, dtype=numpy.complex128)
198
+ a = numpy.asarray(coeffs, dtype=numpy.complex128)
199
199
  deg_z = a.shape[0] - 1
200
200
  deg_y = a.shape[1] - 1
201
201
 
@@ -19,15 +19,15 @@ import scipy.optimize as opt
19
19
  # poly coeffs in y
20
20
  # ================
21
21
 
22
- def _poly_coeffs_in_y(a_coeffs, zeta):
22
+ def _poly_coeffs_in_y(coeffs, zeta):
23
23
  """
24
24
  Build coefficients c_j(zeta) so that P(zeta, y) = sum_j c_j(zeta) y^j.
25
25
 
26
- Assumes a_coeffs[i, j] multiplies z^i y^j (same layout as eval_P in
26
+ Assumes coeffs[i, j] multiplies z^i y^j (same layout as eval_P in
27
27
  _continuation_algebraic). Returns coefficients in ascending powers of y.
28
28
  """
29
29
 
30
- a = numpy.asarray(a_coeffs)
30
+ a = numpy.asarray(coeffs)
31
31
  deg_z = a.shape[0] - 1
32
32
  deg_y = a.shape[1] - 1
33
33
 
@@ -44,14 +44,14 @@ def _poly_coeffs_in_y(a_coeffs, zeta):
44
44
  # pick realish root y
45
45
  # ===================
46
46
 
47
- def _pick_realish_root_y(a_coeffs, zeta):
47
+ def _pick_realish_root_y(coeffs, zeta):
48
48
  """
49
49
  Pick a reasonable real-ish root y of P(zeta, y)=0 to seed Newton.
50
50
 
51
51
  Returns a float (real part of the selected root).
52
52
  """
53
53
 
54
- c_asc = _poly_coeffs_in_y(a_coeffs, zeta) # ascending in y
54
+ c_asc = _poly_coeffs_in_y(coeffs, zeta) # ascending in y
55
55
  # numpy.roots wants descending order
56
56
  c_desc = c_asc[::-1]
57
57
  # strip leading ~0 coefficients
@@ -138,7 +138,7 @@ def cusp_wrap(self, t_grid, edge_kwargs=None, max_iter=80, tol=1e-12,
138
138
  tau = float(numpy.exp(t_star))
139
139
  c = tau - 1.0
140
140
 
141
- a = numpy.asarray(self.a_coeffs, dtype=numpy.complex128)
141
+ a = numpy.asarray(self.coeffs, dtype=numpy.complex128)
142
142
  deg_z = a.shape[0] - 1
143
143
  deg_y = a.shape[1] - 1
144
144
 
@@ -62,7 +62,7 @@ def build_time_grid(sizes, n0, min_n_times=0):
62
62
 
63
63
 
64
64
 
65
- def fd_solve_w(z, t, a_coeffs, w_init, max_iter=50, tol=1e-12,
65
+ def fd_solve_w(z, t, coeffs, w_init, max_iter=50, tol=1e-12,
66
66
  armijo=1e-4, min_lam=1e-6, w_min=1e-14):
67
67
  """
68
68
  Solve for w = m(t,z) from the implicit FD equation using damped Newton.
@@ -83,7 +83,7 @@ def fd_solve_w(z, t, a_coeffs, w_init, max_iter=50, tol=1e-12,
83
83
  Query point in the complex plane.
84
84
  t : float
85
85
  Time parameter (tau = exp(t)).
86
- a_coeffs : ndarray
86
+ coeffs : ndarray
87
87
  Coefficients defining P(zeta,y) in the monomial basis.
88
88
  w_init : complex
89
89
  Initial guess for w.
@@ -117,7 +117,7 @@ def fd_solve_w(z, t, a_coeffs, w_init, max_iter=50, tol=1e-12,
117
117
  .. code-block:: python
118
118
 
119
119
  w, ok = fd_solve_w(
120
- z=0.5 + 1e-6j, t=2.0, a_coeffs=a_coeffs, w_init=m1_fn(0.5 + 1e-6j),
120
+ z=0.5 + 1e-6j, t=2.0, coeffs=coeffs, w_init=m1_fn(0.5 + 1e-6j),
121
121
  max_iter=50, tol=1e-12
122
122
  )
123
123
  """
@@ -132,7 +132,7 @@ def fd_solve_w(z, t, a_coeffs, w_init, max_iter=50, tol=1e-12,
132
132
 
133
133
  for _ in range(max_iter):
134
134
 
135
- a = numpy.asarray(a_coeffs, dtype=numpy.complex128)
135
+ a = numpy.asarray(coeffs, dtype=numpy.complex128)
136
136
  deg_z = a.shape[0] - 1
137
137
  deg_m = a.shape[1] - 1
138
138
 
@@ -195,13 +195,13 @@ def fd_solve_w(z, t, a_coeffs, w_init, max_iter=50, tol=1e-12,
195
195
  w = complex(best)
196
196
 
197
197
  # final residual check
198
- F_end = eval_P_partials(z + alpha / w, tau * w, a_coeffs)[0]
198
+ F_end = eval_P_partials(z + alpha / w, tau * w, coeffs)[0]
199
199
  return w, (abs(F_end) <= 1e3 * tol)
200
200
 
201
201
  # -------------------
202
202
 
203
203
 
204
- F_end = eval_P_partials(z + alpha / w, tau * w, a_coeffs)[0]
204
+ F_end = eval_P_partials(z + alpha / w, tau * w, coeffs)[0]
205
205
  return w, (abs(F_end) <= 10.0 * tol)
206
206
 
207
207
 
@@ -209,7 +209,7 @@ def fd_solve_w(z, t, a_coeffs, w_init, max_iter=50, tol=1e-12,
209
209
  # NEW FUNCTION
210
210
  # ============
211
211
 
212
- def fd_candidates_w(z, t, a_coeffs, w_min=1e-14):
212
+ def fd_candidates_w(z, t, coeffs, w_min=1e-14):
213
213
  """
214
214
  Return candidate roots w solving P(z + alpha/w, tau*w)=0 with Im(w)>0 (if Im(z)>0).
215
215
  """
@@ -218,7 +218,7 @@ def fd_candidates_w(z, t, a_coeffs, w_min=1e-14):
218
218
  alpha = 1.0 - 1.0 / tau
219
219
  want_pos_imag = (z.imag > 0.0)
220
220
 
221
- a = numpy.asarray(a_coeffs, dtype=numpy.complex128)
221
+ a = numpy.asarray(coeffs, dtype=numpy.complex128)
222
222
  deg_z = a.shape[0] - 1
223
223
  deg_m = a.shape[1] - 1
224
224
 
@@ -256,7 +256,7 @@ def fd_candidates_w(z, t, a_coeffs, w_min=1e-14):
256
256
  # residual filter (optional but helps)
257
257
  # -------------
258
258
  # TEST
259
- # F = eval_P_partials(z + alpha / w, tau * w, a_coeffs)[0]
259
+ # F = eval_P_partials(z + alpha / w, tau * w, coeffs)[0]
260
260
  # if abs(F) < 1e-6:
261
261
  # cands.append(complex(w))
262
262
  # ---------------
@@ -271,7 +271,7 @@ def fd_candidates_w(z, t, a_coeffs, w_min=1e-14):
271
271
  # decompress newton
272
272
  # =================
273
273
 
274
- def decompress_newton(z_list, t_grid, a_coeffs, w0_list=None,
274
+ def decompress_newton(z_list, t_grid, coeffs, w0_list=None,
275
275
  dt_max=0.1, sweep=True, time_rel_tol=5.0,
276
276
  active_imag_eps=None, sweep_pad=20,
277
277
  max_iter=50, tol=1e-12, armijo=1e-4,
@@ -285,7 +285,7 @@ def decompress_newton(z_list, t_grid, a_coeffs, w0_list=None,
285
285
  Query points z (typically x + 1j*eta with eta > 0), ordered along x.
286
286
  t_grid : array_like of float
287
287
  Strictly increasing time grid.
288
- a_coeffs : ndarray
288
+ coeffs : ndarray
289
289
  Coefficients defining P(zeta,y) in the monomial basis.
290
290
  w0_list : array_like of complex
291
291
  Initial values at t_grid[0] (typically m0(z_list) on the physical
@@ -351,14 +351,14 @@ def decompress_newton(z_list, t_grid, a_coeffs, w0_list=None,
351
351
  # def solve_with_choice(iz, w_seed):
352
352
  # # Neighbor-seeded candidate (spatial continuity)
353
353
  # w_a, ok_a = fd_solve_w(
354
- # z_list[iz], t, a_coeffs, w_seed,
354
+ # z_list[iz], t, coeffs, w_seed,
355
355
  # max_iter=max_iter, tol=tol, armijo=armijo,
356
356
  # min_lam=min_lam, w_min=w_min
357
357
  # )
358
358
  #
359
359
  # # Time-seeded candidate (time continuation)
360
360
  # w_b, ok_b = fd_solve_w(
361
- # z_list[iz], t, a_coeffs, w_prev[iz],
361
+ # z_list[iz], t, coeffs, w_prev[iz],
362
362
  # max_iter=max_iter, tol=tol, armijo=armijo,
363
363
  # min_lam=min_lam, w_min=w_min
364
364
  # )
@@ -387,7 +387,7 @@ def decompress_newton(z_list, t_grid, a_coeffs, w0_list=None,
387
387
  # TEST
388
388
  def solve_with_choice(iz, w_seed):
389
389
  # candidate roots at this (t,z)
390
- cands = fd_candidates_w(z_list[iz], t, a_coeffs, w_min=w_min)
390
+ cands = fd_candidates_w(z_list[iz], t, coeffs, w_min=w_min)
391
391
 
392
392
  # ---------------------
393
393
  # TEST
@@ -402,7 +402,7 @@ def decompress_newton(z_list, t_grid, a_coeffs, w0_list=None,
402
402
  if len(cands) == 0:
403
403
  # fallback to your existing single-root solver
404
404
  w, success = fd_solve_w(
405
- z_list[iz], t, a_coeffs, w_prev[iz],
405
+ z_list[iz], t, coeffs, w_prev[iz],
406
406
  max_iter=max_iter, tol=tol, armijo=armijo,
407
407
  min_lam=min_lam, w_min=w_min
408
408
  )
@@ -452,7 +452,7 @@ def decompress_newton(z_list, t_grid, a_coeffs, w0_list=None,
452
452
  # problems.
453
453
  for iz in range(nz):
454
454
  w, success = fd_solve_w(
455
- z_list[iz], t, a_coeffs, w_prev[iz],
455
+ z_list[iz], t, coeffs, w_prev[iz],
456
456
  max_iter=max_iter, tol=tol, armijo=armijo,
457
457
  min_lam=min_lam, w_min=w_min
458
458
  )