pepflow 0.1.3a1__py3-none-any.whl → 0.1.4a1__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/scalar_test.py ADDED
@@ -0,0 +1,207 @@
1
+ # Copyright: 2025 The PEPFlow Developers
2
+ #
3
+ # Licensed to the Apache Software Foundation (ASF) under one
4
+ # or more contributor license agreements. See the NOTICE file
5
+ # distributed with this work for additional information
6
+ # regarding copyright ownership. The ASF licenses this file
7
+ # to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance
9
+ # with the License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing,
14
+ # software distributed under the License is distributed on an
15
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ # KIND, either express or implied. See the License for the
17
+ # specific language governing permissions and limitations
18
+ # under the License.
19
+
20
+ from typing import Iterator
21
+
22
+ import numpy as np
23
+ import pytest
24
+
25
+ from pepflow import expression_manager as exm
26
+ from pepflow import pep as pep
27
+ from pepflow import pep_context as pc
28
+ from pepflow import point, scalar
29
+
30
+
31
+ @pytest.fixture
32
+ def pep_context() -> Iterator[pc.PEPContext]:
33
+ """Prepare the pep context and reset the context to None at the end."""
34
+ ctx = pc.PEPContext("test").set_as_current()
35
+ yield ctx
36
+ pc.set_current_context(None)
37
+
38
+
39
+ def test_scalar_add_tag(pep_context: pc.PEPContext):
40
+ s1 = scalar.Scalar(is_basis=True, eval_expression=None, tags=["s1"])
41
+ s2 = scalar.Scalar(is_basis=True, eval_expression=None, tags=["s2"])
42
+
43
+ s_add = s1 + s2
44
+ assert s_add.tag == "s1+s2"
45
+
46
+ s_add = s1 + 0.1
47
+ assert s_add.tag == "s1+0.1"
48
+
49
+ s_radd = 0.1 + s1
50
+ assert s_radd.tag == "0.1+s1"
51
+
52
+ s_sub = s1 - s2
53
+ assert s_sub.tag == "s1-s2"
54
+
55
+ s_sub = s1 - (s2 + s1)
56
+ assert s_sub.tag == "s1-(s2+s1)"
57
+
58
+ s_sub = s1 - (s2 - s1)
59
+ assert s_sub.tag == "s1-(s2-s1)"
60
+
61
+ s_sub = s1 - 0.1
62
+ assert s_sub.tag == "s1-0.1"
63
+
64
+ s_rsub = 0.1 - s1
65
+ assert s_rsub.tag == "0.1-s1"
66
+
67
+
68
+ def test_scalar_mul_tag(pep_context: pc.PEPContext):
69
+ s = scalar.Scalar(is_basis=True, eval_expression=None, tags=["s"])
70
+
71
+ s_mul = s * 0.1
72
+ assert s_mul.tag == "s*0.1"
73
+
74
+ s_rmul = 0.1 * s
75
+ assert s_rmul.tag == "0.1*s"
76
+
77
+ s_neg = -s
78
+ assert s_neg.tag == "-s"
79
+
80
+ s_truediv = s / 0.1
81
+ assert s_truediv.tag == "1/0.1*s"
82
+
83
+
84
+ def test_scalar_add_and_mul_tag(pep_context: pc.PEPContext):
85
+ s1 = scalar.Scalar(is_basis=True, eval_expression=None, tags=["s1"])
86
+ s2 = scalar.Scalar(is_basis=True, eval_expression=None, tags=["s2"])
87
+
88
+ s_add_mul = (s1 + s2) * 0.1
89
+ assert s_add_mul.tag == "(s1+s2)*0.1"
90
+
91
+ s_add_mul = s1 + s2 * 0.1
92
+ assert s_add_mul.tag == "s1+s2*0.1"
93
+
94
+ s_neg_add = -(s1 + s2)
95
+ assert s_neg_add.tag == "-(s1+s2)"
96
+
97
+ s_rmul_add = 0.1 * (s1 + s2)
98
+ assert s_rmul_add.tag == "0.1*(s1+s2)"
99
+
100
+
101
+ def test_scalar_hash_different(pep_context: pc.PEPContext):
102
+ s1 = scalar.Scalar(is_basis=True, eval_expression=None)
103
+ s2 = scalar.Scalar(is_basis=True, eval_expression=None)
104
+ assert s1.uid != s2.uid
105
+
106
+
107
+ def test_scalar_tag(pep_context: pc.PEPContext):
108
+ s1 = scalar.Scalar(is_basis=True, eval_expression=None)
109
+ s1.add_tag(tag="my_tag")
110
+ assert s1.tags == ["my_tag"]
111
+ assert s1.tag == "my_tag"
112
+
113
+
114
+ def test_scalar_repr(pep_context: pc.PEPContext):
115
+ s1 = scalar.Scalar(is_basis=True, tags=["s1"])
116
+ print(s1) # it should be fine without tag
117
+ s1.add_tag("my_tag")
118
+ assert str(s1) == "my_tag"
119
+
120
+
121
+ def test_scalar_in_a_list(pep_context: pc.PEPContext):
122
+ s1 = scalar.Scalar(is_basis=True, eval_expression=None)
123
+ s2 = scalar.Scalar(is_basis=True, eval_expression=None)
124
+ s3 = scalar.Scalar(is_basis=True, eval_expression=None)
125
+ assert s1 in [s1, s2]
126
+ assert s3 not in [s1, s2]
127
+
128
+
129
+ def test_expression_manager_on_basis_scalar(pep_context: pc.PEPContext):
130
+ s1 = scalar.Scalar(is_basis=True, eval_expression=None, tags=["s1"])
131
+ s2 = scalar.Scalar(is_basis=True, eval_expression=None, tags=["s2"])
132
+ pm = exm.ExpressionManager(pep_context)
133
+
134
+ np.testing.assert_allclose(pm.eval_scalar(s1).vector, np.array([1, 0]))
135
+ np.testing.assert_allclose(pm.eval_scalar(s2).vector, np.array([0, 1]))
136
+
137
+ s3 = scalar.Scalar(is_basis=True, eval_expression=None, tags=["s3"]) # noqa: F841
138
+ pm = exm.ExpressionManager(pep_context)
139
+
140
+ np.testing.assert_allclose(pm.eval_scalar(s1).vector, np.array([1, 0, 0]))
141
+ np.testing.assert_allclose(pm.eval_scalar(s2).vector, np.array([0, 1, 0]))
142
+
143
+
144
+ def test_expression_manager_eval_scalar(pep_context: pc.PEPContext):
145
+ s1 = scalar.Scalar(is_basis=True, tags=["s1"])
146
+ s2 = scalar.Scalar(is_basis=True, tags=["s2"])
147
+ s3 = 2 * s1 + s2 / 4 + 5
148
+ s4 = s3 + s1
149
+ s5 = s4 + 5
150
+
151
+ p1 = point.Point(is_basis=True, tags=["p1"])
152
+ p2 = point.Point(is_basis=True, tags=["p2"])
153
+ s6 = p1 * p2
154
+
155
+ p3 = point.Point(is_basis=True, tags=["p3"])
156
+ p4 = point.Point(is_basis=True, tags=["p4"])
157
+ s7 = 5 * p3 * p4
158
+
159
+ s8 = s6 + s7
160
+
161
+ pm = exm.ExpressionManager(pep_context)
162
+
163
+ np.testing.assert_allclose(pm.eval_scalar(s3).vector, np.array([2, 0.25]))
164
+ np.testing.assert_allclose(pm.eval_scalar(s3).constant, 5)
165
+ np.testing.assert_allclose(pm.eval_scalar(s4).vector, np.array([3, 0.25]))
166
+ np.testing.assert_allclose(pm.eval_scalar(s5).vector, np.array([3, 0.25]))
167
+ np.testing.assert_allclose(pm.eval_scalar(s5).constant, 10)
168
+
169
+ np.testing.assert_allclose(pm.eval_point(p1).vector, np.array([1, 0, 0, 0]))
170
+ np.testing.assert_allclose(pm.eval_point(p2).vector, np.array([0, 1, 0, 0]))
171
+ np.testing.assert_allclose(pm.eval_point(p3).vector, np.array([0, 0, 1, 0]))
172
+ np.testing.assert_allclose(pm.eval_point(p4).vector, np.array([0, 0, 0, 1]))
173
+
174
+ np.testing.assert_allclose(
175
+ pm.eval_scalar(s6).matrix,
176
+ np.array(
177
+ [
178
+ [0.0, 0.5, 0.0, 0.0],
179
+ [0.5, 0.0, 0.0, 0.0],
180
+ [0.0, 0.0, 0.0, 0.0],
181
+ [0.0, 0.0, 0.0, 0.0],
182
+ ]
183
+ ),
184
+ )
185
+ np.testing.assert_allclose(
186
+ pm.eval_scalar(s7).matrix,
187
+ np.array(
188
+ [
189
+ [0.0, 0.0, 0.0, 0.0],
190
+ [0.0, 0.0, 0.0, 0.0],
191
+ [0.0, 0.0, 0.0, 2.5],
192
+ [0.0, 0.0, 2.5, 0.0],
193
+ ]
194
+ ),
195
+ )
196
+
197
+ np.testing.assert_allclose(
198
+ pm.eval_scalar(s8).matrix,
199
+ np.array(
200
+ [
201
+ [0.0, 0.5, 0.0, 0.0],
202
+ [0.5, 0.0, 0.0, 0.0],
203
+ [0.0, 0.0, 0.0, 2.5],
204
+ [0.0, 0.0, 2.5, 0.0],
205
+ ]
206
+ ),
207
+ )
pepflow/solver_test.py CHANGED
@@ -27,8 +27,8 @@ from pepflow import solver as ps
27
27
  def test_cvx_solver_case1():
