freealg 0.5.0__py3-none-any.whl → 0.5.2__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.5.0"
1
+ __version__ = "0.5.2"
freealg/_chebyshev.py CHANGED
@@ -16,7 +16,7 @@ from scipy.special import eval_chebyu
16
16
  from ._series import partial_sum, wynn_epsilon
17
17
 
18
18
  __all__ = ['chebyshev_sample_proj', 'chebyshev_kernel_proj',
19
- 'chebyshev_approx', 'chebyshev_stieltjes']
19
+ 'chebyshev_density', 'chebyshev_stieltjes']
20
20
 
21
21
 
22
22
  # =====================
@@ -115,11 +115,11 @@ def chebyshev_kernel_proj(xs, pdf, support, K=10, reg=0.0):
115
115
  return psi
116
116
 
117
117
 
118
- # ================
119
- # chebyshev approx
120
- # ================
118
+ # =================
119
+ # chebyshev density
120
+ # =================
121
121
 
122
- def chebyshev_approx(x, psi, support):
122
+ def chebyshev_density(x, psi, support):
123
123
  """
124
124
  Given \\psi_k, evaluate the approximate density \\rho(x).
125
125
 
freealg/_jacobi.py CHANGED
@@ -14,8 +14,9 @@
14
14
  import numpy
15
15
  from scipy.special import eval_jacobi, roots_jacobi
16
16
  from scipy.special import gammaln, beta as Beta
17
+ from ._series import wynn_epsilon
17
18
 
18
- __all__ = ['jacobi_sample_proj', 'jacobi_kernel_proj', 'jacobi_approx',
19
+ __all__ = ['jacobi_sample_proj', 'jacobi_kernel_proj', 'jacobi_density',
19
20
  'jacobi_stieltjes']
20
21
 
21
22
 
@@ -108,13 +109,13 @@ def jacobi_kernel_proj(xs, pdf, support, K=10, alpha=0.0, beta=0.0, reg=0.0):
108
109
  return psi
109
110
 
110
111
 
111
- # =============
112
- # jacobi approx
113
- # =============
112
+ # ==============
113
+ # jacobi density
114
+ # ==============
114
115
 
115
- def jacobi_approx(x, psi, support, alpha=0.0, beta=0.0):
116
+ def jacobi_density(x, psi, support, alpha=0.0, beta=0.0):
116
117
  """
117
- Reconstruct Jacobi approximation.
118
+ Reconstruct Jacobi approximation of density.
118
119
 
119
120
  Parameters
120
121
  ----------
@@ -144,8 +145,8 @@ def jacobi_approx(x, psi, support, alpha=0.0, beta=0.0):
144
145
  w = (1 - t)**alpha * (1 + t)**beta
145
146
  P = numpy.vstack([eval_jacobi(k, alpha, beta, t) for k in range(len(psi))])
146
147
 
147
- rho_t = w * (psi @ P) # density in tvariable
148
- rho_x = rho_t * (2.0 / (lam_p - lam_m)) # back to xvariable
148
+ rho_t = w * (psi @ P) # density in t-variable
149
+ rho_x = rho_t * (2.0 / (lam_p - lam_m)) # back to x-variable
149
150
 
150
151
  return rho_x
151
152
 
@@ -154,7 +155,8 @@ def jacobi_approx(x, psi, support, alpha=0.0, beta=0.0):
154
155
  # jacobi stieltjes
155
156
  # ================
156
157
 
157
- def jacobi_stieltjes(z, psi, support, alpha=0.0, beta=0.0, n_base=40):
158
+ def jacobi_stieltjes(z, psi, support, alpha=0.0, beta=0.0, n_base=40,
159
+ use_wynn_epsilon=False):
158
160
  """
159
161
  Compute m(z) = sum_k psi_k * m_k(z) where
160
162
 
@@ -178,22 +180,33 @@ def jacobi_stieltjes(z, psi, support, alpha=0.0, beta=0.0, n_base=40):
178
180
  Minimum quadrature size. For degree-k polynomial we use
179
181
  n_quad = max(n_base, k+1).
180
182
 
183
+ use_wynn_epsilon : bool, default=False
184
+ Use Wynn epsilon, otherwise assumes Pade is used.
185
+
181
186
  Returns
182
187
  -------
183
188
 
184
- m1 : ndarray (same shape as z)
189
+ m1 : ndarray
190
+ Same shape as z
185
191
 
186
- m12 : ndarray (same shape as z)
192
+ m2 : ndarray
193
+ Same shape as z
187
194
  """
