ommx-python-mip-adapter 2.5.1__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.
Files changed (17) hide show
  1. {ommx_python_mip_adapter-2.5.1 → ommx_python_mip_adapter-3.0.0a2}/PKG-INFO +3 -3
  2. {ommx_python_mip_adapter-2.5.1 → ommx_python_mip_adapter-3.0.0a2}/README.md +1 -1
  3. {ommx_python_mip_adapter-2.5.1 → ommx_python_mip_adapter-3.0.0a2}/ommx_python_mip_adapter/adapter.py +12 -11
  4. {ommx_python_mip_adapter-2.5.1 → ommx_python_mip_adapter-3.0.0a2}/ommx_python_mip_adapter/python_mip_to_ommx.py +3 -6
  5. {ommx_python_mip_adapter-2.5.1 → ommx_python_mip_adapter-3.0.0a2}/ommx_python_mip_adapter.egg-info/PKG-INFO +3 -3
  6. {ommx_python_mip_adapter-2.5.1 → ommx_python_mip_adapter-3.0.0a2}/ommx_python_mip_adapter.egg-info/requires.txt +1 -1
  7. {ommx_python_mip_adapter-2.5.1 → ommx_python_mip_adapter-3.0.0a2}/pyproject.toml +2 -2
  8. {ommx_python_mip_adapter-2.5.1 → ommx_python_mip_adapter-3.0.0a2}/tests/test_adapter.py +2 -2
  9. {ommx_python_mip_adapter-2.5.1 → ommx_python_mip_adapter-3.0.0a2}/tests/test_constant_constraint.py +8 -8
  10. {ommx_python_mip_adapter-2.5.1 → ommx_python_mip_adapter-3.0.0a2}/tests/test_integration.py +8 -11
  11. {ommx_python_mip_adapter-2.5.1 → ommx_python_mip_adapter-3.0.0a2}/ommx_python_mip_adapter/__init__.py +0 -0
  12. {ommx_python_mip_adapter-2.5.1 → ommx_python_mip_adapter-3.0.0a2}/ommx_python_mip_adapter/exception.py +0 -0
  13. {ommx_python_mip_adapter-2.5.1 → ommx_python_mip_adapter-3.0.0a2}/ommx_python_mip_adapter.egg-info/SOURCES.txt +0 -0
  14. {ommx_python_mip_adapter-2.5.1 → ommx_python_mip_adapter-3.0.0a2}/ommx_python_mip_adapter.egg-info/dependency_links.txt +0 -0
  15. {ommx_python_mip_adapter-2.5.1 → ommx_python_mip_adapter-3.0.0a2}/ommx_python_mip_adapter.egg-info/top_level.txt +0 -0
  16. {ommx_python_mip_adapter-2.5.1 → ommx_python_mip_adapter-3.0.0a2}/setup.cfg +0 -0
  17. {ommx_python_mip_adapter-2.5.1 → 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: 2.5.1
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<3.0.0,>=2.0.0b3
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
 
@@ -52,7 +52,7 @@ x1 = DecisionVariable.integer(1, lower=0, upper=5)
52
52
  ommx_instance = Instance.from_components(
53
53
  decision_variables=[x1],
54
54
  objective=x1,
55
- constraints=[],
55
+ constraints={},
56
56
  sense=Instance.MINIMIZE,
57
57
  )
58
58
 
@@ -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=[(sum(w[i] * x[i] for i in range(6)) <= 47).set_id(0)],
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=[x >= 4],
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=[(x + y <= 1).set_id(0)],
169
+ ... constraints={0: x + y <= 1},
169
170
  ... sense=Instance.MAXIMIZE,
170
171
  ... )
171
172
 
@@ -201,7 +202,7 @@ class OMMXPythonMIPAdapter(SolverAdapter):
201
202
  be set _only_ if `relax=True` was passed to the constructor. There is no
202
203
  way for this adapter to get relaxation information from Python-MIP
203
204
  directly. If relaxing the model separately after obtaining it with
204
- `solver_input`, you must set `solution.raw.relaxation` yourself if you
205
+ `solver_input`, you must set `solution.relaxation` yourself if you
205
206
  care about this value.
206
207
 
207
208
  Examples
@@ -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=[sum(w[i] * x[i] for i in range(6)) <= 47],
222
+ ... constraints={0: sum(w[i] * x[i] for i in range(6)) <= 47},
222
223
  ... sense=Instance.MAXIMIZE,
223
224
  ... )
224
225
 
@@ -229,7 +230,7 @@ class OMMXPythonMIPAdapter(SolverAdapter):
229
230
  <OptimizationStatus.OPTIMAL: 0>
230
231
 
231
232
  >>> solution = adapter.decode(model)
232
- >>> solution.raw.objective
233
+ >>> solution.objective
233
234
  42.0
234
235
 
235
236
  """
@@ -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: {constraint.id}, equality: {constraint.equality}"
381
+ f"id: {cid}, equality: {constraint.equality}"
381
382
  )
382
- self.model.add_constr(constr_expr, name=str(constraint.id))
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) -> list[Constraint]:
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.append(constraint)
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: 2.5.1
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<3.0.0,>=2.0.0b3
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
 
@@ -1,3 +1,3 @@
1
- ommx<3.0.0,>=2.0.0b3
1
+ ommx<4.0.0,>=3.0.0a2
2
2
  mip<2.0.0,>=1.17.0
3
3
  cffi<2.0.0,>=1.15.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ommx_python_mip_adapter"
7
- version = "2.5.1"
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 >= 2.0.0b3, < 3.0.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=[(2.3 * x * x == 0).set_id(0)],
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):
@@ -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=[(x[0] + x[1] + x[2] <= 1).set_id(0)], # one-hot constraint
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=[(x[0] + 2 * x[1] <= 1).set_id(0), (x[1] + x[2] <= 1).set_id(1)],
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=[constraint],
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=[x >= 4],
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)