ommx-python-mip-adapter 2.0.0b2__tar.gz → 2.0.0rc1__tar.gz
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.
- {ommx_python_mip_adapter-2.0.0b2 → ommx_python_mip_adapter-2.0.0rc1}/PKG-INFO +2 -2
- {ommx_python_mip_adapter-2.0.0b2 → ommx_python_mip_adapter-2.0.0rc1}/ommx_python_mip_adapter/adapter.py +15 -19
- {ommx_python_mip_adapter-2.0.0b2 → ommx_python_mip_adapter-2.0.0rc1}/ommx_python_mip_adapter.egg-info/PKG-INFO +2 -2
- ommx_python_mip_adapter-2.0.0rc1/ommx_python_mip_adapter.egg-info/requires.txt +2 -0
- {ommx_python_mip_adapter-2.0.0b2 → ommx_python_mip_adapter-2.0.0rc1}/pyproject.toml +2 -2
- {ommx_python_mip_adapter-2.0.0b2 → ommx_python_mip_adapter-2.0.0rc1}/tests/test_model_to_instance.py +14 -14
- ommx_python_mip_adapter-2.0.0b2/ommx_python_mip_adapter.egg-info/requires.txt +0 -2
- {ommx_python_mip_adapter-2.0.0b2 → ommx_python_mip_adapter-2.0.0rc1}/README.md +0 -0
- {ommx_python_mip_adapter-2.0.0b2 → ommx_python_mip_adapter-2.0.0rc1}/ommx_python_mip_adapter/__init__.py +0 -0
- {ommx_python_mip_adapter-2.0.0b2 → ommx_python_mip_adapter-2.0.0rc1}/ommx_python_mip_adapter/exception.py +0 -0
- {ommx_python_mip_adapter-2.0.0b2 → ommx_python_mip_adapter-2.0.0rc1}/ommx_python_mip_adapter/python_mip_to_ommx.py +0 -0
- {ommx_python_mip_adapter-2.0.0b2 → ommx_python_mip_adapter-2.0.0rc1}/ommx_python_mip_adapter.egg-info/SOURCES.txt +0 -0
- {ommx_python_mip_adapter-2.0.0b2 → ommx_python_mip_adapter-2.0.0rc1}/ommx_python_mip_adapter.egg-info/dependency_links.txt +0 -0
- {ommx_python_mip_adapter-2.0.0b2 → ommx_python_mip_adapter-2.0.0rc1}/ommx_python_mip_adapter.egg-info/top_level.txt +0 -0
- {ommx_python_mip_adapter-2.0.0b2 → ommx_python_mip_adapter-2.0.0rc1}/setup.cfg +0 -0
- {ommx_python_mip_adapter-2.0.0b2 → ommx_python_mip_adapter-2.0.0rc1}/tests/test_adapter.py +0 -0
- {ommx_python_mip_adapter-2.0.0b2 → ommx_python_mip_adapter-2.0.0rc1}/tests/test_constant_constraint.py +0 -0
- {ommx_python_mip_adapter-2.0.0b2 → ommx_python_mip_adapter-2.0.0rc1}/tests/test_integration.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ommx_python_mip_adapter
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.0rc1
|
|
4
4
|
Summary: An adapter for the Python-MIP from/to OMMX.
|
|
5
5
|
Author-email: "Jij Inc." <info@j-ij.com>
|
|
6
6
|
Project-URL: Repository, https://github.com/Jij-Inc/ommx
|
|
@@ -15,7 +15,7 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
15
15
|
Classifier: License :: OSI Approved :: MIT License
|
|
16
16
|
Requires-Python: >=3.9
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
|
-
Requires-Dist: ommx<3.0.0,>=2.0.
|
|
18
|
+
Requires-Dist: ommx<3.0.0,>=2.0.0b3
|
|
19
19
|
Requires-Dist: mip<2.0.0,>=1.15.0
|
|
20
20
|
|
|
21
21
|
OMMX adapter for Python-MIP
|
|
@@ -27,14 +27,12 @@ class OMMXPythonMIPAdapter(SolverAdapter):
|
|
|
27
27
|
:param solver: Passes a specific solver to the Python-MIP model.
|
|
28
28
|
:param verbose: If True, enable Python-MIP's verbose mode
|
|
29
29
|
"""
|
|
30
|
-
if ommx_instance.
|
|
30
|
+
if ommx_instance.sense == Instance.MAXIMIZE:
|
|
31
31
|
sense = mip.MAXIMIZE
|
|
32
|
-
elif ommx_instance.
|
|
32
|
+
elif ommx_instance.sense == Instance.MINIMIZE:
|
|
33
33
|
sense = mip.MINIMIZE
|
|
34
34
|
else:
|
|
35
|
-
raise OMMXPythonMIPAdapterError(
|
|
36
|
-
f"Unsupported sense: {ommx_instance.raw.sense}"
|
|
37
|
-
)
|
|
35
|
+
raise OMMXPythonMIPAdapterError(f"Unsupported sense: {ommx_instance.sense}")
|
|
38
36
|
self.instance = ommx_instance
|
|
39
37
|
self.model = mip.Model(
|
|
40
38
|
sense=sense,
|
|
@@ -86,7 +84,7 @@ class OMMXPythonMIPAdapter(SolverAdapter):
|
|
|
86
84
|
>>> instance = Instance.from_components(
|
|
87
85
|
... decision_variables=x,
|
|
88
86
|
... objective=sum(p[i] * x[i] for i in range(6)),
|
|
89
|
-
... constraints=[sum(w[i] * x[i] for i in range(6)) <= 47],
|
|
87
|
+
... constraints=[(sum(w[i] * x[i] for i in range(6)) <= 47).set_id(0)],
|
|
90
88
|
... sense=Instance.MAXIMIZE,
|
|
91
89
|
... )
|
|
92
90
|
|
|
@@ -107,7 +105,7 @@ class OMMXPythonMIPAdapter(SolverAdapter):
|
|
|
107
105
|
|
|
108
106
|
>>> solution.objective
|
|
109
107
|
42.0
|
|
110
|
-
>>> solution.
|
|
108
|
+
>>> solution.get_constraint_value(0)
|
|
111
109
|
-1.0
|
|
112
110
|
|
|
113
111
|
Infeasible Problem
|
|
@@ -162,12 +160,12 @@ class OMMXPythonMIPAdapter(SolverAdapter):
|
|
|
162
160
|
>>> instance = Instance.from_components(
|
|
163
161
|
... decision_variables=[x, y],
|
|
164
162
|
... objective=x + y,
|
|
165
|
-
... constraints=[x + y <= 1],
|
|
163
|
+
... constraints=[(x + y <= 1).set_id(0)],
|
|
166
164
|
... sense=Instance.MAXIMIZE,
|
|
167
165
|
... )
|
|
168
166
|
|
|
169
167
|
>>> solution = OMMXPythonMIPAdapter.solve(instance)
|
|
170
|
-
>>> solution.
|
|
168
|
+
>>> solution.get_dual_variable(0)
|
|
171
169
|
1.0
|
|
172
170
|
|
|
173
171
|
"""
|
|
@@ -247,16 +245,14 @@ class OMMXPythonMIPAdapter(SolverAdapter):
|
|
|
247
245
|
if pi is not None:
|
|
248
246
|
id = int(constraint.name)
|
|
249
247
|
dual_variables[id] = pi
|
|
250
|
-
for
|
|
251
|
-
|
|
252
|
-
if id in dual_variables:
|
|
253
|
-
constraint.dual_variable = dual_variables[id]
|
|
248
|
+
for constraint_id, dual_value in dual_variables.items():
|
|
249
|
+
solution.set_dual_variable(constraint_id, dual_value)
|
|
254
250
|
|
|
255
251
|
if data.status == mip.OptimizationStatus.OPTIMAL:
|
|
256
|
-
solution.
|
|
252
|
+
solution.optimality = Solution.OPTIMAL
|
|
257
253
|
|
|
258
254
|
if self._relax:
|
|
259
|
-
solution.
|
|
255
|
+
solution.relaxation = Solution.LP_RELAXED
|
|
260
256
|
return solution
|
|
261
257
|
|
|
262
258
|
def decode_to_state(self, data: mip.Model) -> State:
|
|
@@ -299,13 +295,13 @@ class OMMXPythonMIPAdapter(SolverAdapter):
|
|
|
299
295
|
|
|
300
296
|
return State(
|
|
301
297
|
entries={
|
|
302
|
-
|
|
303
|
-
for
|
|
298
|
+
var.id: data.var_by_name(str(var.id)).x # type: ignore
|
|
299
|
+
for var in self.instance.decision_variables
|
|
304
300
|
}
|
|
305
301
|
)
|
|
306
302
|
|
|
307
303
|
def _set_decision_variables(self):
|
|
308
|
-
for
|
|
304
|
+
for var in self.instance.decision_variables:
|
|
309
305
|
if var.kind == DecisionVariable.BINARY:
|
|
310
306
|
self.model.add_var(
|
|
311
307
|
name=str(var.id),
|
|
@@ -360,7 +356,7 @@ class OMMXPythonMIPAdapter(SolverAdapter):
|
|
|
360
356
|
self.model.objective = self._as_lin_expr(self.instance.objective)
|
|
361
357
|
|
|
362
358
|
def _set_constraints(self):
|
|
363
|
-
for constraint in self.instance.
|
|
359
|
+
for constraint in self.instance.constraints:
|
|
364
360
|
lin_expr = self._as_lin_expr(constraint.function)
|
|
365
361
|
if constraint.equality == Constraint.EQUAL_TO_ZERO:
|
|
366
362
|
constr_expr = lin_expr == 0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ommx_python_mip_adapter
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.0rc1
|
|
4
4
|
Summary: An adapter for the Python-MIP from/to OMMX.
|
|
5
5
|
Author-email: "Jij Inc." <info@j-ij.com>
|
|
6
6
|
Project-URL: Repository, https://github.com/Jij-Inc/ommx
|
|
@@ -15,7 +15,7 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
15
15
|
Classifier: License :: OSI Approved :: MIT License
|
|
16
16
|
Requires-Python: >=3.9
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
|
-
Requires-Dist: ommx<3.0.0,>=2.0.
|
|
18
|
+
Requires-Dist: ommx<3.0.0,>=2.0.0b3
|
|
19
19
|
Requires-Dist: mip<2.0.0,>=1.15.0
|
|
20
20
|
|
|
21
21
|
OMMX adapter for Python-MIP
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ommx_python_mip_adapter"
|
|
7
|
-
version = "2.0.
|
|
7
|
+
version = "2.0.0rc1"
|
|
8
8
|
|
|
9
9
|
description = "An adapter for the Python-MIP from/to OMMX."
|
|
10
10
|
authors = [{ name = "Jij Inc.", email = "info@j-ij.com" }]
|
|
@@ -27,7 +27,7 @@ classifiers = [
|
|
|
27
27
|
# To support Python 3.12 and Apple silicon systems, this requires latest version of Python-MIP (will be 1.16.0?),
|
|
28
28
|
# which does not release yet. https://github.com/coin-or/python-mip/issues/384
|
|
29
29
|
# This project uses dev-dependency to use the latest version of Python-MIP not to include pre-release version in the release.
|
|
30
|
-
dependencies = ["ommx >= 2.0.
|
|
30
|
+
dependencies = ["ommx >= 2.0.0b3, < 3.0.0", "mip >= 1.15.0, < 2.0.0"]
|
|
31
31
|
|
|
32
32
|
[project.urls]
|
|
33
33
|
Repository = "https://github.com/Jij-Inc/ommx"
|
{ommx_python_mip_adapter-2.0.0b2 → ommx_python_mip_adapter-2.0.0rc1}/tests/test_model_to_instance.py
RENAMED
|
@@ -48,20 +48,20 @@ def test_milp():
|
|
|
48
48
|
assert ommx_instance.sense == Instance.MINIMIZE
|
|
49
49
|
|
|
50
50
|
# Check the decision variables
|
|
51
|
-
assert len(ommx_instance.
|
|
52
|
-
decision_variables_x1 = ommx_instance.
|
|
51
|
+
assert len(ommx_instance.decision_variables) == 3
|
|
52
|
+
decision_variables_x1 = ommx_instance.get_decision_variable_by_id(0)
|
|
53
53
|
assert decision_variables_x1.id == 0
|
|
54
54
|
assert decision_variables_x1.kind == DecisionVariable.CONTINUOUS
|
|
55
55
|
assert decision_variables_x1.bound.lower == CONTINUOUS_LOWER_BOUND
|
|
56
56
|
assert decision_variables_x1.bound.upper == CONTINUOUS_UPPER_BOUND
|
|
57
57
|
assert decision_variables_x1.name == "1"
|
|
58
|
-
decision_variables_x2 = ommx_instance.
|
|
58
|
+
decision_variables_x2 = ommx_instance.get_decision_variable_by_id(1)
|
|
59
59
|
assert decision_variables_x2.id == 1
|
|
60
60
|
assert decision_variables_x2.kind == DecisionVariable.INTEGER
|
|
61
61
|
assert decision_variables_x2.bound.lower == INTEGER_LOWER_BOUND
|
|
62
62
|
assert decision_variables_x2.bound.upper == INTEGER_UPPER_BOUND
|
|
63
63
|
assert decision_variables_x2.name == "2"
|
|
64
|
-
decision_variables_x3 = ommx_instance.
|
|
64
|
+
decision_variables_x3 = ommx_instance.get_decision_variable_by_id(2)
|
|
65
65
|
assert decision_variables_x3.id == 2
|
|
66
66
|
assert decision_variables_x3.kind == DecisionVariable.BINARY
|
|
67
67
|
assert decision_variables_x3.bound.lower == 0
|
|
@@ -78,9 +78,9 @@ def test_milp():
|
|
|
78
78
|
assert linear_terms[2] == -3
|
|
79
79
|
|
|
80
80
|
# Check the constraints
|
|
81
|
-
assert len(ommx_instance.
|
|
81
|
+
assert len(ommx_instance.constraints) == 3
|
|
82
82
|
|
|
83
|
-
constraint1 = ommx_instance.
|
|
83
|
+
constraint1 = ommx_instance.get_constraint_by_id(0)
|
|
84
84
|
assert constraint1.equality == Constraint.EQUAL_TO_ZERO
|
|
85
85
|
assert constraint1.function.degree() == 1
|
|
86
86
|
assert constraint1.function.constant_term == 6
|
|
@@ -89,7 +89,7 @@ def test_milp():
|
|
|
89
89
|
assert constraint1_terms[0] == 4
|
|
90
90
|
assert constraint1_terms[1] == -5
|
|
91
91
|
|
|
92
|
-
constraint2 = ommx_instance.
|
|
92
|
+
constraint2 = ommx_instance.get_constraint_by_id(1)
|
|
93
93
|
assert constraint2.equality == Constraint.LESS_THAN_OR_EQUAL_TO_ZERO
|
|
94
94
|
assert constraint2.function.degree() == 1
|
|
95
95
|
assert constraint2.function.constant_term == -9
|
|
@@ -98,7 +98,7 @@ def test_milp():
|
|
|
98
98
|
assert constraint2_terms[0] == -7
|
|
99
99
|
assert constraint2_terms[2] == 8
|
|
100
100
|
|
|
101
|
-
constraint3 = ommx_instance.
|
|
101
|
+
constraint3 = ommx_instance.get_constraint_by_id(2)
|
|
102
102
|
assert constraint3.equality == Constraint.LESS_THAN_OR_EQUAL_TO_ZERO
|
|
103
103
|
assert constraint3.function.degree() == 1
|
|
104
104
|
assert constraint3.function.constant_term == -12
|
|
@@ -141,14 +141,14 @@ def test_no_objective_model():
|
|
|
141
141
|
assert ommx_instance.sense == Instance.MAXIMIZE
|
|
142
142
|
|
|
143
143
|
# Check the decision variables
|
|
144
|
-
assert len(ommx_instance.
|
|
145
|
-
decision_variables_x1 = ommx_instance.
|
|
144
|
+
assert len(ommx_instance.decision_variables) == 2
|
|
145
|
+
decision_variables_x1 = ommx_instance.get_decision_variable_by_id(0)
|
|
146
146
|
assert decision_variables_x1.id == 0
|
|
147
147
|
assert decision_variables_x1.kind == DecisionVariable.CONTINUOUS
|
|
148
148
|
assert decision_variables_x1.bound.lower == LOWER_BOUND
|
|
149
149
|
assert decision_variables_x1.bound.upper == UPPER_BOUND
|
|
150
150
|
assert decision_variables_x1.name == "1"
|
|
151
|
-
decision_variables_x2 = ommx_instance.
|
|
151
|
+
decision_variables_x2 = ommx_instance.get_decision_variable_by_id(1)
|
|
152
152
|
assert decision_variables_x2.id == 1
|
|
153
153
|
assert decision_variables_x2.kind == DecisionVariable.CONTINUOUS
|
|
154
154
|
assert decision_variables_x2.bound.lower == LOWER_BOUND
|
|
@@ -160,9 +160,9 @@ def test_no_objective_model():
|
|
|
160
160
|
assert ommx_instance.objective.num_terms() == 0 # Zero function has 0 terms
|
|
161
161
|
|
|
162
162
|
# Check the constraints
|
|
163
|
-
assert len(ommx_instance.
|
|
163
|
+
assert len(ommx_instance.constraints) == 2
|
|
164
164
|
|
|
165
|
-
constraint1 = ommx_instance.
|
|
165
|
+
constraint1 = ommx_instance.get_constraint_by_id(0)
|
|
166
166
|
assert constraint1.equality == Constraint.EQUAL_TO_ZERO
|
|
167
167
|
assert constraint1.function.degree() == 1
|
|
168
168
|
assert constraint1.function.constant_term == -5
|
|
@@ -171,7 +171,7 @@ def test_no_objective_model():
|
|
|
171
171
|
assert constraint1_terms[0] == 1
|
|
172
172
|
assert constraint1_terms[1] == 2
|
|
173
173
|
|
|
174
|
-
constraint2 = ommx_instance.
|
|
174
|
+
constraint2 = ommx_instance.get_constraint_by_id(1)
|
|
175
175
|
assert constraint2.equality == Constraint.EQUAL_TO_ZERO
|
|
176
176
|
assert constraint2.function.degree() == 1
|
|
177
177
|
assert constraint2.function.constant_term == -10
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ommx_python_mip_adapter-2.0.0b2 → ommx_python_mip_adapter-2.0.0rc1}/tests/test_integration.py
RENAMED
|
File without changes
|