188
195
 
189
196
  z = numpy.asarray(z, dtype=numpy.complex128)
190
197
  lam_minus, lam_plus = support
191
198
  span = lam_plus - lam_minus
192
199
  centre = 0.5 * (lam_plus + lam_minus)
193
- u_z = (2.0 / span) * (z - centre) # map z -> u
200
+
201
+ # Map z -> u in the standard [-1,1] domain
202
+ u = (2.0 / span) * (z - centre)
194
203
 
195
204
  m_total = numpy.zeros_like(z, dtype=numpy.complex128)
196
205
 
206
+ if use_wynn_epsilon:
207
+ # Stores m with the ravel size of z.
208
+ m_partial = numpy.zeros((psi.size, z.size), dtype=numpy.complex128)
209
+
197
210
  for k, psi_k in enumerate(psi):
198
211
  # Select quadrature size tailored to this P_k
199
212
  n_quad = max(n_base, k + 1)
@@ -205,14 +218,43 @@ def jacobi_stieltjes(z, psi, support, alpha=0.0, beta=0.0, n_base=40):
205
218
  # Integrand values at nodes: w_nodes already include the weight
206
219
  integrand = w_nodes * P_k_nodes # (n_quad,)
207
220
 
208
- # Broadcast over z: shape (n_quad, ...) / ...
209
- diff = u_z[None, ...] - t_nodes[:, None, None] # (n_quad, Ny, Nx)
210
- m_k = (integrand[:, None, None] / diff).sum(axis=0)
221
+ # Evaluate jacobi polynomals of the second kind, Q_k using quadrature
222
+ diff = t_nodes[:, None, None] - u[None, ...] # (n_quad, Ny, Nx)
223
+ Q_k = (integrand[:, None, None] / diff).sum(axis=0)
224
+
225
+ # Principal branch
226
+ m_k = (2.0 / span) * Q_k
227
+
228
+ # Compute secondary branch from the principal branch
229
+ if use_wynn_epsilon:
230
+
231
+ # Compute analytic extension of rho(z) to lower-half plane for
232
+ # when rho is just the k-th Jacobi basis: w(z) P_k(z). FOr this,
233
+ # we create a psi array (called unit_psi_j), with all zeros, except
234
+ # its k-th element is one. Ten we call jacobi_density.
235
+ unit_psi_k = numpy.zeros_like(psi)
236
+ unit_psi_k[k] = 1.0
237
+
238
+ # Only lower-half plane
239
+ mask_m = z.imag <= 0
240
+ z_m = z[mask_m]
241
+
242
+ # Dnesity here is rho = w(z) P_k
243
+ rho_k = jacobi_density(z_m.ravel(), unit_psi_k, support,
244
+ alpha=alpha, beta=beta).reshape(z_m.shape)
245
+
246
+ # Secondary branch is principal branch + 2 \pi i rho, using Plemelj
247
+ # (in fact, Riemann-Hirbert jump).
248
+ m_k[mask_m] = m_k[mask_m] + 2.0 * numpy.pi * 1j * rho_k
211
249
 
212
250
  # Accumulate with factor 2/span
213
- m_total += psi_k * (2.0 / span) * m_k
251
+ m_total += psi_k * m_k
252
+
253
+ if use_wynn_epsilon:
254
+ m_partial[k, :] = m_total.ravel()
214
255
 
215
- # We use a negative sign convention
216
- m_total = -m_total
256
+ if use_wynn_epsilon:
257
+ S = wynn_epsilon(m_partial)
258
+ m_total = S.reshape(z.shape)
217
259
 
