18 #if !defined(_MSC_VER)
27 #include "absl/status/status.h"
28 #include "absl/status/statusor.h"
29 #include "absl/strings/ascii.h"
30 #include "absl/strings/match.h"
31 #include "absl/strings/str_cat.h"
32 #include "absl/strings/str_format.h"
33 #include "absl/strings/str_replace.h"
34 #include "absl/synchronization/mutex.h"
49 "Systematically verify the solution when calling Solve()"
50 ", and change the return value of Solve() to ABNORMAL if"
51 " an error was detected.");
53 "If --verify_solution is set: LOG(ERROR) all errors detected"
54 " during the verification of the solution.");
55 ABSL_FLAG(
bool, linear_solver_enable_verbose_output,
false,
56 "If set, enables verbose output for the solver. Setting this flag"
57 " is the same as calling MPSolver::EnableOutput().");
59 ABSL_FLAG(
bool, mpsolver_bypass_model_validation,
false,
60 "If set, the user-provided Model won't be verified before Solve()."
61 " Invalid models will typically trigger various error responses"
62 " from the underlying solvers; sometimes crashes.");
67 switch (solver_type) {
68 case MPModelRequest::GLOP_LINEAR_PROGRAMMING:
69 case MPModelRequest::CLP_LINEAR_PROGRAMMING:
70 case MPModelRequest::GLPK_LINEAR_PROGRAMMING:
71 case MPModelRequest::GUROBI_LINEAR_PROGRAMMING:
72 case MPModelRequest::XPRESS_LINEAR_PROGRAMMING:
73 case MPModelRequest::CPLEX_LINEAR_PROGRAMMING:
76 case MPModelRequest::SCIP_MIXED_INTEGER_PROGRAMMING:
77 case MPModelRequest::GLPK_MIXED_INTEGER_PROGRAMMING:
78 case MPModelRequest::CBC_MIXED_INTEGER_PROGRAMMING:
79 case MPModelRequest::GUROBI_MIXED_INTEGER_PROGRAMMING:
80 case MPModelRequest::KNAPSACK_MIXED_INTEGER_PROGRAMMING:
81 case MPModelRequest::BOP_INTEGER_PROGRAMMING:
82 case MPModelRequest::SAT_INTEGER_PROGRAMMING:
83 case MPModelRequest::XPRESS_MIXED_INTEGER_PROGRAMMING:
84 case MPModelRequest::CPLEX_MIXED_INTEGER_PROGRAMMING:
87 LOG(DFATAL) <<
"Invalid SolverType: " << solver_type;
93 if (
var ==
nullptr)
return 0.0;
99 if (
var ==
nullptr)
return;
101 auto it = coefficients_.find(
var);
109 if (it != coefficients_.end() && it->second != 0.0) {
110 const double old_value = it->second;
116 auto insertion_result = coefficients_.insert(std::make_pair(
var, coeff));
117 const double old_value =
118 insertion_result.second ? 0.0 : insertion_result.first->second;
119 insertion_result.first->second = coeff;
125 coefficients_.clear();
129 const bool change =
lb != lb_ ||
ub != ub_;
139 LOG(DFATAL) <<
"Dual value only available for continuous problems";
148 LOG(DFATAL) <<
"Basis status only available for continuous problems";
158 bool MPConstraint::ContainsNewVariables() {
160 for (
const auto& entry : coefficients_) {
161 const int variable_index = entry.first->index();
162 if (variable_index >= last_variable_index ||
174 if (
var ==
nullptr)
return 0.0;
180 if (
var ==
nullptr)
return;
182 auto it = coefficients_.find(
var);
185 if (it == coefficients_.end() || it->second == 0.0)
return;
188 coefficients_[
var] = coeff;
200 for (
auto var_value_pair : linear_expr.
terms()) {
202 <<
"Bad MPVariable* in LinearExpr, did you try adding an integer to an "
203 "MPVariable* directly?";
209 bool is_maximization) {
210 CheckLinearExpr(*interface_->
solver_, linear_expr);
212 coefficients_.clear();
214 for (
const auto& kv : linear_expr.
terms()) {
221 CheckLinearExpr(*interface_->
solver_, linear_expr);
223 for (
const auto& kv : linear_expr.
terms()) {
230 coefficients_.clear();
270 return (integer_ && interface_->
IsMIP()) ? round(solution_value_)
276 return solution_value_;
281 LOG(DFATAL) <<
"Reduced cost only available for continuous problems";
285 return reduced_cost_;
290 LOG(DFATAL) <<
"Basis status only available for continuous problems";
301 const bool change =
lb != lb_ ||
ub != ub_;
319 if (priority == branching_priority_)
return;
320 branching_priority_ = priority;
329 return interface_->SolverVersion();
337 if (num_threads < 1) {
338 return absl::InvalidArgumentError(
"num_threads must be a positive number.");
340 const absl::Status status = interface_->SetNumThreads(num_threads);
342 num_threads_ = num_threads;
349 solver_specific_parameter_string_ =
parameters;
350 return interface_->SetSolverSpecificParametersAsString(
parameters);
355 #if defined(USE_CLP) || defined(USE_CBC)
361 #if defined(USE_GLPK)
367 #if defined(USE_SCIP)
372 #if defined(USE_CPLEX)
377 #if defined(USE_XPRESS)
384 DCHECK(solver !=
nullptr);
392 #if defined(USE_GLPK)
394 return BuildGLPKInterface(
false, solver);
396 return BuildGLPKInterface(
true, solver);
398 #if defined(USE_CLP) || defined(USE_CBC)
406 #if defined(USE_SCIP)
414 #if defined(USE_CPLEX)
416 return BuildCplexInterface(
false, solver);
418 return BuildCplexInterface(
true, solver);
420 #if defined(USE_XPRESS)
422 return BuildXpressInterface(
true, solver);
424 return BuildXpressInterface(
false, solver);
428 LOG(
FATAL) <<
"Linear solver not recognized.";
435 int NumDigits(
int n) {
438 #if defined(_MSC_VER)
439 return static_cast<int>(
std::max(1.0L, log(1.0L * n) / log(10.0L) + 1.0));
441 return static_cast<int>(
std::max(1.0, log10(
static_cast<double>(n)) + 1.0));
450 construction_time_(
absl::Now()) {
451 interface_.reset(BuildSolverInterface(
this));
452 if (absl::GetFlag(FLAGS_linear_solver_enable_verbose_output)) {
455 objective_.reset(
new MPObjective(interface_.get()));
505 struct NamedOptimizationProblemType {
511 #if defined(_MSC_VER)
538 const std::string
id =
539 absl::StrReplaceAll(absl::AsciiStrToUpper(solver_id), {{
"-",
"_"}});
542 MPModelRequest::SolverType solver_type;
543 if (MPModelRequest::SolverType_Parse(
id, &solver_type)) {
549 std::string lower_id = absl::AsciiStrToLower(
id);
552 if (absl::EndsWith(lower_id,
"_mip")) {
553 lower_id = lower_id.substr(0, lower_id.size() - 4);
557 if (lower_id ==
"cp_sat") {
563 if (named_solver.name == lower_id) {
564 *type = named_solver.problem_type;
575 if (named_solver.problem_type == optimization_problem_type) {
576 return named_solver.name;
579 LOG(
FATAL) <<
"Unrecognized solver type: "
580 <<
static_cast<int>(optimization_problem_type);
586 std::string* error) {
587 DCHECK(solver_type !=
nullptr);
591 *error = absl::StrCat(
"Solver type: ", text,
" does not exist.");
598 const std::string& solver_id) {
608 LOG(
WARNING) <<
"Unrecognized solver type: " << solver_id;
613 <<
" not linked in, or the license was not found.";
621 if (!variable_name_to_index_) GenerateVariableNameIndex();
623 absl::flat_hash_map<std::string, int>::const_iterator it =
624 variable_name_to_index_->find(var_name);
625 if (it == variable_name_to_index_->end())
return nullptr;
626 return variables_[it->second];
630 const std::string& constraint_name)
const {
631 if (!constraint_name_to_index_) GenerateConstraintNameIndex();
633 const auto it = constraint_name_to_index_->find(constraint_name);
634 if (it == constraint_name_to_index_->end())
return nullptr;
635 return constraints_[it->second];
641 const MPModelProto& input_model, std::string* error_message) {
648 return LoadModelFromProtoInternal(input_model,
true,
654 const MPModelProto& input_model, std::string* error_message) {
658 GenerateVariableNameIndex();
659 GenerateConstraintNameIndex();
661 return LoadModelFromProtoInternal(input_model,
false,
667 const MPModelProto& input_model,
bool clear_names,
668 bool check_model_validity, std::string* error_message) {
669 CHECK(error_message !=
nullptr);
670 if (check_model_validity) {
672 if (!error.empty()) {
673 *error_message = error;
675 <<
"Invalid model given to LoadModelFromProto(): " << error;
676 if (absl::GetFlag(FLAGS_mpsolver_bypass_model_validation)) {
678 <<
"Ignoring the model error(s) because of"
679 <<
" --mpsolver_bypass_model_validation.";
687 if (input_model.has_quadratic_objective()) {
689 "Optimizing a quadratic objective is only supported through direct "
690 "proto solves. Please use MPSolver::SolveWithProto, or the solver's "
691 "direct proto solve function.";
697 const std::string empty;
698 for (
int i = 0; i < input_model.variable_size(); ++i) {
699 const MPVariableProto& var_proto = input_model.variable(i);
701 MakeNumVar(var_proto.lower_bound(), var_proto.upper_bound(),
702 clear_names ? empty : var_proto.name());
704 if (var_proto.branching_priority() != 0) {
707 objective->SetCoefficient(
variable, var_proto.objective_coefficient());
710 for (
const MPConstraintProto& ct_proto : input_model.constraint()) {
711 if (ct_proto.lower_bound() == -
infinity() &&
712 ct_proto.upper_bound() ==
infinity()) {
716 MPConstraint*
const ct =
718 clear_names ? empty : ct_proto.name());
719 ct->set_is_lazy(ct_proto.is_lazy());
720 for (
int j = 0; j < ct_proto.var_index_size(); ++j) {
721 ct->SetCoefficient(variables_[ct_proto.var_index(j)],
722 ct_proto.coefficient(j));
726 for (
const MPGeneralConstraintProto& general_constraint :
727 input_model.general_constraint()) {
728 switch (general_constraint.general_constraint_case()) {
729 case MPGeneralConstraintProto::kIndicatorConstraint: {
731 general_constraint.indicator_constraint().constraint();
738 MPConstraint*
const constraint =
new MPConstraint(
739 constraint_index,
proto.lower_bound(),
proto.upper_bound(),
740 clear_names ?
"" :
proto.name(), interface_.get());
741 if (constraint_name_to_index_) {
746 constraint_is_extracted_.push_back(
false);
749 for (
int j = 0; j <
proto.var_index_size(); ++j) {
751 proto.coefficient(j));
755 variables_[general_constraint.indicator_constraint().var_index()];
758 general_constraint.indicator_constraint().var_value();
760 if (!interface_->AddIndicatorConstraint(
constraint)) {
761 *error_message =
"Solver doesn't support indicator constraints";
767 *error_message = absl::StrFormat(
768 "Optimizing general constraints of type %i is only supported "
769 "through direct proto solves. Please use MPSolver::SolveWithProto, "
770 "or the solver's direct proto solve function.",
771 general_constraint.general_constraint_case());
776 objective->SetOptimizationDirection(input_model.maximize());
777 if (input_model.has_objective_offset()) {
778 objective->SetOffset(input_model.objective_offset());
782 solution_hint_.clear();
783 for (
int i = 0; i < input_model.solution_hint().var_index_size(); ++i) {
784 solution_hint_.push_back(
785 std::make_pair(variables_[input_model.solution_hint().var_index(i)],
786 input_model.solution_hint().var_value(i)));
818 ResultStatusToMPSolverResponseStatus(interface_->result_status_));
822 for (
int i = 0; i < variables_.size(); ++i) {
823 response->add_variable_value(variables_[i]->solution_value());
826 if (interface_->IsMIP()) {
827 response->set_best_objective_bound(interface_->best_objective_bound());
830 for (
int j = 0; j < constraints_.size(); ++j) {
831 response->add_dual_value(constraints_[j]->dual_value());
834 for (
int i = 0; i < variables_.size(); ++i) {
835 response->add_reduced_cost(variables_[i]->reduced_cost());
845 MPSolver solver(model_request.model().name(),
847 model_request.solver_type()));
848 if (model_request.enable_internal_solver_output()) {
852 auto optional_response = solver.interface_->DirectlySolveProto(model_request);
853 if (optional_response) {
854 *
response = std::move(optional_response).value();
858 const absl::optional<LazyMutableCopy<MPModelProto>> optional_model =
860 if (!optional_model) {
861 LOG_IF(
WARNING, model_request.enable_internal_solver_output())
862 <<
"Failed to extract a valid model from protocol buffer. Status: "
863 << ProtoEnumToString<MPSolverResponseStatus>(
response->status()) <<
" ("
867 std::string error_message;
868 response->set_status(solver.LoadModelFromProtoInternal(
869 optional_model->get(),
true,
870 false, &error_message));
874 response->set_status_str(error_message);
875 LOG_IF(
WARNING, model_request.enable_internal_solver_output())
876 <<
"LoadModelFromProtoInternal() failed even though the model was "
878 << ProtoEnumToString<MPSolverResponseStatus>(
response->status()) <<
" ("
879 <<
response->status() <<
"); Error: " << error_message;
882 if (model_request.has_solver_time_limit_seconds()) {
884 absl::Seconds(model_request.solver_time_limit_seconds()));
886 std::string warning_message;
887 if (model_request.has_solver_specific_parameters()) {
889 model_request.solver_specific_parameters())) {
890 if (model_request.ignore_solver_specific_parameters_failure()) {
893 "Warning: the solver specific parameters were not successfully "
903 if (!warning_message.empty()) {
904 response->set_status_str(absl::StrCat(
911 DCHECK(output_model !=
nullptr);
912 output_model->Clear();
914 output_model->set_name(
Name());
916 for (
int j = 0; j < variables_.size(); ++j) {
918 MPVariableProto*
const variable_proto = output_model->add_variable();
921 variable_proto->set_name(
var->name());
922 variable_proto->set_lower_bound(
var->lb());
923 variable_proto->set_upper_bound(
var->ub());
924 variable_proto->set_is_integer(
var->integer());
925 if (objective_->GetCoefficient(
var) != 0.0) {
926 variable_proto->set_objective_coefficient(
927 objective_->GetCoefficient(
var));
929 if (
var->branching_priority() != 0) {
930 variable_proto->set_branching_priority(
var->branching_priority());
940 absl::flat_hash_map<const MPVariable*, int> var_to_index;
941 for (
int j = 0; j < variables_.size(); ++j) {
942 var_to_index[variables_[j]] = j;
946 for (
int i = 0; i < constraints_.size(); ++i) {
948 MPConstraintProto* constraint_proto;
950 MPGeneralConstraintProto*
const general_constraint_proto =
951 output_model->add_general_constraint();
953 MPIndicatorConstraint*
const indicator_constraint_proto =
954 general_constraint_proto->mutable_indicator_constraint();
955 indicator_constraint_proto->set_var_index(
958 constraint_proto = indicator_constraint_proto->mutable_constraint();
960 constraint_proto = output_model->add_constraint();
968 std::vector<std::pair<int, double>> linear_term;
969 for (
const auto& entry :
constraint->coefficients_) {
973 const double coeff = entry.second;
974 linear_term.push_back(std::pair<int, double>(var_index, coeff));
978 std::sort(linear_term.begin(), linear_term.end());
980 for (
const std::pair<int, double>& var_and_coeff : linear_term) {
981 constraint_proto->add_var_index(var_and_coeff.first);
982 constraint_proto->add_coefficient(var_and_coeff.second);
986 output_model->set_maximize(
Objective().maximization());
987 output_model->set_objective_offset(
Objective().offset());
989 if (!solution_hint_.empty()) {
990 PartialVariableAssignment*
const hint =
991 output_model->mutable_solution_hint();
992 for (
const auto& var_value_pair : solution_hint_) {
993 hint->add_var_index(var_value_pair.first->index());
994 hint->add_var_value(var_value_pair.second);
1004 return absl::InvalidArgumentError(absl::StrCat(
1005 "Cannot load a solution unless its status is OPTIMAL or FEASIBLE"
1007 ProtoEnumToString<MPSolverResponseStatus>(
response.status()),
")"));
1012 if (
response.variable_value_size() != variables_.size()) {
1013 return absl::InvalidArgumentError(absl::StrCat(
1014 "Trying to load a solution whose number of variables (",
1016 ") does not correspond to the Solver's (", variables_.size(),
")"));
1018 interface_->ExtractModel();
1022 double largest_error = 0;
1023 int num_vars_out_of_bounds = 0;
1024 int last_offending_var = -1;
1025 for (
int i = 0; i <
response.variable_value_size(); ++i) {
1026 const double var_value =
response.variable_value(i);
1029 const double lb_error =
var->lb() - var_value;
1030 const double ub_error = var_value -
var->ub();
1031 if (lb_error > tolerance || ub_error > tolerance) {
1032 ++num_vars_out_of_bounds;
1034 last_offending_var = i;
1037 if (num_vars_out_of_bounds > 0) {
1038 return absl::InvalidArgumentError(absl::StrCat(
1039 "Loaded a solution whose variables matched the solver's, but ",
1040 num_vars_out_of_bounds,
" of ", variables_.size(),
1041 " variables were out of their bounds, by more than the primal"
1042 " tolerance which is: ",
1043 tolerance,
". Max error: ", largest_error,
", last offender var is #",
1044 last_offending_var,
": '", variables_[last_offending_var]->name(),
1048 for (
int i = 0; i <
response.variable_value_size(); ++i) {
1049 variables_[i]->set_solution_value(
response.variable_value(i));
1051 if (
response.dual_value_size() > 0) {
1052 if (
response.dual_value_size() != constraints_.size()) {
1053 return absl::InvalidArgumentError(absl::StrCat(
1054 "Trying to load a dual solution whose number of entries (",
1055 response.dual_value_size(),
") does not correspond to the Solver's (",
1056 constraints_.size(),
")"));
1058 for (
int i = 0; i <
response.dual_value_size(); ++i) {
1059 constraints_[i]->set_dual_value(
response.dual_value(i));
1062 if (
response.reduced_cost_size() > 0) {
1063 if (
response.reduced_cost_size() != variables_.size()) {
1064 return absl::InvalidArgumentError(absl::StrCat(
1065 "Trying to load a reduced cost solution whose number of entries (",
1067 ") does not correspond to the Solver's (", variables_.size(),
")"));
1069 for (
int i = 0; i <
response.reduced_cost_size(); ++i) {
1070 variables_[i]->set_reduced_cost(
response.reduced_cost(i));
1075 if (
response.has_objective_value()) {
1076 interface_->objective_value_ =
response.objective_value();
1078 if (
response.has_best_objective_bound()) {
1079 interface_->best_objective_bound_ =
response.best_objective_bound();
1084 return absl::OkStatus();
1092 if (variable_name_to_index_) {
1093 variable_name_to_index_->clear();
1095 variable_is_extracted_.clear();
1096 constraints_.clear();
1097 if (constraint_name_to_index_) {
1098 constraint_name_to_index_->clear();
1100 constraint_is_extracted_.clear();
1101 interface_->Reset();
1102 solution_hint_.clear();
1110 const std::vector<BasisStatus>& variable_statuses,
1111 const std::vector<BasisStatus>& constraint_statuses) {
1112 interface_->SetStartingLpBasis(variable_statuses, constraint_statuses);
1116 const std::string&
name) {
1119 new MPVariable(var_index, lb, ub, integer,
name, interface_.get());
1120 if (variable_name_to_index_) {
1123 variables_.push_back(v);
1124 variable_is_extracted_.push_back(
false);
1125 interface_->AddVariable(v);
1130 const std::string&
name) {
1135 const std::string&
name) {
1144 const std::string&
name,
1145 std::vector<MPVariable*>* vars) {
1147 if (nb <= 0)
return;
1148 const int num_digits = NumDigits(nb);
1149 for (
int i = 0; i < nb; ++i) {
1154 absl::StrFormat(
"%s%0*d",
name.c_str(), num_digits, i);
1155 vars->push_back(
MakeVar(lb, ub, integer, vname));
1161 const std::string&
name,
1162 std::vector<MPVariable*>* vars) {
1167 const std::string&
name,
1168 std::vector<MPVariable*>* vars) {
1173 std::vector<MPVariable*>* vars) {
1186 const std::string&
name) {
1190 if (constraint_name_to_index_) {
1195 constraint_is_extracted_.push_back(
false);
1209 const std::string&
name) {
1219 int MPSolver::ComputeMaxConstraintSize(
int min_constraint_index,
1220 int max_constraint_index)
const {
1221 int max_constraint_size = 0;
1223 DCHECK_LE(max_constraint_index, constraints_.size());
1224 for (
int i = min_constraint_index; i < max_constraint_index; ++i) {
1226 if (
ct->coefficients_.size() > max_constraint_size) {
1227 max_constraint_size =
ct->coefficients_.size();
1230 return max_constraint_size;
1233 bool MPSolver::HasInfeasibleConstraints()
const {
1234 bool hasInfeasibleConstraints =
false;
1235 for (
int i = 0; i < constraints_.size(); ++i) {
1236 if (constraints_[i]->lb() > constraints_[i]->ub()) {
1237 LOG(
WARNING) <<
"Constraint " << constraints_[i]->name() <<
" (" << i
1238 <<
") has contradictory bounds:"
1239 <<
" lower bound = " << constraints_[i]->lb()
1240 <<
" upper bound = " << constraints_[i]->ub();
1241 hasInfeasibleConstraints =
true;
1244 return hasInfeasibleConstraints;
1247 bool MPSolver::HasIntegerVariables()
const {
1248 for (
const MPVariable*
const variable : variables_) {
1256 return Solve(default_param);
1265 if (HasInfeasibleConstraints()) {
1267 return interface_->result_status_;
1271 if (absl::GetFlag(FLAGS_verify_solution)) {
1273 VLOG(1) <<
"--verify_solution enabled, but the solver did not find a"
1274 <<
" solution: skipping the verification.";
1277 absl::GetFlag(FLAGS_log_verification_errors))) {
1279 interface_->result_status_ = status;
1282 DCHECK_EQ(interface_->result_status_, status);
1287 interface_->Write(file_name);
1292 const std::string prefix =
"Variable '" +
var.
name() +
"': domain = ";
1295 return prefix +
"∅";
1299 if (
var.integer() &&
var.ub() -
var.lb() <= 1) {
1300 const int64_t lb =
static_cast<int64_t
>(ceil(
var.lb()));
1301 const int64_t ub =
static_cast<int64_t
>(floor(
var.ub()));
1303 return prefix +
"∅";
1304 }
else if (lb == ub) {
1305 return absl::StrFormat(
"%s{ %d }", prefix.c_str(), lb);
1307 return absl::StrFormat(
"%s{ %d, %d }", prefix.c_str(), lb, ub);
1311 if (
var.lb() ==
var.ub()) {
1312 return absl::StrFormat(
"%s{ %f }", prefix.c_str(),
var.lb());
1314 return prefix + (
var.integer() ?
"Integer" :
"Real") +
" in " +
1316 ? std::string(
"]-∞")
1317 :
absl::StrFormat(
"[%f",
var.lb())) +
1319 (
var.ub() >= MPSolver::infinity() ? std::string(
"+∞[")
1320 :
absl::StrFormat(
"%f]",
var.ub()));
1323 std::string PrettyPrintConstraint(
const MPConstraint& constraint) {
1324 std::string prefix =
"Constraint '" + constraint.name() +
"': ";
1327 constraint.lb() > constraint.ub()) {
1328 return prefix +
"ALWAYS FALSE";
1332 return prefix +
"ALWAYS TRUE";
1334 prefix +=
"<linear expr>";
1336 if (constraint.lb() == constraint.ub()) {
1337 return absl::StrFormat(
"%s = %f", prefix.c_str(), constraint.lb());
1341 return absl::StrFormat(
"%s ≤ %f", prefix.c_str(), constraint.ub());
1344 return absl::StrFormat(
"%s ≥ %f", prefix.c_str(), constraint.lb());
1346 return absl::StrFormat(
"%s ∈ [%f, %f]", prefix.c_str(), constraint.lb(),
1352 interface_->ExtractModel();
1355 if (std::isnan(
value)) {
1356 return absl::InvalidArgumentError(
1357 absl::StrCat(
"NaN value for ", PrettyPrintVar(*
variable)));
1359 if (value < variable->lb()) {
1366 return absl::OkStatus();
1371 if (!interface_->CheckSolutionIsSynchronizedAndExists())
return {};
1372 std::vector<double> activities(constraints_.size(), 0.0);
1373 for (
int i = 0; i < constraints_.size(); ++i) {
1376 for (
const auto& entry :
constraint.coefficients_) {
1377 sum.
Add(entry.first->solution_value() * entry.second);
1379 activities[i] = sum.
Value();
1386 double max_observed_error = 0;
1387 if (tolerance < 0) tolerance =
infinity();
1391 for (
int i = 0; i < variables_.size(); ++i) {
1393 const double value =
var.solution_value();
1395 if (std::isnan(
value)) {
1398 LOG_IF(
ERROR, log_errors) <<
"NaN value for " << PrettyPrintVar(
var);
1403 if (
value <
var.lb() - tolerance) {
1407 <<
"Value " <<
value <<
" too low for " << PrettyPrintVar(
var);
1412 if (
value >
var.ub() + tolerance) {
1416 <<
"Value " <<
value <<
" too high for " << PrettyPrintVar(
var);
1421 if (fabs(
value - round(
value)) > tolerance) {
1423 max_observed_error =
1426 <<
"Non-integer value " <<
value <<
" for " << PrettyPrintVar(
var);
1430 if (!
IsMIP() && HasIntegerVariables()) {
1431 LOG_IF(
INFO, log_errors) <<
"Skipped variable integrality check, because "
1432 <<
"a continuous relaxation of the model was "
1433 <<
"solved (i.e., the selected solver does not "
1434 <<
"support integer variables).";
1439 for (
int i = 0; i < constraints_.size(); ++i) {
1441 const double activity = activities[i];
1443 double inaccurate_activity = 0.0;
1444 for (
const auto& entry :
constraint.coefficients_) {
1445 inaccurate_activity += entry.first->solution_value() * entry.second;
1448 if (std::isnan(activity) || std::isnan(inaccurate_activity)) {
1452 <<
"NaN value for " << PrettyPrintConstraint(
constraint);
1462 max_observed_error =
1465 <<
"Activity " << activity <<
" too low for "
1467 }
else if (inaccurate_activity <
constraint.
lb() - tolerance) {
1469 <<
"Activity " << activity <<
", computed with the (inaccurate)"
1470 <<
" standard sum of its terms, is too low for "
1477 max_observed_error =
1480 <<
"Activity " << activity <<
" too high for "
1482 }
else if (inaccurate_activity >
constraint.
ub() + tolerance) {
1484 <<
"Activity " << activity <<
", computed with the (inaccurate)"
1485 <<
" standard sum of its terms, is too high for "
1496 double inaccurate_objective_value = objective.
offset();
1497 for (
const auto& entry : objective.coefficients_) {
1498 const double term = entry.first->solution_value() * entry.second;
1499 objective_sum.
Add(term);
1500 inaccurate_objective_value += term;
1502 const double actual_objective_value = objective_sum.
Value();
1504 objective.
Value(), actual_objective_value, tolerance, tolerance)) {
1507 max_observed_error, fabs(actual_objective_value - objective.
Value()));
1509 <<
"Objective value " << objective.
Value() <<
" isn't accurate"
1510 <<
", it should be " << actual_objective_value
1511 <<
" (delta=" << actual_objective_value - objective.
Value() <<
").";
1513 inaccurate_objective_value,
1514 tolerance, tolerance)) {
1516 <<
"Objective value " << objective.
Value() <<
" doesn't correspond"
1517 <<
" to the value computed with the standard (and therefore inaccurate)"
1518 <<
" sum of its terms.";
1520 if (num_errors > 0) {
1522 <<
"There were " << num_errors <<
" errors above the tolerance ("
1523 << tolerance <<
"), the largest was " << max_observed_error;
1540 return interface_->ComputeExactConditionNumber();
1544 if (
var ==
nullptr)
return false;
1545 if (
var->index() >= 0 &&
var->index() < variables_.size()) {
1547 return variables_[
var->index()] ==
var;
1553 std::string* model_str)
const {
1558 const auto status_or =
1560 *model_str = status_or.value_or(
"");
1561 return status_or.ok();
1565 std::string* model_str)
const {
1570 const auto status_or =
1572 *model_str = status_or.value_or(
"");
1573 return status_or.ok();
1577 for (
const auto& var_value_pair : hint) {
1579 <<
"hint variable does not belong to this solver";
1581 solution_hint_ = std::move(hint);
1584 void MPSolver::GenerateVariableNameIndex()
const {
1585 if (variable_name_to_index_)
return;
1586 variable_name_to_index_ = absl::flat_hash_map<std::string, int>();
1592 void MPSolver::GenerateConstraintNameIndex()
const {
1593 if (constraint_name_to_index_)
return;
1594 constraint_name_to_index_ = absl::flat_hash_map<std::string, int>();
1595 for (
const MPConstraint*
const cst : constraints_) {
1603 interface_->SetCallback(mp_callback);
1607 return interface_->SupportsCallbacks();
1633 <<
"MPSolverResponseStatusIsRpcError() called with invalid status "
1634 <<
"(value: " << status <<
")";
1646 sync_status_(MODEL_SYNCHRONIZED),
1647 result_status_(
MPSolver::NOT_SOLVED),
1649 last_constraint_index_(0),
1650 last_variable_index_(0),
1651 objective_value_(0.0),
1652 best_objective_bound_(0.0),
1658 LOG(
WARNING) <<
"Writing model not implemented in this solver interface.";
1693 solver_->variable_is_extracted_.assign(
solver_->variables_.size(),
false);
1694 solver_->constraint_is_extracted_.assign(
solver_->constraints_.size(),
false);
1700 <<
"The model has been changed since the solution was last computed."
1701 <<
" MPSolverInterface::sync_status_ = " <<
sync_status_;
1712 LOG(DFATAL) <<
"No solution exists. MPSolverInterface::result_status_ = "
1725 const double trivial_worst_bound =
1726 maximize_ ? -std::numeric_limits<double>::infinity()
1727 : std::numeric_limits<double>::infinity();
1729 LOG(DFATAL) <<
"Best objective bound only available for discrete problems.";
1730 return trivial_worst_bound;
1733 return trivial_worst_bound;
1736 if (
solver_->variables_.empty() &&
solver_->constraints_.empty()) {
1750 LOG(DFATAL) <<
"ComputeExactConditionNumber not implemented for "
1751 << ProtoEnumToString<MPModelRequest::SolverType>(
1752 static_cast<MPModelRequest::SolverType
>(
1787 LOG(
WARNING) <<
"Trying to set an unsupported parameter: " << param <<
".";
1791 LOG(
WARNING) <<
"Trying to set an unsupported parameter: " << param <<
".";
1795 LOG(
WARNING) <<
"Trying to set a supported parameter: " << param
1796 <<
" to an unsupported value: " <<
value;
1800 LOG(
WARNING) <<
"Trying to set a supported parameter: " << param
1801 <<
" to an unsupported value: " <<
value;
1805 return absl::UnimplementedError(
1806 absl::StrFormat(
"SetNumThreads() not supported by %s.",
SolverVersion()));
1815 LOG(
WARNING) <<
"SetSolverSpecificParametersAsString() not supported by "
1840 : relative_mip_gap_value_(kDefaultRelativeMipGap),
1842 dual_tolerance_value_(kDefaultDualTolerance),
1843 presolve_value_(kDefaultPresolve),
1844 scaling_value_(kDefaultIntegerParamValue),
1845 lp_algorithm_value_(kDefaultIntegerParamValue),
1846 incrementality_value_(kDefaultIncrementality),
1847 lp_algorithm_is_default_(true) {}
1853 relative_mip_gap_value_ =
value;
1857 primal_tolerance_value_ =
value;
1861 dual_tolerance_value_ =
value;
1865 LOG(
ERROR) <<
"Trying to set an unknown parameter: " << param <<
".";
1875 LOG(
ERROR) <<
"Trying to set a supported parameter: " << param
1876 <<
" to an unknown value: " <<
value;
1878 presolve_value_ =
value;
1883 LOG(
ERROR) <<
"Trying to set a supported parameter: " << param
1884 <<
" to an unknown value: " <<
value;
1886 scaling_value_ =
value;
1891 LOG(
ERROR) <<
"Trying to set a supported parameter: " << param
1892 <<
" to an unknown value: " <<
value;
1894 lp_algorithm_value_ =
value;
1895 lp_algorithm_is_default_ =
false;
1900 LOG(
ERROR) <<
"Trying to set a supported parameter: " << param
1901 <<
" to an unknown value: " <<
value;
1903 incrementality_value_ =
value;
1907 LOG(
ERROR) <<
"Trying to set an unknown parameter: " << param <<
".";
1928 LOG(
ERROR) <<
"Trying to reset an unknown parameter: " << param <<
".";
1945 lp_algorithm_is_default_ =
true;
1953 LOG(
ERROR) <<
"Trying to reset an unknown parameter: " << param <<
".";
1972 return relative_mip_gap_value_;
1975 return primal_tolerance_value_;
1978 return dual_tolerance_value_;
1981 LOG(
ERROR) <<
"Trying to get an unknown parameter: " << param <<
".";
1991 return presolve_value_;
1995 return lp_algorithm_value_;
1998 return incrementality_value_;
2001 return scaling_value_;
2004 LOG(
ERROR) <<
"Trying to get an unknown parameter: " << param <<
".";
#define DLOG_IF(severity, condition)
#define LOG_IF(severity, condition)
#define DCHECK_LE(val1, val2)
#define DCHECK_NE(val1, val2)
#define DCHECK_GE(val1, val2)
#define DCHECK(condition)
#define DCHECK_EQ(val1, val2)
#define VLOG(verboselevel)
void Add(const FpNumber &value)
LinearExpr models a quantity that is linear in the decision variables (MPVariable) of an optimization...
const absl::flat_hash_map< const MPVariable *, double > & terms() const
An expression of the form:
double upper_bound() const
double lower_bound() const
const LinearExpr & linear_expr() const
The class for constraints of a Mathematical Programming (MP) model.
void SetBounds(double lb, double ub)
Sets both the lower and upper bounds.
void SetCoefficient(const MPVariable *const var, double coeff)
Sets the coefficient of the variable on the constraint.
double GetCoefficient(const MPVariable *const var) const
Gets the coefficient of a given variable on the constraint (which is 0 if the variable does not appea...
double ub() const
Returns the upper bound.
const MPVariable * indicator_variable() const
bool indicator_value() const
void Clear()
Clears all variables and coefficients. Does not clear the bounds.
bool is_lazy() const
Advanced usage: returns true if the constraint is "lazy" (see below).
void set_is_lazy(bool laziness)
Advanced usage: sets the constraint "laziness".
double lb() const
Returns the lower bound.
const std::string & name() const
Returns the name of the constraint.
MPSolver::BasisStatus basis_status() const
Advanced usage: returns the basis status of the constraint.
double dual_value() const
Advanced usage: returns the dual value of the constraint in the current solution (only available for ...
A class to express a linear objective.
void SetCoefficient(const MPVariable *const var, double coeff)
Sets the coefficient of the variable in the objective.
double GetCoefficient(const MPVariable *const var) const
Gets the coefficient of a given variable in the objective.
void SetOffset(double value)
Sets the constant term in the objective.
bool maximization() const
Is the optimization direction set to maximize?
void OptimizeLinearExpr(const LinearExpr &linear_expr, bool is_maximization)
Resets the current objective to take the value of linear_expr, and sets the objective direction to ma...
void AddLinearExpr(const LinearExpr &linear_expr)
Adds linear_expr to the current objective, does not change the direction.
double Value() const
Returns the objective value of the best solution found so far.
double offset() const
Gets the constant term in the objective.
double BestBound() const
Returns the best objective bound.
bool minimization() const
Is the optimization direction set to minimize?
void Clear()
Clears the offset, all variables and coefficients, and the optimization direction.
void SetMinimization()
Sets the optimization direction to minimize.
void SetOptimizationDirection(bool maximize)
Sets the optimization direction (maximize: true or minimize: false).
This mathematical programming (MP) solver class is the main class though which users build and solve ...
void FillSolutionResponseProto(MPSolutionResponse *response) const
Encodes the current solution in a solution response protocol buffer.
int NumConstraints() const
Returns the number of constraints.
static OptimizationProblemType ParseSolverTypeOrDie(const std::string &solver_id)
Parses the name of the solver and returns the correct optimization type or dies.
const std::string & Name() const
Returns the name of the model set at construction.
MPConstraint * constraint(int index) const
Returns the constraint at the given index.
void MakeBoolVarArray(int nb, const std::string &name, std::vector< MPVariable * > *vars)
Creates an array of boolean variables.
MPObjective * MutableObjective()
Returns the mutable objective object.
bool VerifySolution(double tolerance, bool log_errors) const
Advanced usage: Verifies the correctness of the solution.
void Reset()
Advanced usage: resets extracted model to solve from scratch.
MPVariable * LookupVariableOrNull(const std::string &var_name) const
Looks up a variable by name, and returns nullptr if it does not exist.
int64_t iterations() const
Returns the number of simplex iterations.
void SetStartingLpBasis(const std::vector< MPSolver::BasisStatus > &variable_statuses, const std::vector< MPSolver::BasisStatus > &constraint_statuses)
Advanced usage: Incrementality.
static bool SupportsProblemType(OptimizationProblemType problem_type)
Whether the given problem type is supported (this will depend on the targets that you linked).
static MPSolver * CreateSolver(const std::string &solver_id)
Recommended factory method to create a MPSolver instance, especially in non C++ languages.
MPVariable * MakeBoolVar(const std::string &name)
Creates a boolean variable.
void SetHint(std::vector< std::pair< const MPVariable *, double > > hint)
Sets a hint for solution.
double ComputeExactConditionNumber() const
Advanced usage: computes the exact condition number of the current scaled basis: L1norm(B) * L1norm(i...
const MPObjective & Objective() const
Returns the objective object.
ResultStatus
The status of solving the problem.
@ FEASIBLE
feasible, or stopped by limit.
@ NOT_SOLVED
not been solved yet.
@ INFEASIBLE
proven infeasible.
@ UNBOUNDED
proven unbounded.
@ ABNORMAL
abnormal, i.e., error of some kind.
@ MODEL_INVALID
the model is trivially invalid (NaN coefficients, etc).
static void SolveWithProto(const MPModelRequest &model_request, MPSolutionResponse *response)
Solves the model encoded by a MPModelRequest protocol buffer and fills the solution encoded as a MPSo...
void MakeNumVarArray(int nb, double lb, double ub, const std::string &name, std::vector< MPVariable * > *vars)
Creates an array of continuous variables.
void MakeVarArray(int nb, double lb, double ub, bool integer, const std::string &name_prefix, std::vector< MPVariable * > *vars)
Creates an array of variables.
void * underlying_solver()
Advanced usage: returns the underlying solver.
OptimizationProblemType
The type of problems (LP or MIP) that will be solved and the underlying solver (GLOP,...
@ GLOP_LINEAR_PROGRAMMING
@ CPLEX_MIXED_INTEGER_PROGRAMMING
@ KNAPSACK_MIXED_INTEGER_PROGRAMMING
@ XPRESS_LINEAR_PROGRAMMING
@ GLPK_LINEAR_PROGRAMMING
@ CPLEX_LINEAR_PROGRAMMING
@ GUROBI_LINEAR_PROGRAMMING
@ XPRESS_MIXED_INTEGER_PROGRAMMING
@ GUROBI_MIXED_INTEGER_PROGRAMMING
@ BOP_INTEGER_PROGRAMMING
@ SCIP_MIXED_INTEGER_PROGRAMMING
@ SAT_INTEGER_PROGRAMMING
@ GLPK_MIXED_INTEGER_PROGRAMMING
@ CBC_MIXED_INTEGER_PROGRAMMING
bool SetSolverSpecificParametersAsString(const std::string ¶meters)
Advanced usage: pass solver specific parameters in text format.
absl::Status SetNumThreads(int num_threads)
Sets the number of threads to use by the underlying solver.
std::string SolverVersion() const
Returns a string describing the underlying solver and its version.
bool SupportsCallbacks() const
void ExportModelToProto(MPModelProto *output_model) const
Exports model to protocol buffer.
void MakeIntVarArray(int nb, double lb, double ub, const std::string &name, std::vector< MPVariable * > *vars)
Creates an array of integer variables.
std::vector< double > ComputeConstraintActivities() const
Advanced usage: compute the "activities" of all constraints, which are the sums of their linear terms...
static double infinity()
Infinity.
static bool ParseSolverType(absl::string_view solver_id, OptimizationProblemType *type)
Parses the name of the solver.
int NumVariables() const
Returns the number of variables.
absl::Status ClampSolutionWithinBounds()
Resets values of out of bound variables to the corresponding bound and returns an error if any of the...
bool OwnsVariable(const MPVariable *var) const
int64_t nodes() const
Returns the number of branch-and-bound nodes evaluated during the solve.
void Clear()
Clears the objective (including the optimization direction), all variables and constraints.
bool ExportModelAsLpFormat(bool obfuscate, std::string *model_str) const
Shortcuts to the homonymous MPModelProtoExporter methods, via exporting to a MPModelProto with Export...
void Write(const std::string &file_name)
Writes the model using the solver internal write function.
MPConstraint * MakeRowConstraint()
Creates a constraint with -infinity and +infinity bounds.
void SetCallback(MPCallback *mp_callback)
MPSolverResponseStatus LoadModelFromProto(const MPModelProto &input_model, std::string *error_message)
Loads model from protocol buffer.
bool OutputIsEnabled() const
Controls (or queries) the amount of output produced by the underlying solver.
bool ExportModelAsMpsFormat(bool fixed_format, bool obfuscate, std::string *model_str) const
ABSL_MUST_USE_RESULT bool NextSolution()
Some solvers (MIP only, not LP) can produce multiple solutions to the problem.
MPVariable * MakeVar(double lb, double ub, bool integer, const std::string &name)
Creates a variable with the given bounds, integrality requirement and name.
MPConstraint * LookupConstraintOrNull(const std::string &constraint_name) const
Looks up a constraint by name, and returns nullptr if it does not exist.
MPVariable * MakeNumVar(double lb, double ub, const std::string &name)
Creates a continuous variable.
bool InterruptSolve()
Interrupts the Solve() execution to terminate processing if possible.
MPVariable * MakeIntVar(double lb, double ub, const std::string &name)
Creates an integer variable.
MPVariable * variable(int index) const
Returns the variable at position index.
MPSolver(const std::string &name, OptimizationProblemType problem_type)
Create a solver with the given name and underlying solver backend.
ResultStatus Solve()
Solves the problem using the default parameter values.
void EnableOutput()
Enables solver logging.
void SuppressOutput()
Suppresses solver logging.
absl::Status LoadSolutionFromProto(const MPSolutionResponse &response, double tolerance=kDefaultPrimalTolerance)
Load a solution encoded in a protocol buffer onto this solver for easy access via the MPSolver interf...
MPSolverResponseStatus LoadModelFromProtoWithUniqueNamesOrDie(const MPModelProto &input_model, std::string *error_message)
Loads model from protocol buffer.
virtual OptimizationProblemType ProblemType() const
Returns the optimization problem type set at construction.
BasisStatus
Advanced usage: possible basis status values for a variable and the slack variable of a linear constr...
void SetTimeLimit(absl::Duration time_limit)
virtual ~MPSolverInterface()
double best_objective_bound() const
virtual void SetLpAlgorithm(int value)=0
virtual void SetIntegerParamToUnsupportedValue(MPSolverParameters::IntegerParam param, int value)
virtual void ExtractObjective()=0
void SetUnsupportedDoubleParam(MPSolverParameters::DoubleParam param)
virtual void ExtractNewVariables()=0
MPSolver::ResultStatus result_status_
static const int kDummyVariableIndex
void InvalidateSolutionSynchronization()
void SetMIPParameters(const MPSolverParameters ¶m)
int last_constraint_index_
virtual bool IsContinuous() const =0
virtual double ComputeExactConditionNumber() const
virtual void Write(const std::string &filename)
MPSolverInterface(MPSolver *const solver)
bool constraint_is_extracted(int ct_index) const
virtual void SetVariableBounds(int index, double lb, double ub)=0
virtual void SetPrimalTolerance(double value)=0
virtual void BranchingPriorityChangedForVariable(int var_index)
virtual void SetRelativeMipGap(double value)=0
double best_objective_bound_
virtual void SetOptimizationDirection(bool maximize)=0
virtual bool SetSolverSpecificParametersAsString(const std::string ¶meters)
virtual MPSolver::BasisStatus column_status(int variable_index) const =0
virtual void ExtractNewConstraints()=0
virtual MPSolver::BasisStatus row_status(int constraint_index) const =0
virtual std::string SolverVersion() const =0
virtual absl::Status SetNumThreads(int num_threads)
double objective_value() const
int last_variable_index() const
virtual void ClearConstraint(MPConstraint *const constraint)=0
bool CheckSolutionIsSynchronizedAndExists() const
bool CheckSolutionIsSynchronized() const
virtual bool CheckSolutionExists() const
virtual void SetObjectiveOffset(double value)=0
virtual void SetVariableInteger(int index, bool integer)=0
void ResetExtractionInformation()
virtual void ClearObjective()=0
bool variable_is_extracted(int var_index) const
virtual bool IsMIP() const =0
virtual void SetDualTolerance(double value)=0
virtual void SetPresolveMode(int value)=0
virtual void SetUnsupportedIntegerParam(MPSolverParameters::IntegerParam param)
virtual void SetCoefficient(MPConstraint *const constraint, const MPVariable *const variable, double new_value, double old_value)=0
virtual void SetObjectiveCoefficient(const MPVariable *const variable, double coefficient)=0
void SetDoubleParamToUnsupportedValue(MPSolverParameters::DoubleParam param, double value)
virtual void SetConstraintBounds(int index, double lb, double ub)=0
void SetCommonParameters(const MPSolverParameters ¶m)
SynchronizationStatus sync_status_
This class stores parameter settings for LP and MIP solvers.
static const double kDefaultRelativeMipGap
static const int kUnknownIntegerParamValue
void ResetIntegerParam(MPSolverParameters::IntegerParam param)
Sets an integer parameter to its default value (default value defined in MPSolverParameters if it exi...
void SetDoubleParam(MPSolverParameters::DoubleParam param, double value)
Sets a double parameter to a specific value.
IncrementalityValues
Advanced usage: Incrementality options.
@ INCREMENTALITY_OFF
Start solve from scratch.
@ INCREMENTALITY_ON
Reuse results from previous solve as much as the underlying solver allows.
@ SCALING_ON
Scaling is on.
@ SCALING_OFF
Scaling is off.
static const IncrementalityValues kDefaultIncrementality
void Reset()
Sets all parameters to their default value.
DoubleParam
Enumeration of parameters that take continuous values.
@ DUAL_TOLERANCE
Advanced usage: tolerance for dual feasibility of basic solutions.
@ PRIMAL_TOLERANCE
Advanced usage: tolerance for primal feasibility of basic solutions.
@ RELATIVE_MIP_GAP
Limit for relative MIP gap.
static const PresolveValues kDefaultPresolve
double GetDoubleParam(MPSolverParameters::DoubleParam param) const
Returns the value of a double parameter.
static const double kDefaultDualTolerance
static const double kUnknownDoubleParamValue
IntegerParam
Enumeration of parameters that take integer or categorical values.
@ LP_ALGORITHM
Algorithm to solve linear programs.
@ SCALING
Advanced usage: enable or disable matrix scaling.
@ PRESOLVE
Advanced usage: presolve mode.
@ INCREMENTALITY
Advanced usage: incrementality from one solve to the next.
@ BARRIER
Barrier algorithm.
PresolveValues
For each categorical parameter, enumeration of possible values.
@ PRESOLVE_ON
Presolve is on.
@ PRESOLVE_OFF
Presolve is off.
static const int kDefaultIntegerParamValue
static const double kDefaultPrimalTolerance
void SetIntegerParam(MPSolverParameters::IntegerParam param, int value)
Sets a integer parameter to a specific value.
static const double kDefaultDoubleParamValue
int GetIntegerParam(MPSolverParameters::IntegerParam param) const
Returns the value of an integer parameter.
MPSolverParameters()
The constructor sets all parameters to their default value.
void ResetDoubleParam(MPSolverParameters::DoubleParam param)
Sets a double parameter to its default value (default value defined in MPSolverParameters if it exist...
The class for variables of a Mathematical Programming (MP) model.
void SetBounds(double lb, double ub)
Sets both the lower and upper bounds.
double unrounded_solution_value() const
Advanced usage: unrounded solution value.
void set_solution_value(double value)
void SetBranchingPriority(int priority)
double ub() const
Returns the upper bound.
double reduced_cost() const
Advanced usage: returns the reduced cost of the variable in the current solution (only available for ...
void SetInteger(bool integer)
Sets the integrality requirement of the variable.
bool integer() const
Returns the integrality requirement of the variable.
int index() const
Returns the index of the variable in the MPSolver::variables_.
double lb() const
Returns the lower bound.
const std::string & name() const
Returns the name of the variable.
double solution_value() const
Returns the value of the variable in the current solution.
MPSolver::BasisStatus basis_status() const
Advanced usage: returns the basis status of the variable in the current solution (only available for ...
virtual std::string name() const
Object naming.
SharedResponseManager * response
ABSL_FLAG(bool, verify_solution, false, "Systematically verify the solution when calling Solve()" ", and change the return value of Solve() to ABNORMAL if" " an error was detected.")
MPSolver::OptimizationProblemType problem_type
A C++ wrapper that provides a simple and unified interface to several linear programming and mixed in...
void STLDeleteElements(T *container)
void InsertOrDie(Collection *const collection, const typename Collection::value_type &value)
const Collection::value_type::second_type & FindWithDefault(const Collection &collection, const typename Collection::value_type::first_type &key, const typename Collection::value_type::second_type &value)
std::function< int64_t(const Model &)> Value(IntegerVariable v)
Collection of objects used to extend the Constraint Solver library.
MPSolverInterface * BuildGurobiInterface(bool mip, MPSolver *const solver)
MPSolverInterface * BuildSCIPInterface(MPSolver *const solver)
MPSolverInterface * BuildBopInterface(MPSolver *const solver)
constexpr double kDefaultPrimalTolerance
const absl::string_view ToString(MPSolver::OptimizationProblemType optimization_problem_type)
bool SolverTypeIsMip(MPModelRequest::SolverType solver_type)
MPSolverInterface * BuildCBCInterface(MPSolver *const solver)
bool AreWithinAbsoluteOrRelativeTolerances(FloatType x, FloatType y, FloatType relative_tolerance, FloatType absolute_tolerance)
absl::StatusOr< std::string > ExportModelAsMpsFormat(const MPModelProto &model, const MPModelExportOptions &options)
Outputs the current model (variables, constraints, objective) as a string encoded in MPS file format,...
bool AbslParseFlag(const absl::string_view text, MPSolver::OptimizationProblemType *solver_type, std::string *error)
absl::optional< LazyMutableCopy< MPModelProto > > ExtractValidMPModelOrPopulateResponseStatus(const MPModelRequest &request, MPSolutionResponse *response)
If the model is valid and non-empty, returns it (possibly after extracting the model_delta).
MPSolverInterface * BuildSatInterface(MPSolver *const solver)
MPSolverInterface * BuildCLPInterface(MPSolver *const solver)
constexpr NamedOptimizationProblemType kOptimizationProblemTypeNames[]
MPSolverInterface * BuildGLOPInterface(MPSolver *const solver)
std::string FindErrorInMPModelProto(const MPModelProto &model, double abs_value_threshold)
Returns an empty string iff the model is valid and not trivially infeasible.
bool GurobiIsCorrectlyInstalled()
absl::StatusOr< std::string > ExportModelAsLpFormat(const MPModelProto &model, const MPModelExportOptions &options)
Outputs the current model (variables, constraints, objective) as a string encoded in the so-called "C...
@ MPSOLVER_UNKNOWN_STATUS
@ MPSOLVER_MODEL_IS_VALID
@ MPSOLVER_SOLVER_TYPE_UNAVAILABLE
@ MPSOLVER_MODEL_INVALID_SOLUTION_HINT
@ MPSOLVER_MODEL_INVALID_SOLVER_PARAMETERS
bool MPSolverResponseStatusIsRpcError(MPSolverResponseStatus status)
bool obfuscate
Obfuscates variable and constraint names.