freealg 0.7.5__py3-none-any.whl → 0.7.6__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/_constraints.py +98 -0
- freealg/_algebraic_form/_continuation_algebraic.py +80 -7
- freealg/_algebraic_form/algebraic_form.py +45 -5
- freealg/_util.py +24 -1
- {freealg-0.7.5.dist-info → freealg-0.7.6.dist-info}/METADATA +1 -1
- {freealg-0.7.5.dist-info → freealg-0.7.6.dist-info}/RECORD +11 -10
- {freealg-0.7.5.dist-info → freealg-0.7.6.dist-info}/WHEEL +0 -0
- {freealg-0.7.5.dist-info → freealg-0.7.6.dist-info}/licenses/AUTHORS.txt +0 -0
- {freealg-0.7.5.dist-info → freealg-0.7.6.dist-info}/licenses/LICENSE.txt +0 -0
- {freealg-0.7.5.dist-info → freealg-0.7.6.dist-info}/top_level.txt +0 -0
freealg/__version__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.7.
|
|
1
|
+
__version__ = "0.7.6"
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
|
|
2
|
+
# SPDX-FileCopyrightText: Copyright 2025, Siavash Ameli <sameli@berkeley.edu>
|
|
3
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
4
|
+
# SPDX-FileType: SOURCE
|
|
5
|
+
#
|
|
6
|
+
# This program is free software: you can redistribute it and/or modify it under
|
|
7
|
+
# the terms of the license found in the LICENSE.txt file in the root directory
|
|
8
|
+
# of this source tree.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# =======
|
|
12
|
+
# Imports
|
|
13
|
+
# =======
|
|
14
|
+
|
|
15
|
+
import numpy
|
|
16
|
+
|
|
17
|
+
__all__ = ['build_moment_constraint_matrix']
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# ==========
|
|
21
|
+
# series mul
|
|
22
|
+
# ==========
|
|
23
|
+
|
|
24
|
+
def _series_mul(a, b, q_max):
|
|
25
|
+
|
|
26
|
+
na = min(len(a), q_max + 1)
|
|
27
|
+
nb = min(len(b), q_max + 1)
|
|
28
|
+
out = numpy.zeros(q_max + 1, dtype=float)
|
|
29
|
+
for i in range(na):
|
|
30
|
+
if a[i] == 0.0:
|
|
31
|
+
continue
|
|
32
|
+
j_max = min(nb - 1, q_max - i)
|
|
33
|
+
if j_max >= 0:
|
|
34
|
+
out[i:i + j_max + 1] += a[i] * b[:j_max + 1]
|
|
35
|
+
return out
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# ==========
|
|
39
|
+
# series pow
|
|
40
|
+
# ==========
|
|
41
|
+
|
|
42
|
+
def _series_pow(mser, j, q_max):
|
|
43
|
+
if j == 0:
|
|
44
|
+
out = numpy.zeros(q_max + 1, dtype=float)
|
|
45
|
+
out[0] = 1.0
|
|
46
|
+
return out
|
|
47
|
+
out = mser.copy()
|
|
48
|
+
for _ in range(1, j):
|
|
49
|
+
out = _series_mul(out, mser, q_max)
|
|
50
|
+
return out
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# ===============================
|
|
54
|
+
# build moment constraints matrix
|
|
55
|
+
# ===============================
|
|
56
|
+
|
|
57
|
+
def build_moment_constraint_matrix(pairs, deg_z, s, mu):
|
|
58
|
+
|
|
59
|
+
mu = numpy.asarray(mu, dtype=float).ravel()
|
|
60
|
+
if mu.size == 0:
|
|
61
|
+
return numpy.zeros((0, len(pairs)), dtype=float)
|
|
62
|
+
|
|
63
|
+
# m(z) = -sum_{p>=0} mu_p / z^{p+1}; t = 1/z so m(t) = -sum mu_p t^{p+1}
|
|
64
|
+
r = mu.size - 1
|
|
65
|
+
q_max = r
|
|
66
|
+
|
|
67
|
+
mser = numpy.zeros(q_max + 1, dtype=float)
|
|
68
|
+
for p in range(mu.size):
|
|
69
|
+
q = p + 1
|
|
70
|
+
if q <= q_max:
|
|
71
|
+
mser[q] = -float(mu[p])
|
|
72
|
+
|
|
73
|
+
# Precompute (m(t))^j coefficients up to t^{q_max}
|
|
74
|
+
mpow = []
|
|
75
|
+
for j in range(s + 1):
|
|
76
|
+
mpow.append(_series_pow(mser, j, q_max))
|
|
77
|
+
|
|
78
|
+
# Constraints: coeff of t^q in Q(t) := t^{deg_z} P(1/t, m(t)) must be 0
|
|
79
|
+
# Q(t) = sum_{i,j} c_{i,j} * t^{deg_z - i} * (m(t))^j
|
|
80
|
+
n_coef = len(pairs)
|
|
81
|
+
B = numpy.zeros((q_max + 1, n_coef), dtype=float)
|
|
82
|
+
|
|
83
|
+
for k, (i, j) in enumerate(pairs):
|
|
84
|
+
shift = deg_z - i
|
|
85
|
+
if shift < 0:
|
|
86
|
+
continue
|
|
87
|
+
mj = mpow[j]
|
|
88
|
+
for q in range(q_max + 1):
|
|
89
|
+
qq = q - shift
|
|
90
|
+
if 0 <= qq <= q_max:
|
|
91
|
+
B[q, k] = mj[qq]
|
|
92
|
+
|
|
93
|
+
# Drop all-zero rows (can happen if index-set can't support higher moments)
|
|
94
|
+
row_norm = numpy.linalg.norm(B, axis=1)
|
|
95
|
+
keep = row_norm > 0.0
|
|
96
|
+
B = B[keep, :]
|
|
97
|
+
|
|
98
|
+
return B
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import numpy
|
|
15
15
|
from .._geometric_form._continuation_genus0 import joukowski_z
|
|
16
|
+
from ._constraints import build_moment_constraint_matrix
|
|
16
17
|
|
|
17
18
|
__all__ = ['sample_z_joukowski', 'filter_z_away_from_cuts', 'powers',
|
|
18
19
|
'fit_polynomial_relation', 'sanity_check_stieltjes_branch',
|
|
@@ -131,7 +132,11 @@ def powers(x, deg):
|
|
|
131
132
|
# =======================
|
|
132
133
|
|
|
133
134
|
def fit_polynomial_relation(z, m, s, deg_z, ridge_lambda=0.0, weights=None,
|
|
134
|
-
triangular=None, normalize=False
|
|
135
|
+
triangular=None, normalize=False,
|
|
136
|
+
mu=None, mu_reg=None):
|
|
137
|
+
"""
|
|
138
|
+
Fits polynomial P(z, m) = 0 with samples from the physical branch.
|
|
139
|
+
"""
|
|
135
140
|
|
|
136
141
|
z = numpy.asarray(z, dtype=complex).ravel()
|
|
137
142
|
m = numpy.asarray(m, dtype=complex).ravel()
|
|
@@ -198,13 +203,81 @@ def fit_polynomial_relation(z, m, s, deg_z, ridge_lambda=0.0, weights=None,
|
|
|
198
203
|
s_col[s_col == 0.0] = 1.0
|
|
199
204
|
As = Ar / s_col[None, :]
|
|
200
205
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
206
|
+
# Optional moment constraints B c = 0 (hard via nullspace, soft via
|
|
207
|
+
# weighted rows)
|
|
208
|
+
if mu is not None:
|
|
209
|
+
B = build_moment_constraint_matrix(pairs, deg_z, s, mu)
|
|
210
|
+
if B.shape[0] > 0:
|
|
211
|
+
Bs = B / s_col[None, :]
|
|
212
|
+
|
|
213
|
+
if mu_reg is None:
|
|
214
|
+
# Hard constraints: solve in nullspace of Bs
|
|
215
|
+
uB, sB, vhB = numpy.linalg.svd(Bs, full_matrices=True)
|
|
216
|
+
tolB = 1e-12 * (sB[0] if sB.size else 1.0)
|
|
217
|
+
rankB = int(numpy.sum(sB > tolB))
|
|
218
|
+
if rankB >= n_coef:
|
|
219
|
+
raise RuntimeError(
|
|
220
|
+
'Moment constraints leave no feasible coefficients.')
|
|
221
|
+
|
|
222
|
+
N = vhB[rankB:, :].T # (n_coef, n_free)
|
|
223
|
+
AN = As @ N
|
|
224
|
+
|
|
225
|
+
if ridge_lambda > 0.0:
|
|
226
|
+
L = numpy.sqrt(ridge_lambda) * numpy.eye(N.shape[1],
|
|
227
|
+
dtype=float)
|
|
228
|
+
AN = numpy.vstack([AN, L])
|
|
229
|
+
|
|
230
|
+
_, _, vhN = numpy.linalg.svd(AN, full_matrices=False)
|
|
231
|
+
y = vhN[-1, :]
|
|
232
|
+
coef_scaled = N @ y
|
|
233
|
+
|
|
234
|
+
coef = coef_scaled / s_col
|
|
235
|
+
|
|
236
|
+
else:
|
|
237
|
+
mu_reg = float(mu_reg)
|
|
238
|
+
if mu_reg > 0.0:
|
|
239
|
+
As_aug = As
|
|
240
|
+
Bs_w = numpy.sqrt(mu_reg) * Bs
|
|
241
|
+
As_aug = numpy.vstack([As_aug, Bs_w])
|
|
242
|
+
|
|
243
|
+
if ridge_lambda > 0.0:
|
|
244
|
+
L = numpy.sqrt(ridge_lambda) * numpy.eye(n_coef,
|
|
245
|
+
dtype=float)
|
|
246
|
+
As_aug = numpy.vstack([As_aug, L])
|
|
247
|
+
|
|
248
|
+
_, _, vh = numpy.linalg.svd(As_aug, full_matrices=False)
|
|
249
|
+
coef_scaled = vh[-1, :]
|
|
250
|
+
coef = coef_scaled / s_col
|
|
251
|
+
else:
|
|
252
|
+
# mu_reg == 0 => ignore constraints
|
|
253
|
+
if ridge_lambda > 0.0:
|
|
254
|
+
L = numpy.sqrt(ridge_lambda) * numpy.eye(n_coef,
|
|
255
|
+
dtype=float)
|
|
256
|
+
As = numpy.vstack([As, L])
|
|
257
|
+
|
|
258
|
+
_, _, vh = numpy.linalg.svd(As, full_matrices=False)
|
|
259
|
+
coef_scaled = vh[-1, :]
|
|
260
|
+
coef = coef_scaled / s_col
|
|
204
261
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
262
|
+
else:
|
|
263
|
+
# B has no effective rows -> proceed unconstrained
|
|
264
|
+
if ridge_lambda > 0.0:
|
|
265
|
+
L = numpy.sqrt(ridge_lambda) * numpy.eye(n_coef, dtype=float)
|
|
266
|
+
As = numpy.vstack([As, L])
|
|
267
|
+
|
|
268
|
+
_, _, vh = numpy.linalg.svd(As, full_matrices=False)
|
|
269
|
+
coef_scaled = vh[-1, :]
|
|
270
|
+
coef = coef_scaled / s_col
|
|
271
|
+
|
|
272
|
+
else:
|
|
273
|
+
# No moment constraints
|
|
274
|
+
if ridge_lambda > 0.0:
|
|
275
|
+
L = numpy.sqrt(ridge_lambda) * numpy.eye(n_coef, dtype=float)
|
|
276
|
+
As = numpy.vstack([As, L])
|
|
277
|
+
|
|
278
|
+
_, _, vh = numpy.linalg.svd(As, full_matrices=False)
|
|
279
|
+
coef_scaled = vh[-1, :]
|
|
280
|
+
coef = coef_scaled / s_col
|
|
208
281
|
|
|
209
282
|
full = numpy.zeros((deg_z + 1, s + 1), dtype=complex)
|
|
210
283
|
for k, (i, j) in enumerate(pairs):
|
|
@@ -194,6 +194,7 @@ class AlgebraicForm(object):
|
|
|
194
194
|
|
|
195
195
|
# Initialize
|
|
196
196
|
self.a_coeffs = None # Polynomial coefficients
|
|
197
|
+
self.status = None # Fitting status
|
|
197
198
|
self.cache = {} # Cache inner-computations
|
|
198
199
|
|
|
199
200
|
# ===
|
|
@@ -207,10 +208,38 @@ class AlgebraicForm(object):
|
|
|
207
208
|
y_eps=2e-2,
|
|
208
209
|
x_pad=0.0,
|
|
209
210
|
triangular=None,
|
|
211
|
+
mu=None,
|
|
212
|
+
mu_reg=None,
|
|
210
213
|
normalize=False,
|
|
211
214
|
verbose=False):
|
|
212
215
|
"""
|
|
213
|
-
|
|
216
|
+
Fit polynomial.
|
|
217
|
+
|
|
218
|
+
Parameters
|
|
219
|
+
----------
|
|
220
|
+
|
|
221
|
+
deg_m : int
|
|
222
|
+
Degree :math:`\\deg_m(P)`
|
|
223
|
+
|
|
224
|
+
deg_z : int
|
|
225
|
+
Degree :math:`\\deg_z(P)`
|
|
226
|
+
|
|
227
|
+
mu : array_like, default=None
|
|
228
|
+
If an array :math:`[\\mu_0, \\mu_`, \\dots, \\mu_r]` is given,
|
|
229
|
+
it enforces the first :math:`r+1` moments. Note that :math:`\\mu_0`
|
|
230
|
+
should be :math:`1` to ensure unit mass. See also ``mu_reg`.
|
|
231
|
+
|
|
232
|
+
mu_reg: float, default=None
|
|
233
|
+
If `None`, the constraints ``mu`` are applied as hard constraint.
|
|
234
|
+
If a positive number, the constraints are applied as a soft
|
|
235
|
+
constraints with regularisation ``mu_reg``.
|
|
236
|
+
|
|
237
|
+
Notes
|
|
238
|
+
-----
|
|
239
|
+
|
|
240
|
+
When the input data are from an exact model, hard moment constraint is
|
|
241
|
+
preferred over soft constraint as the latter can hurt an already a good
|
|
242
|
+
fit.
|
|
214
243
|
"""
|
|
215
244
|
|
|
216
245
|
# Very important: reset cache whenever this function is called. This
|
|
@@ -231,11 +260,13 @@ class AlgebraicForm(object):
|
|
|
231
260
|
z_fit = filter_z_away_from_cuts(z_fit, self.support, y_eps=y_eps,
|
|
232
261
|
x_pad=x_pad)
|
|
233
262
|
|
|
263
|
+
# Fitting (w_inf = None means adaptive weight selection)
|
|
234
264
|
m1_fit = self.stieltjes(z_fit)
|
|
235
265
|
a_coeffs = fit_polynomial_relation(z_fit, m1_fit, s=deg_m, deg_z=deg_z,
|
|
236
266
|
ridge_lambda=reg,
|
|
237
267
|
triangular=triangular,
|
|
238
|
-
normalize=normalize
|
|
268
|
+
normalize=normalize, mu=mu,
|
|
269
|
+
mu_reg=mu_reg)
|
|
239
270
|
|
|
240
271
|
self.a_coeffs = a_coeffs
|
|
241
272
|
|
|
@@ -251,8 +282,9 @@ class AlgebraicForm(object):
|
|
|
251
282
|
eta=max(y_eps, 1e-2), n_x=128,
|
|
252
283
|
max_bad_frac=0.05)
|
|
253
284
|
|
|
254
|
-
status['res_max'] = res_max
|
|
255
|
-
status['res_99_9'] = res_99_9
|
|
285
|
+
status['res_max'] = float(res_max)
|
|
286
|
+
status['res_99_9'] = float(res_99_9)
|
|
287
|
+
self.status = status
|
|
256
288
|
|
|
257
289
|
if verbose:
|
|
258
290
|
print(f'fit residual max : {res_max:>0.4e}')
|
|
@@ -657,11 +689,16 @@ class AlgebraicForm(object):
|
|
|
657
689
|
z_query = x + 1j * self.delta
|
|
658
690
|
|
|
659
691
|
# Initial condition at t=0 (physical branch)
|
|
660
|
-
w0_list = self.stieltjes(z_query)
|
|
692
|
+
# w0_list = self.stieltjes(z_query)
|
|
693
|
+
stieltjes = numpy.vectorize(m_fn)
|
|
694
|
+
w0_list = stieltjes(z_query)
|
|
661
695
|
|
|
662
696
|
# Times
|
|
663
697
|
t = numpy.log(alpha)
|
|
664
698
|
|
|
699
|
+
# Ensure it starts from t = 0
|
|
700
|
+
t = numpy.concatenate([numpy.zeros(1), t])
|
|
701
|
+
|
|
665
702
|
# Evolve
|
|
666
703
|
W, ok = decompress_newton(
|
|
667
704
|
z_query, t, self.a_coeffs,
|
|
@@ -669,6 +706,9 @@ class AlgebraicForm(object):
|
|
|
669
706
|
|
|
670
707
|
rho = W.imag / numpy.pi
|
|
671
708
|
|
|
709
|
+
# Remove time zero
|
|
710
|
+
rho = rho[1:, :]
|
|
711
|
+
|
|
672
712
|
if verbose:
|
|
673
713
|
print("success rate per t:", ok.mean(axis=1))
|
|
674
714
|
|
freealg/_util.py
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import numpy
|
|
15
15
|
import scipy
|
|
16
16
|
|
|
17
|
-
__all__ = ['resolve_complex_dtype', 'compute_eig']
|
|
17
|
+
__all__ = ['resolve_complex_dtype', 'compute_eig', 'subsample_matrix']
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
# =====================
|
|
@@ -70,3 +70,26 @@ def compute_eig(A, lower=False):
|
|
|
70
70
|
eig = scipy.linalg.eigvalsh(A, lower=lower, driver='ev')
|
|
71
71
|
|
|
72
72
|
return eig
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# ================
|
|
76
|
+
# subsample matrix
|
|
77
|
+
# ================
|
|
78
|
+
|
|
79
|
+
def subsample_matrix(matrix, submatrix_size, seed=None):
|
|
80
|
+
"""
|
|
81
|
+
Generate a random subsample of a larger matrix
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
if matrix.shape[0] != matrix.shape[1]:
|
|
85
|
+
raise ValueError("Matrix must be square")
|
|
86
|
+
|
|
87
|
+
n = matrix.shape[0]
|
|
88
|
+
if submatrix_size > n:
|
|
89
|
+
raise ValueError("Submatrix size cannot exceed matrix size")
|
|
90
|
+
|
|
91
|
+
rng = numpy.random.default_rng(seed)
|
|
92
|
+
idx = rng.choice(n, size=submatrix_size, replace=False)
|
|
93
|
+
idx = numpy.sort(idx) # optional, preserves original ordering
|
|
94
|
+
|
|
95
|
+
return matrix[numpy.ix_(idx, idx)]
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
freealg/__init__.py,sha256=SjcYb6HWmaclnnM-m1eC1honZRyfNBWYDYBx23kSdjo,833
|
|
2
|
-
freealg/__version__.py,sha256=
|
|
3
|
-
freealg/_util.py,sha256=
|
|
2
|
+
freealg/__version__.py,sha256=wu65dmVM9fKR1rBHH263ls8Ca2FZzb0ejYcrP_Ld0iY,22
|
|
3
|
+
freealg/_util.py,sha256=RzccUCORgzrI9NdNqwMVugiHU0uDKkJFcIyjFMUOnv8,2518
|
|
4
4
|
freealg/_algebraic_form/__init__.py,sha256=MIB_jVgw2qI-JW_ypqaFSeNAB6c4GvpjNySnap_a6hg,398
|
|
5
|
-
freealg/_algebraic_form/
|
|
5
|
+
freealg/_algebraic_form/_constraints.py,sha256=37U7nvtCTocuS7l_nfUznkPi195PY7eXFzeiikrv3B0,2448
|
|
6
|
+
freealg/_algebraic_form/_continuation_algebraic.py,sha256=SyuWjw0jABlIst9RjHS13gG2M94KZwwrTa3eeJNfmRI,19098
|
|
6
7
|
freealg/_algebraic_form/_decompress.py,sha256=gGtixLOVxlMy5S-NsXgoA7lIrB7u7nUZImQk1mIDo3s,21101
|
|
7
8
|
freealg/_algebraic_form/_decompress2.py,sha256=Ng9w9xmGe9M-DApp35IeNeQlvszfzT4NZx5BQn0lQ3I,2459
|
|
8
9
|
freealg/_algebraic_form/_edge.py,sha256=7l9QyLJDxaEY4WB6MCUFtfEZSf04wyHwH7YPHFJXSbM,10690
|
|
9
10
|
freealg/_algebraic_form/_homotopy.py,sha256=2oMcqJ2VJGzG7WKGM6FUS3923GT8Adtq_hLPEGgzqoU,3990
|
|
10
11
|
freealg/_algebraic_form/_sheets_util.py,sha256=6OLzWQKu-gN8rxM2rbpbN8TjNZFmD8UJ-8t9kcZdkCo,4174
|
|
11
|
-
freealg/_algebraic_form/algebraic_form.py,sha256=
|
|
12
|
+
freealg/_algebraic_form/algebraic_form.py,sha256=N-R8cv7580p-iPW7oPlDZ9py7BVjEmPcCjs25UVtNV4,32706
|
|
12
13
|
freealg/_free_form/__init__.py,sha256=5cnSX7kHci3wKx6-BEFhmVY_NjjmQAq1JjWPTEqETTg,611
|
|
13
14
|
freealg/_free_form/_chebyshev.py,sha256=zkyVA8NLf7uUKlJdLz4ijd_SurdsqUgkA5nHGWSybaE,6916
|
|
14
15
|
freealg/_free_form/_damp.py,sha256=k2vtBtWOxQBf4qXaWu_En81lQBXbEO4QbxxWpvuVhdE,1802
|
|
@@ -41,9 +42,9 @@ freealg/distributions/_wigner.py,sha256=epgx6ne6R_7to5j6-QsWIAVFJQFquWMmYgnZYMN4
|
|
|
41
42
|
freealg/visualization/__init__.py,sha256=NLq_zwueF7ytZ8sl8zLPqm-AODxxXNvfMozHGmmklcE,435
|
|
42
43
|
freealg/visualization/_glue_util.py,sha256=2oKnEYjUOS4OZfivmciVLauVr53kyHMwi6c2zRKilTQ,693
|
|
43
44
|
freealg/visualization/_rgb_hsv.py,sha256=rEskxXxSlKKxIrHRslVkgxHtD010L3ge9YtcVsOPl8E,3650
|
|
44
|
-
freealg-0.7.
|
|
45
|
-
freealg-0.7.
|
|
46
|
-
freealg-0.7.
|
|
47
|
-
freealg-0.7.
|
|
48
|
-
freealg-0.7.
|
|
49
|
-
freealg-0.7.
|
|
45
|
+
freealg-0.7.6.dist-info/licenses/AUTHORS.txt,sha256=0b67Nz4_JgIzUupHJTAZxu5QdSUM_HRM_X_w4xCb17o,30
|
|
46
|
+
freealg-0.7.6.dist-info/licenses/LICENSE.txt,sha256=J-EEYEtxb3VVf_Bn1TYfWnpY5lMFIM15iLDDcnaDTPA,1443
|
|
47
|
+
freealg-0.7.6.dist-info/METADATA,sha256=cifScuAeI6gPbjzzCzBMMLqTYtxbqIIJhuICSIi-BkE,5516
|
|
48
|
+
freealg-0.7.6.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
49
|
+
freealg-0.7.6.dist-info/top_level.txt,sha256=eR2wrgYwDdnnJ9Zf5PruPqe4kQav0GMvRsqct6y00Q8,8
|
|
50
|
+
freealg-0.7.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|