ommx-python-mip-adapter 0.1.1__tar.gz → 0.4.0__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 (28) hide show
  1. {ommx_python_mip_adapter-0.1.1 → ommx_python_mip_adapter-0.4.0}/PKG-INFO +24 -38
  2. {ommx_python_mip_adapter-0.1.1 → ommx_python_mip_adapter-0.4.0}/README.md +19 -32
  3. {ommx_python_mip_adapter-0.1.1 → ommx_python_mip_adapter-0.4.0}/ommx_python_mip_adapter/__init__.py +1 -1
  4. {ommx_python_mip_adapter-0.1.1 → ommx_python_mip_adapter-0.4.0}/ommx_python_mip_adapter/adapter.py +86 -142
  5. {ommx_python_mip_adapter-0.1.1 → ommx_python_mip_adapter-0.4.0}/ommx_python_mip_adapter.egg-info/PKG-INFO +24 -38
  6. {ommx_python_mip_adapter-0.1.1 → ommx_python_mip_adapter-0.4.0}/ommx_python_mip_adapter.egg-info/SOURCES.txt +1 -12
  7. {ommx_python_mip_adapter-0.1.1 → ommx_python_mip_adapter-0.4.0}/ommx_python_mip_adapter.egg-info/requires.txt +4 -3
  8. {ommx_python_mip_adapter-0.1.1 → ommx_python_mip_adapter-0.4.0}/pyproject.toml +14 -18
  9. ommx_python_mip_adapter-0.4.0/tests/test_instance_to_model.py +90 -0
  10. ommx_python_mip_adapter-0.4.0/tests/test_integration.py +60 -0
  11. {ommx_python_mip_adapter-0.1.1 → ommx_python_mip_adapter-0.4.0}/tests/test_model_to_instance.py +34 -38
  12. ommx_python_mip_adapter-0.1.1/.github/workflows/docs.yml +0 -72
  13. ommx_python_mip_adapter-0.1.1/.github/workflows/publish.yml +0 -49
  14. ommx_python_mip_adapter-0.1.1/.github/workflows/test_and_lint.yml +0 -75
  15. ommx_python_mip_adapter-0.1.1/.gitignore +0 -162
  16. ommx_python_mip_adapter-0.1.1/LICENSE-APACHE +0 -201
  17. ommx_python_mip_adapter-0.1.1/LICENSE-MIT +0 -21
  18. ommx_python_mip_adapter-0.1.1/docs/source/conf.py +0 -50
  19. ommx_python_mip_adapter-0.1.1/docs/source/index.rst +0 -20
  20. ommx_python_mip_adapter-0.1.1/ommx_python_mip_adapter/_version.py +0 -16
  21. ommx_python_mip_adapter-0.1.1/tests/conftest.py +0 -0
  22. ommx_python_mip_adapter-0.1.1/tests/test_instance_to_model.py +0 -127
  23. ommx_python_mip_adapter-0.1.1/tests/test_integration.py +0 -142
  24. ommx_python_mip_adapter-0.1.1/tests/test_model_to_solution.py +0 -27
  25. {ommx_python_mip_adapter-0.1.1 → ommx_python_mip_adapter-0.4.0}/ommx_python_mip_adapter/exception.py +0 -0
  26. {ommx_python_mip_adapter-0.1.1 → ommx_python_mip_adapter-0.4.0}/ommx_python_mip_adapter.egg-info/dependency_links.txt +0 -0
  27. {ommx_python_mip_adapter-0.1.1 → ommx_python_mip_adapter-0.4.0}/ommx_python_mip_adapter.egg-info/top_level.txt +0 -0
  28. {ommx_python_mip_adapter-0.1.1 → ommx_python_mip_adapter-0.4.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ommx_python_mip_adapter
3
- Version: 0.1.1
3
+ Version: 0.4.0
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-python-mip-adapter
@@ -15,9 +15,7 @@ Classifier: License :: OSI Approved :: Apache Software License
15
15
  Classifier: License :: OSI Approved :: MIT License
16
16
  Requires-Python: >=3.8
17
17
  Description-Content-Type: text/markdown
18
- License-File: LICENSE-APACHE
19
- License-File: LICENSE-MIT
20
- Requires-Dist: ommx<0.3.0,>=0.2.0
18
+ Requires-Dist: ommx<0.5.0,>=0.4.0
21
19
  Requires-Dist: mip
22
20
  Provides-Extra: dev
23
21
  Requires-Dist: markdown-code-runner; extra == "dev"
@@ -25,16 +23,17 @@ Requires-Dist: mypy; extra == "dev"
25
23
  Requires-Dist: numpy; extra == "dev"
26
24
  Requires-Dist: pyright; extra == "dev"
27
25
  Requires-Dist: pytest; extra == "dev"
26
+ Requires-Dist: ruff; extra == "dev"
28
27
  Requires-Dist: sphinx; extra == "dev"
29
- Requires-Dist: sphinx_rtd_theme; extra == "dev"
30
- Requires-Dist: sphinx_fontawesome; extra == "dev"
31
28
  Requires-Dist: sphinx-autoapi; extra == "dev"
29
+ Requires-Dist: sphinx_fontawesome; extra == "dev"
30
+ Requires-Dist: sphinx_rtd_theme; extra == "dev"
32
31
 
33
- OMMX adaptor for Python-MIP
32
+ OMMX adapter for Python-MIP
34
33
  ============================
35
- ![PyPI - Version](https://img.shields.io/pypi/v/ommx-python-mip-adapter)
34
+ [![PyPI - Version](https://img.shields.io/pypi/v/ommx-python-mip-adapter)](https://pypi.org/project/ommx-python-mip-adapter/)
36
35
 
37
- This package provides an adaptor for the [Python-MIP](https://www.python-mip.com/) from/to [OMMX](https://github.com/Jij-Inc/ommx)
36
+ This package provides an adapter for the [Python-MIP](https://www.python-mip.com/) from/to [OMMX](https://github.com/Jij-Inc/ommx)
38
37
 
39
38
  Python-MIP as a solver in OMMX toolchain
40
39
  -----------------------------------------
@@ -78,43 +77,30 @@ Python-MIP can be used through `ommx-python-mip-adapter` by using the following:
78
77
 
79
78
  ```python markdown-code-runner
80
79
  import ommx_python_mip_adapter as adapter
81
- from ommx.v1.decision_variables_pb2 import DecisionVariable, Bound
82
- from ommx.v1.instance_pb2 import Instance
83
- from ommx.v1.function_pb2 import Function
84
- from ommx.v1.linear_pb2 import Linear
85
- from ommx.v1.solution_pb2 import SolutionList
86
-
87
- ommx_instance = Instance(
88
- decision_variables=[
89
- DecisionVariable(
90
- id=1,
91
- kind=DecisionVariable.KIND_INTEGER,
92
- bound=Bound(lower=0, upper=5),
93
- ),
94
- ],
95
- objective=Function(
96
- linear=Linear(
97
- terms=[Linear.Term(id=1, coefficient=1)]
98
- ),
99
- ),
80
+ from ommx.v1 import Instance, DecisionVariable
81
+
82
+ x1 = DecisionVariable.integer(1, lower=0, upper=5)
83
+ ommx_instance = Instance.from_components(
84
+ decision_variables=[x1],
85
+ objective=x1,
86
+ constraints=[],
87
+ sense=Instance.MINIMIZE,
100
88
  )
101
- ommx_instance_bytes = ommx_instance.SerializeToString()
102
89
 
103
90
  # Convert from `ommx.v1.Instance` to `mip.Model`
104
- model = adapter.instance_to_model(ommx_instance_bytes)
91
+ model = adapter.instance_to_model(ommx_instance)
105
92
  model.optimize()
106
- # Create `ommx.v1.SolutionList` from Optimized `mip.Model`
107
- ommx_solutions_bytes = adapter.model_to_solution(
108
- model, ommx_instance_bytes
109
- )
93
+ # Create `ommx.v1.State` from Optimized `mip.Model`
94
+ ommx_solutions = adapter.model_to_solution(model, ommx_instance)
110
95
 
111
- print(SolutionList.FromString(ommx_solutions_bytes))
96
+ print(ommx_solutions)
112
97
  ```
98
+
113
99
  You can get `ommx.v1.Instance` from a Python-MIP model as the following:
100
+
114
101
  ```python markdown-code-runner
115
102
  import mip
116
103
  import ommx_python_mip_adapter as adapter
117
- from ommx.v1.instance_pb2 import Instance
118
104
 
119
105
  model = mip.Model()
120
106
  x1=model.add_var(name="1", var_type=mip.INTEGER, lb=0, ub=5)
@@ -122,9 +108,9 @@ x2=model.add_var(name="2", var_type=mip.CONTINUOUS, lb=0, ub=5)
122
108
  model.objective = - x1 - 2 * x2
123
109
  model.add_constr(x1 + x2 - 6 <= 0)
124
110
 
125
- ommx_instance_bytes = adapter.model_to_instance(model)
111
+ ommx_instance = adapter.model_to_instance(model)
126
112
 
127
- print(Instance.FromString(ommx_instance_bytes))
113
+ print(ommx_instance)
128
114
  ```
129
115
 
130
116
  Reference
@@ -1,8 +1,8 @@
1
- OMMX adaptor for Python-MIP
1
+ OMMX adapter for Python-MIP
2
2
  ============================
3
- ![PyPI - Version](https://img.shields.io/pypi/v/ommx-python-mip-adapter)
3
+ [![PyPI - Version](https://img.shields.io/pypi/v/ommx-python-mip-adapter)](https://pypi.org/project/ommx-python-mip-adapter/)
4
4
 
5
- This package provides an adaptor for the [Python-MIP](https://www.python-mip.com/) from/to [OMMX](https://github.com/Jij-Inc/ommx)
5
+ This package provides an adapter for the [Python-MIP](https://www.python-mip.com/) from/to [OMMX](https://github.com/Jij-Inc/ommx)
6
6
 
7
7
  Python-MIP as a solver in OMMX toolchain
8
8
  -----------------------------------------
@@ -46,43 +46,30 @@ Python-MIP can be used through `ommx-python-mip-adapter` by using the following:
46
46
 
47
47
  ```python markdown-code-runner
48
48
  import ommx_python_mip_adapter as adapter
49
- from ommx.v1.decision_variables_pb2 import DecisionVariable, Bound
50
- from ommx.v1.instance_pb2 import Instance
51
- from ommx.v1.function_pb2 import Function
52
- from ommx.v1.linear_pb2 import Linear
53
- from ommx.v1.solution_pb2 import SolutionList
54
-
55
- ommx_instance = Instance(
56
- decision_variables=[
57
- DecisionVariable(
58
- id=1,
59
- kind=DecisionVariable.KIND_INTEGER,
60
- bound=Bound(lower=0, upper=5),
61
- ),
62
- ],
63
- objective=Function(
64
- linear=Linear(
65
- terms=[Linear.Term(id=1, coefficient=1)]
66
- ),
67
- ),
49
+ from ommx.v1 import Instance, DecisionVariable
50
+
51
+ x1 = DecisionVariable.integer(1, lower=0, upper=5)
52
+ ommx_instance = Instance.from_components(
53
+ decision_variables=[x1],
54
+ objective=x1,
55
+ constraints=[],
56
+ sense=Instance.MINIMIZE,
68
57
  )
69
- ommx_instance_bytes = ommx_instance.SerializeToString()
70
58
 
71
59
  # Convert from `ommx.v1.Instance` to `mip.Model`
72
- model = adapter.instance_to_model(ommx_instance_bytes)
60
+ model = adapter.instance_to_model(ommx_instance)
73
61
  model.optimize()
74
- # Create `ommx.v1.SolutionList` from Optimized `mip.Model`
75
- ommx_solutions_bytes = adapter.model_to_solution(
76
- model, ommx_instance_bytes
77
- )
62
+ # Create `ommx.v1.State` from Optimized `mip.Model`
63
+ ommx_solutions = adapter.model_to_solution(model, ommx_instance)
78
64
 
79
- print(SolutionList.FromString(ommx_solutions_bytes))
65
+ print(ommx_solutions)
80
66
  ```
67
+
81
68
  You can get `ommx.v1.Instance` from a Python-MIP model as the following:
69
+
82
70
  ```python markdown-code-runner
83
71
  import mip
84
72
  import ommx_python_mip_adapter as adapter
85
- from ommx.v1.instance_pb2 import Instance
86
73
 
87
74
  model = mip.Model()
88
75
  x1=model.add_var(name="1", var_type=mip.INTEGER, lb=0, ub=5)
@@ -90,9 +77,9 @@ x2=model.add_var(name="2", var_type=mip.CONTINUOUS, lb=0, ub=5)
90
77
  model.objective = - x1 - 2 * x2
91
78
  model.add_constr(x1 + x2 - 6 <= 0)
92
79
 
93
- ommx_instance_bytes = adapter.model_to_instance(model)
80
+ ommx_instance = adapter.model_to_instance(model)
94
81
 
95
- print(Instance.FromString(ommx_instance_bytes))
82
+ print(ommx_instance)
96
83
  ```
97
84
 
98
85
  Reference
@@ -8,4 +8,4 @@ __all__ = [
8
8
  "instance_to_model",
9
9
  "model_to_instance",
10
10
  "model_to_solution",
11
- ]
11
+ ]
@@ -3,12 +3,11 @@ import typing as tp
3
3
  import mip
4
4
 
5
5
  from mip.exceptions import ParameterNotAvailable
6
- from ommx.v1.constraint_pb2 import Constraint
7
- from ommx.v1.decision_variables_pb2 import DecisionVariable, Bound
6
+ from ommx.v1.constraint_pb2 import Constraint, Equality
8
7
  from ommx.v1.function_pb2 import Function
9
- from ommx.v1.instance_pb2 import Instance
10
8
  from ommx.v1.linear_pb2 import Linear
11
- from ommx.v1.solution_pb2 import Solution, SolutionList
9
+ from ommx.v1.solution_pb2 import State
10
+ from ommx.v1 import Instance, DecisionVariable
12
11
 
13
12
  from ommx_python_mip_adapter.exception import OMMXPythonMIPAdapterError
14
13
 
@@ -16,71 +15,65 @@ from ommx_python_mip_adapter.exception import OMMXPythonMIPAdapterError
16
15
  class PythonMIPBuilder:
17
16
  def __init__(
18
17
  self,
19
- ommx_instance_bytes: bytes,
18
+ instance: Instance,
20
19
  *,
21
20
  sense: str = mip.MINIMIZE,
22
21
  solver_name: str = mip.CBC,
23
22
  solver: tp.Optional[mip.Solver] = None,
24
23
  ):
25
- try:
26
- self._ommx_instance = Instance.FromString(ommx_instance_bytes)
27
- except Exception as e:
28
- raise OMMXPythonMIPAdapterError(
29
- "Invalid `ommx_instance_bytes` as ommx.v1.Instance."
30
- ) from e
31
-
24
+ self._ommx_instance = instance.raw
32
25
  self._model = mip.Model(
33
26
  sense=sense,
34
27
  solver_name=solver_name,
35
28
  solver=solver,
36
29
  )
37
30
 
38
-
39
31
  def _set_decision_variables(self):
40
32
  for var in self._ommx_instance.decision_variables:
41
- if var.kind == DecisionVariable.KIND_BINARY:
33
+ if var.kind == DecisionVariable.BINARY:
42
34
  self._model.add_var(
43
35
  name=str(var.id),
44
36
  var_type=mip.BINARY,
45
37
  )
46
- elif var.kind == DecisionVariable.KIND_INTEGER:
38
+ elif var.kind == DecisionVariable.INTEGER:
47
39
  self._model.add_var(
48
40
  name=str(var.id),
49
41
  var_type=mip.INTEGER,
50
- lb=var.bound.lower, # type: ignore
51
- ub=var.bound.upper, # type: ignore
42
+ lb=var.bound.lower, # type: ignore
43
+ ub=var.bound.upper, # type: ignore
52
44
  )
53
- elif var.kind == DecisionVariable.KIND_CONTINUOUS:
45
+ elif var.kind == DecisionVariable.CONTINUOUS:
54
46
  self._model.add_var(
55
47
  name=str(var.id),
56
48
  var_type=mip.CONTINUOUS,
57
- lb=var.bound.lower, # type: ignore
58
- ub=var.bound.upper, # type: ignore
49
+ lb=var.bound.lower, # type: ignore
50
+ ub=var.bound.upper, # type: ignore
59
51
  )
60
52
  else:
61
53
  raise OMMXPythonMIPAdapterError(
62
54
  f"Not supported decision variable kind: "
63
55
  f"id: {var.id}, kind: {var.kind}"
64
56
  )
65
-
66
-
57
+
67
58
  def _make_linear_expr(
68
59
  self,
69
60
  ommx_function: Function,
70
- ) -> mip.LinExpr:
61
+ ) -> mip.LinExpr:
71
62
  ommx_linear = ommx_function.linear
72
63
 
73
- return mip.xsum(
74
- term.coefficient * self._model.vars[str(term.id)] # type: ignore
75
- for term in ommx_linear.terms
76
- ) + ommx_linear.constant # type: ignore
64
+ return (
65
+ mip.xsum(
66
+ term.coefficient * self._model.vars[str(term.id)] # type: ignore
67
+ for term in ommx_linear.terms
68
+ )
69
+ + ommx_linear.constant
70
+ ) # type: ignore
77
71
 
78
-
79
72
  def _set_objective_function(self):
80
73
  ommx_objective = self._ommx_instance.objective
81
74
 
82
75
  if ommx_objective.HasField("constant"):
83
- self._model.objective = ommx_objective.constant # type: ignore
76
+ self._model.objective = ommx_objective.constant # type: ignore
84
77
  elif ommx_objective.HasField("linear"):
85
78
  self._model.objective = self._make_linear_expr(ommx_objective)
86
79
  else:
@@ -88,7 +81,6 @@ class PythonMIPBuilder:
88
81
  "The objective function must be either `constant` or `linear`."
89
82
  )
90
83
 
91
-
92
84
  def _set_constraints(self):
93
85
  ommx_constraints = self._ommx_instance.constraints
94
86
 
@@ -102,18 +94,17 @@ class PythonMIPBuilder:
102
94
 
103
95
  lin_expr = self._make_linear_expr(constraint.function)
104
96
 
105
- if constraint.equality == Constraint.EQUALITY_EQUAL_TO_ZERO:
106
- constr_expr = (lin_expr == 0)
107
- elif (constraint.equality == Constraint.EQUALITY_LESS_THAN_OR_EQUAL_TO_ZERO):
108
- constr_expr = (lin_expr <= 0) # type: ignore
97
+ if constraint.equality == Equality.EQUALITY_EQUAL_TO_ZERO:
98
+ constr_expr = lin_expr == 0
99
+ elif constraint.equality == Equality.EQUALITY_LESS_THAN_OR_EQUAL_TO_ZERO:
100
+ constr_expr = lin_expr <= 0 # type: ignore
109
101
  else:
110
102
  raise OMMXPythonMIPAdapterError(
111
103
  f"Not supported constraint equality: "
112
104
  f"id: {constraint.id}, equality: {constraint.equality}"
113
105
  )
114
-
115
- self._model.add_constr(constr_expr, name=str(constraint.id))
116
106
 
107
+ self._model.add_constr(constr_expr, name=str(constraint.id))
117
108
 
118
109
  def build(self) -> mip.Model:
119
110
  self._set_decision_variables()
@@ -135,11 +126,11 @@ class OMMXInstanceBuilder:
135
126
 
136
127
  for var in self._model.vars:
137
128
  if var.var_type == mip.BINARY:
138
- kind = DecisionVariable.KIND_BINARY
129
+ kind = DecisionVariable.BINARY
139
130
  elif var.var_type == mip.INTEGER:
140
- kind = DecisionVariable.KIND_INTEGER
131
+ kind = DecisionVariable.INTEGER
141
132
  elif var.var_type == mip.CONTINUOUS:
142
- kind = DecisionVariable.KIND_CONTINUOUS
133
+ kind = DecisionVariable.CONTINUOUS
143
134
  else:
144
135
  raise OMMXPythonMIPAdapterError(
145
136
  f"Not supported variable type. "
@@ -147,35 +138,28 @@ class OMMXInstanceBuilder:
147
138
  )
148
139
 
149
140
  decision_variables.append(
150
- DecisionVariable(
151
- id=var.idx,
152
- kind=kind,
153
- bound=Bound(lower=var.lb, upper=var.ub),
154
- description=DecisionVariable.Description(name=var.name)
141
+ DecisionVariable.of_type(
142
+ kind, var.idx, lower=var.lb, upper=var.ub, name=var.name
155
143
  )
156
144
  )
157
145
 
158
146
  return decision_variables
159
-
160
147
 
161
148
  def _make_function_from_lin_expr(
162
149
  self,
163
150
  lin_expr: mip.LinExpr,
164
151
  ) -> Function:
165
152
  terms = [
166
- Linear.Term(id=var.idx, coefficient=coeff) # type: ignore
153
+ Linear.Term(id=var.idx, coefficient=coeff) # type: ignore
167
154
  for var, coeff in lin_expr.expr.items()
168
155
  ]
169
- constant: float = lin_expr.const # type: ignore
156
+ constant: float = lin_expr.const # type: ignore
170
157
 
171
158
  # If the terms are empty, the function is a constant.
172
159
  if len(terms) == 0:
173
160
  return Function(constant=constant)
174
161
  else:
175
- return Function(
176
- linear=Linear(terms=terms, constant=constant)
177
- )
178
-
162
+ return Function(linear=Linear(terms=terms, constant=constant))
179
163
 
180
164
  def _objective(self) -> Function:
181
165
  # In Python-MIP, it is allowed not to set the objective function.
@@ -186,9 +170,8 @@ class OMMXInstanceBuilder:
186
170
  objective = self._model.objective
187
171
  except ParameterNotAvailable:
188
172
  return Function(constant=0)
189
-
190
- return self._make_function_from_lin_expr(objective)
191
173
 
174
+ return self._make_function_from_lin_expr(objective)
192
175
 
193
176
  def _constraints(self) -> tp.List[Constraint]:
194
177
  constraints = []
@@ -201,55 +184,53 @@ class OMMXInstanceBuilder:
201
184
  if lin_expr.sense == "=":
202
185
  constraint = Constraint(
203
186
  id=id,
204
- equality=Constraint.EQUALITY_EQUAL_TO_ZERO,
187
+ equality=Equality.EQUALITY_EQUAL_TO_ZERO,
205
188
  function=self._make_function_from_lin_expr(lin_expr),
206
- description=Constraint.Description(name=name),
189
+ name=name,
207
190
  )
208
191
  elif lin_expr.sense == "<":
209
192
  constraint = Constraint(
210
193
  id=id,
211
- equality=Constraint.EQUALITY_LESS_THAN_OR_EQUAL_TO_ZERO,
194
+ equality=Equality.EQUALITY_LESS_THAN_OR_EQUAL_TO_ZERO,
212
195
  function=self._make_function_from_lin_expr(lin_expr),
213
- description=Constraint.Description(name=name),
196
+ name=name,
214
197
  )
215
198
  elif lin_expr.sense == ">":
216
199
  # `ommx.v1.Constraint` does not support `GREATER_THAN_OR_EQUAL_TO_ZERO`.
217
200
  # So multiply the linear expression by -1.
218
201
  constraint = Constraint(
219
202
  id=id,
220
- equality=Constraint.EQUALITY_LESS_THAN_OR_EQUAL_TO_ZERO,
203
+ equality=Equality.EQUALITY_LESS_THAN_OR_EQUAL_TO_ZERO,
221
204
  function=self._make_function_from_lin_expr(-lin_expr),
222
- description=Constraint.Description(name=name),
205
+ name=name,
223
206
  )
224
207
  else:
225
208
  raise OMMXPythonMIPAdapterError(
226
209
  f"Not supported constraint sense: "
227
210
  f"name: {constr.name}, sense: {lin_expr.sense}"
228
211
  )
229
-
212
+
230
213
  constraints.append(constraint)
231
214
 
232
215
  return constraints
233
216
 
234
-
235
217
  def _sense(self):
236
218
  if self._model.sense == mip.MAXIMIZE:
237
- return Instance.SENSE_MAXIMIZE
219
+ return Instance.MAXIMIZE
238
220
  else:
239
- return Instance.SENSE_MINIMIZE
221
+ return Instance.MINIMIZE
240
222
 
241
-
242
- def build(self) -> bytes:
243
- return Instance(
223
+ def build(self) -> Instance:
224
+ return Instance.from_components(
244
225
  decision_variables=self._decision_variables(),
245
226
  objective=self._objective(),
246
227
  constraints=self._constraints(),
247
228
  sense=self._sense(),
248
- ).SerializeToString()
229
+ )
249
230
 
250
231
 
251
232
  def instance_to_model(
252
- ommx_instance_bytes: bytes,
233
+ instance: Instance,
253
234
  *,
254
235
  sense: str = mip.MINIMIZE,
255
236
  solver_name: str = mip.CBC,
@@ -260,7 +241,7 @@ def instance_to_model(
260
241
 
261
242
  Args:
262
243
  ommx_instance_bytes (bytes): Serialized ommx.v1.Instance.
263
- sense (str): mip.MINIMIZE or mip.MAXIMIZE.
244
+ sense (str): mip.MINIMIZE or mip.MAXIMIZE.
264
245
  solver_name (str): mip.CBC or mip.GUROBI. Searches for which solver is available if not informed.
265
246
  solver (mip.Solver): if this argument is provided, solver_name will be ignored.
266
247
 
@@ -274,37 +255,25 @@ def instance_to_model(
274
255
  The following example of solving an unconstrained linear optimization problem with x1 as the objective function.
275
256
 
276
257
  >>> import ommx_python_mip_adapter as adapter
277
- >>> from ommx.v1.decision_variables_pb2 import DecisionVariable, Bound
278
- >>> from ommx.v1.instance_pb2 import Instance
279
- >>> from ommx.v1.function_pb2 import Function
280
- >>> from ommx.v1.linear_pb2 import Linear
281
- >>> from ommx.v1.solution_pb2 import SolutionList
282
- >>> ommx_instance = Instance(
283
- ... decision_variables=[
284
- ... DecisionVariable(
285
- ... id=1,
286
- ... kind=DecisionVariable.KIND_INTEGER,
287
- ... bound=Bound(lower=0, upper=5),
288
- ... ),
289
- ... ],
290
- ... objective=Function(
291
- ... linear=Linear(
292
- ... terms=[Linear.Term(id=1, coefficient=1)]
293
- ... ),
294
- ... ),
258
+ >>> from ommx.v1 import Instance, DecisionVariable
259
+
260
+ >>> x1 = DecisionVariable.integer(1, lower=0, upper=5)
261
+ >>> ommx_instance = Instance.from_components(
262
+ ... decision_variables=[x1],
263
+ ... objective=x1,
264
+ ... constraints=[],
265
+ ... sense=Instance.MINIMIZE,
295
266
  ... )
296
- >>> ommx_instance_bytes = ommx_instance.SerializeToString()
297
- >>> model = adapter.instance_to_model(ommx_instance_bytes)
267
+ >>> model = adapter.instance_to_model(ommx_instance)
298
268
  >>> model.optimize()
299
269
  <OptimizationStatus.OPTIMAL: 0>
300
- >>> ommx_solutions_bytes = adapter.model_to_solution(
301
- ... model, ommx_instance_bytes
302
- ... )
303
- >>> SolutionList.FromString(ommx_solutions_bytes).solutions[0].entries
270
+
271
+ >>> ommx_solutions = adapter.model_to_solution(model, ommx_instance)
272
+ >>> ommx_solutions.entries
304
273
  {1: 0.0}
305
274
  """
306
275
  builder = PythonMIPBuilder(
307
- ommx_instance_bytes,
276
+ instance,
308
277
  sense=sense,
309
278
  solver_name=solver_name,
310
279
  solver=solver,
@@ -312,13 +281,13 @@ def instance_to_model(
312
281
  return builder.build()
313
282
 
314
283
 
315
- def model_to_instance(model: mip.Model) -> bytes:
284
+ def model_to_instance(model: mip.Model) -> Instance:
316
285
  """
317
286
  The function to convert Python-MIP Model to ommx.v1.Instance.
318
287
 
319
288
  Args:
320
289
  model (mip.Model): Python-MIP Model.
321
-
290
+
322
291
  Returns:
323
292
  bytes: Serialized ommx.v1.Instance.
324
293
 
@@ -328,14 +297,12 @@ def model_to_instance(model: mip.Model) -> bytes:
328
297
  Examples:
329
298
  >>> import mip
330
299
  >>> import ommx_python_mip_adapter as adapter
331
- >>> from ommx.v1.instance_pb2 import Instance
332
300
  >>> model = mip.Model()
333
301
  >>> x1=model.add_var(name="1", var_type=mip.INTEGER, lb=0, ub=5)
334
302
  >>> x2=model.add_var(name="2", var_type=mip.CONTINUOUS, lb=0, ub=5)
335
303
  >>> model.objective = - x1 - 2 * x2
336
304
  >>> constr = model.add_constr(x1 + x2 - 6 <= 0)
337
- >>> ommx_instance_bytes = adapter.model_to_instance(model)
338
- >>> ommx_instance = Instance.FromString(ommx_instance_bytes)
305
+ >>> ommx_instance = adapter.model_to_instance(model)
339
306
  """
340
307
  builder = OMMXInstanceBuilder(model)
341
308
  return builder.build()
@@ -343,8 +310,8 @@ def model_to_instance(model: mip.Model) -> bytes:
343
310
 
344
311
  def model_to_solution(
345
312
  model: mip.Model,
346
- ommx_instance_bytes: bytes,
347
- ) -> bytes:
313
+ instance: Instance,
314
+ ) -> State:
348
315
  """
349
316
  The function to create ommx.v1.SolutionList from optimized Python-MIP Model.
350
317
 
@@ -362,33 +329,21 @@ def model_to_solution(
362
329
  The following example of solving an unconstrained linear optimization problem with x1 as the objective function.
363
330
 
364
331
  >>> import ommx_python_mip_adapter as adapter
365
- >>> from ommx.v1.decision_variables_pb2 import DecisionVariable, Bound
366
- >>> from ommx.v1.instance_pb2 import Instance
367
- >>> from ommx.v1.function_pb2 import Function
368
- >>> from ommx.v1.linear_pb2 import Linear
369
- >>> from ommx.v1.solution_pb2 import SolutionList
370
- >>> ommx_instance = Instance(
371
- ... decision_variables=[
372
- ... DecisionVariable(
373
- ... id=1,
374
- ... kind=DecisionVariable.KIND_INTEGER,
375
- ... bound=Bound(lower=0, upper=5),
376
- ... ),
377
- ... ],
378
- ... objective=Function(
379
- ... linear=Linear(
380
- ... terms=[Linear.Term(id=1, coefficient=1)]
381
- ... ),
382
- ... ),
332
+ >>> from ommx.v1 import Instance, DecisionVariable
333
+
334
+ >>> x1 = DecisionVariable.integer(1, lower=0, upper=5)
335
+ >>> ommx_instance = Instance.from_components(
336
+ ... decision_variables=[x1],
337
+ ... objective=x1,
338
+ ... constraints=[],
339
+ ... sense=Instance.MINIMIZE,
383
340
  ... )
384
- >>> ommx_instance_bytes = ommx_instance.SerializeToString()
385
- >>> model = adapter.instance_to_model(ommx_instance_bytes)
341
+ >>> model = adapter.instance_to_model(ommx_instance)
386
342
  >>> model.optimize()
387
343
  <OptimizationStatus.OPTIMAL: 0>
388
- >>> ommx_solutions_bytes = adapter.model_to_solution(
389
- ... model, ommx_instance_bytes
390
- ... )
391
- >>> SolutionList.FromString(ommx_solutions_bytes).solutions[0].entries
344
+
345
+ >>> ommx_solutions = adapter.model_to_solution(model, ommx_instance)
346
+ >>> ommx_solutions.entries
392
347
  {1: 0.0}
393
348
  """
394
349
  if not (
@@ -399,20 +354,9 @@ def model_to_solution(
399
354
  "`model.status` must be `OPTIMAL` or `FEASIBLE`."
400
355
  )
401
356
 
402
- try:
403
- ommx_instance = Instance.FromString(ommx_instance_bytes)
404
- except Exception as e:
405
- raise OMMXPythonMIPAdapterError(
406
- "Invalid `ommx_instance_bytes` as ommx.v1.Instance."
407
- ) from e
408
-
409
- return SolutionList(
410
- solutions=[
411
- Solution(
412
- entries={
413
- var.id: model.var_by_name(str(var.id)).x # type: ignore
414
- for var in ommx_instance.decision_variables
415
- }
416
- )
417
- ]
418
- ).SerializeToString()
357
+ return State(
358
+ entries={
359
+ var.id: model.var_by_name(str(var.id)).x # type: ignore
360
+ for var in instance.raw.decision_variables
361
+ }
362
+ )