18 #if !defined(_MSC_VER) 28 #include "absl/status/status.h" 29 #include "absl/status/statusor.h" 30 #include "absl/strings/ascii.h" 31 #include "absl/strings/match.h" 32 #include "absl/strings/str_cat.h" 33 #include "absl/strings/str_format.h" 34 #include "absl/strings/str_replace.h" 35 #include "absl/synchronization/mutex.h" 36 #include "absl/synchronization/notification.h" 37 #include "absl/time/time.h" 53 "Systematically verify the solution when calling Solve()" 54 ", and change the return value of Solve() to ABNORMAL if" 55 " an error was detected.");
56 ABSL_FLAG(
bool, log_verification_errors,
true,
57 "If --verify_solution is set: LOG(ERROR) all errors detected" 58 " during the verification of the solution.");
59 ABSL_FLAG(
bool, linear_solver_enable_verbose_output,
false,
60 "If set, enables verbose output for the solver. Setting this flag" 61 " is the same as calling MPSolver::EnableOutput().");
63 ABSL_FLAG(
bool, mpsolver_bypass_model_validation,
false,
64 "If set, the user-provided Model won't be verified before Solve()." 65 " Invalid models will typically trigger various error responses" 66 " from the underlying solvers; sometimes crashes.");
71 switch (solver_type) {
91 LOG(DFATAL) <<
"Invalid SolverType: " << solver_type;
97 if (
var ==
nullptr)
return 0.0;
103 if (
var ==
nullptr)
return;
105 auto it = coefficients_.find(
var);
113 if (it != coefficients_.end() && it->second != 0.0) {
114 const double old_value = it->second;
120 auto insertion_result = coefficients_.insert(std::make_pair(
var, coeff));
121 const double old_value =
122 insertion_result.second ? 0.0 : insertion_result.first->second;
123 insertion_result.first->second = coeff;
129 coefficients_.clear();
133 const bool change =
lb != lb_ ||
ub != ub_;
143 LOG(DFATAL) <<
"Dual value only available for continuous problems";
152 LOG(DFATAL) <<
"Basis status only available for continuous problems";
162 bool MPConstraint::ContainsNewVariables() {
164 for (
const auto& entry : coefficients_) {
165 const int variable_index = entry.first->index();
166 if (variable_index >= last_variable_index ||
178 if (
var ==
nullptr)
return 0.0;
184 if (
var ==
nullptr)
return;
186 auto it = coefficients_.find(
var);
189 if (it == coefficients_.end() || it->second == 0.0)
return;
192 coefficients_[
var] = coeff;
204 for (
auto var_value_pair : linear_expr.
terms()) {
206 <<
"Bad MPVariable* in LinearExpr, did you try adding an integer to an " 207 "MPVariable* directly?";
213 bool is_maximization) {
214 CheckLinearExpr(*interface_->
solver_, linear_expr);
216 coefficients_.clear();
218 for (
const auto& kv : linear_expr.
terms()) {
225 CheckLinearExpr(*interface_->
solver_, linear_expr);
227 for (
const auto& kv : linear_expr.
terms()) {
234 coefficients_.clear();
274 return (integer_ && interface_->
IsMIP()) ? round(solution_value_)
280 return solution_value_;
285 LOG(DFATAL) <<
"Reduced cost only available for continuous problems";
289 return reduced_cost_;
294 LOG(DFATAL) <<
"Basis status only available for continuous problems";
305 const bool change =
lb != lb_ ||
ub != ub_;
323 if (priority == branching_priority_)
return;
324 branching_priority_ = priority;
333 return interface_->SolverVersion();
341 if (num_threads < 1) {
342 return absl::InvalidArgumentError(
"num_threads must be a positive number.");
344 const absl::Status status = interface_->SetNumThreads(num_threads);
346 num_threads_ = num_threads;
353 solver_specific_parameter_string_ =
parameters;
354 return interface_->SetSolverSpecificParametersAsString(
parameters);
359 #if defined(USE_CLP) || defined(USE_CBC) 365 #if defined(USE_GLPK) 371 #if defined(USE_SCIP) 376 #if defined(USE_CPLEX) 381 #if defined(USE_XPRESS) 388 DCHECK(solver !=
nullptr);
396 #if defined(USE_GLPK) 398 return BuildGLPKInterface(
false, solver);
400 return BuildGLPKInterface(
true, solver);
402 #if defined(USE_CLP) || defined(USE_CBC) 410 #if defined(USE_SCIP) 418 #if defined(USE_CPLEX) 420 return BuildCplexInterface(
false, solver);
422 return BuildCplexInterface(
true, solver);
424 #if defined(USE_XPRESS) 426 return BuildXpressInterface(
true, solver);
428 return BuildXpressInterface(
false, solver);
432 LOG(
FATAL) <<
"Linear solver not recognized.";
439 int NumDigits(
int n) {
442 #if defined(_MSC_VER) 443 return static_cast<int>(
std::max(1.0L, log(1.0L * n) / log(10.0L) + 1.0));
445 return static_cast<int>(
std::max(1.0, log10(static_cast<double>(n)) + 1.0));
454 construction_time_(
absl::Now()) {
455 interface_.reset(BuildSolverInterface(
this));
456 if (absl::GetFlag(FLAGS_linear_solver_enable_verbose_output)) {
459 objective_.reset(
new MPObjective(interface_.get()));
509 struct NamedOptimizationProblemType {
515 #if defined(_MSC_VER) 542 const std::string
id =
543 absl::StrReplaceAll(absl::AsciiStrToUpper(solver_id), {{
"-",
"_"}});
548 *type = static_cast<MPSolver::OptimizationProblemType>(solver_type);
553 std::string lower_id = absl::AsciiStrToLower(
id);
556 if (absl::EndsWith(lower_id,
"_mip")) {
557 lower_id = lower_id.substr(0, lower_id.size() - 4);
561 if (lower_id ==
"cp_sat") {
567 if (named_solver.name == lower_id) {
568 *type = named_solver.problem_type;
579 if (named_solver.problem_type == optimization_problem_type) {
580 return named_solver.name;
583 LOG(
FATAL) <<
"Unrecognized solver type: " 584 << static_cast<int>(optimization_problem_type);
590 std::string* error) {
591 DCHECK(solver_type !=
nullptr);
595 *error = absl::StrCat(
"Solver type: ", text,
" does not exist.");
602 const std::string& solver_id) {
612 LOG(
WARNING) <<
"Unrecognized solver type: " << solver_id;
617 <<
" not linked in, or the license was not found.";
625 if (!variable_name_to_index_) GenerateVariableNameIndex();
627 absl::flat_hash_map<std::string, int>::const_iterator it =
628 variable_name_to_index_->find(var_name);
629 if (it == variable_name_to_index_->end())
return nullptr;
630 return variables_[it->second];
634 const std::string& constraint_name)
const {
635 if (!constraint_name_to_index_) GenerateConstraintNameIndex();
637 const auto it = constraint_name_to_index_->find(constraint_name);
638 if (it == constraint_name_to_index_->end())
return nullptr;
639 return constraints_[it->second];
645 const MPModelProto& input_model, std::string* error_message) {
652 return LoadModelFromProtoInternal(input_model,
true,
658 const MPModelProto& input_model, std::string* error_message) {
662 GenerateVariableNameIndex();
663 GenerateConstraintNameIndex();
665 return LoadModelFromProtoInternal(input_model,
false,
672 bool check_model_validity, std::string* error_message) {
673 CHECK(error_message !=
nullptr);
674 if (check_model_validity) {
676 if (!error.empty()) {
677 *error_message = error;
679 <<
"Invalid model given to LoadModelFromProto(): " << error;
680 if (absl::GetFlag(FLAGS_mpsolver_bypass_model_validation)) {
682 <<
"Ignoring the model error(s) because of" 683 <<
" --mpsolver_bypass_model_validation.";
693 "Optimizing a quadratic objective is only supported through direct " 694 "proto solves. Please use MPSolver::SolveWithProto, or the solver's " 695 "direct proto solve function.";
701 const std::string empty;
703 const MPVariableProto& var_proto = input_model.
variable(i);
705 MakeNumVar(var_proto.lower_bound(), var_proto.upper_bound(),
706 clear_names ? empty : var_proto.name());
708 if (var_proto.branching_priority() != 0) {
711 objective->SetCoefficient(
variable, var_proto.objective_coefficient());
714 for (
const MPConstraintProto& ct_proto : input_model.
constraint()) {
715 if (ct_proto.lower_bound() == -
infinity() &&
716 ct_proto.upper_bound() ==
infinity()) {
720 MPConstraint*
const ct =
722 clear_names ? empty : ct_proto.name());
723 ct->set_is_lazy(ct_proto.is_lazy());
724 for (
int j = 0; j < ct_proto.var_index_size(); ++j) {
725 ct->SetCoefficient(variables_[ct_proto.var_index(j)],
726 ct_proto.coefficient(j));
730 for (
const MPGeneralConstraintProto& general_constraint :
732 switch (general_constraint.general_constraint_case()) {
735 general_constraint.indicator_constraint().constraint();
742 MPConstraint*
const constraint =
new MPConstraint(
743 constraint_index,
proto.lower_bound(),
proto.upper_bound(),
744 clear_names ?
"" :
proto.name(), interface_.get());
745 if (constraint_name_to_index_) {
750 constraint_is_extracted_.push_back(
false);
753 for (
int j = 0; j <
proto.var_index_size(); ++j) {
755 proto.coefficient(j));
759 variables_[general_constraint.indicator_constraint().var_index()];
762 general_constraint.indicator_constraint().var_value();
764 if (!interface_->AddIndicatorConstraint(
constraint)) {
765 *error_message =
"Solver doesn't support indicator constraints";
771 *error_message = absl::StrFormat(
772 "Optimizing general constraints of type %i is only supported " 773 "through direct proto solves. Please use MPSolver::SolveWithProto, " 774 "or the solver's direct proto solve function.",
775 general_constraint.general_constraint_case());
780 objective->SetOptimizationDirection(input_model.
maximize());
786 solution_hint_.clear();
788 solution_hint_.push_back(
822 ResultStatusToMPSolverResponseStatus(interface_->result_status_));
826 for (
int i = 0; i < variables_.size(); ++i) {
827 response->add_variable_value(variables_[i]->solution_value());
830 if (interface_->IsMIP()) {
831 response->set_best_objective_bound(interface_->best_objective_bound());
834 for (
int j = 0; j < constraints_.size(); ++j) {
835 response->add_dual_value(constraints_[j]->dual_value());
838 for (
int i = 0; i < variables_.size(); ++i) {
839 response->add_reduced_cost(variables_[i]->reduced_cost());
846 bool InCategory(
int status,
int category) {
848 while (status > category) status >>= 4;
849 return status == category;
852 void AppendStatusStr(
const std::string& msg, MPSolutionResponse*
response) {
854 absl::StrCat(
response->status_str(),
855 (
response->status_str().empty() ?
"" :
"\n"), msg));
862 const std::atomic<bool>* interrupt) {
865 if (interrupt !=
nullptr &&
869 "Called MPSolver::SolveWithProto with an underlying solver that " 870 "doesn't support interruption.");
875 static_cast<MPSolver::OptimizationProblemType>(
883 if (interrupt ==
nullptr) {
884 auto optional_response =
885 solver.interface_->DirectlySolveProto(model_request);
886 if (optional_response) {
887 *
response = std::move(optional_response).value();
892 const absl::optional<LazyMutableCopy<MPModelProto>> optional_model =
894 if (!optional_model) {
896 <<
"Failed to extract a valid model from protocol buffer. Status: " 897 << ProtoEnumToString<MPSolverResponseStatus>(
response->status()) <<
" (" 901 std::string error_message;
902 response->set_status(solver.LoadModelFromProtoInternal(
903 optional_model->get(),
true,
904 false, &error_message));
908 response->set_status_str(error_message);
910 <<
"LoadModelFromProtoInternal() failed even though the model was " 912 << ProtoEnumToString<MPSolverResponseStatus>(
response->status()) <<
" (" 913 <<
response->status() <<
"); Error: " << error_message;
920 std::string warning_message;
927 "Warning: the solver specific parameters were not successfully " 936 if (interrupt ==
nullptr) {
942 const absl::Time start_time = absl::Now();
943 absl::Time interrupt_time;
944 bool interrupted_by_user =
false;
946 absl::Notification solve_finished;
947 auto polling_func = [&interrupt, &solve_finished, &solver,
948 &interrupted_by_user, &interrupt_time,
950 constexpr absl::Duration kPollDelay = absl::Microseconds(100);
951 constexpr absl::Duration kMaxInterruptionDelay = absl::Seconds(10);
954 if (solve_finished.HasBeenNotified())
return;
955 absl::SleepFor(kPollDelay);
960 solver.InterruptSolve();
961 interrupt_time = absl::Now();
962 interrupted_by_user =
true;
977 for (absl::Duration poll_delay = kPollDelay;
978 absl::Now() <= interrupt_time + kMaxInterruptionDelay;
980 if (solve_finished.WaitForNotificationWithTimeout(poll_delay)) {
983 solver.InterruptSolve();
988 <<
"MPSolver::InterruptSolve() seems to be ignored by the " 989 "underlying solver, despite repeated calls over at least " 990 << absl::FormatDuration(kMaxInterruptionDelay)
991 <<
". Solver type used: " 1005 thread_pool.
Schedule(polling_func);
1011 solver.FillSolutionResponseProto(
response);
1015 "Solve not started, because the user set the atomic<bool> in " 1016 "MPSolver::SolveWithProto() to true before solving could " 1019 solve_finished.Notify();
1024 if (interrupted_by_user) {
1032 "User interrupted MPSolver::SolveWithProto() by setting the " 1033 "atomic<bool> to true at %s (%s after solving started.)",
1034 absl::FormatTime(interrupt_time),
1035 absl::FormatDuration(interrupt_time - start_time)),
1040 if (!warning_message.empty()) {
1041 AppendStatusStr(warning_message,
response);
1046 DCHECK(output_model !=
nullptr);
1047 output_model->
Clear();
1051 for (
int j = 0; j < variables_.size(); ++j) {
1060 if (objective_->GetCoefficient(
var) != 0.0) {
1062 objective_->GetCoefficient(
var));
1064 if (
var->branching_priority() != 0) {
1075 absl::flat_hash_map<const MPVariable*, int> var_to_index;
1076 for (
int j = 0; j < variables_.size(); ++j) {
1077 var_to_index[variables_[j]] = j;
1081 for (
int i = 0; i < constraints_.size(); ++i) {
1103 std::vector<std::pair<int, double>> linear_term;
1104 for (
const auto& entry :
constraint->coefficients_) {
1108 const double coeff = entry.second;
1109 linear_term.push_back(std::pair<int, double>(var_index, coeff));
1113 std::sort(linear_term.begin(), linear_term.end());
1115 for (
const std::pair<int, double>& var_and_coeff : linear_term) {
1124 if (!solution_hint_.empty()) {
1127 for (
const auto& var_value_pair : solution_hint_) {
1136 interface_->result_status_ = static_cast<ResultStatus>(
response.status());
1139 return absl::InvalidArgumentError(absl::StrCat(
1140 "Cannot load a solution unless its status is OPTIMAL or FEASIBLE" 1142 ProtoEnumToString<MPSolverResponseStatus>(
response.status()),
")"));
1147 if (
response.variable_value_size() != variables_.size()) {
1148 return absl::InvalidArgumentError(absl::StrCat(
1149 "Trying to load a solution whose number of variables (",
1151 ") does not correspond to the Solver's (", variables_.size(),
")"));
1153 interface_->ExtractModel();
1157 double largest_error = 0;
1158 int num_vars_out_of_bounds = 0;
1159 int last_offending_var = -1;
1160 for (
int i = 0; i <
response.variable_value_size(); ++i) {
1161 const double var_value =
response.variable_value(i);
1164 const double lb_error =
var->lb() - var_value;
1165 const double ub_error = var_value -
var->ub();
1166 if (lb_error > tolerance || ub_error > tolerance) {
1167 ++num_vars_out_of_bounds;
1169 last_offending_var = i;
1172 if (num_vars_out_of_bounds > 0) {
1173 return absl::InvalidArgumentError(absl::StrCat(
1174 "Loaded a solution whose variables matched the solver's, but ",
1175 num_vars_out_of_bounds,
" of ", variables_.size(),
1176 " variables were out of their bounds, by more than the primal" 1177 " tolerance which is: ",
1178 tolerance,
". Max error: ", largest_error,
", last offender var is #",
1179 last_offending_var,
": '", variables_[last_offending_var]->name(),
1183 for (
int i = 0; i <
response.variable_value_size(); ++i) {
1184 variables_[i]->set_solution_value(
response.variable_value(i));
1186 if (
response.dual_value_size() > 0) {
1187 if (
response.dual_value_size() != constraints_.size()) {
1188 return absl::InvalidArgumentError(absl::StrCat(
1189 "Trying to load a dual solution whose number of entries (",
1190 response.dual_value_size(),
") does not correspond to the Solver's (",
1191 constraints_.size(),
")"));
1193 for (
int i = 0; i <
response.dual_value_size(); ++i) {
1194 constraints_[i]->set_dual_value(
response.dual_value(i));
1197 if (
response.reduced_cost_size() > 0) {
1198 if (
response.reduced_cost_size() != variables_.size()) {
1199 return absl::InvalidArgumentError(absl::StrCat(
1200 "Trying to load a reduced cost solution whose number of entries (",
1202 ") does not correspond to the Solver's (", variables_.size(),
")"));
1204 for (
int i = 0; i <
response.reduced_cost_size(); ++i) {
1205 variables_[i]->set_reduced_cost(
response.reduced_cost(i));
1210 if (
response.has_objective_value()) {
1211 interface_->objective_value_ =
response.objective_value();
1213 if (
response.has_best_objective_bound()) {
1214 interface_->best_objective_bound_ =
response.best_objective_bound();
1219 return absl::OkStatus();
1227 if (variable_name_to_index_) {
1228 variable_name_to_index_->clear();
1230 variable_is_extracted_.clear();
1231 constraints_.clear();
1232 if (constraint_name_to_index_) {
1233 constraint_name_to_index_->clear();
1235 constraint_is_extracted_.clear();
1236 interface_->Reset();
1237 solution_hint_.clear();
1245 const std::vector<BasisStatus>& variable_statuses,
1246 const std::vector<BasisStatus>& constraint_statuses) {
1247 interface_->SetStartingLpBasis(variable_statuses, constraint_statuses);
1251 const std::string&
name) {
1254 new MPVariable(var_index, lb, ub, integer,
name, interface_.get());
1255 if (variable_name_to_index_) {
1258 variables_.push_back(v);
1259 variable_is_extracted_.push_back(
false);
1260 interface_->AddVariable(v);
1265 const std::string&
name) {
1270 const std::string&
name) {
1279 const std::string&
name,
1280 std::vector<MPVariable*>* vars) {
1282 if (nb <= 0)
return;
1283 const int num_digits = NumDigits(nb);
1284 for (
int i = 0; i < nb; ++i) {
1289 absl::StrFormat(
"%s%0*d",
name.c_str(), num_digits, i);
1290 vars->push_back(
MakeVar(lb, ub, integer, vname));
1296 const std::string&
name,
1297 std::vector<MPVariable*>* vars) {
1302 const std::string&
name,
1303 std::vector<MPVariable*>* vars) {
1308 std::vector<MPVariable*>* vars) {
1321 const std::string&
name) {
1325 if (constraint_name_to_index_) {
1330 constraint_is_extracted_.push_back(
false);
1344 const std::string&
name) {
1354 int MPSolver::ComputeMaxConstraintSize(
int min_constraint_index,
1355 int max_constraint_index)
const {
1356 int max_constraint_size = 0;
1358 DCHECK_LE(max_constraint_index, constraints_.size());
1359 for (
int i = min_constraint_index; i < max_constraint_index; ++i) {
1361 if (
ct->coefficients_.size() > max_constraint_size) {
1362 max_constraint_size =
ct->coefficients_.size();
1365 return max_constraint_size;
1368 bool MPSolver::HasInfeasibleConstraints()
const {
1369 bool hasInfeasibleConstraints =
false;
1370 for (
int i = 0; i < constraints_.size(); ++i) {
1371 if (constraints_[i]->lb() > constraints_[i]->ub()) {
1372 LOG(
WARNING) <<
"Constraint " << constraints_[i]->name() <<
" (" << i
1373 <<
") has contradictory bounds:" 1374 <<
" lower bound = " << constraints_[i]->lb()
1375 <<
" upper bound = " << constraints_[i]->ub();
1376 hasInfeasibleConstraints =
true;
1379 return hasInfeasibleConstraints;
1382 bool MPSolver::HasIntegerVariables()
const {
1383 for (
const MPVariable*
const variable : variables_) {
1391 return Solve(default_param);
1400 if (HasInfeasibleConstraints()) {
1402 return interface_->result_status_;
1406 if (absl::GetFlag(FLAGS_verify_solution)) {
1408 VLOG(1) <<
"--verify_solution enabled, but the solver did not find a" 1409 <<
" solution: skipping the verification.";
1412 absl::GetFlag(FLAGS_log_verification_errors))) {
1414 interface_->result_status_ = status;
1417 DCHECK_EQ(interface_->result_status_, status);
1422 interface_->Write(file_name);
1427 const std::string prefix =
"Variable '" +
var.
name() +
"': domain = ";
1430 return prefix +
"∅";
1434 if (
var.integer() &&
var.ub() -
var.lb() <= 1) {
1435 const int64_t lb = static_cast<int64_t>(ceil(
var.lb()));
1436 const int64_t ub = static_cast<int64_t>(floor(
var.ub()));
1438 return prefix +
"∅";
1439 }
else if (lb == ub) {
1440 return absl::StrFormat(
"%s{ %d }", prefix.c_str(), lb);
1442 return absl::StrFormat(
"%s{ %d, %d }", prefix.c_str(), lb, ub);
1446 if (
var.lb() ==
var.ub()) {
1447 return absl::StrFormat(
"%s{ %f }", prefix.c_str(),
var.lb());
1449 return prefix + (
var.integer() ?
"Integer" :
"Real") +
" in " +
1451 ? std::string(
"]-∞")
1452 :
absl::StrFormat(
"[%f",
var.lb())) +
1454 (
var.ub() >= MPSolver::infinity() ? std::string(
"+∞[")
1455 :
absl::StrFormat(
"%f]",
var.ub()));
1458 std::string PrettyPrintConstraint(
const MPConstraint& constraint) {
1459 std::string prefix =
"Constraint '" + constraint.name() +
"': ";
1462 constraint.lb() > constraint.ub()) {
1463 return prefix +
"ALWAYS FALSE";
1467 return prefix +
"ALWAYS TRUE";
1469 prefix +=
"<linear expr>";
1471 if (constraint.lb() == constraint.ub()) {
1472 return absl::StrFormat(
"%s = %f", prefix.c_str(), constraint.lb());
1476 return absl::StrFormat(
"%s ≤ %f", prefix.c_str(), constraint.ub());
1479 return absl::StrFormat(
"%s ≥ %f", prefix.c_str(), constraint.lb());
1481 return absl::StrFormat(
"%s ∈ [%f, %f]", prefix.c_str(), constraint.lb(),
1487 interface_->ExtractModel();
1490 if (std::isnan(
value)) {
1491 return absl::InvalidArgumentError(
1492 absl::StrCat(
"NaN value for ", PrettyPrintVar(*
variable)));
1494 if (value < variable->lb()) {
1501 return absl::OkStatus();
1506 if (!interface_->CheckSolutionIsSynchronizedAndExists())
return {};
1507 std::vector<double> activities(constraints_.size(), 0.0);
1508 for (
int i = 0; i < constraints_.size(); ++i) {
1511 for (
const auto& entry :
constraint.coefficients_) {
1512 sum.
Add(entry.first->solution_value() * entry.second);
1514 activities[i] = sum.
Value();
1521 double max_observed_error = 0;
1522 if (tolerance < 0) tolerance =
infinity();
1526 for (
int i = 0; i < variables_.size(); ++i) {
1528 const double value =
var.solution_value();
1530 if (std::isnan(
value)) {
1533 LOG_IF(
ERROR, log_errors) <<
"NaN value for " << PrettyPrintVar(
var);
1538 if (
value <
var.lb() - tolerance) {
1542 <<
"Value " <<
value <<
" too low for " << PrettyPrintVar(
var);
1547 if (
value >
var.ub() + tolerance) {
1551 <<
"Value " <<
value <<
" too high for " << PrettyPrintVar(
var);
1556 if (fabs(
value - round(
value)) > tolerance) {
1558 max_observed_error =
1561 <<
"Non-integer value " <<
value <<
" for " << PrettyPrintVar(
var);
1565 if (!
IsMIP() && HasIntegerVariables()) {
1566 LOG_IF(
INFO, log_errors) <<
"Skipped variable integrality check, because " 1567 <<
"a continuous relaxation of the model was " 1568 <<
"solved (i.e., the selected solver does not " 1569 <<
"support integer variables).";
1574 for (
int i = 0; i < constraints_.size(); ++i) {
1576 const double activity = activities[i];
1578 double inaccurate_activity = 0.0;
1579 for (
const auto& entry :
constraint.coefficients_) {
1580 inaccurate_activity += entry.first->solution_value() * entry.second;
1583 if (std::isnan(activity) || std::isnan(inaccurate_activity)) {
1587 <<
"NaN value for " << PrettyPrintConstraint(
constraint);
1597 max_observed_error =
1600 <<
"Activity " << activity <<
" too low for " 1602 }
else if (inaccurate_activity <
constraint.
lb() - tolerance) {
1604 <<
"Activity " << activity <<
", computed with the (inaccurate)" 1605 <<
" standard sum of its terms, is too low for " 1612 max_observed_error =
1615 <<
"Activity " << activity <<
" too high for " 1617 }
else if (inaccurate_activity >
constraint.
ub() + tolerance) {
1619 <<
"Activity " << activity <<
", computed with the (inaccurate)" 1620 <<
" standard sum of its terms, is too high for " 1631 double inaccurate_objective_value = objective.
offset();
1632 for (
const auto& entry : objective.coefficients_) {
1633 const double term = entry.first->solution_value() * entry.second;
1634 objective_sum.
Add(term);
1635 inaccurate_objective_value += term;
1637 const double actual_objective_value = objective_sum.
Value();
1639 objective.
Value(), actual_objective_value, tolerance, tolerance)) {
1642 max_observed_error, fabs(actual_objective_value - objective.
Value()));
1644 <<
"Objective value " << objective.
Value() <<
" isn't accurate" 1645 <<
", it should be " << actual_objective_value
1646 <<
" (delta=" << actual_objective_value - objective.
Value() <<
").";
1648 inaccurate_objective_value,
1649 tolerance, tolerance)) {
1651 <<
"Objective value " << objective.
Value() <<
" doesn't correspond" 1652 <<
" to the value computed with the standard (and therefore inaccurate)" 1653 <<
" sum of its terms.";
1655 if (num_errors > 0) {
1657 <<
"There were " << num_errors <<
" errors above the tolerance (" 1658 << tolerance <<
"), the largest was " << max_observed_error;
1675 return interface_->ComputeExactConditionNumber();
1679 if (
var ==
nullptr)
return false;
1680 if (
var->index() >= 0 &&
var->index() < variables_.size()) {
1682 return variables_[
var->index()] ==
var;
1688 std::string* model_str)
const {
1693 const auto status_or =
1695 *model_str = status_or.value_or(
"");
1696 return status_or.ok();
1700 std::string* model_str)
const {
1705 const auto status_or =
1707 *model_str = status_or.value_or(
"");
1708 return status_or.ok();
1712 for (
const auto& var_value_pair : hint) {
1714 <<
"hint variable does not belong to this solver";
1716 solution_hint_ = std::move(hint);
1719 void MPSolver::GenerateVariableNameIndex()
const {
1720 if (variable_name_to_index_)
return;
1721 variable_name_to_index_ = absl::flat_hash_map<std::string, int>();
1727 void MPSolver::GenerateConstraintNameIndex()
const {
1728 if (constraint_name_to_index_)
return;
1729 constraint_name_to_index_ = absl::flat_hash_map<std::string, int>();
1730 for (
const MPConstraint*
const cst : constraints_) {
1738 interface_->SetCallback(mp_callback);
1742 return interface_->SupportsCallbacks();
1770 <<
"MPSolverResponseStatusIsRpcError() called with invalid status " 1771 <<
"(value: " << status <<
")";
1783 sync_status_(MODEL_SYNCHRONIZED),
1784 result_status_(
MPSolver::NOT_SOLVED),
1786 last_constraint_index_(0),
1787 last_variable_index_(0),
1788 objective_value_(0.0),
1789 best_objective_bound_(0.0),
1795 LOG(
WARNING) <<
"Writing model not implemented in this solver interface.";
1830 solver_->variable_is_extracted_.assign(
solver_->variables_.size(),
false);
1831 solver_->constraint_is_extracted_.assign(
solver_->constraints_.size(),
false);
1837 <<
"The model has been changed since the solution was last computed." 1838 <<
" MPSolverInterface::sync_status_ = " <<
sync_status_;
1849 LOG(DFATAL) <<
"No solution exists. MPSolverInterface::result_status_ = " 1862 const double trivial_worst_bound =
1863 maximize_ ? -std::numeric_limits<double>::infinity()
1864 : std::numeric_limits<double>::infinity();
1866 LOG(DFATAL) <<
"Best objective bound only available for discrete problems.";
1867 return trivial_worst_bound;
1870 return trivial_worst_bound;
1873 if (
solver_->variables_.empty() &&
solver_->constraints_.empty()) {
1887 LOG(DFATAL) <<
"ComputeExactConditionNumber not implemented for " 1888 << ProtoEnumToString<MPModelRequest::SolverType>(
1889 static_cast<MPModelRequest::SolverType>(
1924 LOG(
WARNING) <<
"Trying to set an unsupported parameter: " << param <<
".";
1928 LOG(
WARNING) <<
"Trying to set an unsupported parameter: " << param <<
".";
1932 LOG(
WARNING) <<
"Trying to set a supported parameter: " << param
1933 <<
" to an unsupported value: " <<
value;
1937 LOG(
WARNING) <<
"Trying to set a supported parameter: " << param
1938 <<
" to an unsupported value: " <<
value;
1942 return absl::UnimplementedError(
1943 absl::StrFormat(
"SetNumThreads() not supported by %s.",
SolverVersion()));
1952 LOG(
WARNING) <<
"SetSolverSpecificParametersAsString() not supported by " 1977 : relative_mip_gap_value_(kDefaultRelativeMipGap),
1979 dual_tolerance_value_(kDefaultDualTolerance),
1980 presolve_value_(kDefaultPresolve),
1981 scaling_value_(kDefaultIntegerParamValue),
1982 lp_algorithm_value_(kDefaultIntegerParamValue),
1983 incrementality_value_(kDefaultIncrementality),
1984 lp_algorithm_is_default_(true) {}
1990 relative_mip_gap_value_ =
value;
1994 primal_tolerance_value_ =
value;
1998 dual_tolerance_value_ =
value;
2002 LOG(
ERROR) <<
"Trying to set an unknown parameter: " << param <<
".";
2012 LOG(
ERROR) <<
"Trying to set a supported parameter: " << param
2013 <<
" to an unknown value: " <<
value;
2015 presolve_value_ =
value;
2020 LOG(
ERROR) <<
"Trying to set a supported parameter: " << param
2021 <<
" to an unknown value: " <<
value;
2023 scaling_value_ =
value;
2028 LOG(
ERROR) <<
"Trying to set a supported parameter: " << param
2029 <<
" to an unknown value: " <<
value;
2031 lp_algorithm_value_ =
value;
2032 lp_algorithm_is_default_ =
false;
2037 LOG(
ERROR) <<
"Trying to set a supported parameter: " << param
2038 <<
" to an unknown value: " <<
value;
2040 incrementality_value_ =
value;
2044 LOG(
ERROR) <<
"Trying to set an unknown parameter: " << param <<
".";
2065 LOG(
ERROR) <<
"Trying to reset an unknown parameter: " << param <<
".";
2082 lp_algorithm_is_default_ =
true;
2090 LOG(
ERROR) <<
"Trying to reset an unknown parameter: " << param <<
".";
2109 return relative_mip_gap_value_;
2112 return primal_tolerance_value_;
2115 return dual_tolerance_value_;
2118 LOG(
ERROR) <<
"Trying to get an unknown parameter: " << param <<
".";
2128 return presolve_value_;
2132 return lp_algorithm_value_;
2135 return incrementality_value_;
2138 return scaling_value_;
2141 LOG(
ERROR) <<
"Trying to get an unknown parameter: " << param <<
".";
MPSolverInterface * BuildGurobiInterface(bool mip, MPSolver *const solver)
static void SolveWithProto(const MPModelRequest &model_request, MPSolutionResponse *response, const std::atomic< bool > *interrupt=nullptr)
Solves the model encoded by a MPModelRequest protocol buffer and fills the solution encoded as a MPSo...
::operations_research::MPIndicatorConstraint * mutable_indicator_constraint()
void set_lower_bound(double value)
::operations_research::MPConstraintProto * mutable_constraint()
ResultStatus
The status of solving the problem.
bool ExportModelAsMpsFormat(bool fixed_format, bool obfuscate, std::string *model_str) const
static const IncrementalityValues kDefaultIncrementality
virtual OptimizationProblemType ProblemType() const
Returns the optimization problem type set at construction.
MPVariable * LookupVariableOrNull(const std::string &var_name) const
Looks up a variable by name, and returns nullptr if it does not exist.
void Add(const FpNumber &value)
bool InterruptSolve()
Interrupts the Solve() execution to terminate processing if possible.
static const double kDefaultPrimalTolerance
static constexpr SolverType GLPK_LINEAR_PROGRAMMING
MPVariable * MakeIntVar(double lb, double ub, const std::string &name)
Creates an integer variable.
Advanced usage: incrementality from one solve to the next.
const ::operations_research::MPGeneralConstraintProto & general_constraint(int index) const
virtual absl::Status SetNumThreads(int num_threads)
static MPSolver * CreateSolver(const std::string &solver_id)
Recommended factory method to create a MPSolver instance, especially in non C++ languages.
void SetDoubleParam(MPSolverParameters::DoubleParam param, double value)
Sets a double parameter to a specific value.
constexpr NamedOptimizationProblemType kOptimizationProblemTypeNames[]
virtual void SetLpAlgorithm(int value)=0
static constexpr SolverType GUROBI_LINEAR_PROGRAMMING
double lower_bound() const
double Value() const
Returns the objective value of the best solution found so far.
virtual void SetOptimizationDirection(bool maximize)=0
virtual void ExtractNewVariables()=0
double best_objective_bound_
virtual void SetPresolveMode(int value)=0
const std::string & MPModelRequest_SolverType_Name(T enum_t_value)
void set_objective_offset(double value)
static OptimizationProblemType ParseSolverTypeOrDie(const std::string &solver_id)
Parses the name of the solver and returns the correct optimization type or dies.
void Clear()
Clears the objective (including the optimization direction), all variables and constraints.
void SetOffset(double value)
Sets the constant term in the objective.
void SetStartingLpBasis(const std::vector< MPSolver::BasisStatus > &variable_statuses, const std::vector< MPSolver::BasisStatus > &constraint_statuses)
Advanced usage: Incrementality.
SynchronizationStatus sync_status_
virtual double ComputeExactConditionNumber() const
static constexpr SolverType CPLEX_MIXED_INTEGER_PROGRAMMING
#define VLOG(verboselevel)
double best_objective_bound() const
const std::string & name() const
Returns the name of the constraint.
static bool SolverType_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, SolverType *value)
bool ignore_solver_specific_parameters_failure() const
const MPObjective & Objective() const
Returns the objective object.
MPSolverParameters()
The constructor sets all parameters to their default value.
double ub() const
Returns the upper bound.
static double infinity()
Infinity.
virtual void ClearConstraint(MPConstraint *const constraint)=0
bool has_solver_specific_parameters() const
void SetCoefficient(const MPVariable *const var, double coeff)
Sets the coefficient of the variable in the objective.
void ResetDoubleParam(MPSolverParameters::DoubleParam param)
Sets a double parameter to its default value (default value defined in MPSolverParameters if it exist...
void Clear()
Clears all variables and coefficients. Does not clear the bounds.
void SetDoubleParamToUnsupportedValue(MPSolverParameters::DoubleParam param, double value)
A C++ wrapper that provides a simple and unified interface to several linear programming and mixed in...
void InsertOrDie(Collection *const collection, const typename Collection::value_type &value)
double BestBound() const
Returns the best objective bound.
int NumVariables() const
Returns the number of variables.
static bool SupportsProblemType(OptimizationProblemType problem_type)
Whether the given problem type is supported (this will depend on the targets that you linked).
void set_name(ArgT0 &&arg0, ArgT... args)
const absl::string_view ToString(MPSolver::OptimizationProblemType optimization_problem_type)
virtual std::string name() const
Object naming.
bool integer() const
Returns the integrality requirement of the variable.
bool minimization() const
Is the optimization direction set to minimize?
OptimizationProblemType
The type of problems (LP or MIP) that will be solved and the underlying solver (GLOP,...
void SetMinimization()
Sets the optimization direction to minimize.
void SetBounds(double lb, double ub)
Sets both the lower and upper bounds.
A class to express a linear objective.
static const double kDefaultRelativeMipGap
void set_var_index(::PROTOBUF_NAMESPACE_ID::int32 value)
static constexpr SolverType BOP_INTEGER_PROGRAMMING
static constexpr SolverType SCIP_MIXED_INTEGER_PROGRAMMING
void set_is_lazy(bool value)
static const double kUnknownDoubleParamValue
Advanced usage: presolve mode.
BasisStatus
Advanced usage: possible basis status values for a variable and the slack variable of a linear constr...
const MPVariable * indicator_variable() const
IntegerParam
Enumeration of parameters that take integer or categorical values.
virtual void Write(const std::string &filename)
MPSolver::ResultStatus result_status_
virtual bool IsContinuous() const =0
MPObjective * MutableObjective()
Returns the mutable objective object.
void Reset()
Advanced usage: resets extracted model to solve from scratch.
const ::operations_research::MPConstraintProto & constraint(int index) const
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...
MPSolverInterface(MPSolver *const solver)
MPVariable * MakeBoolVar(const std::string &name)
Creates a boolean variable.
void ResetIntegerParam(MPSolverParameters::IntegerParam param)
Sets an integer parameter to its default value (default value defined in MPSolverParameters if it exi...
int GetIntegerParam(MPSolverParameters::IntegerParam param) const
Returns the value of an integer parameter.
virtual void SetObjectiveCoefficient(const MPVariable *const variable, double coefficient)=0
std::function< int64_t(const Model &)> Value(IntegerVariable v)
virtual void SetRelativeMipGap(double value)=0
void set_upper_bound(double value)
void SetIntegerParam(MPSolverParameters::IntegerParam param, int value)
Sets a integer parameter to a specific value.
absl::Status ClampSolutionWithinBounds()
Resets values of out of bound variables to the corresponding bound and returns an error if any of the...
virtual void ExtractNewConstraints()=0
void set_solution_value(double value)
void SetHint(std::vector< std::pair< const MPVariable *, double > > hint)
Sets a hint for solution.
std::string FindErrorInMPModelProto(const MPModelProto &model, double abs_value_threshold, const bool accept_trivially_infeasible_bounds)
Returns an empty string iff the model is valid and not trivially infeasible.
MPSolver(const std::string &name, OptimizationProblemType problem_type)
Create a solver with the given name and underlying solver backend.
The class for variables of a Mathematical Programming (MP) model.
void add_coefficient(double value)
MPSolverInterface * BuildBopInterface(MPSolver *const solver)
MPSolver::BasisStatus basis_status() const
Advanced usage: returns the basis status of the variable in the current solution (only available for ...
bool SupportsCallbacks() const
bool SetSolverSpecificParametersAsString(const std::string ¶meters)
Advanced usage: pass solver specific parameters in text format.
void MakeIntVarArray(int nb, double lb, double ub, const std::string &name, std::vector< MPVariable * > *vars)
Creates an array of integer variables.
::operations_research::MPConstraintProto * add_constraint()
void add_var_index(::PROTOBUF_NAMESPACE_ID::int32 value)
void set_var_value(::PROTOBUF_NAMESPACE_ID::int32 value)
int variable_size() const
virtual void ExtractObjective()=0
Limit for relative MIP gap.
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...
the model is trivially invalid (NaN coefficients, etc).
virtual void SetObjectiveOffset(double value)=0
const absl::flat_hash_map< const MPVariable *, double > & terms() const
DoubleParam
Enumeration of parameters that take continuous values.
virtual void SetDualTolerance(double value)=0
#define DCHECK_NE(val1, val2)
static const int kDummyVariableIndex
::operations_research::MPGeneralConstraintProto * add_general_constraint()
const ::operations_research::MPModelProto & model() const
double ub() const
Returns the upper bound.
const ::operations_research::MPVariableProto & variable(int index) const
void SetBounds(double lb, double ub)
Sets both the lower and upper bounds.
absl::Status SetNumThreads(int num_threads)
Sets the number of threads to use by the underlying solver.
void set_is_integer(bool value)
MPSolverInterface * BuildCBCInterface(MPSolver *const solver)
MPConstraint * LookupConstraintOrNull(const std::string &constraint_name) const
Looks up a constraint by name, and returns nullptr if it does not exist.
virtual void SetIntegerParamToUnsupportedValue(MPSolverParameters::IntegerParam param, int value)
static const int kDefaultIntegerParamValue
std::vector< double > ComputeConstraintActivities() const
Advanced usage: compute the "activities" of all constraints, which are the sums of their linear terms...
double ComputeExactConditionNumber() const
Advanced usage: computes the exact condition number of the current scaled basis: L1norm(B) * L1norm(i...
bool has_solver_time_limit_seconds() const
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.")
bool VerifySolution(double tolerance, bool log_errors) const
Advanced usage: Verifies the correctness of the solution.
int64_t iterations() const
Returns the number of simplex iterations.
MPVariable * MakeVar(double lb, double ub, bool integer, const std::string &name)
Creates a variable with the given bounds, integrality requirement and name.
void MakeVarArray(int nb, double lb, double ub, bool integer, const std::string &name_prefix, std::vector< MPVariable * > *vars)
Creates an array of variables.
bool indicator_value() const
virtual void SetConstraintBounds(int index, double lb, double ub)=0
bool SolverTypeIsMip(MPModelRequest::SolverType solver_type)
double objective_value() const
void STLDeleteElements(T *container)
void Write(const std::string &file_name)
Writes the model using the solver internal write function.
void SetCommonParameters(const MPSolverParameters ¶m)
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...
virtual std::string SolverVersion() const =0
virtual void SetUnsupportedIntegerParam(MPSolverParameters::IntegerParam param)
const std::string & name() const
Returns the name of the variable.
void SuppressOutput()
Suppresses solver logging.
static constexpr SolverType CPLEX_LINEAR_PROGRAMMING
void Reset()
Sets all parameters to their default value.
double solution_value() const
Returns the value of the variable in the current solution.
virtual void SetVariableBounds(int index, double lb, double ub)=0
const std::string & name() const
const std::string & solver_specific_parameters() const
The class for constraints of a Mathematical Programming (MP) model.
bool has_objective_offset() const
static const PresolveValues kDefaultPresolve
feasible, or stopped by limit.
static const double kDefaultDualTolerance
static constexpr SolverType XPRESS_MIXED_INTEGER_PROGRAMMING
#define DCHECK_GE(val1, val2)
double GetCoefficient(const MPVariable *const var) const
Gets the coefficient of a given variable in the objective.
void SetMIPParameters(const MPSolverParameters ¶m)
void set_branching_priority(::PROTOBUF_NAMESPACE_ID::int32 value)
SharedResponseManager * response
virtual ~MPSolverInterface()
static bool SolverTypeSupportsInterruption(const MPModelRequest::SolverType solver)
void EnableOutput()
Enables solver logging.
bool has_quadratic_objective() const
bool constraint_is_extracted(int ct_index) const
static constexpr SolverType KNAPSACK_MIXED_INTEGER_PROGRAMMING
double objective_offset() const
void InvalidateSolutionSynchronization()
Advanced usage: tolerance for primal feasibility of basic solutions.
virtual void SetCoefficient(MPConstraint *const constraint, const MPVariable *const variable, double new_value, double old_value)=0
bool GurobiIsCorrectlyInstalled()
double upper_bound() const
virtual bool IsMIP() const =0
static const double kDefaultDoubleParamValue
double var_value(int index) const
MPVariable * MakeNumVar(double lb, double ub, const std::string &name)
Creates a continuous variable.
double dual_value() const
Advanced usage: returns the dual value of the constraint in the current solution (only available for ...
static constexpr SolverType XPRESS_LINEAR_PROGRAMMING
void set_name(ArgT0 &&arg0, ArgT... args)
bool OutputIsEnabled() const
Controls (or queries) the amount of output produced by the underlying solver.
virtual void BranchingPriorityChangedForVariable(int var_index)
int NumConstraints() const
Returns the number of constraints.
#define LOG_IF(severity, condition)
#define DCHECK(condition)
void set_lower_bound(double 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)
int last_constraint_index_
void MakeNumVarArray(int nb, double lb, double ub, const std::string &name, std::vector< MPVariable * > *vars)
Creates an array of continuous variables.
int index() const
Returns the index of the variable in the MPSolver::variables_.
Advanced usage: enable or disable matrix scaling.
bool CheckSolutionIsSynchronized() const
void SetCallback(MPCallback *mp_callback)
void SetBranchingPriority(int priority)
const ::operations_research::PartialVariableAssignment & solution_hint() const
void Schedule(std::function< void()> closure)
double unrounded_solution_value() const
Advanced usage: unrounded solution value.
#define DLOG_IF(severity, condition)
MPSolver::BasisStatus basis_status() const
Advanced usage: returns the basis status of the constraint.
bool AbslParseFlag(const absl::string_view text, MPSolver::OptimizationProblemType *solver_type, std::string *error)
void set_upper_bound(double value)
double GetDoubleParam(MPSolverParameters::DoubleParam param) const
Returns the value of a double parameter.
void set_maximize(bool value)
Advanced usage: tolerance for dual feasibility of basic solutions.
#define DCHECK_EQ(val1, val2)
::operations_research::MPVariableProto * add_variable()
void AddLinearExpr(const LinearExpr &linear_expr)
Adds linear_expr to the current objective, does not change the direction.
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final
MPSolverResponseStatus LoadModelFromProto(const MPModelProto &input_model, std::string *error_message)
Loads model from protocol buffer.
bool CheckSolutionIsSynchronizedAndExists() const
bool AreWithinAbsoluteOrRelativeTolerances(FloatType x, FloatType y, FloatType relative_tolerance, FloatType absolute_tolerance)
bool maximization() const
Is the optimization direction set to maximize?
double lb() const
Returns the lower bound.
void SetTimeLimit(absl::Duration time_limit)
MPVariable * variable(int index) const
Returns the variable at position index.
::PROTOBUF_NAMESPACE_ID::int32 var_index(int index) const
void set_objective_coefficient(double value)
virtual void ClearObjective()=0
void SetCoefficient(const MPVariable *const var, double coeff)
Sets the coefficient of the variable on the constraint.
::operations_research::PartialVariableAssignment * mutable_solution_hint()
int var_index_size() const
int64_t nodes() const
Returns the number of branch-and-bound nodes evaluated during the solve.
MPSolverInterface * BuildSatInterface(MPSolver *const solver)
MPSolverInterface * BuildGLOPInterface(MPSolver *const solver)
#define DCHECK_LE(val1, val2)
double lb() const
Returns the lower bound.
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...
Reuse results from previous solve as much as the underlying solver allows.
double solver_time_limit_seconds() const
ResultStatus Solve()
Solves the problem using the default parameter values.
This mathematical programming (MP) solver class is the main class though which users build and solve ...
void set_name(ArgT0 &&arg0, ArgT... args)
IncrementalityValues
Advanced usage: Incrementality options.
LinearExpr models a quantity that is linear in the decision variables (MPVariable) of an optimization...
bool OwnsVariable(const MPVariable *var) const
virtual void SetVariableInteger(int index, bool integer)=0
Collection of objects used to extend the Constraint Solver library.
MPSolverInterface * BuildCLPInterface(MPSolver *const solver)
void MakeBoolVarArray(int nb, const std::string &name, std::vector< MPVariable * > *vars)
Creates an array of boolean variables.
static const int kUnknownIntegerParamValue
abnormal, i.e., error of some kind.
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,...
Start solve from scratch.
MPConstraint * MakeRowConstraint()
Creates a constraint with -infinity and +infinity bounds.
static constexpr SolverType SAT_INTEGER_PROGRAMMING
MPSolver::OptimizationProblemType problem_type
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).
virtual bool CheckSolutionExists() const
bool is_lazy() const
Advanced usage: returns true if the constraint is "lazy" (see below).
std::string SolverVersion() const
Returns a string describing the underlying solver and its version.
const std::string & Name() const
Returns the name of the model set at construction.
const LinearExpr & linear_expr() const
This class stores parameter settings for LP and MIP solvers.
void Clear()
Clears the offset, all variables and coefficients, and the optimization direction.
MPSolverResponseStatus LoadModelFromProtoWithUniqueNamesOrDie(const MPModelProto &input_model, std::string *error_message)
Loads model from protocol buffer.
static constexpr SolverType CBC_MIXED_INTEGER_PROGRAMMING
bool ExportModelAsLpFormat(bool obfuscate, std::string *model_str) const
Shortcuts to the homonymous MPModelProtoExporter methods, via exporting to a MPModelProto with Export...
virtual MPSolver::BasisStatus column_status(int variable_index) const =0
bool MPSolverResponseStatusIsRpcError(MPSolverResponseStatus status)
Algorithm to solve linear programs.
PresolveValues
For each categorical parameter, enumeration of possible values.
An expression of the form:
virtual void SetPrimalTolerance(double value)=0
bool obfuscate
Obfuscates variable and constraint names.
void ExportModelToProto(MPModelProto *output_model) const
Exports model to protocol buffer.
static constexpr SolverType GLOP_LINEAR_PROGRAMMING
void ResetExtractionInformation()
void * underlying_solver()
Advanced usage: returns the underlying solver.
virtual bool SetSolverSpecificParametersAsString(const std::string ¶meters)
void SetInteger(bool integer)
Sets the integrality requirement of the variable.
int last_variable_index() const
void SetUnsupportedDoubleParam(MPSolverParameters::DoubleParam param)
bool enable_internal_solver_output() const
MPConstraint * constraint(int index) const
Returns the constraint at the given index.
constexpr double kDefaultPrimalTolerance
void set_name(ArgT0 &&arg0, ArgT... args)
void FillSolutionResponseProto(MPSolutionResponse *response) const
Encodes the current solution in a solution response protocol buffer.
virtual MPSolver::BasisStatus row_status(int constraint_index) const =0
double offset() const
Gets the constant term in the objective.
double reduced_cost() const
Advanced usage: returns the reduced cost of the variable in the current solution (only available for ...
static constexpr SolverType GLPK_MIXED_INTEGER_PROGRAMMING
::operations_research::MPModelRequest_SolverType solver_type() const
void add_var_index(::PROTOBUF_NAMESPACE_ID::int32 value)
static constexpr SolverType GUROBI_MIXED_INTEGER_PROGRAMMING
void SetOptimizationDirection(bool maximize)
Sets the optimization direction (maximize: true or minimize: false).
MPModelRequest_SolverType
bool variable_is_extracted(int var_index) const
ABSL_MUST_USE_RESULT bool NextSolution()
Some solvers (MIP only, not LP) can produce multiple solutions to the problem.
MPSolverInterface * BuildSCIPInterface(MPSolver *const solver)
static bool ParseSolverType(absl::string_view solver_id, OptimizationProblemType *type)
Parses the name of the solver.
void add_var_value(double value)
void set_is_lazy(bool laziness)
Advanced usage: sets the constraint "laziness".
static constexpr SolverType CLP_LINEAR_PROGRAMMING