218
260
  return m_total
freealg/_plot_util.py CHANGED
@@ -20,7 +20,7 @@ import matplotlib.ticker as ticker
20
20
  import matplotlib.gridspec as gridspec
21
21
 
22
22
  __all__ = ['plot_fit', 'plot_density', 'plot_hilbert', 'plot_stieltjes',
23
- 'plot_stieltjes_on_disk']
23
+ 'plot_stieltjes_on_disk', 'plot_samples']
24
24
 
25
25
 
26
26
  # ========
freealg/_series.py CHANGED
@@ -84,18 +84,40 @@ def wynn_epsilon(Sn):
84
84
  S : numpy.array
85
85
  A 1D array of the size (d,) which is the accelerated value of the
86
86
  series at each vector element.
87
+
88
+ Notes
89
+ -----
90
+
91
+ Given a series of vectors:
92
+
93
+ .. math::
94
+
95
+ (S_n)_{n=1}^N = (S1, \\dots, S_n)
96
+
97
+ this function finds the limit S = \\lim_{n \\to infty} S_n.
98
+
99
+ Each :math:`S_i \\in \\mathbb{C}^d` is a vector. However, instead of using
100
+ the vector version of the Wynn's epsilon algorithm, we use the scalar
101
+ version on each component of the vector. The reason for this is that in our
102
+ dataset, each component has its own convergence rate. The convergence rate
103
+ of vector version of the algorithm is bounded by the worse point, and this
104
+ potentially stall convergence for all points. As such, vector version is
105
+ avoided.
106
+
107
+ In our dataset, the series is indeed divergent. The Wynn's accelerated
108
+ method computes the principal value of the convergence series.
87
109
  """
88
110
 
89
111
  # N: number of partial sums, d: vector size
90
112
  N, d = Sn.shape
91
113
 
92
- eps = numpy.zeros((N+1, N, d), dtype=Sn.dtype)
114
+ eps = numpy.zeros((N, N, d), dtype=Sn.dtype)
93
115
  eps[0, :, :] = Sn
94
116
 
95
117
  tol = numpy.finfo(float).eps
96
118
 
97
- # Wynn's epsilon algorithm
98
- for k in range(1, N+1):
119
+ # Wynn's triangle table
120
+ for k in range(1, N):
99
121
  Nk = N - k
100
122
 
101
123
  delta = eps[k-1, 1:N-k+1, :] - eps[k-1, :Nk, :]
@@ -117,7 +139,7 @@ def wynn_epsilon(Sn):
117
139
  if k > 1:
118
140
  eps[k, :Nk, :] += eps[k-2, 1:Nk+1, :]
119
141
 
120
- k_even = 2 * (N // 2)
121
- series = eps[k_even, 0, :]
142
+ k_even = 2 * ((N - 1) // 2)
143
+ S = eps[k_even, 0, :]
122
144
 
123
- return series
145
+ return S
freealg/_util.py CHANGED
@@ -89,7 +89,7 @@ def beta_kde(eig, xs, lam_m, lam_p, h):
89
89
  # force density
90
90
  # =============
91
91
 
92
- def force_density(psi0, support, approx, grid, alpha=0.0, beta=0.0):
92
+ def force_density(psi0, support, density, grid, alpha=0.0, beta=0.0):
93
93
  """
94
94
  Starting from psi0 (raw projection), solve
95
95
  min 0.5 ||psi - psi0||^2
@@ -113,26 +113,26 @@ def force_density(psi0, support, approx, grid, alpha=0.0, beta=0.0):
113
113
 
114
114
  # Enforce positivity
115
115
  constraints.append({'type': 'ineq',
116
- 'fun': lambda psi: approx(grid, psi)})
116
+ 'fun': lambda psi: density(grid, psi)})
117
117
 
118
118
  # Enforce unit mass
119
119
  constraints.append({
120
120
  'type': 'eq',
121
- 'fun': lambda psi: numpy.trapz(approx(grid, psi), grid) - 1.0
121
+ 'fun': lambda psi: numpy.trapz(density(grid, psi), grid) - 1.0
122
122
  })