28
28
  pep_builder = pep.PEPBuilder()
29
29
  with pep_builder.make_context("test"):
30
- p1 = pp.Point(is_basis=True)
31
- s1 = pp.Scalar(is_basis=True)
30
+ p1 = pp.Point(is_basis=True, tags=["p1"])
31
+ s1 = pp.Scalar(is_basis=True, tags=["s1"])
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
 
@@ -50,9 +50,9 @@ def test_cvx_solver_case1():
50
50
  def test_cvx_solver_case2():
51
51
  pep_builder = pep.PEPBuilder()
52
52
  with pep_builder.make_context("test"):
53
- p1 = pp.Point(is_basis=True)
54
- s1 = pp.Scalar(is_basis=True)
55
- s2 = -(p1 - 1) * (p1 - 2)
53
+ p1 = pp.Point(is_basis=True, tags=["p1"])
54
+ s1 = pp.Scalar(is_basis=True, tags=["s1"])
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
58
  solver = ps.CVXSolver(
@@ -61,10 +61,10 @@ def test_cvx_solver_case2():
61
61
  context=pep_builder.get_context("test"),
62
62
  )
63
63
 
64
- # It is a simple `min_x (x-1)(x-2); s.t. x^2 <= 1` problem.
64
+ # It is a simple `min_x x^2-2; s.t. x^2 <= 1` problem.
65
65
  problem = solver.build_problem()
