ortools.math_opt.python.solve
Solve optimization problems, as defined by Model in model.py.
1#!/usr/bin/env python3 2# Copyright 2010-2025 Google LLC 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15"""Solve optimization problems, as defined by Model in model.py.""" 16import types 17from typing import Callable, Optional 18 19from ortools.math_opt import parameters_pb2 20from ortools.math_opt import rpc_pb2 21from ortools.math_opt.core.python import solver 22from ortools.math_opt.python import callback 23from ortools.math_opt.python import compute_infeasible_subsystem_result 24from ortools.math_opt.python import errors 25from ortools.math_opt.python import init_arguments 26from ortools.math_opt.python import message_callback 27from ortools.math_opt.python import model 28from ortools.math_opt.python import model_parameters 29from ortools.math_opt.python import parameters 30from ortools.math_opt.python import result 31from ortools.util.python import solve_interrupter 32from pybind11_abseil.status import StatusNotOk 33 34SolveCallback = Callable[[callback.CallbackData], callback.CallbackResult] 35 36 37def solve( 38 opt_model: model.Model, 39 solver_type: parameters.SolverType, 40 *, 41 params: Optional[parameters.SolveParameters] = None, 42 model_params: Optional[model_parameters.ModelSolveParameters] = None, 43 msg_cb: Optional[message_callback.SolveMessageCallback] = None, 44 callback_reg: Optional[callback.CallbackRegistration] = None, 45 cb: Optional[SolveCallback] = None, 46 streamable_init_args: Optional[init_arguments.StreamableSolverInitArguments] = None, 47 remove_names: bool = False, 48 interrupter: Optional[solve_interrupter.SolveInterrupter] = None, 49) -> result.SolveResult: 50 """Solves an optimization model. 51 52 Thread-safety: this function must not be called while modifying the Model 53 (adding variables...). Some solvers may add more restriction regarding 54 threading. Please see SolverType::XXX documentation for details. 55 56 Args: 57 opt_model: The optimization model. 58 solver_type: The underlying solver to use. 59 params: Configuration of the underlying solver. 60 model_params: Configuration of the solver that is model specific. 61 msg_cb: A callback that gives back the underlying solver's logs by the line. 62 callback_reg: Configures when the callback will be invoked (if provided) and 63 what data will be collected to access in the callback. 64 cb: A callback that will be called periodically as the solver runs. 65 streamable_init_args: Configuration for initializing the underlying solver. 66 remove_names: When true, remove all names for the ModelProto. 67 interrupter: An optional interrupter that the solver can use to interrupt 68 the solve early. 69 70 Returns: 71 A SolveResult containing the termination reason, solution(s) and stats. 72 73 Raises: 74 RuntimeError: On a solve error. 75 """ 76 # First, initialize optional arguments that were not set to default values. 77 # Note that in python, default arguments must be immutable, and these are not. 78 params = params or parameters.SolveParameters() 79 model_params = model_params or model_parameters.ModelSolveParameters() 80 callback_reg = callback_reg or callback.CallbackRegistration() 81 streamable_init_args = ( 82 streamable_init_args or init_arguments.StreamableSolverInitArguments() 83 ) 84 model_proto = opt_model.export_model(remove_names=remove_names) 85 proto_cb = None 86 if cb is not None: 87 proto_cb = lambda x: cb( # pylint: disable=g-long-lambda 88 callback.parse_callback_data(x, opt_model) 89 ).to_proto() 90 # Solve 91 try: 92 proto_result = solver.solve( 93 model_proto, 94 solver_type.value, 95 streamable_init_args.to_proto(), 96 params.to_proto(), 97 model_params.to_proto(), 98 msg_cb, 99 callback_reg.to_proto(), 100 proto_cb, 101 interrupter.pybind_interrupter if interrupter is not None else None, 102 ) 103 except StatusNotOk as e: 104 raise _status_not_ok_to_exception(e) from None 105 return result.parse_solve_result(proto_result, opt_model, validate=False) 106 107 108def compute_infeasible_subsystem( 109 opt_model: model.Model, 110 solver_type: parameters.SolverType, 111 *, 112 params: Optional[parameters.SolveParameters] = None, 113 msg_cb: Optional[message_callback.SolveMessageCallback] = None, 114 streamable_init_args: Optional[init_arguments.StreamableSolverInitArguments] = None, 115 remove_names: bool = False, 116 interrupter: Optional[solve_interrupter.SolveInterrupter] = None, 117) -> compute_infeasible_subsystem_result.ComputeInfeasibleSubsystemResult: 118 """Computes an infeasible subsystem of the input model. 119 120 Args: 121 opt_model: The optimization model to check for infeasibility. 122 solver_type: Which solver to use to compute the infeasible subsystem. As of 123 August 2023, the only supported solver is Gurobi. 124 params: Configuration of the underlying solver. 125 msg_cb: A callback that gives back the underlying solver's logs by the line. 126 streamable_init_args: Configuration for initializing the underlying solver. 127 remove_names: When true, remove all names for the ModelProto. 128 interrupter: An optional interrupter that the solver can use to interrupt 129 the solve early. 130 131 Returns: 132 An `ComputeInfeasibleSubsystemResult` where `feasibility` indicates if the 133 problem was proven infeasible. 134 135 Throws: 136 RuntimeError: on invalid inputs or an internal solver error. 137 """ 138 params = params or parameters.SolveParameters() 139 streamable_init_args = ( 140 streamable_init_args or init_arguments.StreamableSolverInitArguments() 141 ) 142 model_proto = opt_model.export_model(remove_names=remove_names) 143 # Solve 144 try: 145 proto_result = solver.compute_infeasible_subsystem( 146 model_proto, 147 solver_type.value, 148 streamable_init_args.to_proto(), 149 params.to_proto(), 150 msg_cb, 151 interrupter.pybind_interrupter if interrupter is not None else None, 152 ) 153 except StatusNotOk as e: 154 raise _status_not_ok_to_exception(e) from None 155 return ( 156 compute_infeasible_subsystem_result.parse_compute_infeasible_subsystem_result( 157 proto_result, opt_model 158 ) 159 ) 160 161 162class IncrementalSolver: 163 """Solve an optimization multiple times, with modifications between solves. 164 165 Prefer calling simply solve() above in most cases when incrementalism is not 166 needed. 167 168 Thread-safety: The __init__(), solve() methods must not be called while 169 modifying the Model (adding variables...). The user is expected to use proper 170 synchronization primitives to serialize changes to the model and the use of 171 this object. Note though that it is safe to call methods from different 172 IncrementalSolver instances on the same Model concurrently. The solve() method 173 must not be called concurrently on different threads for the same 174 IncrementalSolver. Some solvers may add more restriction regarding 175 threading. Please see to SolverType::XXX documentation for details. 176 177 This class references some resources that are freed when it is garbage 178 collected (which should usually happen when the last reference is lost). In 179 particular, it references some C++ objects. Although it is not mandatory, it 180 is recommended to free those as soon as possible. To do so it is possible to 181 use this class in the `with` statement: 182 183 with IncrementalSolver(model, SolverType.GLOP) as solver: 184 ... 185 186 When it is not possible to use `with`, the close() method can be called. 187 """ 188 189 def __init__( 190 self, 191 opt_model: model.Model, 192 solver_type: parameters.SolverType, 193 *, 194 streamable_init_args: Optional[ 195 init_arguments.StreamableSolverInitArguments 196 ] = None, 197 remove_names: bool = False, 198 ): 199 streamable_init_args = ( 200 streamable_init_args or init_arguments.StreamableSolverInitArguments() 201 ) 202 self._model = opt_model 203 self._solver_type = solver_type 204 self._update_tracker = self._model.add_update_tracker() 205 try: 206 self._proto_solver = solver.new( 207 solver_type.value, 208 self._model.export_model(remove_names=remove_names), 209 streamable_init_args.to_proto(), 210 ) 211 except StatusNotOk as e: 212 raise _status_not_ok_to_exception(e) from None 213 self._closed = False 214 215 def solve( 216 self, 217 *, 218 params: Optional[parameters.SolveParameters] = None, 219 model_params: Optional[model_parameters.ModelSolveParameters] = None, 220 msg_cb: Optional[message_callback.SolveMessageCallback] = None, 221 callback_reg: Optional[callback.CallbackRegistration] = None, 222 cb: Optional[SolveCallback] = None, 223 interrupter: Optional[solve_interrupter.SolveInterrupter] = None, 224 ) -> result.SolveResult: 225 """Solves the current optimization model. 226 227 Args: 228 params: The non-model specific solve parameters. 229 model_params: The model specific solve parameters. 230 msg_cb: An optional callback for solver messages. 231 callback_reg: The parameters controlling when cb is called. 232 cb: An optional callback for LP/MIP events. 233 interrupter: An optional interrupter that the solver can use to interrupt 234 the solve early. 235 236 Returns: 237 The result of the solve. 238 239 Raises: 240 RuntimeError: If called after being closed, or on a solve error. 241 """ 242 if self._closed: 243 raise RuntimeError("the solver is closed") 244 245 update = self._update_tracker.export_update() 246 if update is not None: 247 try: 248 if not self._proto_solver.update(update): 249 self._proto_solver = solver.new( 250 self._solver_type.value, 251 self._model.export_model(), 252 parameters_pb2.SolverInitializerProto(), 253 ) 254 except StatusNotOk as e: 255 raise _status_not_ok_to_exception(e) from None 256 self._update_tracker.advance_checkpoint() 257 params = params or parameters.SolveParameters() 258 model_params = model_params or model_parameters.ModelSolveParameters() 259 callback_reg = callback_reg or callback.CallbackRegistration() 260 proto_cb = None 261 if cb is not None: 262 proto_cb = lambda x: cb( # pylint: disable=g-long-lambda 263 callback.parse_callback_data(x, self._model) 264 ).to_proto() 265 try: 266 result_proto = self._proto_solver.solve( 267 params.to_proto(), 268 model_params.to_proto(), 269 msg_cb, 270 callback_reg.to_proto(), 271 proto_cb, 272 interrupter.pybind_interrupter if interrupter is not None else None, 273 ) 274 except StatusNotOk as e: 275 raise _status_not_ok_to_exception(e) from None 276 return result.parse_solve_result(result_proto, self._model, validate=False) 277 278 def close(self) -> None: 279 """Closes this solver, freeing all its resources. 280 281 This is optional, the code is correct without calling this function. See the 282 class documentation for details. 283 284 After a solver has been closed, it can't be used anymore. Prefer using the 285 context manager API when possible instead of calling close() directly: 286 287 with IncrementalSolver(model, SolverType.GLOP) as solver: 288 ... 289 """ 290 if self._closed: 291 return 292 self._closed = True 293 294 del self._model 295 del self._solver_type 296 del self._update_tracker 297 del self._proto_solver 298 299 def __enter__(self) -> "IncrementalSolver": 300 """Returns the solver itself.""" 301 return self 302 303 def __exit__( 304 self, 305 exc_type: Optional[type[BaseException]], 306 exc_val: Optional[BaseException], 307 exc_tb: Optional[types.TracebackType], 308 ) -> None: 309 """Closes the solver.""" 310 self.close() 311 312 313def _status_not_ok_to_exception(err: StatusNotOk) -> Exception: 314 """Converts a StatusNotOk to the best matching Python exception. 315 316 Args: 317 err: The input errors. 318 319 Returns: 320 The corresponding exception. 321 """ 322 ret = errors.status_proto_to_exception( 323 rpc_pb2.StatusProto(code=err.canonical_code, message=err.message) 324 ) 325 # We never expect StatusNotOk to be OK. 326 assert ret is not None, err 327 return ret
38def solve( 39 opt_model: model.Model, 40 solver_type: parameters.SolverType, 41 *, 42 params: Optional[parameters.SolveParameters] = None, 43 model_params: Optional[model_parameters.ModelSolveParameters] = None, 44 msg_cb: Optional[message_callback.SolveMessageCallback] = None, 45 callback_reg: Optional[callback.CallbackRegistration] = None, 46 cb: Optional[SolveCallback] = None, 47 streamable_init_args: Optional[init_arguments.StreamableSolverInitArguments] = None, 48 remove_names: bool = False, 49 interrupter: Optional[solve_interrupter.SolveInterrupter] = None, 50) -> result.SolveResult: 51 """Solves an optimization model. 52 53 Thread-safety: this function must not be called while modifying the Model 54 (adding variables...). Some solvers may add more restriction regarding 55 threading. Please see SolverType::XXX documentation for details. 56 57 Args: 58 opt_model: The optimization model. 59 solver_type: The underlying solver to use. 60 params: Configuration of the underlying solver. 61 model_params: Configuration of the solver that is model specific. 62 msg_cb: A callback that gives back the underlying solver's logs by the line. 63 callback_reg: Configures when the callback will be invoked (if provided) and 64 what data will be collected to access in the callback. 65 cb: A callback that will be called periodically as the solver runs. 66 streamable_init_args: Configuration for initializing the underlying solver. 67 remove_names: When true, remove all names for the ModelProto. 68 interrupter: An optional interrupter that the solver can use to interrupt 69 the solve early. 70 71 Returns: 72 A SolveResult containing the termination reason, solution(s) and stats. 73 74 Raises: 75 RuntimeError: On a solve error. 76 """ 77 # First, initialize optional arguments that were not set to default values. 78 # Note that in python, default arguments must be immutable, and these are not. 79 params = params or parameters.SolveParameters() 80 model_params = model_params or model_parameters.ModelSolveParameters() 81 callback_reg = callback_reg or callback.CallbackRegistration() 82 streamable_init_args = ( 83 streamable_init_args or init_arguments.StreamableSolverInitArguments() 84 ) 85 model_proto = opt_model.export_model(remove_names=remove_names) 86 proto_cb = None 87 if cb is not None: 88 proto_cb = lambda x: cb( # pylint: disable=g-long-lambda 89 callback.parse_callback_data(x, opt_model) 90 ).to_proto() 91 # Solve 92 try: 93 proto_result = solver.solve( 94 model_proto, 95 solver_type.value, 96 streamable_init_args.to_proto(), 97 params.to_proto(), 98 model_params.to_proto(), 99 msg_cb, 100 callback_reg.to_proto(), 101 proto_cb, 102 interrupter.pybind_interrupter if interrupter is not None else None, 103 ) 104 except StatusNotOk as e: 105 raise _status_not_ok_to_exception(e) from None 106 return result.parse_solve_result(proto_result, opt_model, validate=False)
Solves an optimization model.
Thread-safety: this function must not be called while modifying the Model (adding variables...). Some solvers may add more restriction regarding threading. Please see SolverType::XXX documentation for details.
Arguments:
- opt_model: The optimization model.
- solver_type: The underlying solver to use.
- params: Configuration of the underlying solver.
- model_params: Configuration of the solver that is model specific.
- msg_cb: A callback that gives back the underlying solver's logs by the line.
- callback_reg: Configures when the callback will be invoked (if provided) and what data will be collected to access in the callback.
- cb: A callback that will be called periodically as the solver runs.
- streamable_init_args: Configuration for initializing the underlying solver.
- remove_names: When true, remove all names for the ModelProto.
- interrupter: An optional interrupter that the solver can use to interrupt the solve early.
Returns:
A SolveResult containing the termination reason, solution(s) and stats.
Raises:
- RuntimeError: On a solve error.
109def compute_infeasible_subsystem( 110 opt_model: model.Model, 111 solver_type: parameters.SolverType, 112 *, 113 params: Optional[parameters.SolveParameters] = None, 114 msg_cb: Optional[message_callback.SolveMessageCallback] = None, 115 streamable_init_args: Optional[init_arguments.StreamableSolverInitArguments] = None, 116 remove_names: bool = False, 117 interrupter: Optional[solve_interrupter.SolveInterrupter] = None, 118) -> compute_infeasible_subsystem_result.ComputeInfeasibleSubsystemResult: 119 """Computes an infeasible subsystem of the input model. 120 121 Args: 122 opt_model: The optimization model to check for infeasibility. 123 solver_type: Which solver to use to compute the infeasible subsystem. As of 124 August 2023, the only supported solver is Gurobi. 125 params: Configuration of the underlying solver. 126 msg_cb: A callback that gives back the underlying solver's logs by the line. 127 streamable_init_args: Configuration for initializing the underlying solver. 128 remove_names: When true, remove all names for the ModelProto. 129 interrupter: An optional interrupter that the solver can use to interrupt 130 the solve early. 131 132 Returns: 133 An `ComputeInfeasibleSubsystemResult` where `feasibility` indicates if the 134 problem was proven infeasible. 135 136 Throws: 137 RuntimeError: on invalid inputs or an internal solver error. 138 """ 139 params = params or parameters.SolveParameters() 140 streamable_init_args = ( 141 streamable_init_args or init_arguments.StreamableSolverInitArguments() 142 ) 143 model_proto = opt_model.export_model(remove_names=remove_names) 144 # Solve 145 try: 146 proto_result = solver.compute_infeasible_subsystem( 147 model_proto, 148 solver_type.value, 149 streamable_init_args.to_proto(), 150 params.to_proto(), 151 msg_cb, 152 interrupter.pybind_interrupter if interrupter is not None else None, 153 ) 154 except StatusNotOk as e: 155 raise _status_not_ok_to_exception(e) from None 156 return ( 157 compute_infeasible_subsystem_result.parse_compute_infeasible_subsystem_result( 158 proto_result, opt_model 159 ) 160 )
Computes an infeasible subsystem of the input model.
Arguments:
- opt_model: The optimization model to check for infeasibility.
- solver_type: Which solver to use to compute the infeasible subsystem. As of August 2023, the only supported solver is Gurobi.
- params: Configuration of the underlying solver.
- msg_cb: A callback that gives back the underlying solver's logs by the line.
- streamable_init_args: Configuration for initializing the underlying solver.
- remove_names: When true, remove all names for the ModelProto.
- interrupter: An optional interrupter that the solver can use to interrupt the solve early.
Returns:
An
ComputeInfeasibleSubsystemResultwherefeasibilityindicates if the problem was proven infeasible.
Throws:
RuntimeError: on invalid inputs or an internal solver error.
163class IncrementalSolver: 164 """Solve an optimization multiple times, with modifications between solves. 165 166 Prefer calling simply solve() above in most cases when incrementalism is not 167 needed. 168 169 Thread-safety: The __init__(), solve() methods must not be called while 170 modifying the Model (adding variables...). The user is expected to use proper 171 synchronization primitives to serialize changes to the model and the use of 172 this object. Note though that it is safe to call methods from different 173 IncrementalSolver instances on the same Model concurrently. The solve() method 174 must not be called concurrently on different threads for the same 175 IncrementalSolver. Some solvers may add more restriction regarding 176 threading. Please see to SolverType::XXX documentation for details. 177 178 This class references some resources that are freed when it is garbage 179 collected (which should usually happen when the last reference is lost). In 180 particular, it references some C++ objects. Although it is not mandatory, it 181 is recommended to free those as soon as possible. To do so it is possible to 182 use this class in the `with` statement: 183 184 with IncrementalSolver(model, SolverType.GLOP) as solver: 185 ... 186 187 When it is not possible to use `with`, the close() method can be called. 188 """ 189 190 def __init__( 191 self, 192 opt_model: model.Model, 193 solver_type: parameters.SolverType, 194 *, 195 streamable_init_args: Optional[ 196 init_arguments.StreamableSolverInitArguments 197 ] = None, 198 remove_names: bool = False, 199 ): 200 streamable_init_args = ( 201 streamable_init_args or init_arguments.StreamableSolverInitArguments() 202 ) 203 self._model = opt_model 204 self._solver_type = solver_type 205 self._update_tracker = self._model.add_update_tracker() 206 try: 207 self._proto_solver = solver.new( 208 solver_type.value, 209 self._model.export_model(remove_names=remove_names), 210 streamable_init_args.to_proto(), 211 ) 212 except StatusNotOk as e: 213 raise _status_not_ok_to_exception(e) from None 214 self._closed = False 215 216 def solve( 217 self, 218 *, 219 params: Optional[parameters.SolveParameters] = None, 220 model_params: Optional[model_parameters.ModelSolveParameters] = None, 221 msg_cb: Optional[message_callback.SolveMessageCallback] = None, 222 callback_reg: Optional[callback.CallbackRegistration] = None, 223 cb: Optional[SolveCallback] = None, 224 interrupter: Optional[solve_interrupter.SolveInterrupter] = None, 225 ) -> result.SolveResult: 226 """Solves the current optimization model. 227 228 Args: 229 params: The non-model specific solve parameters. 230 model_params: The model specific solve parameters. 231 msg_cb: An optional callback for solver messages. 232 callback_reg: The parameters controlling when cb is called. 233 cb: An optional callback for LP/MIP events. 234 interrupter: An optional interrupter that the solver can use to interrupt 235 the solve early. 236 237 Returns: 238 The result of the solve. 239 240 Raises: 241 RuntimeError: If called after being closed, or on a solve error. 242 """ 243 if self._closed: 244 raise RuntimeError("the solver is closed") 245 246 update = self._update_tracker.export_update() 247 if update is not None: 248 try: 249 if not self._proto_solver.update(update): 250 self._proto_solver = solver.new( 251 self._solver_type.value, 252 self._model.export_model(), 253 parameters_pb2.SolverInitializerProto(), 254 ) 255 except StatusNotOk as e: 256 raise _status_not_ok_to_exception(e) from None 257 self._update_tracker.advance_checkpoint() 258 params = params or parameters.SolveParameters() 259 model_params = model_params or model_parameters.ModelSolveParameters() 260 callback_reg = callback_reg or callback.CallbackRegistration() 261 proto_cb = None 262 if cb is not None: 263 proto_cb = lambda x: cb( # pylint: disable=g-long-lambda 264 callback.parse_callback_data(x, self._model) 265 ).to_proto() 266 try: 267 result_proto = self._proto_solver.solve( 268 params.to_proto(), 269 model_params.to_proto(), 270 msg_cb, 271 callback_reg.to_proto(), 272 proto_cb, 273 interrupter.pybind_interrupter if interrupter is not None else None, 274 ) 275 except StatusNotOk as e: 276 raise _status_not_ok_to_exception(e) from None 277 return result.parse_solve_result(result_proto, self._model, validate=False) 278 279 def close(self) -> None: 280 """Closes this solver, freeing all its resources. 281 282 This is optional, the code is correct without calling this function. See the 283 class documentation for details. 284 285 After a solver has been closed, it can't be used anymore. Prefer using the 286 context manager API when possible instead of calling close() directly: 287 288 with IncrementalSolver(model, SolverType.GLOP) as solver: 289 ... 290 """ 291 if self._closed: 292 return 293 self._closed = True 294 295 del self._model 296 del self._solver_type 297 del self._update_tracker 298 del self._proto_solver 299 300 def __enter__(self) -> "IncrementalSolver": 301 """Returns the solver itself.""" 302 return self 303 304 def __exit__( 305 self, 306 exc_type: Optional[type[BaseException]], 307 exc_val: Optional[BaseException], 308 exc_tb: Optional[types.TracebackType], 309 ) -> None: 310 """Closes the solver.""" 311 self.close()
Solve an optimization multiple times, with modifications between solves.
Prefer calling simply solve() above in most cases when incrementalism is not needed.
Thread-safety: The __init__(), solve() methods must not be called while modifying the Model (adding variables...). The user is expected to use proper synchronization primitives to serialize changes to the model and the use of this object. Note though that it is safe to call methods from different IncrementalSolver instances on the same Model concurrently. The solve() method must not be called concurrently on different threads for the same IncrementalSolver. Some solvers may add more restriction regarding threading. Please see to SolverType::XXX documentation for details.
This class references some resources that are freed when it is garbage
collected (which should usually happen when the last reference is lost). In
particular, it references some C++ objects. Although it is not mandatory, it
is recommended to free those as soon as possible. To do so it is possible to
use this class in the with statement:
with IncrementalSolver(model, SolverType.GLOP) as solver: ...
When it is not possible to use with, the close() method can be called.
190 def __init__( 191 self, 192 opt_model: model.Model, 193 solver_type: parameters.SolverType, 194 *, 195 streamable_init_args: Optional[ 196 init_arguments.StreamableSolverInitArguments 197 ] = None, 198 remove_names: bool = False, 199 ): 200 streamable_init_args = ( 201 streamable_init_args or init_arguments.StreamableSolverInitArguments() 202 ) 203 self._model = opt_model 204 self._solver_type = solver_type 205 self._update_tracker = self._model.add_update_tracker() 206 try: 207 self._proto_solver = solver.new( 208 solver_type.value, 209 self._model.export_model(remove_names=remove_names), 210 streamable_init_args.to_proto(), 211 ) 212 except StatusNotOk as e: 213 raise _status_not_ok_to_exception(e) from None 214 self._closed = False
216 def solve( 217 self, 218 *, 219 params: Optional[parameters.SolveParameters] = None, 220 model_params: Optional[model_parameters.ModelSolveParameters] = None, 221 msg_cb: Optional[message_callback.SolveMessageCallback] = None, 222 callback_reg: Optional[callback.CallbackRegistration] = None, 223 cb: Optional[SolveCallback] = None, 224 interrupter: Optional[solve_interrupter.SolveInterrupter] = None, 225 ) -> result.SolveResult: 226 """Solves the current optimization model. 227 228 Args: 229 params: The non-model specific solve parameters. 230 model_params: The model specific solve parameters. 231 msg_cb: An optional callback for solver messages. 232 callback_reg: The parameters controlling when cb is called. 233 cb: An optional callback for LP/MIP events. 234 interrupter: An optional interrupter that the solver can use to interrupt 235 the solve early. 236 237 Returns: 238 The result of the solve. 239 240 Raises: 241 RuntimeError: If called after being closed, or on a solve error. 242 """ 243 if self._closed: 244 raise RuntimeError("the solver is closed") 245 246 update = self._update_tracker.export_update() 247 if update is not None: 248 try: 249 if not self._proto_solver.update(update): 250 self._proto_solver = solver.new( 251 self._solver_type.value, 252 self._model.export_model(), 253 parameters_pb2.SolverInitializerProto(), 254 ) 255 except StatusNotOk as e: 256 raise _status_not_ok_to_exception(e) from None 257 self._update_tracker.advance_checkpoint() 258 params = params or parameters.SolveParameters() 259 model_params = model_params or model_parameters.ModelSolveParameters() 260 callback_reg = callback_reg or callback.CallbackRegistration() 261 proto_cb = None 262 if cb is not None: 263 proto_cb = lambda x: cb( # pylint: disable=g-long-lambda 264 callback.parse_callback_data(x, self._model) 265 ).to_proto() 266 try: 267 result_proto = self._proto_solver.solve( 268 params.to_proto(), 269 model_params.to_proto(), 270 msg_cb, 271 callback_reg.to_proto(), 272 proto_cb, 273 interrupter.pybind_interrupter if interrupter is not None else None, 274 ) 275 except StatusNotOk as e: 276 raise _status_not_ok_to_exception(e) from None 277 return result.parse_solve_result(result_proto, self._model, validate=False)
Solves the current optimization model.
Arguments:
- params: The non-model specific solve parameters.
- model_params: The model specific solve parameters.
- msg_cb: An optional callback for solver messages.
- callback_reg: The parameters controlling when cb is called.
- cb: An optional callback for LP/MIP events.
- interrupter: An optional interrupter that the solver can use to interrupt the solve early.
Returns:
The result of the solve.
Raises:
- RuntimeError: If called after being closed, or on a solve error.
279 def close(self) -> None: 280 """Closes this solver, freeing all its resources. 281 282 This is optional, the code is correct without calling this function. See the 283 class documentation for details. 284 285 After a solver has been closed, it can't be used anymore. Prefer using the 286 context manager API when possible instead of calling close() directly: 287 288 with IncrementalSolver(model, SolverType.GLOP) as solver: 289 ... 290 """ 291 if self._closed: 292 return 293 self._closed = True 294 295 del self._model 296 del self._solver_type 297 del self._update_tracker 298 del self._proto_solver
Closes this solver, freeing all its resources.
This is optional, the code is correct without calling this function. See the class documentation for details.
After a solver has been closed, it can't be used anymore. Prefer using the context manager API when possible instead of calling close() directly:
with IncrementalSolver(model, SolverType.GLOP) as solver: ...