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.");
57 "If --verify_solution is set: LOG(ERROR) all errors detected"
58 " during the verification of the solution.");
59ABSL_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().");
63ABSL_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";
162bool 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)
376#if defined(USE_CPLEX)
381#if defined(USE_XPRESS)
388 DCHECK(solver !=
nullptr);
398 return BuildGLPKInterface(
false, solver);
400 return BuildGLPKInterface(
true, solver);
402#if defined(USE_CLP) || defined(USE_CBC)
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.";
439int NumDigits(
int n) {
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()));
509struct NamedOptimizationProblemType {
542 const std::string
id =
543 absl::StrReplaceAll(absl::AsciiStrToUpper(solver_id), {{
"-",
"_"}});
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();
787 for (
int i = 0; i < input_model.
solution_hint().var_index_size(); ++i) {
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());
846bool InCategory(
int status,
int category) {
848 while (status > category) status >>= 4;
849 return status == category;
852void AppendStatusStr(
const std::string& msg, MPSolutionResponse*
response) {
854 absl::StrCat(
response->status_str(),
855 (
response->status_str().empty() ?
"" :
"\n"), msg));
862 std::atomic<bool>* interrupt) {
865 if (interrupt !=
nullptr &&
869 "Called MPSolver::SolveWithProto with an underlying solver that "
870 "doesn't support interruption.");
883 auto optional_response =
884 solver.interface_->DirectlySolveProto(model_request, interrupt);
885 if (optional_response) {
886 *
response = std::move(optional_response).value();
890 const absl::optional<LazyMutableCopy<MPModelProto>> optional_model =
892 if (!optional_model) {
894 <<
"Failed to extract a valid model from protocol buffer. Status: "
895 << ProtoEnumToString<MPSolverResponseStatus>(
response->status()) <<
" ("
899 std::string error_message;
900 response->set_status(solver.LoadModelFromProtoInternal(
901 optional_model->get(),
true,
902 false, &error_message));
906 response->set_status_str(error_message);
908 <<
"LoadModelFromProtoInternal() failed even though the model was "
910 << ProtoEnumToString<MPSolverResponseStatus>(
response->status()) <<
" ("
911 <<
response->status() <<
"); Error: " << error_message;
918 std::string warning_message;
925 "Warning: the solver specific parameters were not successfully "
934 if (interrupt ==
nullptr) {
940 const absl::Time start_time = absl::Now();
941 absl::Time interrupt_time;
942 bool interrupted_by_user =
false;
944 absl::Notification solve_finished;
945 auto polling_func = [&interrupt, &solve_finished, &solver,
946 &interrupted_by_user, &interrupt_time,
948 constexpr absl::Duration kPollDelay = absl::Microseconds(100);
949 constexpr absl::Duration kMaxInterruptionDelay = absl::Seconds(10);
951 while (!interrupt->load()) {
952 if (solve_finished.HasBeenNotified())
return;
953 absl::SleepFor(kPollDelay);
958 solver.InterruptSolve();
959 interrupt_time = absl::Now();
960 interrupted_by_user =
true;
975 for (absl::Duration poll_delay = kPollDelay;
976 absl::Now() <= interrupt_time + kMaxInterruptionDelay;
978 if (solve_finished.WaitForNotificationWithTimeout(poll_delay)) {
981 solver.InterruptSolve();
986 <<
"MPSolver::InterruptSolve() seems to be ignored by the "
987 "underlying solver, despite repeated calls over at least "
988 << absl::FormatDuration(kMaxInterruptionDelay)
989 <<
". Solver type used: "
1003 thread_pool.
Schedule(polling_func);
1007 if (!interrupt->load()) {
1009 solver.FillSolutionResponseProto(
response);
1013 "Solve not started, because the user set the atomic<bool> in "
1014 "MPSolver::SolveWithProto() to true before solving could "
1017 solve_finished.Notify();
1022 if (interrupted_by_user) {
1030 "User interrupted MPSolver::SolveWithProto() by setting the "
1031 "atomic<bool> to true at %s (%s after solving started.)",
1032 absl::FormatTime(interrupt_time),
1033 absl::FormatDuration(interrupt_time - start_time)),
1038 if (!warning_message.empty()) {
1039 AppendStatusStr(warning_message,
response);
1044 DCHECK(output_model !=
nullptr);
1045 output_model->
Clear();
1049 for (
int j = 0; j < variables_.size(); ++j) {
1058 if (objective_->GetCoefficient(
var) != 0.0) {
1060 objective_->GetCoefficient(
var));
1062 if (
var->branching_priority() != 0) {
1073 absl::flat_hash_map<const MPVariable*, int> var_to_index;
1074 for (
int j = 0; j < variables_.size(); ++j) {
1075 var_to_index[variables_[j]] = j;
1079 for (
int i = 0; i < constraints_.size(); ++i) {
1101 std::vector<std::pair<int, double>> linear_term;
1102 for (
const auto& entry :
constraint->coefficients_) {
1106 const double coeff = entry.second;
1107 linear_term.push_back(std::pair<int, double>(var_index, coeff));
1111 std::sort(linear_term.begin(), linear_term.end());
1113 for (
const std::pair<int, double>& var_and_coeff : linear_term) {
1122 if (!solution_hint_.empty()) {
1125 for (
const auto& var_value_pair : solution_hint_) {
1137 return absl::InvalidArgumentError(absl::StrCat(
1138 "Cannot load a solution unless its status is OPTIMAL or FEASIBLE"
1140 ProtoEnumToString<MPSolverResponseStatus>(
response.status()),
")"));
1145 if (
response.variable_value_size() != variables_.size()) {
1146 return absl::InvalidArgumentError(absl::StrCat(
1147 "Trying to load a solution whose number of variables (",
1149 ") does not correspond to the Solver's (", variables_.size(),
")"));
1151 interface_->ExtractModel();
1155 double largest_error = 0;
1156 int num_vars_out_of_bounds = 0;
1157 int last_offending_var = -1;
1158 for (
int i = 0; i <
response.variable_value_size(); ++i) {
1159 const double var_value =
response.variable_value(i);
1162 const double lb_error =
var->lb() - var_value;
1163 const double ub_error = var_value -
var->ub();
1164 if (lb_error > tolerance || ub_error > tolerance) {
1165 ++num_vars_out_of_bounds;
1167 last_offending_var = i;
1170 if (num_vars_out_of_bounds > 0) {
1171 return absl::InvalidArgumentError(absl::StrCat(
1172 "Loaded a solution whose variables matched the solver's, but ",
1173 num_vars_out_of_bounds,
" of ", variables_.size(),
1174 " variables were out of their bounds, by more than the primal"
1175 " tolerance which is: ",
1176 tolerance,
". Max error: ", largest_error,
", last offender var is #",
1177 last_offending_var,
": '", variables_[last_offending_var]->name(),
1181 for (
int i = 0; i <
response.variable_value_size(); ++i) {
1182 variables_[i]->set_solution_value(
response.variable_value(i));
1184 if (
response.dual_value_size() > 0) {
1185 if (
response.dual_value_size() != constraints_.size()) {
1186 return absl::InvalidArgumentError(absl::StrCat(
1187 "Trying to load a dual solution whose number of entries (",
1188 response.dual_value_size(),
") does not correspond to the Solver's (",
1189 constraints_.size(),
")"));
1191 for (
int i = 0; i <
response.dual_value_size(); ++i) {
1192 constraints_[i]->set_dual_value(
response.dual_value(i));
1195 if (
response.reduced_cost_size() > 0) {
1196 if (
response.reduced_cost_size() != variables_.size()) {
1197 return absl::InvalidArgumentError(absl::StrCat(
1198 "Trying to load a reduced cost solution whose number of entries (",
1200 ") does not correspond to the Solver's (", variables_.size(),
")"));
1202 for (
int i = 0; i <
response.reduced_cost_size(); ++i) {
1203 variables_[i]->set_reduced_cost(
response.reduced_cost(i));
1208 if (
response.has_objective_value()) {
1209 interface_->objective_value_ =
response.objective_value();
1211 if (
response.has_best_objective_bound()) {
1212 interface_->best_objective_bound_ =
response.best_objective_bound();
1217 return absl::OkStatus();
1222 absl::MutexLock lock(&global_count_mutex_);
1223 global_num_variables_ += variables_.size();
1224 global_num_constraints_ += constraints_.size();
1229 if (variable_name_to_index_) {
1230 variable_name_to_index_->clear();
1232 variable_is_extracted_.clear();
1233 if (constraint_name_to_index_) {
1234 constraint_name_to_index_->clear();
1236 constraint_is_extracted_.clear();
1237 interface_->Reset();
1238 solution_hint_.clear();
1246 const std::vector<BasisStatus>& variable_statuses,
1247 const std::vector<BasisStatus>& constraint_statuses) {
1248 interface_->SetStartingLpBasis(variable_statuses, constraint_statuses);
1252 const std::string&
name) {
1255 new MPVariable(var_index, lb, ub, integer,
name, interface_.get());
1256 if (variable_name_to_index_) {
1259 variables_.push_back(v);
1260 variable_is_extracted_.push_back(
false);
1261 interface_->AddVariable(v);
1266 const std::string&
name) {
1271 const std::string&
name) {
1280 const std::string&
name,
1281 std::vector<MPVariable*>* vars) {
1283 if (nb <= 0)
return;
1284 const int num_digits = NumDigits(nb);
1285 for (
int i = 0; i < nb; ++i) {
1290 absl::StrFormat(
"%s%0*d",
name.c_str(), num_digits, i);
1291 vars->push_back(
MakeVar(lb, ub, integer, vname));
1297 const std::string&
name,
1298 std::vector<MPVariable*>* vars) {
1303 const std::string&
name,
1304 std::vector<MPVariable*>* vars) {
1309 std::vector<MPVariable*>* vars) {
1322 const std::string&
name) {
1326 if (constraint_name_to_index_) {
1331 constraint_is_extracted_.push_back(
false);
1345 const std::string&
name) {
1355int MPSolver::ComputeMaxConstraintSize(
int min_constraint_index,
1356 int max_constraint_index)
const {
1357 int max_constraint_size = 0;
1359 DCHECK_LE(max_constraint_index, constraints_.size());
1360 for (
int i = min_constraint_index; i < max_constraint_index; ++i) {
1362 if (
ct->coefficients_.size() > max_constraint_size) {
1363 max_constraint_size =
ct->coefficients_.size();
1366 return max_constraint_size;
1369bool MPSolver::HasInfeasibleConstraints()
const {
1370 bool hasInfeasibleConstraints =
false;
1371 for (
int i = 0; i < constraints_.size(); ++i) {
1372 if (constraints_[i]->lb() > constraints_[i]->ub()) {
1373 LOG(
WARNING) <<
"Constraint " << constraints_[i]->name() <<
" (" << i
1374 <<
") has contradictory bounds:"
1375 <<
" lower bound = " << constraints_[i]->lb()
1376 <<
" upper bound = " << constraints_[i]->ub();
1377 hasInfeasibleConstraints =
true;
1380 return hasInfeasibleConstraints;
1383bool MPSolver::HasIntegerVariables()
const {
1384 for (
const MPVariable*
const variable : variables_) {
1392 return Solve(default_param);
1401 if (HasInfeasibleConstraints()) {
1403 return interface_->result_status_;
1407 if (absl::GetFlag(FLAGS_verify_solution)) {
1409 VLOG(1) <<
"--verify_solution enabled, but the solver did not find a"
1410 <<
" solution: skipping the verification.";
1413 absl::GetFlag(FLAGS_log_verification_errors))) {
1415 interface_->result_status_ = status;
1418 DCHECK_EQ(interface_->result_status_, status);
1423 interface_->Write(file_name);
1428 const std::string prefix =
"Variable '" +
var.
name() +
"': domain = ";
1431 return prefix +
"∅";
1435 if (
var.integer() &&
var.ub() -
var.lb() <= 1) {
1436 const int64_t lb =
static_cast<int64_t
>(ceil(
var.lb()));
1437 const int64_t ub =
static_cast<int64_t
>(floor(
var.ub()));
1439 return prefix +
"∅";
1440 }
else if (lb == ub) {
1441 return absl::StrFormat(
"%s{ %d }", prefix.c_str(), lb);
1443 return absl::StrFormat(
"%s{ %d, %d }", prefix.c_str(), lb, ub);
1447 if (
var.lb() ==
var.ub()) {
1448 return absl::StrFormat(
"%s{ %f }", prefix.c_str(),
var.lb());
1450 return prefix + (
var.integer() ?
"Integer" :
"Real") +
" in " +
1452 ? std::string(
"]-∞")
1453 :
absl::StrFormat(
"[%f",
var.lb())) +
1455 (
var.ub() >= MPSolver::infinity() ?
std::string(
"+∞[")
1456 :
absl::StrFormat(
"%f]",
var.ub()));
1459std::string PrettyPrintConstraint(
const MPConstraint& constraint) {
1460 std::string prefix =
"Constraint '" + constraint.name() +
"': ";
1463 constraint.lb() > constraint.ub()) {
1464 return prefix +
"ALWAYS FALSE";
1468 return prefix +
"ALWAYS TRUE";
1470 prefix +=
"<linear expr>";
1472 if (constraint.lb() == constraint.ub()) {
1473 return absl::StrFormat(
"%s = %f", prefix.c_str(), constraint.lb());
1477 return absl::StrFormat(
"%s ≤ %f", prefix.c_str(), constraint.ub());
1480 return absl::StrFormat(
"%s ≥ %f", prefix.c_str(), constraint.lb());
1482 return absl::StrFormat(
"%s ∈ [%f, %f]", prefix.c_str(), constraint.lb(),
1488 interface_->ExtractModel();
1491 if (std::isnan(
value)) {
1492 return absl::InvalidArgumentError(
1493 absl::StrCat(
"NaN value for ", PrettyPrintVar(*
variable)));
1495 if (value < variable->lb()) {
1502 return absl::OkStatus();
1507 if (!interface_->CheckSolutionIsSynchronizedAndExists())
return {};
1508 std::vector<double> activities(constraints_.size(), 0.0);
1509 for (
int i = 0; i < constraints_.size(); ++i) {
1512 for (
const auto& entry :
constraint.coefficients_) {
1513 sum.
Add(entry.first->solution_value() * entry.second);
1515 activities[i] = sum.
Value();
1522 double max_observed_error = 0;
1523 if (tolerance < 0) tolerance =
infinity();
1527 for (
int i = 0; i < variables_.size(); ++i) {
1529 const double value =
var.solution_value();
1531 if (std::isnan(
value)) {
1534 LOG_IF(
ERROR, log_errors) <<
"NaN value for " << PrettyPrintVar(
var);
1539 if (
value <
var.lb() - tolerance) {
1543 <<
"Value " <<
value <<
" too low for " << PrettyPrintVar(
var);
1548 if (
value >
var.ub() + tolerance) {
1552 <<
"Value " <<
value <<
" too high for " << PrettyPrintVar(
var);
1557 if (fabs(
value - round(
value)) > tolerance) {
1559 max_observed_error =
1562 <<
"Non-integer value " <<
value <<
" for " << PrettyPrintVar(
var);
1566 if (!
IsMIP() && HasIntegerVariables()) {
1567 LOG_IF(
INFO, log_errors) <<
"Skipped variable integrality check, because "
1568 <<
"a continuous relaxation of the model was "
1569 <<
"solved (i.e., the selected solver does not "
1570 <<
"support integer variables).";
1575 for (
int i = 0; i < constraints_.size(); ++i) {
1577 const double activity = activities[i];
1579 double inaccurate_activity = 0.0;
1580 for (
const auto& entry :
constraint.coefficients_) {
1581 inaccurate_activity += entry.first->solution_value() * entry.second;
1584 if (std::isnan(activity) || std::isnan(inaccurate_activity)) {
1588 <<
"NaN value for " << PrettyPrintConstraint(
constraint);
1598 max_observed_error =
1601 <<
"Activity " << activity <<
" too low for "
1603 }
else if (inaccurate_activity <
constraint.
lb() - tolerance) {
1605 <<
"Activity " << activity <<
", computed with the (inaccurate)"
1606 <<
" standard sum of its terms, is too low for "
1613 max_observed_error =
1616 <<
"Activity " << activity <<
" too high for "
1618 }
else if (inaccurate_activity >
constraint.
ub() + tolerance) {
1620 <<
"Activity " << activity <<
", computed with the (inaccurate)"
1621 <<
" standard sum of its terms, is too high for "
1632 double inaccurate_objective_value = objective.
offset();
1633 for (
const auto& entry : objective.coefficients_) {
1634 const double term = entry.first->solution_value() * entry.second;
1635 objective_sum.
Add(term);
1636 inaccurate_objective_value += term;
1638 const double actual_objective_value = objective_sum.
Value();
1640 objective.
Value(), actual_objective_value, tolerance, tolerance)) {
1643 max_observed_error, fabs(actual_objective_value - objective.
Value()));
1645 <<
"Objective value " << objective.
Value() <<
" isn't accurate"
1646 <<
", it should be " << actual_objective_value
1647 <<
" (delta=" << actual_objective_value - objective.
Value() <<
").";
1649 inaccurate_objective_value,
1650 tolerance, tolerance)) {
1652 <<
"Objective value " << objective.
Value() <<
" doesn't correspond"
1653 <<
" to the value computed with the standard (and therefore inaccurate)"
1654 <<
" sum of its terms.";
1656 if (num_errors > 0) {
1658 <<
"There were " << num_errors <<
" errors above the tolerance ("
1659 << tolerance <<
"), the largest was " << max_observed_error;
1676 return interface_->ComputeExactConditionNumber();
1680 if (
var ==
nullptr)
return false;
1681 if (
var->index() >= 0 &&
var->index() < variables_.size()) {
1683 return variables_[
var->index()] ==
var;
1689 std::string* model_str)
const {
1694 const auto status_or =
1696 *model_str = status_or.value_or(
"");
1697 return status_or.ok();
1701 std::string* model_str)
const {
1706 const auto status_or =
1708 *model_str = status_or.value_or(
"");
1709 return status_or.ok();
1713 for (
const auto& var_value_pair : hint) {
1715 <<
"hint variable does not belong to this solver";
1717 solution_hint_ = std::move(hint);
1720void MPSolver::GenerateVariableNameIndex()
const {
1721 if (variable_name_to_index_)
return;
1722 variable_name_to_index_ = absl::flat_hash_map<std::string, int>();
1728void MPSolver::GenerateConstraintNameIndex()
const {
1729 if (constraint_name_to_index_)
return;
1730 constraint_name_to_index_ = absl::flat_hash_map<std::string, int>();
1731 for (
const MPConstraint*
const cst : constraints_) {
1739 interface_->SetCallback(mp_callback);
1743 return interface_->SupportsCallbacks();
1747absl::Mutex MPSolver::global_count_mutex_(absl::kConstInit);
1748int64_t MPSolver::global_num_variables_ = 0;
1749int64_t MPSolver::global_num_constraints_ = 0;
1754 absl::MutexLock lock(&global_count_mutex_);
1755 return global_num_variables_;
1761 absl::MutexLock lock(&global_count_mutex_);
1762 return global_num_constraints_;
1790 <<
"MPSolverResponseStatusIsRpcError() called with invalid status "
1791 <<
"(value: " << status <<
")";
1803 sync_status_(MODEL_SYNCHRONIZED),
1804 result_status_(
MPSolver::NOT_SOLVED),
1806 last_constraint_index_(0),
1807 last_variable_index_(0),
1808 objective_value_(0.0),
1809 best_objective_bound_(0.0),
1815 LOG(
WARNING) <<
"Writing model not implemented in this solver interface.";
1850 solver_->variable_is_extracted_.assign(
solver_->variables_.size(),
false);
1851 solver_->constraint_is_extracted_.assign(
solver_->constraints_.size(),
false);
1857 <<
"The model has been changed since the solution was last computed."
1858 <<
" MPSolverInterface::sync_status_ = " <<
sync_status_;
1869 LOG(DFATAL) <<
"No solution exists. MPSolverInterface::result_status_ = "
1882 const double trivial_worst_bound =
1883 maximize_ ? -std::numeric_limits<double>::infinity()
1884 : std::numeric_limits<double>::infinity();
1886 LOG(DFATAL) <<
"Best objective bound only available for discrete problems.";
1887 return trivial_worst_bound;
1890 return trivial_worst_bound;
1893 if (
solver_->variables_.empty() &&
solver_->constraints_.empty()) {
1907 LOG(DFATAL) <<
"ComputeExactConditionNumber not implemented for "
1908 << ProtoEnumToString<MPModelRequest::SolverType>(
1944 LOG(
WARNING) <<
"Trying to set an unsupported parameter: " << param <<
".";
1948 LOG(
WARNING) <<
"Trying to set an unsupported parameter: " << param <<
".";
1952 LOG(
WARNING) <<
"Trying to set a supported parameter: " << param
1953 <<
" to an unsupported value: " <<
value;
1957 LOG(
WARNING) <<
"Trying to set a supported parameter: " << param
1958 <<
" to an unsupported value: " <<
value;
1962 return absl::UnimplementedError(
1963 absl::StrFormat(
"SetNumThreads() not supported by %s.",
SolverVersion()));
1972 LOG(
WARNING) <<
"SetSolverSpecificParametersAsString() not supported by "
1997 : relative_mip_gap_value_(kDefaultRelativeMipGap),
1999 dual_tolerance_value_(kDefaultDualTolerance),
2000 presolve_value_(kDefaultPresolve),
2001 scaling_value_(kDefaultIntegerParamValue),
2002 lp_algorithm_value_(kDefaultIntegerParamValue),
2003 incrementality_value_(kDefaultIncrementality),
2004 lp_algorithm_is_default_(true) {}
2010 relative_mip_gap_value_ =
value;
2014 primal_tolerance_value_ =
value;
2018 dual_tolerance_value_ =
value;
2022 LOG(
ERROR) <<
"Trying to set an unknown parameter: " << param <<
".";
2032 LOG(
ERROR) <<
"Trying to set a supported parameter: " << param
2033 <<
" to an unknown value: " <<
value;
2035 presolve_value_ =
value;
2040 LOG(
ERROR) <<
"Trying to set a supported parameter: " << param
2041 <<
" to an unknown value: " <<
value;
2043 scaling_value_ =
value;
2048 LOG(
ERROR) <<
"Trying to set a supported parameter: " << param
2049 <<
" to an unknown value: " <<
value;
2051 lp_algorithm_value_ =
value;
2052 lp_algorithm_is_default_ =
false;
2057 LOG(
ERROR) <<
"Trying to set a supported parameter: " << param
2058 <<
" to an unknown value: " <<
value;
2060 incrementality_value_ =
value;
2064 LOG(
ERROR) <<
"Trying to set an unknown parameter: " << param <<
".";
2085 LOG(
ERROR) <<
"Trying to reset an unknown parameter: " << param <<
".";
2102 lp_algorithm_is_default_ =
true;
2110 LOG(
ERROR) <<
"Trying to reset an unknown parameter: " << param <<
".";
2129 return relative_mip_gap_value_;
2132 return primal_tolerance_value_;
2135 return dual_tolerance_value_;
2138 LOG(
ERROR) <<
"Trying to get an unknown parameter: " << param <<
".";
2148 return presolve_value_;
2152 return lp_algorithm_value_;
2155 return incrementality_value_;
2158 return scaling_value_;
2161 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:
const LinearExpr & linear_expr() const
double upper_bound() const
double lower_bound() const
The class for constraints of a Mathematical Programming (MP) model.
void SetBounds(double lb, double ub)
Sets both the lower and upper bounds.
const std::string & name() const
Returns the name of the constraint.
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.
bool indicator_value() const
const MPVariable * indicator_variable() 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.
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 ...
void set_is_lazy(bool value)
void set_name(ArgT0 &&arg0, ArgT... args)
void set_lower_bound(double value)
void add_var_index(::PROTOBUF_NAMESPACE_ID::int32 value)
void add_coefficient(double value)
void set_upper_bound(double value)
::operations_research::MPIndicatorConstraint * mutable_indicator_constraint()
void set_name(ArgT0 &&arg0, ArgT... args)
void set_var_value(::PROTOBUF_NAMESPACE_ID::int32 value)
::operations_research::MPConstraintProto * mutable_constraint()
void set_var_index(::PROTOBUF_NAMESPACE_ID::int32 value)
const ::operations_research::MPConstraintProto & constraint(int index) const
int variable_size() const
const std::string & name() const
const ::operations_research::MPVariableProto & variable(int index) const
::operations_research::MPVariableProto * add_variable()
bool has_quadratic_objective() const
::operations_research::MPGeneralConstraintProto * add_general_constraint()
double objective_offset() const
void set_name(ArgT0 &&arg0, ArgT... args)
const ::operations_research::PartialVariableAssignment & solution_hint() const
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final
const ::operations_research::MPGeneralConstraintProto & general_constraint(int index) const
::operations_research::MPConstraintProto * add_constraint()
bool has_objective_offset() const
void set_maximize(bool value)
::operations_research::PartialVariableAssignment * mutable_solution_hint()
void set_objective_offset(double value)
static bool SolverType_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, SolverType *value)
static constexpr SolverType CPLEX_MIXED_INTEGER_PROGRAMMING
double solver_time_limit_seconds() const
static constexpr SolverType GLOP_LINEAR_PROGRAMMING
static constexpr SolverType KNAPSACK_MIXED_INTEGER_PROGRAMMING
static constexpr SolverType CLP_LINEAR_PROGRAMMING
static constexpr SolverType BOP_INTEGER_PROGRAMMING
static constexpr SolverType CPLEX_LINEAR_PROGRAMMING
bool enable_internal_solver_output() const
::operations_research::MPModelRequest_SolverType solver_type() const
const std::string & solver_specific_parameters() const
static constexpr SolverType SCIP_MIXED_INTEGER_PROGRAMMING
static constexpr SolverType GUROBI_MIXED_INTEGER_PROGRAMMING
bool has_solver_specific_parameters() const
bool has_solver_time_limit_seconds() const
static constexpr SolverType XPRESS_MIXED_INTEGER_PROGRAMMING
bool ignore_solver_specific_parameters_failure() const
static constexpr SolverType SAT_INTEGER_PROGRAMMING
const ::operations_research::MPModelProto & model() const
static constexpr SolverType GUROBI_LINEAR_PROGRAMMING
static constexpr SolverType GLPK_MIXED_INTEGER_PROGRAMMING
static constexpr SolverType XPRESS_LINEAR_PROGRAMMING
static constexpr SolverType GLPK_LINEAR_PROGRAMMING
static constexpr SolverType CBC_MIXED_INTEGER_PROGRAMMING
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 int64_t global_num_constraints()
static OptimizationProblemType ParseSolverTypeOrDie(const std::string &solver_id)
Parses the name of the solver and returns the correct optimization type or dies.
void MakeBoolVarArray(int nb, const std::string &name, std::vector< MPVariable * > *vars)
Creates an array of boolean variables.
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.
MPConstraint * constraint(int index) const
Returns the constraint at the given index.
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...
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 int64_t global_num_variables()
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.
const std::string & Name() const
Returns the name of the model set at construction.
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.
MPVariable * variable(int index) const
Returns the variable at position index.
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.
static void SolveWithProto(const MPModelRequest &model_request, MPSolutionResponse *response, std::atomic< bool > *interrupt=nullptr)
Solves the model encoded by a MPModelRequest protocol buffer and fills the solution encoded as a MPSo...
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.
const MPObjective & Objective() const
Returns the objective object.
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...
static bool SolverTypeSupportsInterruption(const MPModelRequest::SolverType solver)
MPSolverResponseStatus LoadModelFromProtoWithUniqueNamesOrDie(const MPModelProto &input_model, std::string *error_message)
Loads model from protocol buffer.
MPObjective * MutableObjective()
Returns the mutable objective object.
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.
const std::string & name() const
Returns the name of the variable.
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.
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 ...
void set_is_integer(bool value)
void set_objective_coefficient(double value)
void set_name(ArgT0 &&arg0, ArgT... args)
void set_lower_bound(double value)
void set_branching_priority(::PROTOBUF_NAMESPACE_ID::int32 value)
void set_upper_bound(double value)
double var_value(int index) const
::PROTOBUF_NAMESPACE_ID::int32 var_index(int index) const
void add_var_value(double value)
void add_var_index(::PROTOBUF_NAMESPACE_ID::int32 value)
virtual std::string name() const
Object naming.
void Schedule(std::function< void()> closure)
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)
const std::string & MPModelRequest_SolverType_Name(T enum_t_value)
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).
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.
MPSolverInterface * BuildSatInterface(MPSolver *const solver)
MPSolverInterface * BuildCLPInterface(MPSolver *const solver)
constexpr NamedOptimizationProblemType kOptimizationProblemTypeNames[]
MPSolverInterface * BuildGLOPInterface(MPSolver *const solver)
MPModelRequest_SolverType
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_CANCELLED_BY_USER
@ MPSOLVER_UNKNOWN_STATUS
@ MPSOLVER_MODEL_IS_VALID
@ MPSOLVER_INCOMPATIBLE_OPTIONS
@ 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.