14"""Solve optimization problems, as defined by Model in model.py."""
16from typing
import Callable, Optional
30from pybind11_abseil.status
import StatusNotOk
36 opt_model: model.Model,
41 msg_cb: Optional[message_callback.SolveMessageCallback] =
None,
43 cb: Optional[SolveCallback] =
None,
46 """Solves an optimization model.
48 Thread-safety: this function must not be called while modifying the Model
49 (adding variables...). Some solvers may add more restriction regarding
50 threading. Please see SolverType::XXX documentation for details.
53 opt_model: The optimization model.
54 solver_type: The underlying solver to use.
55 params: Configuration of the underlying solver.
56 model_params: Configuration of the solver that is model specific.
57 msg_cb: A callback that gives back the underlying solver's logs by the line.
58 callback_reg: Configures when the callback will be invoked (if provided) and
59 what data will be collected to access in the callback.
60 cb: A callback that will be called periodically as the solver runs.
61 streamable_init_args: Configuration for initializing the underlying solver.
64 A SolveResult containing the termination reason, solution(s) and stats.
67 RuntimeError: On a solve error.
74 streamable_init_args = (
77 model_proto = opt_model.export_model()
80 proto_cb =
lambda x: cb(
81 callback.parse_callback_data(x, opt_model)
85 proto_result = solver.solve(
88 streamable_init_args.to_proto(),
90 model_params.to_proto(),
92 callback_reg.to_proto(),
96 except StatusNotOk
as e:
98 return result.parse_solve_result(proto_result, opt_model)
102 opt_model: model.Model,
106 msg_cb: Optional[message_callback.SolveMessageCallback] =
None,
109 """Computes an infeasible subsystem of the input model.
112 opt_model: The optimization model to check for infeasibility.
113 solver_type: Which solver to use to compute the infeasible subsystem. As of
114 August 2023, the only supported solver is Gurobi.
115 params: Configuration of the underlying solver.
116 msg_cb: A callback that gives back the underlying solver's logs by the line.
117 streamable_init_args: Configuration for initializing the underlying solver.
120 An `ComputeInfeasibleSubsystemResult` where `feasibility` indicates if the
121 problem was proven infeasible.
124 RuntimeError: on invalid inputs or an internal solver error.
127 streamable_init_args = (
130 model_proto = opt_model.export_model()
133 proto_result = solver.compute_infeasible_subsystem(
136 streamable_init_args.to_proto(),
141 except StatusNotOk
as e:
144 compute_infeasible_subsystem_result.parse_compute_infeasible_subsystem_result(
145 proto_result, opt_model
151 """Solve an optimization multiple times, with modifications between solves.
153 Prefer calling simply solve() above in most cases when incrementalism is not
156 Thread-safety: The __init__(), solve() methods must not be called while
157 modifying the Model (adding variables...). The user is expected to use proper
158 synchronization primitives to serialize changes to the model and the use of
159 this object. Note though that it is safe to call methods from different
160 IncrementalSolver instances on the same Model concurrently. The solve() method
161 must not be called concurrently on different threads for the same
162 IncrementalSolver. Some solvers may add more restriction regarding
163 threading. Please see to SolverType::XXX documentation for details.
165 This class references some resources that are freed when it is garbage
166 collected (which should usually happen when the last reference is lost). In
167 particular, it references some C++ objects. Although it is not mandatory, it
168 is recommended to free those as soon as possible. To do so it is possible to
169 use this class in the `with` statement:
171 with IncrementalSolver(model, SolverType.GLOP) as solver:
174 When it is not possible to use `with`, the close() method can be called.
179 opt_model: model.Model,
182 streamable_init_args: Optional[
186 streamable_init_args = (
195 self.
_model.export_model(),
196 streamable_init_args.to_proto(),
198 except StatusNotOk
as e:
207 msg_cb: Optional[message_callback.SolveMessageCallback] =
None,
209 cb: Optional[SolveCallback] =
None,
211 """Solves the current optimization model.
214 params: The non-model specific solve parameters.
215 model_params: The model specific solve parameters.
216 msg_cb: An optional callback for solver messages.
217 callback_reg: The parameters controlling when cb is called.
218 cb: An optional callback for LP/MIP events.
221 The result of the solve.
224 RuntimeError: If called after being closed, or on a solve error.
227 raise RuntimeError(
"the solver is closed")
230 if update
is not None:
235 self.
_model.export_model(),
236 parameters_pb2.SolverInitializerProto(),
238 except StatusNotOk
as e:
246 proto_cb =
lambda x: cb(
247 callback.parse_callback_data(x, self.
_model)
252 model_params.to_proto(),
254 callback_reg.to_proto(),
258 except StatusNotOk
as e:
260 return result.parse_solve_result(result_proto, self.
_model)
263 """Closes this solver, freeing all its resources.
265 This is optional, the code is correct without calling this function. See the
266 class documentation for details.
268 After a solver has been closed, it can't be used anymore. Prefer using the
269 context manager API when possible instead of calling close() directly:
271 with IncrementalSolver(model, SolverType.GLOP) as solver:
284 """Returns the solver itself."""
289 exc_type: Optional[type[BaseException]],
290 exc_val: Optional[BaseException],
291 exc_tb: Optional[types.TracebackType],
293 """Closes the solver."""
298 """Converts a StatusNotOk to the best matching Python exception.
301 err: The input errors.
304 The corresponding exception.
306 ret = errors.status_proto_to_exception(
307 rpc_pb2.StatusProto(code=err.canonical_code, message=err.message)
310 assert ret
is not None, err