123
123
 
124
124
  # Enforce zero at left edge
125
125
  if beta <= 0.0 and beta > -0.5:
126
126
  constraints.append({
127
127
  'type': 'eq',
128
- 'fun': lambda psi: approx(numpy.array([lam_m]), psi)[0]
128
+ 'fun': lambda psi: density(numpy.array([lam_m]), psi)[0]
129
129
  })
130
130
 
131
131
  # Enforce zero at right edge
132
132
  if alpha <= 0.0 and alpha > -0.5:
133
133
  constraints.append({
134
134
  'type': 'eq',
135
- 'fun': lambda psi: approx(numpy.array([lam_p]), psi)[0]
135
+ 'fun': lambda psi: density(numpy.array([lam_p]), psi)[0]
136
136
  })
137
137
 
138
138
  # Solve a small quadratic programming
@@ -146,7 +146,7 @@ def force_density(psi0, support, approx, grid, alpha=0.0, beta=0.0):
146
146
 
147
147
  # Normalize first mode to unit mass
148
148
  x = numpy.linspace(lam_m, lam_p, 1000)
149
- rho = approx(x, psi)
149
+ rho = density(x, psi)
150
150
  mass = numpy.trapezoid(rho, x)
151
151
  psi[0] = psi[0] / mass
152
152
 
freealg/freeform.py CHANGED
@@ -16,10 +16,10 @@ from scipy.stats import gaussian_kde
16
16
  # from statsmodels.nonparametric.kde import KDEUnivariate
17
17
  from functools import partial
18
18
  from ._util import compute_eig, beta_kde, force_density
19
- from ._jacobi import jacobi_sample_proj, jacobi_kernel_proj, jacobi_approx, \
19
+ from ._jacobi import jacobi_sample_proj, jacobi_kernel_proj, jacobi_density, \
20
20
  jacobi_stieltjes
21
21
  from ._chebyshev import chebyshev_sample_proj, chebyshev_kernel_proj, \
22
- chebyshev_approx, chebyshev_stieltjes
22
+ chebyshev_density, chebyshev_stieltjes
23
23
  from ._damp import jackson_damping, lanczos_damping, fejer_damping, \
24
24
  exponential_damping, parzen_damping
25
25
  from ._plot_util import plot_fit, plot_density, plot_hilbert, plot_stieltjes
@@ -234,11 +234,11 @@ class FreeForm(object):
234
234
  If `True`, it forces the density to have unit mass and to be
235
235
  strictly positive.
236
236
 
237
- continuation : {``'pade'``, ``wynn``}, default= ``'pade'``
237
+ continuation : {``'pade'``, ``'wynn'``}, default= ``'pade'``
238
238
  Method of analytic continuation to construct the second branch of
239
239
  Steltjes transform in the lower-half complex plane:
240
240
 
241
- * ``'pade'``: using Reimann-Hilbert problem witth Pade
241
+ * ``'pade'``: using Riemann-Hilbert problem with Pade
242
242
  approximation.
243
243
  * ``'wynn'``: Wynn's epsilon algorithm.
244
244
 
@@ -401,15 +401,15 @@ class FreeForm(object):
401
401
  grid = numpy.linspace(self.lam_m, self.lam_p, 500)
402
402
 
403
403
  if method == 'jacobi':
404
- approx = partial(jacobi_approx, support=self.support,
405
- alpha=alpha, beta=beta)
404
+ density = partial(jacobi_density, support=self.support,
405
+ alpha=alpha, beta=beta)
406
406
  elif method == 'chebyshev':
407
- approx = partial(chebyshev_approx, support=self.support)
407
+ density = partial(chebyshev_density, support=self.support)
408
408
  else:
409
409
  raise RuntimeError('"method" is invalid.')
410
410
 
411
411
  # Enforce positivity, unit mass, and zero at edges
