ommx-python-mip-adapter 3.0.0a1__tar.gz → 3.0.0a2__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-3.0.0a1 → ommx_python_mip_adapter-3.0.0a2}/PKG-INFO +3 -3
- {ommx_python_mip_adapter-3.0.0a1 → ommx_python_mip_adapter-3.0.0a2}/README.md +1 -1
- {ommx_python_mip_adapter-3.0.0a1 → ommx_python_mip_adapter-3.0.0a2}/ommx_python_mip_adapter/adapter.py +10 -9
- {ommx_python_mip_adapter-3.0.0a1 → ommx_python_mip_adapter-3.0.0a2}/ommx_python_mip_adapter/python_mip_to_ommx.py +3 -6
- {ommx_python_mip_adapter-3.0.0a1 → ommx_python_mip_adapter-3.0.0a2}/ommx_python_mip_adapter.egg-info/PKG-INFO +3 -3
- {ommx_python_mip_adapter-3.0.0a1 → ommx_python_mip_adapter-3.0.0a2}/ommx_python_mip_adapter.egg-info/requires.txt +1 -1
- {ommx_python_mip_adapter-3.0.0a1 → ommx_python_mip_adapter-3.0.0a2}/pyproject.toml +2 -2
- {ommx_python_mip_adapter-3.0.0a1 → ommx_python_mip_adapter-3.0.0a2}/tests/test_adapter.py +2 -2
- {ommx_python_mip_adapter-3.0.0a1 → ommx_python_mip_adapter-3.0.0a2}/tests/test_constant_constraint.py +8 -8
- {ommx_python_mip_adapter-3.0.0a1 → ommx_python_mip_adapter-3.0.0a2}/tests/test_integration.py +8 -11
- {ommx_python_mip_adapter-3.0.0a1 → ommx_python_mip_adapter-3.0.0a2}/ommx_python_mip_adapter/__init__.py +0 -0
- {ommx_python_mip_adapter-3.0.0a1 → ommx_python_mip_adapter-3.0.0a2}/ommx_python_mip_adapter/exception.py +0 -0
- {ommx_python_mip_adapter-3.0.0a1 → ommx_python_mip_adapter-3.0.0a2}/ommx_python_mip_adapter.egg-info/SOURCES.txt +0 -0
- {ommx_python_mip_adapter-3.0.0a1 → ommx_python_mip_adapter-3.0.0a2}/ommx_python_mip_adapter.egg-info/dependency_links.txt +0 -0
- {ommx_python_mip_adapter-3.0.0a1 → ommx_python_mip_adapter-3.0.0a2}/ommx_python_mip_adapter.egg-info/top_level.txt +0 -0
- {ommx_python_mip_adapter-3.0.0a1 → ommx_python_mip_adapter-3.0.0a2}/setup.cfg +0 -0
- {ommx_python_mip_adapter-3.0.0a1 → ommx_python_mip_adapter-3.0.0a2}/tests/test_model_to_instance.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ommx_python_mip_adapter
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.0a2
|
|
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.10
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
|
-
Requires-Dist: ommx<4.0.0,>=3.0.
|
|
18
|
+
Requires-Dist: ommx<4.0.0,>=3.0.0a2
|
|
19
19
|
Requires-Dist: mip<2.0.0,>=1.17.0
|
|
20
20
|
Requires-Dist: cffi<2.0.0,>=1.15.0
|
|
21
21
|
|
|
@@ -73,7 +73,7 @@ x1 = DecisionVariable.integer(1, lower=0, upper=5)
|
|
|
73
73
|
ommx_instance = Instance.from_components(
|
|
74
74
|
decision_variables=[x1],
|
|
75
75
|
objective=x1,
|
|
76
|
-
constraints=
|
|
76
|
+
constraints={},
|
|
77
77
|
sense=Instance.MINIMIZE,
|
|
78
78
|
)
|
|
79
79
|
|
|
@@ -32,6 +32,7 @@ class OMMXPythonMIPAdapter(SolverAdapter):
|
|
|
32
32
|
:param solver: Passes a specific solver to the Python-MIP model.
|
|
33
33
|
:param verbose: If True, enable Python-MIP's verbose mode
|
|
34
34
|
"""
|
|
35
|
+
super().__init__(ommx_instance)
|
|
35
36
|
if ommx_instance.sense == Instance.MAXIMIZE:
|
|
36
37
|
sense = mip.MAXIMIZE
|
|
37
38
|
elif ommx_instance.sense == Instance.MINIMIZE:
|
|
@@ -89,7 +90,7 @@ class OMMXPythonMIPAdapter(SolverAdapter):
|
|
|
89
90
|
>>> instance = Instance.from_components(
|
|
90
91
|
... decision_variables=x,
|
|
91
92
|
... objective=sum(p[i] * x[i] for i in range(6)),
|
|
92
|
-
... constraints=
|
|
93
|
+
... constraints={0: sum(w[i] * x[i] for i in range(6)) <= 47},
|
|
93
94
|
... sense=Instance.MAXIMIZE,
|
|
94
95
|
... )
|
|
95
96
|
|
|
@@ -124,7 +125,7 @@ class OMMXPythonMIPAdapter(SolverAdapter):
|
|
|
124
125
|
>>> instance = Instance.from_components(
|
|
125
126
|
... decision_variables=[x],
|
|
126
127
|
... objective=x,
|
|
127
|
-
... constraints=
|
|
128
|
+
... constraints={0: x >= 4},
|
|
128
129
|
... sense=Instance.MAXIMIZE,
|
|
129
130
|
... )
|
|
130
131
|
|
|
@@ -144,7 +145,7 @@ class OMMXPythonMIPAdapter(SolverAdapter):
|
|
|
144
145
|
>>> instance = Instance.from_components(
|
|
145
146
|
... decision_variables=[x],
|
|
146
147
|
... objective=x,
|
|
147
|
-
... constraints=
|
|
148
|
+
... constraints={},
|
|
148
149
|
... sense=Instance.MAXIMIZE,
|
|
149
150
|
... )
|
|
150
151
|
|
|
@@ -165,7 +166,7 @@ class OMMXPythonMIPAdapter(SolverAdapter):
|
|
|
165
166
|
>>> instance = Instance.from_components(
|
|
166
167
|
... decision_variables=[x, y],
|
|
167
168
|
... objective=x + y,
|
|
168
|
-
... constraints=
|
|
169
|
+
... constraints={0: x + y <= 1},
|
|
169
170
|
... sense=Instance.MAXIMIZE,
|
|
170
171
|
... )
|
|
171
172
|
|
|
@@ -218,7 +219,7 @@ class OMMXPythonMIPAdapter(SolverAdapter):
|
|
|
218
219
|
>>> instance = Instance.from_components(
|
|
219
220
|
... decision_variables=x,
|
|
220
221
|
... objective=sum(p[i] * x[i] for i in range(6)),
|
|
221
|
-
... constraints=
|
|
222
|
+
... constraints={0: sum(w[i] * x[i] for i in range(6)) <= 47},
|
|
222
223
|
... sense=Instance.MAXIMIZE,
|
|
223
224
|
... )
|
|
224
225
|
|
|
@@ -270,7 +271,7 @@ class OMMXPythonMIPAdapter(SolverAdapter):
|
|
|
270
271
|
>>> ommx_instance = Instance.from_components(
|
|
271
272
|
... decision_variables=[x1],
|
|
272
273
|
... objective=x1,
|
|
273
|
-
... constraints=
|
|
274
|
+
... constraints={},
|
|
274
275
|
... sense=Instance.MINIMIZE,
|
|
275
276
|
... )
|
|
276
277
|
>>> adapter = OMMXPythonMIPAdapter(ommx_instance)
|
|
@@ -368,7 +369,7 @@ class OMMXPythonMIPAdapter(SolverAdapter):
|
|
|
368
369
|
self.model.objective = self._as_lin_expr(self.instance.objective)
|
|
369
370
|
|
|
370
371
|
def _set_constraints(self):
|
|
371
|
-
for constraint in self.instance.constraints:
|
|
372
|
+
for cid, constraint in self.instance.constraints.items():
|
|
372
373
|
lin_expr = self._as_lin_expr(constraint.function)
|
|
373
374
|
if constraint.equality == Constraint.EQUAL_TO_ZERO:
|
|
374
375
|
constr_expr = lin_expr == 0
|
|
@@ -377,6 +378,6 @@ class OMMXPythonMIPAdapter(SolverAdapter):
|
|
|
377
378
|
else:
|
|
378
379
|
raise OMMXPythonMIPAdapterError(
|
|
379
380
|
f"Not supported constraint equality: "
|
|
380
|
-
f"id: {
|
|
381
|
+
f"id: {cid}, equality: {constraint.equality}"
|
|
381
382
|
)
|
|
382
|
-
self.model.add_constr(constr_expr, name=str(
|
|
383
|
+
self.model.add_constr(constr_expr, name=str(cid))
|
|
@@ -72,8 +72,8 @@ class OMMXInstanceBuilder:
|
|
|
72
72
|
|
|
73
73
|
return self.as_ommx_function(objective)
|
|
74
74
|
|
|
75
|
-
def constraints(self) ->
|
|
76
|
-
constraints =
|
|
75
|
+
def constraints(self) -> dict[int, Constraint]:
|
|
76
|
+
constraints: dict[int, Constraint] = {}
|
|
77
77
|
|
|
78
78
|
for constr in self.model.constrs:
|
|
79
79
|
id = constr.idx
|
|
@@ -82,14 +82,12 @@ class OMMXInstanceBuilder:
|
|
|
82
82
|
|
|
83
83
|
if lin_expr.sense == "=":
|
|
84
84
|
constraint = Constraint(
|
|
85
|
-
id=id,
|
|
86
85
|
function=self.as_ommx_function(lin_expr),
|
|
87
86
|
equality=Constraint.EQUAL_TO_ZERO,
|
|
88
87
|
name=name,
|
|
89
88
|
)
|
|
90
89
|
elif lin_expr.sense == "<":
|
|
91
90
|
constraint = Constraint(
|
|
92
|
-
id=id,
|
|
93
91
|
function=self.as_ommx_function(lin_expr),
|
|
94
92
|
equality=Constraint.LESS_THAN_OR_EQUAL_TO_ZERO,
|
|
95
93
|
name=name,
|
|
@@ -98,7 +96,6 @@ class OMMXInstanceBuilder:
|
|
|
98
96
|
# `ommx.v1.Constraint` does not support `GREATER_THAN_OR_EQUAL_TO_ZERO`.
|
|
99
97
|
# So multiply the linear expression by -1.
|
|
100
98
|
constraint = Constraint(
|
|
101
|
-
id=id,
|
|
102
99
|
function=self.as_ommx_function(-lin_expr),
|
|
103
100
|
equality=Constraint.LESS_THAN_OR_EQUAL_TO_ZERO,
|
|
104
101
|
name=name,
|
|
@@ -109,7 +106,7 @@ class OMMXInstanceBuilder:
|
|
|
109
106
|
f"name: {constr.name}, sense: {lin_expr.sense}"
|
|
110
107
|
)
|
|
111
108
|
|
|
112
|
-
constraints
|
|
109
|
+
constraints[id] = constraint
|
|
113
110
|
|
|
114
111
|
return constraints
|
|
115
112
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ommx_python_mip_adapter
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.0a2
|
|
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.10
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
|
-
Requires-Dist: ommx<4.0.0,>=3.0.
|
|
18
|
+
Requires-Dist: ommx<4.0.0,>=3.0.0a2
|
|
19
19
|
Requires-Dist: mip<2.0.0,>=1.17.0
|
|
20
20
|
Requires-Dist: cffi<2.0.0,>=1.15.0
|
|
21
21
|
|
|
@@ -73,7 +73,7 @@ x1 = DecisionVariable.integer(1, lower=0, upper=5)
|
|
|
73
73
|
ommx_instance = Instance.from_components(
|
|
74
74
|
decision_variables=[x1],
|
|
75
75
|
objective=x1,
|
|
76
|
-
constraints=
|
|
76
|
+
constraints={},
|
|
77
77
|
sense=Instance.MINIMIZE,
|
|
78
78
|
)
|
|
79
79
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ommx_python_mip_adapter"
|
|
7
|
-
version = "3.0.
|
|
7
|
+
version = "3.0.0a2"
|
|
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" }]
|
|
@@ -23,7 +23,7 @@ classifiers = [
|
|
|
23
23
|
]
|
|
24
24
|
|
|
25
25
|
dependencies = [
|
|
26
|
-
"ommx >= 3.0.
|
|
26
|
+
"ommx >= 3.0.0a2, < 4.0.0",
|
|
27
27
|
"mip >= 1.17.0, < 2.0.0",
|
|
28
28
|
"cffi >= 1.15.0, < 2.0.0",
|
|
29
29
|
]
|
|
@@ -10,7 +10,7 @@ def test_error_nonlinear_objective():
|
|
|
10
10
|
ommx_instance = Instance.from_components(
|
|
11
11
|
decision_variables=[x],
|
|
12
12
|
objective=2.3 * x * x,
|
|
13
|
-
constraints=
|
|
13
|
+
constraints={},
|
|
14
14
|
sense=Instance.MINIMIZE,
|
|
15
15
|
)
|
|
16
16
|
|
|
@@ -29,7 +29,7 @@ def test_error_nonlinear_constraint():
|
|
|
29
29
|
ommx_instance = Instance.from_components(
|
|
30
30
|
decision_variables=[x],
|
|
31
31
|
objective=0.0,
|
|
32
|
-
constraints=
|
|
32
|
+
constraints={0: 2.3 * x * x == 0},
|
|
33
33
|
sense=Instance.MINIMIZE,
|
|
34
34
|
)
|
|
35
35
|
|
|
@@ -12,11 +12,11 @@ def test_constant_constraint_feasible():
|
|
|
12
12
|
instance = Instance.from_components(
|
|
13
13
|
decision_variables=[x],
|
|
14
14
|
objective=x,
|
|
15
|
-
constraints=
|
|
16
|
-
# 1 >= 0 is always true
|
|
15
|
+
constraints={
|
|
16
|
+
0: # 1 >= 0 is always true
|
|
17
17
|
Linear(terms={}, constant=1) >= 0,
|
|
18
|
-
x <= 1,
|
|
19
|
-
|
|
18
|
+
1: x <= 1,
|
|
19
|
+
},
|
|
20
20
|
sense=Instance.MAXIMIZE,
|
|
21
21
|
)
|
|
22
22
|
solution = OMMXPythonMIPAdapter.solve(instance)
|
|
@@ -35,11 +35,11 @@ def test_constant_constraint_infeasible():
|
|
|
35
35
|
instance = Instance.from_components(
|
|
36
36
|
decision_variables=[x],
|
|
37
37
|
objective=x,
|
|
38
|
-
constraints=
|
|
39
|
-
# -1 >= 0 is always false
|
|
38
|
+
constraints={
|
|
39
|
+
0: # -1 >= 0 is always false
|
|
40
40
|
Linear(terms={}, constant=-1) >= 0,
|
|
41
|
-
x <= 1,
|
|
42
|
-
|
|
41
|
+
1: x <= 1,
|
|
42
|
+
},
|
|
43
43
|
sense=Instance.MAXIMIZE,
|
|
44
44
|
)
|
|
45
45
|
with pytest.raises(InfeasibleDetected):
|
{ommx_python_mip_adapter-3.0.0a1 → ommx_python_mip_adapter-3.0.0a2}/tests/test_integration.py
RENAMED
|
@@ -48,10 +48,7 @@ def test_integration_milp():
|
|
|
48
48
|
ommx_instance = Instance.from_components(
|
|
49
49
|
decision_variables=[x1, x2],
|
|
50
50
|
objective=-x1 - x2,
|
|
51
|
-
constraints=
|
|
52
|
-
3 * x1 - x2 <= 6,
|
|
53
|
-
-x1 + 3 * x2 <= 6,
|
|
54
|
-
],
|
|
51
|
+
constraints={0: 3 * x1 - x2 <= 6, 1: -x1 + 3 * x2 <= 6},
|
|
55
52
|
sense=Instance.MINIMIZE,
|
|
56
53
|
)
|
|
57
54
|
|
|
@@ -70,7 +67,7 @@ def test_solution_optimality():
|
|
|
70
67
|
ommx_instance = Instance.from_components(
|
|
71
68
|
decision_variables=[x, y],
|
|
72
69
|
objective=x + y,
|
|
73
|
-
constraints=
|
|
70
|
+
constraints={},
|
|
74
71
|
sense=Instance.MAXIMIZE,
|
|
75
72
|
)
|
|
76
73
|
|
|
@@ -83,7 +80,7 @@ def test_partial_evaluate():
|
|
|
83
80
|
instance = Instance.from_components(
|
|
84
81
|
decision_variables=x,
|
|
85
82
|
objective=x[0] + x[1] + x[2],
|
|
86
|
-
constraints=
|
|
83
|
+
constraints={0: x[0] + x[1] + x[2] <= 1}, # one-hot constraint
|
|
87
84
|
sense=Instance.MINIMIZE,
|
|
88
85
|
)
|
|
89
86
|
assert instance.used_decision_variables == x
|
|
@@ -109,7 +106,7 @@ def test_relax_constraint():
|
|
|
109
106
|
instance = Instance.from_components(
|
|
110
107
|
decision_variables=x,
|
|
111
108
|
objective=x[0] + x[1],
|
|
112
|
-
constraints=
|
|
109
|
+
constraints={0: x[0] + 2 * x[1] <= 1, 1: x[1] + x[2] <= 1},
|
|
113
110
|
sense=Instance.MINIMIZE,
|
|
114
111
|
)
|
|
115
112
|
|
|
@@ -150,7 +147,7 @@ def test_integration_timelimit():
|
|
|
150
147
|
instance = Instance.from_components(
|
|
151
148
|
decision_variables=x,
|
|
152
149
|
objective=sum(v[i] * x[i] for i in range(n)),
|
|
153
|
-
constraints=
|
|
150
|
+
constraints={0: constraint},
|
|
154
151
|
sense=Instance.MAXIMIZE,
|
|
155
152
|
)
|
|
156
153
|
adapter = OMMXPythonMIPAdapter(instance)
|
|
@@ -172,7 +169,7 @@ def test_infeasible_problem():
|
|
|
172
169
|
instance = Instance.from_components(
|
|
173
170
|
decision_variables=[x],
|
|
174
171
|
objective=x,
|
|
175
|
-
constraints=
|
|
172
|
+
constraints={0: x >= 4},
|
|
176
173
|
sense=Instance.MAXIMIZE,
|
|
177
174
|
)
|
|
178
175
|
adapter = OMMXPythonMIPAdapter(instance)
|
|
@@ -189,7 +186,7 @@ def test_unbounded_problem():
|
|
|
189
186
|
instance = Instance.from_components(
|
|
190
187
|
decision_variables=[x],
|
|
191
188
|
objective=x,
|
|
192
|
-
constraints=
|
|
189
|
+
constraints={},
|
|
193
190
|
sense=Instance.MAXIMIZE,
|
|
194
191
|
)
|
|
195
192
|
adapter = OMMXPythonMIPAdapter(instance)
|
|
@@ -205,7 +202,7 @@ def test_decode_before_optimize():
|
|
|
205
202
|
instance = Instance.from_components(
|
|
206
203
|
decision_variables=[x],
|
|
207
204
|
objective=x,
|
|
208
|
-
constraints=
|
|
205
|
+
constraints={},
|
|
209
206
|
sense=Instance.MINIMIZE,
|
|
210
207
|
)
|
|
211
208
|
adapter = OMMXPythonMIPAdapter(instance)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ommx_python_mip_adapter-3.0.0a1 → ommx_python_mip_adapter-3.0.0a2}/tests/test_model_to_instance.py
RENAMED
|
File without changes
|