66
66
  result = problem.solve()
67
- assert abs(-result) < 1e-6
67
+ assert abs(-result + 2) < 1e-6
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
pepflow/utils.py CHANGED
@@ -21,10 +21,15 @@ from __future__ import annotations
21
21
 
22
22
  import enum
23
23
  import numbers
24
- from typing import Any
24
+ from typing import TYPE_CHECKING, Any
25
25
 
26
26
  import numpy as np
27
27
 
28
+ if TYPE_CHECKING:
29
+ from pepflow.function import Function
30
+ from pepflow.point import Point
31
+ from pepflow.scalar import Scalar
32
+
28
33
 
29
34
  def SOP(v, w):
30
35
  """Symmetric Outer Product."""
@@ -50,3 +55,11 @@ class Comparator(enum.Enum):
50
55
 
51
56
  def is_numerical(val: Any) -> bool:
52
57
  return isinstance(val, numbers.Number)
58
+
59
+
60
+ def parenthesize_tag(val: Point | Scalar | Function) -> str:
61
+ tmp_tag = val.tag
62
+ if not val.is_basis:
63
+ if val.eval_expression.op == Op.ADD or val.eval_expression.op == Op.SUB:
64
+ tmp_tag = f"({val.tag})"
65
+ return tmp_tag
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pepflow
3
- Version: 0.1.3a1
3
+ Version: 0.1.4a1
4
4
  Summary: PEPFlow: A framework for Performance Estimation Problem (PEP) Workflow
