pyoframe 0.0.4__py3-none-any.whl → 0.0.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.
- pyoframe/__init__.py +12 -3
- pyoframe/_arithmetic.py +3 -6
- pyoframe/constants.py +20 -14
- pyoframe/{constraints.py → core.py} +504 -74
- pyoframe/io.py +66 -30
- pyoframe/io_mappers.py +66 -34
- pyoframe/model.py +65 -41
- pyoframe/model_element.py +128 -18
- pyoframe/monkey_patch.py +2 -2
- pyoframe/objective.py +16 -13
- pyoframe/solvers.py +300 -109
- pyoframe/user_defined.py +60 -0
- pyoframe/util.py +56 -55
- {pyoframe-0.0.4.dist-info → pyoframe-0.0.6.dist-info}/METADATA +9 -2
- pyoframe-0.0.6.dist-info/RECORD +18 -0
- pyoframe/variables.py +0 -193
- pyoframe-0.0.4.dist-info/RECORD +0 -18
- {pyoframe-0.0.4.dist-info → pyoframe-0.0.6.dist-info}/LICENSE +0 -0
- {pyoframe-0.0.4.dist-info → pyoframe-0.0.6.dist-info}/WHEEL +0 -0
- {pyoframe-0.0.4.dist-info → pyoframe-0.0.6.dist-info}/top_level.txt +0 -0
pyoframe/__init__.py
CHANGED
|
@@ -4,12 +4,21 @@ Also applies the monkey patch to the DataFrame libraries.
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
from pyoframe.monkey_patch import patch_dataframe_libraries
|
|
7
|
-
from pyoframe.
|
|
7
|
+
from pyoframe.core import sum, sum_by, Set, Constraint, Expression, Variable
|
|
8
8
|
from pyoframe.constants import Config
|
|
9
|
-
from pyoframe.variables import Variable
|
|
10
9
|
from pyoframe.model import Model
|
|
11
10
|
from pyoframe.constants import VType
|
|
12
11
|
|
|
13
12
|
patch_dataframe_libraries()
|
|
14
13
|
|
|
15
|
-
__all__ = [
|
|
14
|
+
__all__ = [
|
|
15
|
+
"sum",
|
|
16
|
+
"sum_by",
|
|
17
|
+
"Variable",
|
|
18
|
+
"Model",
|
|
19
|
+
"Set",
|
|
20
|
+
"VType",
|
|
21
|
+
"Config",
|
|
22
|
+
"Constraint",
|
|
23
|
+
"Expression",
|
|
24
|
+
]
|
pyoframe/_arithmetic.py
CHANGED
|
@@ -7,14 +7,11 @@ from pyoframe.constants import (
|
|
|
7
7
|
VAR_KEY,
|
|
8
8
|
UnmatchedStrategy,
|
|
9
9
|
Config,
|
|
10
|
+
PyoframeError,
|
|
10
11
|
)
|
|
11
12
|
|
|
12
13
|
if TYPE_CHECKING: # pragma: no cover
|
|
13
|
-
from pyoframe.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class PyoframeError(Exception):
|
|
17
|
-
pass
|
|
14
|
+
from pyoframe.core import Expression
|
|
18
15
|
|
|
19
16
|
|
|
20
17
|
def _add_expressions(*expressions: "Expression") -> "Expression":
|
|
@@ -109,7 +106,7 @@ def _add_expressions_core(*expressions: "Expression") -> "Expression":
|
|
|
109
106
|
|
|
110
107
|
strat = (left.unmatched_strategy, right.unmatched_strategy)
|
|
111
108
|
|
|
112
|
-
propogate_strat = propogatation_strategies[strat]
|
|
109
|
+
propogate_strat = propogatation_strategies[strat] # type: ignore
|
|
113
110
|
|
|
114
111
|
if strat == (UnmatchedStrategy.DROP, UnmatchedStrategy.DROP):
|
|
115
112
|
left_data = left.data.join(get_indices(right), how="inner", on=dims)
|
pyoframe/constants.py
CHANGED
|
@@ -9,7 +9,7 @@ MIT License
|
|
|
9
9
|
from dataclasses import dataclass
|
|
10
10
|
from enum import Enum
|
|
11
11
|
import typing
|
|
12
|
-
from typing import
|
|
12
|
+
from typing import Literal, Optional, Union
|
|
13
13
|
import polars as pl
|
|
14
14
|
|
|
15
15
|
|
|
@@ -18,7 +18,8 @@ VAR_KEY = "__variable_id"
|
|
|
18
18
|
CONSTRAINT_KEY = "__constraint_id"
|
|
19
19
|
SOLUTION_KEY = "solution"
|
|
20
20
|
DUAL_KEY = "dual"
|
|
21
|
-
|
|
21
|
+
RC_COL = "RC"
|
|
22
|
+
SLACK_COL = "slack"
|
|
22
23
|
|
|
23
24
|
CONST_TERM = 0
|
|
24
25
|
|
|
@@ -28,7 +29,8 @@ RESERVED_COL_KEYS = (
|
|
|
28
29
|
CONSTRAINT_KEY,
|
|
29
30
|
SOLUTION_KEY,
|
|
30
31
|
DUAL_KEY,
|
|
31
|
-
|
|
32
|
+
RC_COL,
|
|
33
|
+
SLACK_COL,
|
|
32
34
|
)
|
|
33
35
|
|
|
34
36
|
|
|
@@ -48,6 +50,9 @@ class Config(metaclass=_ConfigMeta):
|
|
|
48
50
|
disable_unmatched_checks: bool = False
|
|
49
51
|
print_float_precision: Optional[int] = 5
|
|
50
52
|
print_uses_variable_names: bool = True
|
|
53
|
+
# Number of elements to show when printing a set to the console (additional elements are replaced with ...)
|
|
54
|
+
print_max_set_elements: int = 50
|
|
55
|
+
enable_is_duplicated_expression_safety_check: bool = False
|
|
51
56
|
|
|
52
57
|
@classmethod
|
|
53
58
|
def reset_defaults(cls):
|
|
@@ -65,8 +70,8 @@ class ConstraintSense(Enum):
|
|
|
65
70
|
|
|
66
71
|
|
|
67
72
|
class ObjSense(Enum):
|
|
68
|
-
MIN = "
|
|
69
|
-
MAX = "
|
|
73
|
+
MIN = "min"
|
|
74
|
+
MAX = "max"
|
|
70
75
|
|
|
71
76
|
|
|
72
77
|
class VType(Enum):
|
|
@@ -83,7 +88,7 @@ class UnmatchedStrategy(Enum):
|
|
|
83
88
|
|
|
84
89
|
# This is a hack to get the Literal type for VType
|
|
85
90
|
# See: https://stackoverflow.com/questions/67292470/type-hinting-enum-member-value-in-python
|
|
86
|
-
ObjSenseValue = Literal["
|
|
91
|
+
ObjSenseValue = Literal["min", "max"]
|
|
87
92
|
VTypeValue = Literal["continuous", "binary", "integer"]
|
|
88
93
|
for enum, type in [(ObjSense, ObjSenseValue), (VType, VTypeValue)]:
|
|
89
94
|
assert set(typing.get_args(type)) == {vtype.value for vtype in enum}
|
|
@@ -127,8 +132,11 @@ class SolverStatus(Enum):
|
|
|
127
132
|
def from_termination_condition(
|
|
128
133
|
cls, termination_condition: "TerminationCondition"
|
|
129
134
|
) -> "SolverStatus":
|
|
130
|
-
for
|
|
131
|
-
|
|
135
|
+
for (
|
|
136
|
+
status,
|
|
137
|
+
termination_conditions,
|
|
138
|
+
) in STATUS_TO_TERMINATION_CONDITION_MAP.items():
|
|
139
|
+
if termination_condition in termination_conditions:
|
|
132
140
|
return status
|
|
133
141
|
return cls("unknown")
|
|
134
142
|
|
|
@@ -248,13 +256,8 @@ class Result:
|
|
|
248
256
|
|
|
249
257
|
status: Status
|
|
250
258
|
solution: Optional[Solution] = None
|
|
251
|
-
solver_model: Optional[Any] = None
|
|
252
259
|
|
|
253
260
|
def __repr__(self) -> str:
|
|
254
|
-
solver_model_string = (
|
|
255
|
-
"not available" if self.solver_model is None else "available"
|
|
256
|
-
)
|
|
257
|
-
|
|
258
261
|
res = (
|
|
259
262
|
f"Status: {self.status.status.value}\n"
|
|
260
263
|
f"Termination condition: {self.status.termination_condition.value}\n"
|
|
@@ -264,7 +267,6 @@ class Result:
|
|
|
264
267
|
f"Solution: {len(self.solution.primal)} primals, {len(self.solution.dual) if self.solution.dual is not None else 0} duals\n"
|
|
265
268
|
f"Objective: {self.solution.objective:.2e}\n"
|
|
266
269
|
)
|
|
267
|
-
res += f"Solver model: {solver_model_string}\n"
|
|
268
270
|
|
|
269
271
|
return res
|
|
270
272
|
|
|
@@ -278,3 +280,7 @@ class Result:
|
|
|
278
280
|
print(f" Optimization successful: \n{self}\n")
|
|
279
281
|
else:
|
|
280
282
|
print(f"Optimization failed: \n{self}\n")
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
class PyoframeError(Exception):
|
|
286
|
+
pass
|