Add exception handling to the solver creation call

This is a very targeted addition, which can be generalized. It
makes the following changes:

1. In the solver creation call of the Gurobi interface, i.e.
the constructor `GurobiInterface::GurobiInterface`, the GLOG
severity level is reduced to `DFATAL`, which becomes `ERROR` in
production. This means errors in calls to `GRBloadenv` no longer
automatically kill the process as a side effect.

2. An `std::runtime_error` exception is raised with the return code
and the error message from GRBloadenv. This replaces the functionality
of exiting the process when this error is unhandled. Additionally,
it enables alternate handling by the caller.

3. In the linear solver SWIG wrapper, exception wrapping is turned
on specifically for the `MPSolver::MPSolver` constructor call and
the `std::runtime_error` that may now occur there. This exception
is re-raised as the corresponding RuntimeError in the target language.

Addresses issue #699.
This commit is contained in:
Ying-zong Huang
2018-05-24 21:40:38 -04:00
parent 225e819021
commit b400cf8c2f
2 changed files with 19 additions and 4 deletions

View File

@@ -21,6 +21,7 @@
#include <string>
#include <utility>
#include <vector>
#include <stdexcept>
#include "ortools/base/commandlineflags.h"
#include "ortools/base/integral_types.h"
@@ -176,10 +177,13 @@ class GurobiInterface : public MPSolverInterface {
// Creates a LP/MIP instance with the specified name and minimization objective.
GurobiInterface::GurobiInterface(MPSolver* const solver, bool mip)
: MPSolverInterface(solver), model_(nullptr), env_(nullptr), mip_(mip) {
if (GRBloadenv(&env_, nullptr) != 0 || env_ == nullptr) {
LOG(FATAL) << "Error: could not create environment: "
<< GRBgeterrormsg(env_);
}
int ret = GRBloadenv(&env_, nullptr);
if (ret != 0 || env_ == nullptr) {
std::string err_msg = GRBgeterrormsg(env_);
LOG(DFATAL) << "Error: could not create environment: " << err_msg;
throw std::runtime_error(std::to_string(ret) + ", " + err_msg);
}
CheckedGurobiCall(GRBnewmodel(env_, &model_, solver_->name_.c_str(),
0, // numvars

View File

@@ -73,6 +73,17 @@ from ortools.linear_solver.linear_solver_natural_api import VariableExpr
} // %pythoncode
}
// Catch runtime exceptions in class methods
%extend MPSolver {
%exception MPSolver {
try {
$action
} catch ( std::runtime_error& e ) {
SWIG_exception(SWIG_RuntimeError, e.what());
}
}
}
%extend MPSolver {
// Change a (bool, std::string*) outputs to a python std::string (empty if bool=false).
std::string ExportModelAsLpFormat(bool obfuscated) {