5
5
  Requires-Python: >=3.9
6
6
  Description-Content-Type: text/markdown
@@ -53,4 +53,22 @@ We use `pytest` framework to do the test. To run all unit tests, run the followi
53
53
  pytest -s -vv pepflow
54
54
  ```
55
55
 
56
+ ### Build doc website
57
+
58
+ Install the required library (one-time) and `pandoc` in order to build ipynb.
59
+ ```bash
60
+ pip install -r docs/requirements.txt
61
+ ```
62
+
63
+ To build the website, run
64
+ ```bash
65
+ cd docs; make html
66
+ ```
67
+ Make sure it succeeded, then examine it locally through
68
+ ```bash
69
+ cd build/html; python -m http.server
70
+ ```
71
+
72
+
73
+
56
74
 
@@ -0,0 +1,26 @@
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,,
@@ -1,22 +0,0 @@
1
- pepflow/__init__.py,sha256=tLnOlZ1y_mIodRl5Fr5HMLPP5M7h_ad76s4in5OgiHE,1930
2
- pepflow/constants.py,sha256=t29CDRE8kw773zgKS0ZZCYGegwagaDDdLfpSaeDpK14,871
3
- pepflow/constraint.py,sha256=n-01dcQplvsXB7V4fceJBImbwSr-Wa9k9tE7ZcVmi3o,1153
4
- pepflow/expression_manager.py,sha256=64FbdMjcUrIqtbFZyJoxoDZ42j1bl1CeGxhJnKcGTD8,5222
5
- pepflow/function.py,sha256=dTEGK65JGTYyKzb7sD4TbbcfTNdDclkl4M_OJr5boXk,13423
6
- pepflow/function_test.py,sha256=947Jv0i7HtQ-LOi9-Hd7YsIGbX6BjnHsW3N4Q9HZE-A,4833
7
- pepflow/interactive_constraint.py,sha256=HMwAo80tJyCKwWKryxNGk1LAh-qlnQk5OeULLwKZUOQ,9826
8
- pepflow/pep.py,sha256=IKrYW6DBIekKOjGfL7rc6t1xU06VJEyL_gxj1sH_m_Q,5824
9
- pepflow/pep_context.py,sha256=RmEPMLqzP3o5wdqE-jGYV36STYb5ssqTaKd_ucw3VdA,4544
10
- pepflow/pep_context_test.py,sha256=1kFkmG56JVkmjaT9ic9byV-F9WOs9ZNQz5P1P5v5lLw,3092
11
- pepflow/pep_test.py,sha256=aWwP3CqXNJzQUhJqC5sNcsM83i_asJaZewpGNqC1G7M,2504
12
- pepflow/point.py,sha256=sVQ8txNTNvLDEAIXXgH4bBnsE66s-b5nn3Ns5Vjkp8A,7125
13
- pepflow/point_test.py,sha256=jwbvjfwHP_9oY7KLp4UE_uSEbAVlDTXAQjr8d0z-eME,12602
14
- pepflow/scalar.py,sha256=Dj-kQlXHLhQopTkleFBTanTCQImHXFjGrEJx-RJjEEA,8259
15
- pepflow/solver.py,sha256=WzeN_IWNBs9IpE212jenhYMWFuuwH890h0vaFmJRM6I,4312
16
- pepflow/solver_test.py,sha256=BC37ggL_S8NDtnq8nPwRR2xItMCYMLs-n931u7f34YE,2414
17
- pepflow/utils.py,sha256=tYcpOOWAieNay5Ly7v7dRll69RPYCUGMEuW-Bwp2z68,1321
18
- pepflow-0.1.3a1.dist-info/licenses/LICENSE,sha256=na5oVXAps-5f1hLGG4SYnwFdavQeXgYUeN-E3MxOA_s,11361
19
- pepflow-0.1.3a1.dist-info/METADATA,sha256=0XSqgCb63395I2lgwMPAwKbX17oHOQLsloc0utws0eQ,1436
20
- pepflow-0.1.3a1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
21
- pepflow-0.1.3a1.dist-info/top_level.txt,sha256=0YEPCZQQa6yIAIwMumzDg4pj7AME8aXu2sXkuq8xM6M,8
22
- pepflow-0.1.3a1.dist-info/RECORD,,