18 #if !defined(_MSC_VER)
26 #include "absl/status/status.h"
27 #include "absl/status/statusor.h"
28 #include "absl/strings/ascii.h"
29 #include "absl/strings/match.h"
30 #include "absl/strings/str_cat.h"
31 #include "absl/strings/str_format.h"
32 #include "absl/strings/str_replace.h"
33 #include "absl/synchronization/mutex.h"
48 "Systematically verify the solution when calling Solve()"
49 ", and change the return value of Solve() to ABNORMAL if"
50 " an error was detected.");
52 "If --verify_solution is set: LOG(ERROR) all errors detected"
53 " during the verification of the solution.");
54 ABSL_FLAG(
bool, linear_solver_enable_verbose_output,
false,
55 "If set, enables verbose output for the solver. Setting this flag"
56 " is the same as calling MPSolver::EnableOutput().");
58 ABSL_FLAG(
bool, mpsolver_bypass_model_validation,
false,
59 "If set, the user-provided Model won't be verified before Solve()."
60 " Invalid models will typically trigger various error responses"
61 " from the underlying solvers; sometimes crashes.");
66 switch (solver_type) {
67 case MPModelRequest::GLOP_LINEAR_PROGRAMMING:
68 case MPModelRequest::CLP_LINEAR_PROGRAMMING:
69 case MPModelRequest::GLPK_LINEAR_PROGRAMMING:
70 case MPModelRequest::GUROBI_LINEAR_PROGRAMMING:
71 case MPModelRequest::XPRESS_LINEAR_PROGRAMMING:
72 case MPModelRequest::CPLEX_LINEAR_PROGRAMMING:
75 case MPModelRequest::SCIP_MIXED_INTEGER_PROGRAMMING:
76 case MPModelRequest::GLPK_MIXED_INTEGER_PROGRAMMING:
77 case MPModelRequest::CBC_MIXED_INTEGER_PROGRAMMING:
78 case MPModelRequest::GUROBI_MIXED_INTEGER_PROGRAMMING:
79 case MPModelRequest::KNAPSACK_MIXED_INTEGER_PROGRAMMING:
80 case MPModelRequest::BOP_INTEGER_PROGRAMMING:
81 case MPModelRequest::SAT_INTEGER_PROGRAMMING:
82 case MPModelRequest::XPRESS_MIXED_INTEGER_PROGRAMMING:
83 case MPModelRequest::CPLEX_MIXED_INTEGER_PROGRAMMING:
86 LOG(DFATAL) <<
"Invalid SolverType: " << solver_type;
92 if (
var ==
nullptr)
return 0.0;
98 if (
var ==
nullptr)
return;
100 auto it = coefficients_.find(
var);
108 if (it != coefficients_.end() && it->second != 0.0) {
109 const double old_value = it->second;
115 auto insertion_result = coefficients_.insert(std::make_pair(
var, coeff));
116 const double old_value =
117 insertion_result.second ? 0.0 : insertion_result.first->second;
118 insertion_result.first->second = coeff;
124 coefficients_.clear();
128 const bool change =
lb != lb_ ||
ub != ub_;
138 LOG(DFATAL) <<
"Dual value only available for continuous problems";
147 LOG(DFATAL) <<
"Basis status only available for continuous problems";
157 bool MPConstraint::ContainsNewVariables() {
159 for (
const auto& entry : coefficients_) {
160 const int variable_index = entry.first->index();
161 if (variable_index >= last_variable_index ||
173 if (
var ==
nullptr)
return 0.0;
179 if (
var ==
nullptr)
return;
181 auto it = coefficients_.find(
var);
184 if (it == coefficients_.end() || it->second == 0.0)
return;
187 coefficients_[
var] = coeff;
199 for (
auto var_value_pair : linear_expr.
terms()) {
201 <<
"Bad MPVariable* in LinearExpr, did you try adding an integer to an "
202 "MPVariable* directly?";
208 bool is_maximization) {
209 CheckLinearExpr(*interface_->
solver_, linear_expr);
211 coefficients_.clear();
213 for (
const auto& kv : linear_expr.
terms()) {
220 CheckLinearExpr(*interface_->
solver_, linear_expr);
222 for (
const auto& kv : linear_expr.
terms()) {
229 coefficients_.clear();
269 return (integer_ && interface_->
IsMIP()) ? round(solution_value_)
275 return solution_value_;
280 LOG(DFATAL) <<
"Reduced cost only available for continuous problems";
284 return reduced_cost_;
289 LOG(DFATAL) <<
"Basis status only available for continuous problems";
300 const bool change =
lb != lb_ ||
ub != ub_;
318 if (priority == branching_priority_)
return;
319 branching_priority_ = priority;
328 return interface_->SolverVersion();
336 if (num_threads < 1) {
337 return absl::InvalidArgumentError(
"num_threads must be a positive number.");
339 const absl::Status status = interface_->SetNumThreads(num_threads);
341 num_threads_ = num_threads;
348 solver_specific_parameter_string_ =
parameters;
349 return interface_->SetSolverSpecificParametersAsString(
parameters);
354 #if defined(USE_CLP) || defined(USE_CBC)
360 #if defined(USE_GLPK)
366 #if defined(USE_SCIP)
371 #if defined(USE_CPLEX)
376 #if defined(USE_XPRESS)
383 DCHECK(solver !=
nullptr);
391 #if defined(USE_GLPK)
393 return BuildGLPKInterface(
false, solver);
395 return BuildGLPKInterface(
true, solver);
397 #if defined(USE_CLP) || defined(USE_CBC)
405 #if defined(USE_SCIP)
413 #if defined(USE_CPLEX)
415 return BuildCplexInterface(
false, solver);
417 return BuildCplexInterface(
true, solver);
419 #if defined(USE_XPRESS)
421 return BuildXpressInterface(
true, solver);
423 return BuildXpressInterface(
false, solver);
427 LOG(
FATAL) <<
"Linear solver not recognized.";
434 int NumDigits(
int n) {
437 #if defined(_MSC_VER)
438 return static_cast<int>(
std::max(1.0L, log(1.0L * n) / log(10.0L) + 1.0));
440 return static_cast<int>(
std::max(1.0, log10(
static_cast<double>(n)) + 1.0));
449 construction_time_(
absl::Now()) {
450 interface_.reset(BuildSolverInterface(
this));
451 if (absl::GetFlag(FLAGS_linear_solver_enable_verbose_output)) {
454 objective_.reset(
new MPObjective(interface_.get()));
475 return MPSolver::GurobiIsCorrectlyInstalled();
502 struct NamedOptimizationProblemType {
508 #if defined(_MSC_VER)
535 const std::string
id =
536 absl::StrReplaceAll(absl::AsciiStrToUpper(solver_id), {{
"-",
"_"}});
539 MPModelRequest::SolverType solver_type;
540 if (MPModelRequest::SolverType_Parse(
id, &solver_type)) {
546 std::string lower_id = absl::AsciiStrToLower(
id);
549 if (absl::EndsWith(lower_id,
"_mip")) {
550 lower_id = lower_id.substr(0, lower_id.size() - 4);
554 if (lower_id ==
"cp_sat") {
560 if (named_solver.name == lower_id) {
561 *type = named_solver.problem_type;
572 if (named_solver.problem_type == optimization_problem_type) {
573 return named_solver.name;
576 LOG(
FATAL) <<
"Unrecognized solver type: "
577 <<
static_cast<int>(optimization_problem_type);
583 std::string* error) {
584 DCHECK(solver_type !=
nullptr);
588 *error = absl::StrCat(
"Solver type: ", text,
" does not exist.");
595 const std::string& solver_id) {
605 LOG(
WARNING) <<
"Unrecognized solver type: " << solver_id;
610 <<
" not linked in, or the license was not found.";
617 if (!variable_name_to_index_) GenerateVariableNameIndex();
619 absl::flat_hash_map<std::string, int>::const_iterator it =
620 variable_name_to_index_->find(var_name);
621 if (it == variable_name_to_index_->end())
return nullptr;
622 return variables_[it->second];
626 const std::string& constraint_name)
const {
627 if (!constraint_name_to_index_) GenerateConstraintNameIndex();
629 const auto it = constraint_name_to_index_->find(constraint_name);
630 if (it == constraint_name_to_index_->end())
return nullptr;
631 return constraints_[it->second];
637 const MPModelProto& input_model, std::string* error_message) {
642 return LoadModelFromProtoInternal(input_model,
true,
648 const MPModelProto& input_model, std::string* error_message) {
650 GenerateVariableNameIndex();
651 GenerateConstraintNameIndex();
653 return LoadModelFromProtoInternal(input_model,
false,
659 const MPModelProto& input_model,
bool clear_names,
660 bool check_model_validity, std::string* error_message) {
661 CHECK(error_message !=
nullptr);
662 if (check_model_validity) {
664 if (!error.empty()) {
665 *error_message = error;
667 <<
"Invalid model given to LoadModelFromProto(): " << error;
668 if (absl::GetFlag(FLAGS_mpsolver_bypass_model_validation)) {
670 <<
"Ignoring the model error(s) because of"
671 <<
" --mpsolver_bypass_model_validation.";
679 if (input_model.has_quadratic_objective()) {
681 "Optimizing a quadratic objective is only supported through direct "
682 "proto solves. Please use MPSolver::SolveWithProto, or the solver's "
683 "direct proto solve function.";
689 const std::string empty;
690 for (
int i = 0; i < input_model.variable_size(); ++i) {
691 const MPVariableProto& var_proto = input_model.variable(i);
692 MPVariable* variable =
693 MakeNumVar(var_proto.lower_bound(), var_proto.upper_bound(),
694 clear_names ? empty : var_proto.name());
695 variable->SetInteger(var_proto.is_integer());
696 if (var_proto.branching_priority() != 0) {
697 variable->SetBranchingPriority(var_proto.branching_priority());
699 objective->SetCoefficient(variable, var_proto.objective_coefficient());
702 for (
const MPConstraintProto& ct_proto : input_model.constraint()) {
703 if (ct_proto.lower_bound() == -
infinity() &&
704 ct_proto.upper_bound() ==
infinity()) {
708 MPConstraint*
const ct =
710 clear_names ? empty : ct_proto.name());
711 ct->set_is_lazy(ct_proto.is_lazy());
712 for (
int j = 0; j < ct_proto.var_index_size(); ++j) {
713 ct->SetCoefficient(variables_[ct_proto.var_index(j)],
714 ct_proto.coefficient(j));
718 for (
const MPGeneralConstraintProto& general_constraint :
719 input_model.general_constraint()) {
720 switch (general_constraint.general_constraint_case()) {
721 case MPGeneralConstraintProto::kIndicatorConstraint: {
723 general_constraint.indicator_constraint().constraint();
730 MPConstraint*
const constraint =
new MPConstraint(
731 constraint_index,
proto.lower_bound(),
proto.upper_bound(),
732 clear_names ?
"" :
proto.name(), interface_.get());
733 if (constraint_name_to_index_) {
737 constraints_.push_back(constraint);
738 constraint_is_extracted_.push_back(
false);
740 constraint->set_is_lazy(
proto.is_lazy());
741 for (
int j = 0; j <
proto.var_index_size(); ++j) {
742 constraint->SetCoefficient(variables_[
proto.var_index(j)],
743 proto.coefficient(j));
746 MPVariable*
const variable =
747 variables_[general_constraint.indicator_constraint().var_index()];
748 constraint->indicator_variable_ = variable;
749 constraint->indicator_value_ =
750 general_constraint.indicator_constraint().var_value();
752 if (!interface_->AddIndicatorConstraint(constraint)) {
753 *error_message =
"Solver doesn't support indicator constraints";
759 *error_message = absl::StrFormat(
760 "Optimizing general constraints of type %i is only supported "
761 "through direct proto solves. Please use MPSolver::SolveWithProto, "
762 "or the solver's direct proto solve function.",
763 general_constraint.general_constraint_case());
768 objective->SetOptimizationDirection(input_model.maximize());
769 if (input_model.has_objective_offset()) {
770 objective->SetOffset(input_model.objective_offset());
774 solution_hint_.clear();
775 for (
int i = 0; i < input_model.solution_hint().var_index_size(); ++i) {
776 solution_hint_.push_back(
777 std::make_pair(variables_[input_model.solution_hint().var_index(i)],
778 input_model.solution_hint().var_value(i)));
810 ResultStatusToMPSolverResponseStatus(interface_->result_status_));
814 for (
int i = 0; i < variables_.size(); ++i) {
815 response->add_variable_value(variables_[i]->solution_value());
818 if (interface_->IsMIP()) {
819 response->set_best_objective_bound(interface_->best_objective_bound());
822 for (
int j = 0; j < constraints_.size(); ++j) {
823 response->add_dual_value(constraints_[j]->dual_value());
826 for (
int i = 0; i < variables_.size(); ++i) {
827 response->add_reduced_cost(variables_[i]->reduced_cost());
837 MPSolver solver(model_request.model().name(),
839 model_request.solver_type()));
840 if (model_request.enable_internal_solver_output()) {
844 auto optional_response = solver.interface_->DirectlySolveProto(model_request);
845 if (optional_response) {
846 *
response = std::move(optional_response).value();
850 const absl::optional<LazyMutableCopy<MPModelProto>> optional_model =
852 if (!optional_model) {
853 LOG_IF(
WARNING, model_request.enable_internal_solver_output())
854 <<
"Failed to extract a valid model from protocol buffer. Status: "
855 << ProtoEnumToString<MPSolverResponseStatus>(
response->status()) <<
" ("
859 std::string error_message;
860 response->set_status(solver.LoadModelFromProtoInternal(
861 optional_model->get(),
true,
862 false, &error_message));
866 response->set_status_str(error_message);
867 LOG_IF(
WARNING, model_request.enable_internal_solver_output())
868 <<
"LoadModelFromProtoInternal() failed even though the model was "
870 << ProtoEnumToString<MPSolverResponseStatus>(
response->status()) <<
" ("
871 <<
response->status() <<
"); Error: " << error_message;
874 if (model_request.has_solver_time_limit_seconds()) {
876 absl::Seconds(model_request.solver_time_limit_seconds()));
878 std::string warning_message;
879 if (model_request.has_solver_specific_parameters()) {
881 model_request.solver_specific_parameters())) {
882 if (model_request.ignore_solver_specific_parameters_failure()) {
885 "Warning: the solver specific parameters were not successfully "
895 if (!warning_message.empty()) {
896 response->set_status_str(absl::StrCat(
903 DCHECK(output_model !=
nullptr);
904 output_model->Clear();
906 output_model->set_name(
Name());
908 for (
int j = 0; j < variables_.size(); ++j) {
910 MPVariableProto*
const variable_proto = output_model->add_variable();
913 variable_proto->set_name(
var->name());
914 variable_proto->set_lower_bound(
var->lb());
915 variable_proto->set_upper_bound(
var->ub());
916 variable_proto->set_is_integer(
var->integer());
917 if (objective_->GetCoefficient(
var) != 0.0) {
918 variable_proto->set_objective_coefficient(
919 objective_->GetCoefficient(
var));
921 if (
var->branching_priority() != 0) {
922 variable_proto->set_branching_priority(
var->branching_priority());
932 absl::flat_hash_map<const MPVariable*, int> var_to_index;
933 for (
int j = 0; j < variables_.size(); ++j) {
934 var_to_index[variables_[j]] = j;
938 for (
int i = 0; i < constraints_.size(); ++i) {
940 MPConstraintProto* constraint_proto;
942 MPGeneralConstraintProto*
const general_constraint_proto =
943 output_model->add_general_constraint();
944 general_constraint_proto->set_name(constraint->
name());
945 MPIndicatorConstraint*
const indicator_constraint_proto =
946 general_constraint_proto->mutable_indicator_constraint();
947 indicator_constraint_proto->set_var_index(
949 indicator_constraint_proto->set_var_value(constraint->
indicator_value());
950 constraint_proto = indicator_constraint_proto->mutable_constraint();
952 constraint_proto = output_model->add_constraint();
954 constraint_proto->set_name(constraint->
name());
955 constraint_proto->set_lower_bound(constraint->
lb());
956 constraint_proto->set_upper_bound(constraint->
ub());
957 constraint_proto->set_is_lazy(constraint->
is_lazy());
960 std::vector<std::pair<int, double>> linear_term;
961 for (
const auto& entry : constraint->coefficients_) {
965 const double coeff = entry.second;
966 linear_term.push_back(std::pair<int, double>(var_index, coeff));
970 std::sort(linear_term.begin(), linear_term.end());
972 for (
const std::pair<int, double>& var_and_coeff : linear_term) {
973 constraint_proto->add_var_index(var_and_coeff.first);
974 constraint_proto->add_coefficient(var_and_coeff.second);
978 output_model->set_maximize(
Objective().maximization());
979 output_model->set_objective_offset(
Objective().offset());
981 if (!solution_hint_.empty()) {
982 PartialVariableAssignment*
const hint =
983 output_model->mutable_solution_hint();
984 for (
const auto& var_value_pair : solution_hint_) {
985 hint->add_var_index(var_value_pair.first->index());
986 hint->add_var_value(var_value_pair.second);
996 return absl::InvalidArgumentError(absl::StrCat(
997 "Cannot load a solution unless its status is OPTIMAL or FEASIBLE"
999 ProtoEnumToString<MPSolverResponseStatus>(
response.status()),
")"));
1004 if (
response.variable_value_size() != variables_.size()) {
1005 return absl::InvalidArgumentError(absl::StrCat(
1006 "Trying to load a solution whose number of variables (",
1008 ") does not correspond to the Solver's (", variables_.size(),
")"));
1010 interface_->ExtractModel();
1014 double largest_error = 0;
1015 int num_vars_out_of_bounds = 0;
1016 int last_offending_var = -1;
1017 for (
int i = 0; i <
response.variable_value_size(); ++i) {
1018 const double var_value =
response.variable_value(i);
1021 const double lb_error =
var->lb() - var_value;
1022 const double ub_error = var_value -
var->ub();
1023 if (lb_error > tolerance || ub_error > tolerance) {
1024 ++num_vars_out_of_bounds;
1026 last_offending_var = i;
1029 if (num_vars_out_of_bounds > 0) {
1030 return absl::InvalidArgumentError(absl::StrCat(
1031 "Loaded a solution whose variables matched the solver's, but ",
1032 num_vars_out_of_bounds,
" of ", variables_.size(),
1033 " variables were out of their bounds, by more than the primal"
1034 " tolerance which is: ",
1035 tolerance,
". Max error: ", largest_error,
", last offender var is #",
1036 last_offending_var,
": '", variables_[last_offending_var]->name(),
1041 for (
int i = 0; i <
response.variable_value_size(); ++i) {
1042 variables_[i]->set_solution_value(
response.variable_value(i));
1046 if (
response.has_objective_value()) {
1047 interface_->objective_value_ =
response.objective_value();
1049 if (
response.has_best_objective_bound()) {
1050 interface_->best_objective_bound_ =
response.best_objective_bound();
1055 return absl::OkStatus();
1063 if (variable_name_to_index_) {
1064 variable_name_to_index_->clear();
1066 variable_is_extracted_.clear();
1067 constraints_.clear();
1068 if (constraint_name_to_index_) {
1069 constraint_name_to_index_->clear();
1071 constraint_is_extracted_.clear();
1072 interface_->Reset();
1073 solution_hint_.clear();
1081 const std::vector<BasisStatus>& variable_statuses,
1082 const std::vector<BasisStatus>& constraint_statuses) {
1083 interface_->SetStartingLpBasis(variable_statuses, constraint_statuses);
1087 const std::string&
name) {
1090 new MPVariable(var_index, lb, ub, integer,
name, interface_.get());
1091 if (variable_name_to_index_) {
1094 variables_.push_back(v);
1095 variable_is_extracted_.push_back(
false);
1096 interface_->AddVariable(v);
1101 const std::string&
name) {
1106 const std::string&
name) {
1115 const std::string&
name,
1116 std::vector<MPVariable*>* vars) {
1118 if (nb <= 0)
return;
1119 const int num_digits = NumDigits(nb);
1120 for (
int i = 0; i < nb; ++i) {
1125 absl::StrFormat(
"%s%0*d",
name.c_str(), num_digits, i);
1126 vars->push_back(
MakeVar(lb, ub, integer, vname));
1132 const std::string&
name,
1133 std::vector<MPVariable*>* vars) {
1138 const std::string&
name,
1139 std::vector<MPVariable*>* vars) {
1144 std::vector<MPVariable*>* vars) {
1157 const std::string&
name) {
1161 if (constraint_name_to_index_) {
1165 constraints_.push_back(constraint);
1166 constraint_is_extracted_.push_back(
false);
1167 interface_->AddRowConstraint(constraint);
1180 const std::string&
name) {
1190 int MPSolver::ComputeMaxConstraintSize(
int min_constraint_index,
1191 int max_constraint_index)
const {
1192 int max_constraint_size = 0;
1194 DCHECK_LE(max_constraint_index, constraints_.size());
1195 for (
int i = min_constraint_index; i < max_constraint_index; ++i) {
1197 if (
ct->coefficients_.size() > max_constraint_size) {
1198 max_constraint_size =
ct->coefficients_.size();
1201 return max_constraint_size;
1204 bool MPSolver::HasInfeasibleConstraints()
const {
1205 bool hasInfeasibleConstraints =
false;
1206 for (
int i = 0; i < constraints_.size(); ++i) {
1207 if (constraints_[i]->lb() > constraints_[i]->ub()) {
1208 LOG(
WARNING) <<
"Constraint " << constraints_[i]->name() <<
" (" << i
1209 <<
") has contradictory bounds:"
1210 <<
" lower bound = " << constraints_[i]->lb()
1211 <<
" upper bound = " << constraints_[i]->ub();
1212 hasInfeasibleConstraints =
true;
1215 return hasInfeasibleConstraints;
1218 bool MPSolver::HasIntegerVariables()
const {
1219 for (
const MPVariable*
const variable : variables_) {
1220 if (variable->integer())
return true;
1227 return Solve(default_param);
1236 if (HasInfeasibleConstraints()) {
1238 return interface_->result_status_;
1242 if (absl::GetFlag(FLAGS_verify_solution)) {
1244 VLOG(1) <<
"--verify_solution enabled, but the solver did not find a"
1245 <<
" solution: skipping the verification.";
1248 absl::GetFlag(FLAGS_log_verification_errors))) {
1250 interface_->result_status_ = status;
1253 DCHECK_EQ(interface_->result_status_, status);
1258 interface_->Write(file_name);
1263 const std::string prefix =
"Variable '" +
var.
name() +
"': domain = ";
1266 return prefix +
"∅";
1270 if (
var.integer() &&
var.ub() -
var.lb() <= 1) {
1274 return prefix +
"∅";
1275 }
else if (lb == ub) {
1276 return absl::StrFormat(
"%s{ %d }", prefix.c_str(), lb);
1278 return absl::StrFormat(
"%s{ %d, %d }", prefix.c_str(), lb, ub);
1282 if (
var.lb() ==
var.ub()) {
1283 return absl::StrFormat(
"%s{ %f }", prefix.c_str(),
var.lb());
1285 return prefix + (
var.integer() ?
"Integer" :
"Real") +
" in " +
1287 ? std::string(
"]-∞")
1288 :
absl::StrFormat(
"[%f",
var.lb())) +
1290 (
var.ub() >= MPSolver::infinity() ? std::string(
"+∞[")
1291 :
absl::StrFormat(
"%f]",
var.ub()));
1294 std::string PrettyPrintConstraint(
const MPConstraint& constraint) {
1295 std::string prefix =
"Constraint '" + constraint.name() +
"': ";
1298 constraint.lb() > constraint.ub()) {
1299 return prefix +
"ALWAYS FALSE";
1303 return prefix +
"ALWAYS TRUE";
1305 prefix +=
"<linear expr>";
1307 if (constraint.lb() == constraint.ub()) {
1308 return absl::StrFormat(
"%s = %f", prefix.c_str(), constraint.lb());
1312 return absl::StrFormat(
"%s ≤ %f", prefix.c_str(), constraint.ub());
1315 return absl::StrFormat(
"%s ≥ %f", prefix.c_str(), constraint.lb());
1317 return absl::StrFormat(
"%s ∈ [%f, %f]", prefix.c_str(), constraint.lb(),
1323 interface_->ExtractModel();
1324 for (
MPVariable*
const variable : variables_) {
1325 const double value = variable->solution_value();
1326 if (std::isnan(
value)) {
1327 return absl::InvalidArgumentError(
1328 absl::StrCat(
"NaN value for ", PrettyPrintVar(*variable)));
1330 if (value < variable->lb()) {
1331 variable->set_solution_value(variable->lb());
1332 }
else if (
value > variable->ub()) {
1333 variable->set_solution_value(variable->ub());
1337 return absl::OkStatus();
1342 if (!interface_->CheckSolutionIsSynchronizedAndExists())
return {};
1343 std::vector<double> activities(constraints_.size(), 0.0);
1344 for (
int i = 0; i < constraints_.size(); ++i) {
1347 for (
const auto& entry : constraint.coefficients_) {
1348 sum.
Add(entry.first->solution_value() * entry.second);
1350 activities[i] = sum.
Value();
1357 double max_observed_error = 0;
1358 if (tolerance < 0) tolerance =
infinity();
1362 for (
int i = 0; i < variables_.size(); ++i) {
1364 const double value =
var.solution_value();
1366 if (std::isnan(
value)) {
1369 LOG_IF(
ERROR, log_errors) <<
"NaN value for " << PrettyPrintVar(
var);
1374 if (
value <
var.lb() - tolerance) {
1378 <<
"Value " <<
value <<
" too low for " << PrettyPrintVar(
var);
1383 if (
value >
var.ub() + tolerance) {
1387 <<
"Value " <<
value <<
" too high for " << PrettyPrintVar(
var);
1392 if (fabs(
value - round(
value)) > tolerance) {
1394 max_observed_error =
1397 <<
"Non-integer value " <<
value <<
" for " << PrettyPrintVar(
var);
1401 if (!
IsMIP() && HasIntegerVariables()) {
1402 LOG_IF(
INFO, log_errors) <<
"Skipped variable integrality check, because "
1403 <<
"a continuous relaxation of the model was "
1404 <<
"solved (i.e., the selected solver does not "
1405 <<
"support integer variables).";
1410 for (
int i = 0; i < constraints_.size(); ++i) {
1412 const double activity = activities[i];
1414 double inaccurate_activity = 0.0;
1415 for (
const auto& entry : constraint.coefficients_) {
1416 inaccurate_activity += entry.first->solution_value() * entry.second;
1419 if (std::isnan(activity) || std::isnan(inaccurate_activity)) {
1423 <<
"NaN value for " << PrettyPrintConstraint(constraint);
1431 if (activity < constraint.
lb() - tolerance) {
1433 max_observed_error =
1434 std::max(max_observed_error, constraint.
lb() - activity);
1436 <<
"Activity " << activity <<
" too low for "
1437 << PrettyPrintConstraint(constraint);
1438 }
else if (inaccurate_activity < constraint.
lb() - tolerance) {
1440 <<
"Activity " << activity <<
", computed with the (inaccurate)"
1441 <<
" standard sum of its terms, is too low for "
1442 << PrettyPrintConstraint(constraint);
1446 if (activity > constraint.
ub() + tolerance) {
1448 max_observed_error =
1449 std::max(max_observed_error, activity - constraint.
ub());
1451 <<
"Activity " << activity <<
" too high for "
1452 << PrettyPrintConstraint(constraint);
1453 }
else if (inaccurate_activity > constraint.
ub() + tolerance) {
1455 <<
"Activity " << activity <<
", computed with the (inaccurate)"
1456 <<
" standard sum of its terms, is too high for "
1457 << PrettyPrintConstraint(constraint);
1467 double inaccurate_objective_value = objective.
offset();
1468 for (
const auto& entry : objective.coefficients_) {
1469 const double term = entry.first->solution_value() * entry.second;
1470 objective_sum.
Add(term);
1471 inaccurate_objective_value += term;
1473 const double actual_objective_value = objective_sum.
Value();
1475 objective.
Value(), actual_objective_value, tolerance, tolerance)) {
1478 max_observed_error, fabs(actual_objective_value - objective.
Value()));
1480 <<
"Objective value " << objective.
Value() <<
" isn't accurate"
1481 <<
", it should be " << actual_objective_value
1482 <<
" (delta=" << actual_objective_value - objective.
Value() <<
").";
1484 inaccurate_objective_value,
1485 tolerance, tolerance)) {
1487 <<
"Objective value " << objective.
Value() <<
" doesn't correspond"
1488 <<
" to the value computed with the standard (and therefore inaccurate)"
1489 <<
" sum of its terms.";
1491 if (num_errors > 0) {
1493 <<
"There were " << num_errors <<
" errors above the tolerance ("
1494 << tolerance <<
"), the largest was " << max_observed_error;
1511 return interface_->ComputeExactConditionNumber();
1515 if (
var ==
nullptr)
return false;
1516 if (
var->index() >= 0 &&
var->index() < variables_.size()) {
1518 return variables_[
var->index()] ==
var;
1524 std::string* model_str)
const {
1529 const auto status_or =
1531 *model_str = status_or.value_or(
"");
1532 return status_or.ok();
1536 std::string* model_str)
const {
1546 const auto status_or =
1548 *model_str = status_or.value_or(
"");
1549 return status_or.ok();
1553 for (
const auto& var_value_pair : hint) {
1555 <<
"hint variable does not belong to this solver";
1557 solution_hint_ = std::move(hint);
1560 void MPSolver::GenerateVariableNameIndex()
const {
1561 if (variable_name_to_index_)
return;
1562 variable_name_to_index_ = absl::flat_hash_map<std::string, int>();
1568 void MPSolver::GenerateConstraintNameIndex()
const {
1569 if (constraint_name_to_index_)
return;
1570 constraint_name_to_index_ = absl::flat_hash_map<std::string, int>();
1571 for (
const MPConstraint*
const cst : constraints_) {
1579 interface_->SetCallback(mp_callback);
1583 return interface_->SupportsCallbacks();
1609 <<
"MPSolverResponseStatusIsRpcError() called with invalid status "
1610 <<
"(value: " << status <<
")";
1622 sync_status_(MODEL_SYNCHRONIZED),
1623 result_status_(
MPSolver::NOT_SOLVED),
1625 last_constraint_index_(0),
1626 last_variable_index_(0),
1627 objective_value_(0.0),
1628 best_objective_bound_(0.0),
1634 LOG(
WARNING) <<
"Writing model not implemented in this solver interface.";
1669 solver_->variable_is_extracted_.assign(
solver_->variables_.size(),
false);
1670 solver_->constraint_is_extracted_.assign(
solver_->constraints_.size(),
false);
1676 <<
"The model has been changed since the solution was last computed."
1677 <<
" MPSolverInterface::sync_status_ = " <<
sync_status_;
1688 LOG(DFATAL) <<
"No solution exists. MPSolverInterface::result_status_ = "
1701 const double trivial_worst_bound =
1702 maximize_ ? -std::numeric_limits<double>::infinity()
1703 : std::numeric_limits<double>::infinity();
1705 LOG(DFATAL) <<
"Best objective bound only available for discrete problems.";
1706 return trivial_worst_bound;
1709 return trivial_worst_bound;
1712 if (
solver_->variables_.empty() &&
solver_->constraints_.empty()) {
1726 LOG(DFATAL) <<
"ComputeExactConditionNumber not implemented for "
1727 << ProtoEnumToString<MPModelRequest::SolverType>(
1728 static_cast<MPModelRequest::SolverType
>(
1763 LOG(
WARNING) <<
"Trying to set an unsupported parameter: " << param <<
".";
1767 LOG(
WARNING) <<
"Trying to set an unsupported parameter: " << param <<
".";
1771 LOG(
WARNING) <<
"Trying to set a supported parameter: " << param
1772 <<
" to an unsupported value: " <<
value;
1776 LOG(
WARNING) <<
"Trying to set a supported parameter: " << param
1777 <<
" to an unsupported value: " <<
value;
1781 return absl::UnimplementedError(
1782 absl::StrFormat(
"SetNumThreads() not supported by %s.",
SolverVersion()));
1791 LOG(
WARNING) <<
"SetSolverSpecificParametersAsString() not supported by "
1816 : relative_mip_gap_value_(kDefaultRelativeMipGap),
1818 dual_tolerance_value_(kDefaultDualTolerance),
1819 presolve_value_(kDefaultPresolve),
1820 scaling_value_(kDefaultIntegerParamValue),
1821 lp_algorithm_value_(kDefaultIntegerParamValue),
1822 incrementality_value_(kDefaultIncrementality),
1823 lp_algorithm_is_default_(true) {}
1829 relative_mip_gap_value_ =
value;
1833 primal_tolerance_value_ =
value;
1837 dual_tolerance_value_ =
value;
1841 LOG(
ERROR) <<
"Trying to set an unknown parameter: " << param <<
".";
1851 LOG(
ERROR) <<
"Trying to set a supported parameter: " << param
1852 <<
" to an unknown value: " <<
value;
1854 presolve_value_ =
value;
1859 LOG(
ERROR) <<
"Trying to set a supported parameter: " << param
1860 <<
" to an unknown value: " <<
value;
1862 scaling_value_ =
value;
1867 LOG(
ERROR) <<
"Trying to set a supported parameter: " << param
1868 <<
" to an unknown value: " <<
value;
1870 lp_algorithm_value_ =
value;
1871 lp_algorithm_is_default_ =
false;
1876 LOG(
ERROR) <<
"Trying to set a supported parameter: " << param
1877 <<
" to an unknown value: " <<
value;
1879 incrementality_value_ =
value;
1883 LOG(
ERROR) <<
"Trying to set an unknown parameter: " << param <<
".";
1904 LOG(
ERROR) <<
"Trying to reset an unknown parameter: " << param <<
".";
1921 lp_algorithm_is_default_ =
true;
1929 LOG(
ERROR) <<
"Trying to reset an unknown parameter: " << param <<
".";
1948 return relative_mip_gap_value_;
1951 return primal_tolerance_value_;
1954 return dual_tolerance_value_;
1957 LOG(
ERROR) <<
"Trying to get an unknown parameter: " << param <<
".";
1967 return presolve_value_;
1971 return lp_algorithm_value_;
1974 return incrementality_value_;
1977 return scaling_value_;
1980 LOG(
ERROR) <<
"Trying to get an unknown parameter: " << param <<
".";
#define DLOG_IF(severity, condition)
#define LOG_IF(severity, condition)
#define DCHECK_LE(val1, val2)
#define DCHECK_NE(val1, val2)
#define DCHECK_GE(val1, val2)
#define DCHECK(condition)
#define DCHECK_EQ(val1, val2)
#define VLOG(verboselevel)
void Add(const FpNumber &value)
LinearExpr models a quantity that is linear in the decision variables (MPVariable) of an optimization...
const absl::flat_hash_map< const MPVariable *, double > & terms() const
An expression of the form:
double upper_bound() const
double lower_bound() const
const LinearExpr & linear_expr() const
The class for constraints of a Mathematical Programming (MP) model.
void SetBounds(double lb, double ub)
Sets both the lower and upper bounds.
void SetCoefficient(const MPVariable *const var, double coeff)
Sets the coefficient of the variable on the constraint.
double GetCoefficient(const MPVariable *const var) const
Gets the coefficient of a given variable on the constraint (which is 0 if the variable does not appea...
double ub() const
Returns the upper bound.
const MPVariable * indicator_variable() const
bool indicator_value() const
void Clear()
Clears all variables and coefficients. Does not clear the bounds.
bool is_lazy() const
Advanced usage: returns true if the constraint is "lazy" (see below).
double lb() const
Returns the lower bound.
const std::string & name() const
Returns the name of the constraint.
MPSolver::BasisStatus basis_status() const
Advanced usage: returns the basis status of the constraint.
double dual_value() const
Advanced usage: returns the dual value of the constraint in the current solution (only available for ...
A class to express a linear objective.
void SetCoefficient(const MPVariable *const var, double coeff)
Sets the coefficient of the variable in the objective.
double GetCoefficient(const MPVariable *const var) const
Gets the coefficient of a given variable in the objective.
void SetOffset(double value)
Sets the constant term in the objective.
bool maximization() const
Is the optimization direction set to maximize?
void OptimizeLinearExpr(const LinearExpr &linear_expr, bool is_maximization)
Resets the current objective to take the value of linear_expr, and sets the objective direction to ma...
void AddLinearExpr(const LinearExpr &linear_expr)
Adds linear_expr to the current objective, does not change the direction.
double Value() const
Returns the objective value of the best solution found so far.
double offset() const
Gets the constant term in the objective.
double BestBound() const
Returns the best objective bound.
bool minimization() const
Is the optimization direction set to minimize?
void Clear()
Clears the offset, all variables and coefficients, and the optimization direction.
void SetMinimization()
Sets the optimization direction to minimize.
void SetOptimizationDirection(bool maximize)
Sets the optimization direction (maximize: true or minimize: false).
This mathematical programming (MP) solver class is the main class though which users build and solve ...
void FillSolutionResponseProto(MPSolutionResponse *response) const
Encodes the current solution in a solution response protocol buffer.
int NumConstraints() const
Returns the number of constraints.
static OptimizationProblemType ParseSolverTypeOrDie(const std::string &solver_id)
Parses the name of the solver and returns the correct optimization type or dies.
const std::string & Name() const
Returns the name of the model set at construction.
void MakeBoolVarArray(int nb, const std::string &name, std::vector< MPVariable * > *vars)
Creates an array of boolean variables.
MPObjective * MutableObjective()
Returns the mutable objective object.
bool VerifySolution(double tolerance, bool log_errors) const
Advanced usage: Verifies the correctness of the solution.
void Reset()
Advanced usage: resets extracted model to solve from scratch.
MPVariable * LookupVariableOrNull(const std::string &var_name) const
Looks up a variable by name, and returns nullptr if it does not exist.
void SetStartingLpBasis(const std::vector< MPSolver::BasisStatus > &variable_statuses, const std::vector< MPSolver::BasisStatus > &constraint_statuses)
Advanced usage: Incrementality.
static bool SupportsProblemType(OptimizationProblemType problem_type)
Whether the given problem type is supported (this will depend on the targets that you linked).
static MPSolver * CreateSolver(const std::string &solver_id)
Recommended factory method to create a MPSolver instance, especially in non C++ languages.
MPVariable * MakeBoolVar(const std::string &name)
Creates a boolean variable.
void SetHint(std::vector< std::pair< const MPVariable *, double > > hint)
Sets a hint for solution.
double ComputeExactConditionNumber() const
Advanced usage: computes the exact condition number of the current scaled basis: L1norm(B) * L1norm(i...
const MPObjective & Objective() const
Returns the objective object.
int64 nodes() const
Returns the number of branch-and-bound nodes evaluated during the solve.
ResultStatus
The status of solving the problem.
@ FEASIBLE
feasible, or stopped by limit.
@ NOT_SOLVED
not been solved yet.
@ INFEASIBLE
proven infeasible.
@ UNBOUNDED
proven unbounded.
@ ABNORMAL
abnormal, i.e., error of some kind.
@ MODEL_INVALID
the model is trivially invalid (NaN coefficients, etc).
static void SolveWithProto(const MPModelRequest &model_request, MPSolutionResponse *response)
Solves the model encoded by a MPModelRequest protocol buffer and fills the solution encoded as a MPSo...
void MakeNumVarArray(int nb, double lb, double ub, const std::string &name, std::vector< MPVariable * > *vars)
Creates an array of continuous variables.
void MakeVarArray(int nb, double lb, double ub, bool integer, const std::string &name_prefix, std::vector< MPVariable * > *vars)
Creates an array of variables.
void * underlying_solver()
Advanced usage: returns the underlying solver.
OptimizationProblemType
The type of problems (LP or MIP) that will be solved and the underlying solver (GLOP,...
@ GLOP_LINEAR_PROGRAMMING
@ CPLEX_MIXED_INTEGER_PROGRAMMING
@ KNAPSACK_MIXED_INTEGER_PROGRAMMING
@ XPRESS_LINEAR_PROGRAMMING
@ GLPK_LINEAR_PROGRAMMING
@ CPLEX_LINEAR_PROGRAMMING
@ GUROBI_LINEAR_PROGRAMMING
@ XPRESS_MIXED_INTEGER_PROGRAMMING
@ GUROBI_MIXED_INTEGER_PROGRAMMING
@ BOP_INTEGER_PROGRAMMING
@ SCIP_MIXED_INTEGER_PROGRAMMING
@ SAT_INTEGER_PROGRAMMING
@ GLPK_MIXED_INTEGER_PROGRAMMING
@ CBC_MIXED_INTEGER_PROGRAMMING
bool SetSolverSpecificParametersAsString(const std::string ¶meters)
Advanced usage: pass solver specific parameters in text format.
absl::Status SetNumThreads(int num_threads)
Sets the number of threads to use by the underlying solver.
std::string SolverVersion() const
Returns a string describing the underlying solver and its version.
bool SupportsCallbacks() const
void ExportModelToProto(MPModelProto *output_model) const
Exports model to protocol buffer.
int64 iterations() const
Returns the number of simplex iterations.
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
void Clear()
Clears the objective (including the optimization direction), all variables and constraints.
bool ExportModelAsLpFormat(bool obfuscate, std::string *model_str) const
Shortcuts to the homonymous MPModelProtoExporter methods, via exporting to a MPModelProto with Export...
void Write(const std::string &file_name)
Writes the model using the solver internal write function.
MPConstraint * MakeRowConstraint()
Creates a constraint with -infinity and +infinity bounds.
void SetCallback(MPCallback *mp_callback)
MPSolverResponseStatus LoadModelFromProto(const MPModelProto &input_model, std::string *error_message)
Loads model from protocol buffer.
bool OutputIsEnabled() const
Controls (or queries) the amount of output produced by the underlying solver.
bool ExportModelAsMpsFormat(bool fixed_format, bool obfuscate, std::string *model_str) const
ABSL_MUST_USE_RESULT bool NextSolution()
Some solvers (MIP only, not LP) can produce multiple solutions to the problem.
MPVariable * MakeVar(double lb, double ub, bool integer, const std::string &name)
Creates a variable with the given bounds, integrality requirement and name.
MPConstraint * LookupConstraintOrNull(const std::string &constraint_name) const
Looks up a constraint by name, and returns nullptr if it does not exist.
MPVariable * MakeNumVar(double lb, double ub, const std::string &name)
Creates a continuous variable.
bool InterruptSolve()
Interrupts the Solve() execution to terminate processing if possible.
MPVariable * MakeIntVar(double lb, double ub, const std::string &name)
Creates an integer variable.
MPSolver(const std::string &name, OptimizationProblemType problem_type)
Create a solver with the given name and underlying solver backend.
ResultStatus Solve()
Solves the problem using the default parameter values.
void EnableOutput()
Enables solver logging.
void SuppressOutput()
Suppresses solver logging.
absl::Status LoadSolutionFromProto(const MPSolutionResponse &response, double tolerance=kDefaultPrimalTolerance)
Load a solution encoded in a protocol buffer onto this solver for easy access via the MPSolver interf...
MPSolverResponseStatus LoadModelFromProtoWithUniqueNamesOrDie(const MPModelProto &input_model, std::string *error_message)
Loads model from protocol buffer.
virtual OptimizationProblemType ProblemType() const
Returns the optimization problem type set at construction.
BasisStatus
Advanced usage: possible basis status values for a variable and the slack variable of a linear constr...
void SetTimeLimit(absl::Duration time_limit)
virtual ~MPSolverInterface()
double best_objective_bound() const
virtual void SetLpAlgorithm(int value)=0
virtual void SetIntegerParamToUnsupportedValue(MPSolverParameters::IntegerParam param, int value)
virtual void ExtractObjective()=0
void SetUnsupportedDoubleParam(MPSolverParameters::DoubleParam param)
virtual void ExtractNewVariables()=0
MPSolver::ResultStatus result_status_
static const int kDummyVariableIndex
void InvalidateSolutionSynchronization()
void SetMIPParameters(const MPSolverParameters ¶m)
int last_constraint_index_
virtual bool IsContinuous() const =0
virtual double ComputeExactConditionNumber() const
virtual void Write(const std::string &filename)
MPSolverInterface(MPSolver *const solver)
bool constraint_is_extracted(int ct_index) const
virtual void SetVariableBounds(int index, double lb, double ub)=0
virtual void SetPrimalTolerance(double value)=0
virtual void BranchingPriorityChangedForVariable(int var_index)
virtual void SetRelativeMipGap(double value)=0
double best_objective_bound_
virtual void SetOptimizationDirection(bool maximize)=0
virtual bool SetSolverSpecificParametersAsString(const std::string ¶meters)
virtual MPSolver::BasisStatus column_status(int variable_index) const =0
virtual void ExtractNewConstraints()=0
virtual MPSolver::BasisStatus row_status(int constraint_index) const =0
virtual std::string SolverVersion() const =0
virtual absl::Status SetNumThreads(int num_threads)
double objective_value() const
int last_variable_index() const
virtual void ClearConstraint(MPConstraint *const constraint)=0
bool CheckSolutionIsSynchronizedAndExists() const
bool CheckSolutionIsSynchronized() const
virtual bool CheckSolutionExists() const
virtual void SetObjectiveOffset(double value)=0
virtual void SetVariableInteger(int index, bool integer)=0
void ResetExtractionInformation()
virtual void ClearObjective()=0
bool variable_is_extracted(int var_index) const
virtual bool IsMIP() const =0
virtual void SetDualTolerance(double value)=0
virtual void SetPresolveMode(int value)=0
virtual void SetUnsupportedIntegerParam(MPSolverParameters::IntegerParam param)
virtual void SetCoefficient(MPConstraint *const constraint, const MPVariable *const variable, double new_value, double old_value)=0
virtual void SetObjectiveCoefficient(const MPVariable *const variable, double coefficient)=0
void SetDoubleParamToUnsupportedValue(MPSolverParameters::DoubleParam param, double value)
virtual void SetConstraintBounds(int index, double lb, double ub)=0
void SetCommonParameters(const MPSolverParameters ¶m)
SynchronizationStatus sync_status_
This class stores parameter settings for LP and MIP solvers.
static const double kDefaultRelativeMipGap
static const int kUnknownIntegerParamValue
void ResetIntegerParam(MPSolverParameters::IntegerParam param)
Sets an integer parameter to its default value (default value defined in MPSolverParameters if it exi...
void SetDoubleParam(MPSolverParameters::DoubleParam param, double value)
Sets a double parameter to a specific value.
IncrementalityValues
Advanced usage: Incrementality options.
@ INCREMENTALITY_OFF
Start solve from scratch.
@ INCREMENTALITY_ON
Reuse results from previous solve as much as the underlying solver allows.
@ SCALING_ON
Scaling is on.
@ SCALING_OFF
Scaling is off.
static const IncrementalityValues kDefaultIncrementality
void Reset()
Sets all parameters to their default value.
DoubleParam
Enumeration of parameters that take continuous values.
@ DUAL_TOLERANCE
Advanced usage: tolerance for dual feasibility of basic solutions.
@ PRIMAL_TOLERANCE
Advanced usage: tolerance for primal feasibility of basic solutions.
@ RELATIVE_MIP_GAP
Limit for relative MIP gap.
static const PresolveValues kDefaultPresolve
double GetDoubleParam(MPSolverParameters::DoubleParam param) const
Returns the value of a double parameter.
static const double kDefaultDualTolerance
static const double kUnknownDoubleParamValue
IntegerParam
Enumeration of parameters that take integer or categorical values.
@ LP_ALGORITHM
Algorithm to solve linear programs.
@ SCALING
Advanced usage: enable or disable matrix scaling.
@ PRESOLVE
Advanced usage: presolve mode.
@ INCREMENTALITY
Advanced usage: incrementality from one solve to the next.
@ BARRIER
Barrier algorithm.
PresolveValues
For each categorical parameter, enumeration of possible values.
@ PRESOLVE_ON
Presolve is on.
@ PRESOLVE_OFF
Presolve is off.
static const int kDefaultIntegerParamValue
static const double kDefaultPrimalTolerance
void SetIntegerParam(MPSolverParameters::IntegerParam param, int value)
Sets a integer parameter to a specific value.
static const double kDefaultDoubleParamValue
int GetIntegerParam(MPSolverParameters::IntegerParam param) const
Returns the value of an integer parameter.
MPSolverParameters()
The constructor sets all parameters to their default value.
void ResetDoubleParam(MPSolverParameters::DoubleParam param)
Sets a double parameter to its default value (default value defined in MPSolverParameters if it exist...
The class for variables of a Mathematical Programming (MP) model.
void SetBounds(double lb, double ub)
Sets both the lower and upper bounds.
double unrounded_solution_value() const
Advanced usage: unrounded solution value.
void SetBranchingPriority(int priority)
double ub() const
Returns the upper bound.
double reduced_cost() const
Advanced usage: returns the reduced cost of the variable in the current solution (only available for ...
void SetInteger(bool integer)
Sets the integrality requirement of the variable.
bool integer() const
Returns the integrality requirement of the variable.
int index() const
Returns the index of the variable in the MPSolver::variables_.
double lb() const
Returns the lower bound.
const std::string & name() const
Returns the name of the variable.
double solution_value() const
Returns the value of the variable in the current solution.
MPSolver::BasisStatus basis_status() const
Advanced usage: returns the basis status of the variable in the current solution (only available for ...
virtual std::string name() const
Object naming.
SharedResponseManager * response
ABSL_FLAG(bool, verify_solution, false, "Systematically verify the solution when calling Solve()" ", and change the return value of Solve() to ABNORMAL if" " an error was detected.")
MPSolver::OptimizationProblemType problem_type
A C++ wrapper that provides a simple and unified interface to several linear programming and mixed in...
void STLDeleteElements(T *container)
void InsertOrDie(Collection *const collection, const typename Collection::value_type &value)
const Collection::value_type::second_type & FindWithDefault(const Collection &collection, const typename Collection::value_type::first_type &key, const typename Collection::value_type::second_type &value)
std::function< int64(const Model &)> Value(IntegerVariable v)
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...
MPSolverInterface * BuildGurobiInterface(bool mip, MPSolver *const solver)
MPSolverInterface * BuildSCIPInterface(MPSolver *const solver)
MPSolverInterface * BuildBopInterface(MPSolver *const solver)
constexpr double kDefaultPrimalTolerance
const absl::string_view ToString(MPSolver::OptimizationProblemType optimization_problem_type)
bool SolverTypeIsMip(MPModelRequest::SolverType solver_type)
MPSolverInterface * BuildCBCInterface(MPSolver *const solver)
bool AreWithinAbsoluteOrRelativeTolerances(FloatType x, FloatType y, FloatType relative_tolerance, FloatType absolute_tolerance)
absl::StatusOr< std::string > ExportModelAsMpsFormat(const MPModelProto &model, const MPModelExportOptions &options)
Outputs the current model (variables, constraints, objective) as a string encoded in MPS file format,...
bool AbslParseFlag(const absl::string_view text, MPSolver::OptimizationProblemType *solver_type, std::string *error)
absl::optional< LazyMutableCopy< MPModelProto > > ExtractValidMPModelOrPopulateResponseStatus(const MPModelRequest &request, MPSolutionResponse *response)
If the model is valid and non-empty, returns it (possibly after extracting the model_delta).
MPSolverInterface * BuildSatInterface(MPSolver *const solver)
MPSolverInterface * BuildCLPInterface(MPSolver *const solver)
constexpr NamedOptimizationProblemType kOptimizationProblemTypeNames[]
MPSolverInterface * BuildGLOPInterface(MPSolver *const solver)
std::string FindErrorInMPModelProto(const MPModelProto &model, double abs_value_threshold)
Returns an empty string iff the model is valid and not trivially infeasible.
absl::StatusOr< std::string > ExportModelAsLpFormat(const MPModelProto &model, const MPModelExportOptions &options)
Outputs the current model (variables, constraints, objective) as a string encoded in the so-called "C...
@ MPSOLVER_UNKNOWN_STATUS
@ MPSOLVER_MODEL_IS_VALID
@ MPSOLVER_SOLVER_TYPE_UNAVAILABLE
@ MPSOLVER_MODEL_INVALID_SOLUTION_HINT
@ MPSOLVER_MODEL_INVALID_SOLVER_PARAMETERS
bool MPSolverResponseStatusIsRpcError(MPSolverResponseStatus status)
bool obfuscate
Obfuscates variable and constraint names.