412
- psi = force_density(psi, support=self.support, approx=approx,
412
+ psi = force_density(psi, support=self.support, density=density,
413
413
  grid=grid, alpha=alpha, beta=beta)
414
414
 
415
415
  # Update attributes
@@ -438,12 +438,6 @@ class FreeForm(object):
438
438
  # Do nothing. Make sure _pade_sol is still None
439
439
  self._pade_sol = None
440
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.')
446
-
447
441
  if plot:
448
442
  if self._pade_sol is not None:
449
443
  g_supp_approx = eval_pade(x_supp[None, :],
@@ -539,10 +533,10 @@ class FreeForm(object):
539
533
  mask = numpy.logical_and(x >= self.lam_m, x <= self.lam_p)
540
534
 
541
535
  if self.method == 'jacobi':
542
- rho[mask] = jacobi_approx(x[mask], self.psi, self.support,
543
- self.alpha, self.beta)
536
+ rho[mask] = jacobi_density(x[mask], self.psi, self.support,
537
+ self.alpha, self.beta)
544
538
  elif self.method == 'chebyshev':
545
- rho[mask] = chebyshev_approx(x[mask], self.psi, self.support)
539
+ rho[mask] = chebyshev_density(x[mask], self.psi, self.support)
546
540
  else:
547
541
  raise RuntimeError('"method" is invalid.')
548
542
 
@@ -821,19 +815,20 @@ class FreeForm(object):
821
815
  # z.real <= self.lam_p)
822
816
  # n_base = 2 * numpy.sum(mask_sup)
823
817
 
818
+ if self.continuation == 'wynn':
819
+ use_wynn_epsilon = True
820
+ else:
821
+ use_wynn_epsilon = False
822
+
824
823
  # Stieltjes function
825
824
  if self.method == 'jacobi':
826
825
  stieltjes = partial(jacobi_stieltjes, psi=self.psi,
827
826
  support=self.support, alpha=self.alpha,
828
- beta=self.beta) # n_base = n_base
827
+ beta=self.beta,
828
+ use_wynn_epsilon=use_wynn_epsilon)
829
+ # n_base = n_base
829
830
 
830
831
  elif self.method == 'chebyshev':
831
-
832
- if self.continuation == 'wynn':
833
- use_wynn_epsilon = True
834
- else:
835
- use_wynn_epsilon = False
836
-
837
832
  stieltjes = partial(chebyshev_stieltjes, psi=self.psi,
838
833
  support=self.support,
839
834
  use_wynn_epsilon=use_wynn_epsilon)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: freealg
3
- Version: 0.5.0
3
+ Version: 0.5.2
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
@@ -26,7 +26,7 @@ Classifier: Intended Audience :: Science/Research
26
26
  Classifier: Intended Audience :: Developers
27
27
  Classifier: Topic :: Software Development
28
28
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
29
- Requires-Python: >=3.9
29
+ Requires-Python: >=3.10
30
30
  Description-Content-Type: text/x-rst
31
31
  License-File: LICENSE.txt
32
32
  License-File: AUTHORS.txt
@@ -1,26 +1,26 @@
1
1
  freealg/__init__.py,sha256=KfzqG7qig6ZZCKqgHcC2ApTg4rTLkrbJsvVoJd8UFG8,625
2
- freealg/__version__.py,sha256=LBK46heutvn3KmsCrKIYu8RQikbfnjZaj2xFrXaeCzQ,22
3
- freealg/_chebyshev.py,sha256=-XiMKPra9pjkvMLjLusPo8n4NfjcJd9K0tAm5TF8PdA,6311
2
+ freealg/__version__.py,sha256=isJrmDBLRag7Zc2UK9ZovWGOv7ji1Oh-zJtJMNJFkXw,22
3
+ freealg/_chebyshev.py,sha256=xtHsSu8_aqGNqfBJfZLvdBZ8F71oVDdOS3JJw1dYxck,6316
4
4
  freealg/_damp.py,sha256=k2vtBtWOxQBf4qXaWu_En81lQBXbEO4QbxxWpvuVhdE,1802
5
5
  freealg/_decompress.py,sha256=RKYnuLKMx1V6-XrFjYX1UkGMRbUD9Gmf9XTyS4ffPSc,31970
6
- freealg/_jacobi.py,sha256=AT4ONSHGGDxVKE3MGMLyMR8uDFiO-e9u3x5udYfdJJk,5635
6
+ freealg/_jacobi.py,sha256=Q6LkE84AaL49-FamB_Nj3wVAfE4zqS9EeaJWcc0uGqE,7147
7
7
  freealg/_linalg.py,sha256=khfRwdQIDtf45aOIq3QSeihAEtUCL-HgwEYtEs0YELc,13137
8
8
  freealg/_pade.py,sha256=Ecm373RvBWznAaf8a5D9qtjcRA8O_8NQsePwto-dsP4,13656
9
- freealg/_plot_util.py,sha256=mkvOZJDXCxIo8jUZoS8gsSDgieMCL8oZNZEo_-mYreQ,20052
9
+ freealg/_plot_util.py,sha256=GKvmc1wjVGeqoomrULPbzBEt6P86FdoR2idBLYh5EDY,20068
10
10
  freealg/_sample.py,sha256=MUY9ZkJbdhbC5thoy5_JMRWOHz_OfqMfaH0g2VhKPhg,2550
11
- freealg/_series.py,sha256=x0_NNaNjv-_FSAnZzlp8BO5XI5q8ELF_kwnGlAUBZZg,2603
11
+ freealg/_series.py,sha256=_ln_DW_4xrRbwyfQTVunnxUhDFi9N_JLiveFQItVjuE,3393
12
12
  freealg/_support.py,sha256=ZfU0T7CCDaTXMdEHSbwOL-rMnCPvJWsRb6JtqUMsrzY,6441
13
- freealg/_util.py,sha256=yerqBCedkglc9soWmRgxcm7HTnJGKeiDq9xxfKcE9WY,3780
14
- freealg/freeform.py,sha256=zkjkkMkvCTn25k8QvefrvNBaGYQhIkPLBiV_Ij01l04,42286
13
+ freealg/_util.py,sha256=xKhtPgbW4vHidNAG6F5c5aQhTaG4MmaUqCsxwjBznfU,3786
14
+ freealg/freeform.py,sha256=vvURyf8wd6-73HWRwO3KjdyUozRI4J71ysMfbl29F94,42084
15
15
  freealg/distributions/__init__.py,sha256=t_yZyEkW_W_tSV9IvgYXtVASxD2BEdiNVXcV2ebMy8M,579
16
16
  freealg/distributions/_kesten_mckay.py,sha256=4EvW0seBZUv-cZjuLzfVCredmrCiOJcQ_hJM0mJDl6g,19899
17
17
  freealg/distributions/_marchenko_pastur.py,sha256=r-jmz8Wq5vG0-x7rB0qvVemqvu0Oq6S-BN67pqH0uiw,16992
18
18
  freealg/distributions/_meixner.py,sha256=bZv-x4mwS4yjisKoYSZAffHXtvDEKEis-74BeAjK4_s,17530
19
19
  freealg/distributions/_wachter.py,sha256=rkAmrBLqD2zvpBh0F32aQBscjXv8earXDH9_BITgFF0,16900
20
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,,
21
+ freealg-0.5.2.dist-info/licenses/AUTHORS.txt,sha256=0b67Nz4_JgIzUupHJTAZxu5QdSUM_HRM_X_w4xCb17o,30
22
+ freealg-0.5.2.dist-info/licenses/LICENSE.txt,sha256=J-EEYEtxb3VVf_Bn1TYfWnpY5lMFIM15iLDDcnaDTPA,1443
23
+ freealg-0.5.2.dist-info/METADATA,sha256=0Vz7b2mbf5Mf6QLU6Y7X0ajGjs0A83eGBZbMfHkRdTE,5530
24
+ freealg-0.5.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
+ freealg-0.5.2.dist-info/top_level.txt,sha256=eR2wrgYwDdnnJ9Zf5PruPqe4kQav0GMvRsqct6y00Q8,8
26
+ freealg-0.5.2.dist-info/RECORD,,