pepflow 0.1.4a1__py3-none-any.whl → 0.1.5__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.
- pepflow/__init__.py +5 -1
- pepflow/constraint.py +58 -1
- pepflow/e2e_test.py +47 -3
- pepflow/expression_manager.py +272 -57
- pepflow/expression_manager_test.py +36 -2
- pepflow/function.py +180 -10
- pepflow/parameter.py +187 -0
- pepflow/parameter_test.py +128 -0
- pepflow/pep.py +254 -14
- pepflow/pep_context.py +116 -0
- pepflow/pep_context_test.py +21 -0
- pepflow/point.py +155 -49
- pepflow/point_test.py +12 -0
- pepflow/scalar.py +260 -47
- pepflow/scalar_test.py +15 -0
- pepflow/solver.py +170 -3
- pepflow/solver_test.py +50 -2
- pepflow/utils.py +39 -7
- {pepflow-0.1.4a1.dist-info → pepflow-0.1.5.dist-info}/METADATA +12 -11
- pepflow-0.1.5.dist-info/RECORD +28 -0
- pepflow-0.1.4a1.dist-info/RECORD +0 -26
- {pepflow-0.1.4a1.dist-info → pepflow-0.1.5.dist-info}/WHEEL +0 -0
- {pepflow-0.1.4a1.dist-info → pepflow-0.1.5.dist-info}/licenses/LICENSE +0 -0
- {pepflow-0.1.4a1.dist-info → pepflow-0.1.5.dist-info}/top_level.txt +0 -0
pepflow/solver.py
CHANGED
@@ -46,6 +46,14 @@ def evaled_scalar_to_cvx_express(
|
|
46
46
|
|
47
47
|
|
48
48
|
class DualVariableManager:
|
49
|
+
"""
|
50
|
+
A class to access the dual variables associated with the constraints
|
51
|
+
of the Primal PEP. Should not be instantiated directly. Automatically
|
52
|
+
generated as a member variable of the :class:`PEPResult` object
|
53
|
+
returned when calling :py:func:`pepflow.PEPBuilder.solve_primal`.
|
54
|
+
"""
|
55
|
+
|
56
|
+
# It is used in the primal PEP to get the dual variables.
|
49
57
|
def __init__(self, named_constraints: list[tuple[str, cvxpy.Constraint]]):
|
50
58
|
self.named_constraints = {}
|
51
59
|
for name, c in named_constraints:
|
@@ -63,6 +71,19 @@ class DualVariableManager:
|
|
63
71
|
self.named_constraints[name] = constraint
|
64
72
|
|
65
73
|
def dual_value(self, name: str) -> float | None:
|
74
|
+
"""
|
75
|
+
Given the name of a :class:`Constraint` object that represents a
|
76
|
+
constraint in Primal PEP, return the value of its corresponding
|
77
|
+
dual variable.
|
78
|
+
|
79
|
+
Args:
|
80
|
+
name (str): The name of the :class:`Constraint` object whose
|
81
|
+
associated dual variable we want to retrieve.
|
82
|
+
|
83
|
+
Returns:
|
84
|
+
float: The value of the dual variable corresponding to the
|
85
|
+
:class:`Constraint` object associated with the `name` argument.
|
86
|
+
"""
|
66
87
|
if name not in self.named_constraints:
|
67
88
|
return None # Is this good choice?
|
68
89
|
dual_value = self.named_constraints[name].dual_value
|
@@ -71,7 +92,65 @@ class DualVariableManager:
|
|
71
92
|
return dual_value
|
72
93
|
|
73
94
|
|
74
|
-
class
|
95
|
+
class PrimalVariableManager:
|
96
|
+
"""
|
97
|
+
A class to access the primal variables of the Dual PEP. The primal
|
98
|
+
variables of the Dual PEP are the dual variables associated with the
|
99
|
+
constraints of the Primal PEP. Should not be instantiated directly.
|
100
|
+
Automatically generated as a member variable of the :class:`PEPResult`
|
101
|
+
object returned when calling :py:func:`pepflow.PEPBuilder.solve_dual`.
|
102
|
+
"""
|
103
|
+
|
104
|
+
# It is used in the dual PEP to get the primal variables.
|
105
|
+
def __init__(self, named_variables: list[tuple[str, cvxpy.Variable]]):
|
106
|
+
self.named_variables = {}
|
107
|
+
for name, v in named_variables:
|
108
|
+
self.add_variable(name, v)
|
109
|
+
|
110
|
+
def cvx_variables(self) -> list[cvxpy.Variable]:
|
111
|
+
return list(self.named_variables.values())
|
112
|
+
|
113
|
+
def clear(self) -> None:
|
114
|
+
self.named_variables.clear()
|
115
|
+
|
116
|
+
def add_variable(self, name: str, variable: cvxpy.Variable) -> None:
|
117
|
+
if name in self.named_variables:
|
118
|
+
raise KeyError(f"There is already a variable named {name}")
|
119
|
+
self.named_variables[name] = variable
|
120
|
+
|
121
|
+
def get_variable(self, name: str) -> cvxpy.Variable:
|
122
|
+
if name not in self.named_variables:
|
123
|
+
raise KeyError(f"Cannot find a variable named {name}")
|
124
|
+
return self.named_variables[name]
|
125
|
+
|
126
|
+
def primal_value(self, name: str) -> float | None:
|
127
|
+
"""
|
128
|
+
The primal variables of the Dual PEP are the dual variables associated
|
129
|
+
with the constraints of the Primal PEP.
|
130
|
+
|
131
|
+
Given the name of a :class:`Constraint` object that represents a
|
132
|
+
constraint in the Primal PEP, return the value of the corresponding
|
133
|
+
primal variable of the Dual PEP.
|
134
|
+
|
135
|
+
Args:
|
136
|
+
name (str): The name of the :class:`Constraint` object whose
|
137
|
+
corresponding primal variable of the Dual PEP we want to
|
138
|
+
retrieve.
|
139
|
+
|
140
|
+
Returns:
|
141
|
+
float: The value of the primal variable of the Dual PEP
|
142
|
+
corresponding to the :class:`Constraint` object associated with
|
143
|
+
the `name` argument.
|
144
|
+
"""
|
145
|
+
if name not in self.named_variables:
|
146
|
+
return None # Is this good choice?
|
147
|
+
primal_value = self.named_variables[name].value
|
148
|
+
if primal_value is None:
|
149
|
+
return None
|
150
|
+
return primal_value
|
151
|
+
|
152
|
+
|
153
|
+
class CVXPrimalSolver:
|
75
154
|
def __init__(
|
76
155
|
self,
|
77
156
|
perf_metric: sc.Scalar,
|
@@ -83,8 +162,10 @@ class CVXSolver:
|
|
83
162
|
self.dual_var_manager = DualVariableManager([])
|
84
163
|
self.context = context
|
85
164
|
|
86
|
-
def build_problem(
|
87
|
-
|
165
|
+
def build_problem(
|
166
|
+
self, resolve_parameters: dict[str, utils.NUMERICAL_TYPE] | None = None
|
167
|
+
) -> cvxpy.Problem:
|
168
|
+
em = exm.ExpressionManager(self.context, resolve_parameters=resolve_parameters)
|
88
169
|
f_var = cvxpy.Variable(em._num_basis_scalars)
|
89
170
|
g_var = cvxpy.Variable(
|
90
171
|
(em._num_basis_points, em._num_basis_points), symmetric=True
|
@@ -121,3 +202,89 @@ class CVXSolver:
|
|
121
202
|
problem = self.build_problem()
|
122
203
|
result = problem.solve(**kwargs)
|
123
204
|
return result
|
205
|
+
|
206
|
+
|
207
|
+
class CVXDualSolver:
|
208
|
+
def __init__(
|
209
|
+
self,
|
210
|
+
perf_metric: sc.Scalar,
|
211
|
+
constraints: list[ctr.Constraint],
|
212
|
+
context: pc.PEPContext,
|
213
|
+
):
|
214
|
+
self.perf_metric = perf_metric
|
215
|
+
self.constraints = constraints
|
216
|
+
self.primal_var_manager = PrimalVariableManager([])
|
217
|
+
self.context = context
|
218
|
+
|
219
|
+
def build_problem(
|
220
|
+
self, resolve_parameters: dict[str, utils.NUMERICAL_TYPE] | None = None
|
221
|
+
) -> cvxpy.Problem:
|
222
|
+
# The primal problem is always the following form:
|
223
|
+
#
|
224
|
+
# max_{F, G}: <perf.vec, F> + Tr(G perf.Mat) + perf.const
|
225
|
+
# s.t. <constraint.vec, F> + Tr(G constraint.Mat) + constraint.const <= 0
|
226
|
+
# G >= 0
|
227
|
+
# Caveat: we use max instead of min in primal problem.
|
228
|
+
#
|
229
|
+
# Dual prob = min_{l, S} [max_{F, G} (<perf.vec, F> + Tr(G perf.Mat) - l * (constraint) + Tr(S*G))]
|
230
|
+
# Note the sign above.
|
231
|
+
# Becaus F is unbounded and the Lagrangian w.r.t. F is linear, the coefficients of F must be 0.
|
232
|
+
# Similarly, the Lagrangian w.r.t. G is linear and G is PSD, the coefficients of G must << 0.
|
233
|
+
dual_constraints = []
|
234
|
+
lambd_constraints = []
|
235
|
+
em = exm.ExpressionManager(self.context, resolve_parameters=resolve_parameters)
|
236
|
+
# The one corresponding to G >= 0
|
237
|
+
S = cvxpy.Variable((em._num_basis_points, em._num_basis_points), PSD=True)
|
238
|
+
evaled_perf_metric_scalar = em.eval_scalar(self.perf_metric)
|
239
|
+
|
240
|
+
extra_constraints = []
|
241
|
+
obj = evaled_perf_metric_scalar.constant
|
242
|
+
F_coef_vec = 0
|
243
|
+
G_coef_mat = 0
|
244
|
+
# l * (Tr(G*eval_s.Matrix) + <F, eval_s.vec> + eval_s.const)
|
245
|
+
for c in self.constraints:
|
246
|
+
lambd = cvxpy.Variable()
|
247
|
+
self.primal_var_manager.add_variable(c.name, lambd)
|
248
|
+
evaled_scalar = em.eval_scalar(c.scalar)
|
249
|
+
if c.comparator == utils.Comparator.GT:
|
250
|
+
sign = 1
|
251
|
+
lambd_constraints.append(lambd >= 0)
|
252
|
+
elif c.comparator == utils.Comparator.LT:
|
253
|
+
sign = -1 # We flip f(x) <=0 into -f(x) >= 0
|
254
|
+
lambd_constraints.append(lambd >= 0)
|
255
|
+
elif c.comparator == utils.Comparator.EQ:
|
256
|
+
sign = 1
|
257
|
+
else:
|
258
|
+
raise RuntimeError(
|
259
|
+
f"Unknown comparator in constraint {c.anme}: get {c.comparator=}"
|
260
|
+
)
|
261
|
+
G_coef_mat += sign * lambd * evaled_scalar.matrix
|
262
|
+
F_coef_vec += sign * lambd * evaled_scalar.vector
|
263
|
+
obj += sign * lambd * evaled_scalar.constant
|
264
|
+
|
265
|
+
# We can add extra constraints to directly manipulate the primal variable in dual PEP.
|
266
|
+
for comparator, val in c.associated_dual_var_constraints:
|
267
|
+
if c.comparator == utils.Comparator.GT:
|
268
|
+
extra_constraints.append(lambd >= val)
|
269
|
+
elif c.comparator == utils.Comparator.LT:
|
270
|
+
extra_constraints.append(lambd <= val)
|
271
|
+
elif c.comparator == utils.Comparator.EQ:
|
272
|
+
extra_constraints.append(lambd == val)
|
273
|
+
else:
|
274
|
+
raise RuntimeError(
|
275
|
+
f"Unknown comparator in constraint {c.anme} associated dual one:"
|
276
|
+
f"get {c.comparator=}"
|
277
|
+
)
|
278
|
+
|
279
|
+
dual_constraints.append(F_coef_vec + evaled_perf_metric_scalar.vector == 0)
|
280
|
+
dual_constraints.append(S + evaled_perf_metric_scalar.matrix + G_coef_mat == 0)
|
281
|
+
|
282
|
+
return cvxpy.Problem(
|
283
|
+
cvxpy.Minimize(obj),
|
284
|
+
dual_constraints + lambd_constraints + extra_constraints,
|
285
|
+
)
|
286
|
+
|
287
|
+
def solve(self, **kwargs):
|
288
|
+
problem = self.build_problem()
|
289
|
+
result = problem.solve(**kwargs)
|
290
|
+
return result
|
pepflow/solver_test.py
CHANGED
@@ -32,7 +32,7 @@ def test_cvx_solver_case1():
|
|
32
32
|
s2 = -(1 + p1 * p1)
|
33
33
|
constraints = [(p1 * p1).gt(1, name="x^2 >= 1"), s1.gt(0, name="s1 > 0")]
|
34
34
|
|
35
|
-
solver = ps.
|
35
|
+
solver = ps.CVXPrimalSolver(
|
36
36
|
perf_metric=s2,
|
37
37
|
constraints=constraints,
|
38
38
|
context=pep_builder.get_context("test"),
|
@@ -55,7 +55,7 @@ def test_cvx_solver_case2():
|
|
55
55
|
s2 = -p1 * p1 + 2
|
56
56
|
constraints = [(p1 * p1).lt(1, name="x^2 <= 1"), s1.gt(0, name="s1 > 0")]
|
57
57
|
|
58
|
-
solver = ps.
|
58
|
+
solver = ps.CVXPrimalSolver(
|
59
59
|
perf_metric=s2,
|
60
60
|
constraints=constraints,
|
61
61
|
context=pep_builder.get_context("test"),
|
@@ -68,3 +68,51 @@ def test_cvx_solver_case2():
|
|
68
68
|
|
69
69
|
assert np.isclose(solver.dual_var_manager.dual_value("x^2 <= 1"), 0)
|
70
70
|
assert solver.dual_var_manager.dual_value("s1 > 0") == 0
|
71
|
+
|
72
|
+
|
73
|
+
def test_cvx_dual_solver_case1():
|
74
|
+
pep_builder = pep.PEPBuilder()
|
75
|
+
with pep_builder.make_context("test"):
|
76
|
+
p1 = pp.Point(is_basis=True, tags=["p1"])
|
77
|
+
s1 = pp.Scalar(is_basis=True, tags=["s1"])
|
78
|
+
s2 = -(1 + p1 * p1)
|
79
|
+
constraints = [(p1 * p1).gt(1, name="x^2 >= 1"), s1.gt(0, name="s1 > 0")]
|
80
|
+
|
81
|
+
dual_solver = ps.CVXDualSolver(
|
82
|
+
perf_metric=s2,
|
83
|
+
constraints=constraints,
|
84
|
+
context=pep_builder.get_context("test"),
|
85
|
+
)
|
86
|
+
problem = dual_solver.build_problem()
|
87
|
+
result = problem.solve()
|
88
|
+
assert abs(-result - 2) < 1e-6
|
89
|
+
|
90
|
+
assert np.isclose(dual_solver.primal_var_manager.primal_value("x^2 >= 1"), 1)
|
91
|
+
assert np.isclose(dual_solver.primal_var_manager.primal_value("s1 > 0"), 0)
|
92
|
+
|
93
|
+
|
94
|
+
def test_cvx_dual_solver_case2():
|
95
|
+
pep_builder = pep.PEPBuilder()
|
96
|
+
with pep_builder.make_context("test"):
|
97
|
+
p1 = pp.Point(is_basis=True, tags=["p1"])
|
98
|
+
s1 = pp.Scalar(is_basis=True, tags=["s1"])
|
99
|
+
s2 = -p1 * p1 + 2
|
100
|
+
constraints = [(p1 * p1).lt(1, name="x^2 <= 1"), s1.gt(0, name="s1 > 0")]
|
101
|
+
|
102
|
+
dual_solver = ps.CVXDualSolver(
|
103
|
+
perf_metric=s2,
|
104
|
+
constraints=constraints,
|
105
|
+
context=pep_builder.get_context("test"),
|
106
|
+
)
|
107
|
+
|
108
|
+
# It is a simple `min_x x^2-2; s.t. x^2 <= 1` problem.
|
109
|
+
problem = dual_solver.build_problem()
|
110
|
+
result = problem.solve()
|
111
|
+
assert abs(-result + 2) < 1e-6
|
112
|
+
|
113
|
+
assert np.isclose(
|
114
|
+
dual_solver.primal_var_manager.primal_value("x^2 <= 1"), 0, atol=1e-7
|
115
|
+
)
|
116
|
+
assert np.isclose(
|
117
|
+
dual_solver.primal_var_manager.primal_value("s1 > 0"), 0, atol=1e-7
|
118
|
+
)
|
pepflow/utils.py
CHANGED
@@ -24,6 +24,7 @@ import numbers
|
|
24
24
|
from typing import TYPE_CHECKING, Any
|
25
25
|
|
26
26
|
import numpy as np
|
27
|
+
import sympy as sp
|
27
28
|
|
28
29
|
if TYPE_CHECKING:
|
29
30
|
from pepflow.function import Function
|
@@ -31,13 +32,17 @@ if TYPE_CHECKING:
|
|
31
32
|
from pepflow.scalar import Scalar
|
32
33
|
|
33
34
|
|
34
|
-
|
35
|
+
NUMERICAL_TYPE = numbers.Number | sp.Rational
|
36
|
+
|
37
|
+
|
38
|
+
def SOP(v, w, sympy_mode: bool = False) -> np.ndarray:
|
35
39
|
"""Symmetric Outer Product."""
|
36
|
-
|
40
|
+
coef = sp.S(1) / 2 if sympy_mode else 1 / 2
|
41
|
+
return coef * (np.outer(v, w) + np.outer(w, v))
|
37
42
|
|
38
43
|
|
39
|
-
def SOP_self(v):
|
40
|
-
return SOP(v, v)
|
44
|
+
def SOP_self(v, sympy_mode: bool = False) -> np.ndarray:
|
45
|
+
return SOP(v, v, sympy_mode=sympy_mode)
|
41
46
|
|
42
47
|
|
43
48
|
class Op(enum.Enum):
|
@@ -54,12 +59,39 @@ class Comparator(enum.Enum):
|
|
54
59
|
|
55
60
|
|
56
61
|
def is_numerical(val: Any) -> bool:
|
57
|
-
return isinstance(val, numbers.Number)
|
62
|
+
return isinstance(val, numbers.Number) or isinstance(val, sp.Rational)
|
63
|
+
|
64
|
+
|
65
|
+
def is_numerical_or_parameter(val: Any) -> bool:
|
66
|
+
from pepflow import parameter as param
|
67
|
+
|
68
|
+
return is_numerical(val) or isinstance(val, param.Parameter)
|
69
|
+
|
70
|
+
|
71
|
+
def numerical_str(val: Any) -> str:
|
72
|
+
from pepflow import parameter as param
|
73
|
+
|
74
|
+
if not is_numerical_or_parameter(val):
|
75
|
+
raise ValueError(
|
76
|
+
"Cannot call numerical_str for {val} since it is not numerical."
|
77
|
+
)
|
78
|
+
if isinstance(val, param.Parameter):
|
79
|
+
return str(val)
|
80
|
+
return str(val) if isinstance(val, sp.Rational) else f"{val:.4g}"
|
58
81
|
|
59
82
|
|
60
83
|
def parenthesize_tag(val: Point | Scalar | Function) -> str:
|
61
84
|
tmp_tag = val.tag
|
62
85
|
if not val.is_basis:
|
63
|
-
if
|
64
|
-
|
86
|
+
if op := getattr(val.eval_expression, "op", None):
|
87
|
+
if op in (Op.ADD, Op.SUB):
|
88
|
+
tmp_tag = f"({val.tag})"
|
65
89
|
return tmp_tag
|
90
|
+
|
91
|
+
|
92
|
+
def str_to_latex(s: str) -> str:
|
93
|
+
"""Convert string into latex style."""
|
94
|
+
s = s.replace("star", r"\star")
|
95
|
+
s = s.replace("gradient_", r"\nabla ")
|
96
|
+
s = s.replace("|", r"\|")
|
97
|
+
return rf"$\displaystyle {s}$"
|
@@ -1,8 +1,8 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: pepflow
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.5
|
4
4
|
Summary: PEPFlow: A framework for Performance Estimation Problem (PEP) Workflow
|
5
|
-
Requires-Python: >=3.
|
5
|
+
Requires-Python: >=3.10
|
6
6
|
Description-Content-Type: text/markdown
|
7
7
|
License-File: LICENSE
|
8
8
|
Requires-Dist: attrs>=25.3.0
|
@@ -37,6 +37,7 @@ uv sync; source .venv/bin/activate;
|
|
37
37
|
|
38
38
|
In windows, use `.venv\Scripts\activate` instead.
|
39
39
|
|
40
|
+
### Lint & Testing
|
40
41
|
We use `ruff` to do the format and lint and `isort` to do the import ordering.
|
41
42
|
|
42
43
|
```bash
|
@@ -45,14 +46,18 @@ ruff check .;
|
|
45
46
|
isort .;
|
46
47
|
```
|
47
48
|
|
48
|
-
### Testing
|
49
|
-
|
50
49
|
We use `pytest` framework to do the test. To run all unit tests, run the following command:
|
51
50
|
|
52
|
-
```
|
51
|
+
```bash
|
53
52
|
pytest -s -vv pepflow
|
54
53
|
```
|
55
54
|
|
55
|
+
We have a convenient script to above
|
56
|
+
```bash
|
57
|
+
scripts/check.sh [format|lint|typecheck|test]
|
58
|
+
```
|
59
|
+
See the script for the options.
|
60
|
+
|
56
61
|
### Build doc website
|
57
62
|
|
58
63
|
Install the required library (one-time) and `pandoc` in order to build ipynb.
|
@@ -62,13 +67,9 @@ pip install -r docs/requirements.txt
|
|
62
67
|
|
63
68
|
To build the website, run
|
64
69
|
```bash
|
65
|
-
|
66
|
-
```
|
67
|
-
Make sure it succeeded, then examine it locally through
|
68
|
-
```bash
|
69
|
-
cd build/html; python -m http.server
|
70
|
+
scripts/build_doc.sh [--serve-only]
|
70
71
|
```
|
71
|
-
|
72
|
+
The argument `--serve-only` is optional for hosting the website locally.
|
72
73
|
|
73
74
|
|
74
75
|
|
@@ -0,0 +1,28 @@
|
|
1
|
+
pepflow/__init__.py,sha256=uF-c0NyR8z9sASDj8nvd3Vz1a4gFm7ZcdH-SyR3h0bs,2250
|
2
|
+
pepflow/constants.py,sha256=t29CDRE8kw773zgKS0ZZCYGegwagaDDdLfpSaeDpK14,871
|
3
|
+
pepflow/constraint.py,sha256=aFcdOprdBc5peT7oL5IXlfnvnGw1qadPLtKsy1Cbrac,3555
|
4
|
+
pepflow/constraint_test.py,sha256=6MF__r67NooqOVXHtkeOVcg_ebycMF_xI9OpFDFiV4c,2676
|
5
|
+
pepflow/e2e_test.py,sha256=jo4pWoXq9XJFmdfvJeSUdCIlmdmk_Qp2QCjOLelPqMY,3701
|
6
|
+
pepflow/expression_manager.py,sha256=AD2AHQGvmjRltsKgXiG9QV5oUZFpQsTgd-dky5uNRi0,17875
|
7
|
+
pepflow/expression_manager_test.py,sha256=ZzwZGc-rP5iey8aXMakeq_0PbMW6Tf7DmMxzSeJe2Bg,5493
|
8
|
+
pepflow/function.py,sha256=19TocYEjO5Wn24IpJYmzP_UTwyR_Pg3uzE_-zluC3CM,22867
|
9
|
+
pepflow/function_test.py,sha256=RBBm_Z6SKD3Vd03eUAO4XPONyXXueT8w1eiRLeA4IuI,8263
|
10
|
+
pepflow/interactive_constraint.py,sha256=mB3AQt21kIdRR0yqtvUksoELSLSoTDkMeu07ThKPerE,12757
|
11
|
+
pepflow/parameter.py,sha256=yknpFWzj91gfDKjRVgRDMG57mKeKE1Qqcnm4i2tZzok,6246
|
12
|
+
pepflow/parameter_test.py,sha256=fLmKvoLKu_-GULDXcpXmoAZA17mx0m9Zm3twfXQUin0,4199
|
13
|
+
pepflow/pep.py,sha256=hCB2jXjLCU_5jgykZD6jwch4fDvdvy-aX4jmQpF6jWs,16222
|
14
|
+
pepflow/pep_context.py,sha256=Y6JD28TAf39SB8G_FuqQnd4HVgit1viGIOTs4lzdzgg,9184
|
15
|
+
pepflow/pep_context_test.py,sha256=B12M4eni0MVL_30v6yAf4ognWc1YxNTaR50_F01iGnI,4052
|
16
|
+
pepflow/pep_test.py,sha256=-diI87sk10417oBnPRgWxY6XhiKOPoK7m5-MTkmlTcw,2788
|
17
|
+
pepflow/point.py,sha256=pv0yr4oQsfBlzKLPMWPeR6WfdF4W-l_AaR5GFg_Me7o,12570
|
18
|
+
pepflow/point_test.py,sha256=Rm-uOvB9GjIwH3XGnWr5UfTRqzlZRb8u-esV5b-bgtY,5667
|
19
|
+
pepflow/scalar.py,sha256=oZjsfXZEhofxszk21pmcvNQOh8_N_6G_PfH3STbugH4,18315
|
20
|
+
pepflow/scalar_test.py,sha256=fYtKfe-nO4GhAIIrZrW0Lx_fbFHqIxsKbPPA-G5udnE,7082
|
21
|
+
pepflow/solver.py,sha256=ZThfiaSDru-gHxn21PC8T71ePzTykAhSRCteOaOBbcQ,11381
|
22
|
+
pepflow/solver_test.py,sha256=NuH6yF-NTItkv3x0U40HFJ7xbSNi407qg4QGlVmXqHU,4063
|
23
|
+
pepflow/utils.py,sha256=-Uu0TlJyqpGNT4DmdLtvXWNFPHn06zKHF7Jr1NHz7LQ,2743
|
24
|
+
pepflow-0.1.5.dist-info/licenses/LICENSE,sha256=na5oVXAps-5f1hLGG4SYnwFdavQeXgYUeN-E3MxOA_s,11361
|
25
|
+
pepflow-0.1.5.dist-info/METADATA,sha256=ULyUflh7uT2lqFhobLqMqWxU4uPwfKoBWPa5u7Ojmvc,1867
|
26
|
+
pepflow-0.1.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
27
|
+
pepflow-0.1.5.dist-info/top_level.txt,sha256=0YEPCZQQa6yIAIwMumzDg4pj7AME8aXu2sXkuq8xM6M,8
|
28
|
+
pepflow-0.1.5.dist-info/RECORD,,
|
pepflow-0.1.4a1.dist-info/RECORD
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
pepflow/__init__.py,sha256=xvtX_jzS-wEqjHicdWWRp-lL71VbGv3vhuvfKncRFsQ,1985
|
2
|
-
pepflow/constants.py,sha256=t29CDRE8kw773zgKS0ZZCYGegwagaDDdLfpSaeDpK14,871
|
3
|
-
pepflow/constraint.py,sha256=n-01dcQplvsXB7V4fceJBImbwSr-Wa9k9tE7ZcVmi3o,1153
|
4
|
-
pepflow/constraint_test.py,sha256=6MF__r67NooqOVXHtkeOVcg_ebycMF_xI9OpFDFiV4c,2676
|
5
|
-
pepflow/e2e_test.py,sha256=7FDFUe-TfxiJ5LN57gxO1OzdqnGHgRJe_Eoega6TpMI,2193
|
6
|
-
pepflow/expression_manager.py,sha256=94G1PyD-W1uS72AgyeCMwDEcLWwuhdIimuZ1nXjMNJA,7680
|
7
|
-
pepflow/expression_manager_test.py,sha256=1NmFZUoxZ3Lf0qP10uYQplWMX4-OYSAnvhiVLBXvt3U,4164
|
8
|
-
pepflow/function.py,sha256=bhL8cVX_KctJC9JyT_fgxXM-9HjnNJ0b6SlTBkwdzOw,16305
|
9
|
-
pepflow/function_test.py,sha256=RBBm_Z6SKD3Vd03eUAO4XPONyXXueT8w1eiRLeA4IuI,8263
|
10
|
-
pepflow/interactive_constraint.py,sha256=mB3AQt21kIdRR0yqtvUksoELSLSoTDkMeu07ThKPerE,12757
|
11
|
-
pepflow/pep.py,sha256=cEFhnY-81OZTJ-1rwVReIBehH4S8qF5TOHkYiy02trk,6380
|
12
|
-
pepflow/pep_context.py,sha256=p1cN4THwH8WKQfkzp8nw8PiQMRIzhCtSd3lkZqsGBPg,4804
|
13
|
-
pepflow/pep_context_test.py,sha256=iNbsr1PRlVBBoKpgmochmdOjpHCNDlY86NPTwSqJrt4,3392
|
14
|
-
pepflow/pep_test.py,sha256=-diI87sk10417oBnPRgWxY6XhiKOPoK7m5-MTkmlTcw,2788
|
15
|
-
pepflow/point.py,sha256=vSKCuivJL3zyUCnV48rfM5XpAGsVbdQ8YWdO3fKrViI,8514
|
16
|
-
pepflow/point_test.py,sha256=vuG8GbEU9vLf-btyax0XWEgiQm5hZMxscYk8HdyKjSE,5270
|
17
|
-
pepflow/scalar.py,sha256=8E-D5pgZCDpyEX13VwrFARo87v-HWAUs4gAD_-Ty_g8,9653
|
18
|
-
pepflow/scalar_test.py,sha256=mzLJOtNdZd54wJir5uiaEoMtcwEWiYh9C-oRWxbeb_A,6472
|
19
|
-
pepflow/solver.py,sha256=WzeN_IWNBs9IpE212jenhYMWFuuwH890h0vaFmJRM6I,4312
|
20
|
-
pepflow/solver_test.py,sha256=-aCEe-oQ26xJUWR64b-CIIfFOK_pNJnMlOly2bagk68,2457
|
21
|
-
pepflow/utils.py,sha256=Xd-DwtUoUSMw_i6xjYsOxsHmn8l3ZbYCyptXEBfoyZk,1718
|
22
|
-
pepflow-0.1.4a1.dist-info/licenses/LICENSE,sha256=na5oVXAps-5f1hLGG4SYnwFdavQeXgYUeN-E3MxOA_s,11361
|
23
|
-
pepflow-0.1.4a1.dist-info/METADATA,sha256=NR2LXX5TJWYrEmHVTIIiUrre_n896lnnH0ffbx74Cyc,1752
|
24
|
-
pepflow-0.1.4a1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
25
|
-
pepflow-0.1.4a1.dist-info/top_level.txt,sha256=0YEPCZQQa6yIAIwMumzDg4pj7AME8aXu2sXkuq8xM6M,8
|
26
|
-
pepflow-0.1.4a1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|