57 #include "absl/base/attributes.h"
58 #include "absl/container/flat_hash_set.h"
59 #include "absl/status/status.h"
60 #include "absl/strings/match.h"
61 #include "absl/strings/str_format.h"
74 "Number of threads available for Gurobi.");
91 const MPModelRequest& request, std::atomic<bool>* interrupt)
override;
93 void Write(
const std::string& filename)
override;
97 void Reset()
override;
111 const MPVariable*
const variable,
double new_value,
112 double old_value)
override;
128 int64_t
nodes()
const override;
138 bool IsLP()
const override {
return !mip_; }
139 bool IsMIP()
const override {
return mip_; }
146 int major, minor, technical;
148 return absl::StrFormat(
"Gurobi library version %d.%d.%d\n", major, minor,
153 const absl::MutexLock lock(&hold_interruptions_mutex_);
162 LOG(DFATAL) <<
"ComputeExactConditionNumber not implemented for"
163 <<
" GUROBI_MIXED_INTEGER_PROGRAMMING";
168 LOG(DFATAL) <<
"ComputeExactConditionNumber not implemented for"
169 <<
" GUROBI_LINEAR_PROGRAMMING";
203 bool SetSolverSpecificParametersAsString(
206 void SetRelativeMipGap(
double value)
override;
207 void SetPrimalTolerance(
double value)
override;
208 void SetDualTolerance(
double value)
override;
209 void SetPresolveMode(
int value)
override;
210 void SetScalingMode(
int value)
override;
211 void SetLpAlgorithm(
int value)
override;
214 int gurobi_basis_status)
const;
216 int gurobi_basis_status,
int constraint_index)
const;
219 bool ModelIsNonincremental()
const;
221 void SetIntAttr(
const char*
name,
int value);
222 int GetIntAttr(
const char*
name)
const;
223 void SetDoubleAttr(
const char*
name,
double value);
224 double GetDoubleAttr(
const char*
name)
const;
226 int GetIntAttrElement(
const char*
name,
int index)
const;
227 void SetDoubleAttrElement(
const char*
name,
int index,
double value);
228 double GetDoubleAttrElement(
const char*
name,
int index)
const;
229 std::vector<double> GetDoubleAttrArray(
const char*
name,
int elements);
231 char GetCharAttrElement(
const char*
name,
int index)
const;
233 void CheckedGurobiCall(
int err)
const;
235 int SolutionCount()
const;
240 int current_solution_index_;
242 bool update_branching_priorities_ =
false;
248 std::vector<int> mp_var_to_gurobi_var_;
253 std::vector<int> mp_cons_to_gurobi_linear_cons_;
255 int num_gurobi_vars_ = 0;
258 int num_gurobi_linear_cons_ = 0;
260 bool had_nonincremental_change_ =
false;
265 mutable absl::Mutex hold_interruptions_mutex_;
270 constexpr
int kGurobiOkCode = 0;
271 void CheckedGurobiCall(
int err,
GRBenv*
const env) {
272 CHECK_EQ(kGurobiOkCode, err)
273 <<
"Fatal error with code " << err <<
", due to " <<
GRBgeterrormsg(env);
277 struct GurobiInternalCallbackContext {
283 class GurobiMPCallbackContext :
public MPCallbackContext {
285 GurobiMPCallbackContext(
GRBenv* env,
286 const std::vector<int>* mp_var_to_gurobi_var,
287 int num_gurobi_vars,
bool might_add_cuts,
288 bool might_add_lazy_constraints);
292 bool CanQueryVariableValues()
override;
293 double VariableValue(
const MPVariable* variable)
override;
294 void AddCut(
const LinearRange& cutting_plane)
override;
295 void AddLazyConstraint(
const LinearRange& lazy_constraint)
override;
296 double SuggestSolution(
297 const absl::flat_hash_map<const MPVariable*, double>& solution)
override;
298 int64_t NumExploredNodes()
override;
302 void UpdateFromGurobiState(
303 const GurobiInternalCallbackContext& gurobi_internal_context);
309 template <
typename T>
311 const GurobiInternalCallbackContext& gurobi_internal_context,
313 void CheckedGurobiCall(
int gurobi_error_code)
const;
315 template <
typename GRBConstra
intFunction>
316 void AddGeneratedConstraint(
const LinearRange& linear_range,
317 GRBConstraintFunction grb_constraint_function);
320 const std::vector<int>*
const mp_var_to_gurobi_var_;
321 const int num_gurobi_vars_;
323 const bool might_add_cuts_;
324 const bool might_add_lazy_constraints_;
327 GurobiInternalCallbackContext current_gurobi_internal_callback_context_;
328 bool variable_values_extracted_ =
false;
329 std::vector<double> gurobi_variable_values_;
332 void GurobiMPCallbackContext::CheckedGurobiCall(
int gurobi_error_code)
const {
333 ::operations_research::CheckedGurobiCall(gurobi_error_code, env_);
336 GurobiMPCallbackContext::GurobiMPCallbackContext(
337 GRBenv* env,
const std::vector<int>* mp_var_to_gurobi_var,
338 int num_gurobi_vars,
bool might_add_cuts,
bool might_add_lazy_constraints)
339 : env_(ABSL_DIE_IF_NULL(env)),
340 mp_var_to_gurobi_var_(ABSL_DIE_IF_NULL(mp_var_to_gurobi_var)),
341 num_gurobi_vars_(num_gurobi_vars),
342 might_add_cuts_(might_add_cuts),
343 might_add_lazy_constraints_(might_add_lazy_constraints) {}
345 void GurobiMPCallbackContext::UpdateFromGurobiState(
346 const GurobiInternalCallbackContext& gurobi_internal_context) {
347 current_gurobi_internal_callback_context_ = gurobi_internal_context;
348 variable_values_extracted_ =
false;
351 int64_t GurobiMPCallbackContext::NumExploredNodes() {
353 case MPCallbackEvent::kMipNode:
354 return static_cast<int64_t
>(GurobiCallbackGet<double>(
356 case MPCallbackEvent::kMipSolution:
357 return static_cast<int64_t
>(GurobiCallbackGet<double>(
360 LOG(FATAL) <<
"Node count is supported only for callback events MIP_NODE "
361 "and MIP_SOL, but was requested at: "
366 template <
typename T>
367 T GurobiMPCallbackContext::GurobiCallbackGet(
368 const GurobiInternalCallbackContext& gurobi_internal_context,
369 const int callback_code) {
372 GRBcbget(gurobi_internal_context.gurobi_internal_callback_data,
373 gurobi_internal_context.where, callback_code,
374 static_cast<void*
>(&result)));
379 switch (current_gurobi_internal_callback_context_.where) {
381 return MPCallbackEvent::kPolling;
383 return MPCallbackEvent::kPresolve;
385 return MPCallbackEvent::kSimplex;
387 return MPCallbackEvent::kMip;
389 return MPCallbackEvent::kMipSolution;
391 return MPCallbackEvent::kMipNode;
393 return MPCallbackEvent::kMessage;
395 return MPCallbackEvent::kBarrier;
400 LOG_FIRST_N(ERROR, 1) <<
"Gurobi callback at unknown where="
401 << current_gurobi_internal_callback_context_.where;
402 return MPCallbackEvent::kUnknown;
406 bool GurobiMPCallbackContext::CanQueryVariableValues() {
408 if (
where == MPCallbackEvent::kMipSolution) {
411 if (
where == MPCallbackEvent::kMipNode) {
412 const int gurobi_node_status = GurobiCallbackGet<int>(
419 double GurobiMPCallbackContext::VariableValue(
const MPVariable* variable) {
420 CHECK(variable !=
nullptr);
421 if (!variable_values_extracted_) {
423 CHECK(
where == MPCallbackEvent::kMipSolution ||
424 where == MPCallbackEvent::kMipNode)
425 <<
"You can only call VariableValue at "
426 <<
ToString(MPCallbackEvent::kMipSolution) <<
" or "
427 <<
ToString(MPCallbackEvent::kMipNode)
429 const int gurobi_get_var_param =
where == MPCallbackEvent::kMipNode
433 gurobi_variable_values_.resize(num_gurobi_vars_);
435 current_gurobi_internal_callback_context_.gurobi_internal_callback_data,
436 current_gurobi_internal_callback_context_.where, gurobi_get_var_param,
437 static_cast<void*
>(gurobi_variable_values_.data())));
438 variable_values_extracted_ =
true;
440 return gurobi_variable_values_[mp_var_to_gurobi_var_->at(variable->index())];
443 template <
typename GRBConstra
intFunction>
444 void GurobiMPCallbackContext::AddGeneratedConstraint(
445 const LinearRange& linear_range,
446 GRBConstraintFunction grb_constraint_function) {
447 std::vector<int> variable_indices;
448 std::vector<double> variable_coefficients;
449 const int num_terms = linear_range.linear_expr().terms().size();
450 variable_indices.reserve(num_terms);
451 variable_coefficients.reserve(num_terms);
452 for (
const auto& var_coef_pair : linear_range.linear_expr().terms()) {
453 variable_indices.push_back(
454 mp_var_to_gurobi_var_->at(var_coef_pair.first->index()));
455 variable_coefficients.push_back(var_coef_pair.second);
457 if (std::isfinite(linear_range.upper_bound())) {
458 CheckedGurobiCall(grb_constraint_function(
459 current_gurobi_internal_callback_context_.gurobi_internal_callback_data,
460 variable_indices.size(), variable_indices.data(),
462 linear_range.upper_bound()));
464 if (std::isfinite(linear_range.lower_bound())) {
465 CheckedGurobiCall(grb_constraint_function(
466 current_gurobi_internal_callback_context_.gurobi_internal_callback_data,
467 variable_indices.size(), variable_indices.data(),
469 linear_range.lower_bound()));
473 void GurobiMPCallbackContext::AddCut(
const LinearRange& cutting_plane) {
474 CHECK(might_add_cuts_);
476 CHECK(
where == MPCallbackEvent::kMipNode)
477 <<
"Cuts can only be added at MIP_NODE, tried to add cut at: "
479 AddGeneratedConstraint(cutting_plane,
GRBcbcut);
482 void GurobiMPCallbackContext::AddLazyConstraint(
483 const LinearRange& lazy_constraint) {
484 CHECK(might_add_lazy_constraints_);
486 CHECK(
where == MPCallbackEvent::kMipNode ||
487 where == MPCallbackEvent::kMipSolution)
488 <<
"Lazy constraints can only be added at MIP_NODE or MIP_SOL, tried to "
489 "add lazy constraint at: "
491 AddGeneratedConstraint(lazy_constraint,
GRBcblazy);
494 double GurobiMPCallbackContext::SuggestSolution(
495 const absl::flat_hash_map<const MPVariable*, double>& solution) {
497 CHECK(
where == MPCallbackEvent::kMipNode)
498 <<
"Feasible solutions can only be added at MIP_NODE, tried to add "
502 std::vector<double> full_solution(num_gurobi_vars_,
GRB_UNDEFINED);
503 for (
const auto& variable_value : solution) {
504 const MPVariable*
var = variable_value.first;
505 full_solution[mp_var_to_gurobi_var_->at(
var->index())] =
506 variable_value.second;
511 current_gurobi_internal_callback_context_.gurobi_internal_callback_data,
512 full_solution.data(), &objval));
517 struct MPCallbackWithGurobiContext {
526 void* raw_model_and_callback) {
527 MPCallbackWithGurobiContext*
const callback_with_context =
528 static_cast<MPCallbackWithGurobiContext*
>(raw_model_and_callback);
529 CHECK(callback_with_context !=
nullptr);
530 CHECK(callback_with_context->context !=
nullptr);
531 CHECK(callback_with_context->callback !=
nullptr);
532 GurobiInternalCallbackContext gurobi_internal_context{
534 callback_with_context->context->UpdateFromGurobiState(
535 gurobi_internal_context);
536 callback_with_context->callback->RunCallback(callback_with_context->context);
542 void GurobiInterface::CheckedGurobiCall(
int err)
const {
543 ::operations_research::CheckedGurobiCall(err, env_);
546 void GurobiInterface::SetIntAttr(
const char*
name,
int value) {
550 int GurobiInterface::GetIntAttr(
const char*
name)
const {
556 void GurobiInterface::SetDoubleAttr(
const char*
name,
double value) {
560 double GurobiInterface::GetDoubleAttr(
const char*
name)
const {
566 void GurobiInterface::SetIntAttrElement(
const char*
name,
int index,
571 int GurobiInterface::GetIntAttrElement(
const char*
name,
int index)
const {
577 void GurobiInterface::SetDoubleAttrElement(
const char*
name,
int index,
581 double GurobiInterface::GetDoubleAttrElement(
const char*
name,
588 std::vector<double> GurobiInterface::GetDoubleAttrArray(
const char*
name,
590 std::vector<double> results(elements);
596 void GurobiInterface::SetCharAttrElement(
const char*
name,
int index,
600 char GurobiInterface::GetCharAttrElement(
const char*
name,
int index)
const {
607 GurobiInterface::GurobiInterface(
MPSolver*
const solver,
bool mip)
612 current_solution_index_(0) {
623 absl::GetFlag(FLAGS_num_gurobi_threads)));
635 const absl::MutexLock lock(&hold_interruptions_mutex_);
660 mp_var_to_gurobi_var_.clear();
661 mp_cons_to_gurobi_linear_cons_.clear();
662 num_gurobi_vars_ = 0;
663 num_gurobi_linear_cons_ = 0;
664 had_nonincremental_change_ =
false;
675 SetDoubleAttrElement(
GRB_DBL_ATTR_LB, mp_var_to_gurobi_var_.at(var_index),
677 SetDoubleAttrElement(
GRB_DBL_ATTR_UB, mp_var_to_gurobi_var_.at(var_index),
703 had_nonincremental_change_ =
true;
720 had_nonincremental_change_ =
true;
731 double new_value,
double old_value) {
736 int grb_var = mp_var_to_gurobi_var_.at(variable->
index());
737 int grb_cons = mp_cons_to_gurobi_linear_cons_.at(constraint->
index());
739 had_nonincremental_change_ =
true;
744 GRBchgcoeffs(model_, 1, &grb_cons, &grb_var, &new_value));
752 had_nonincremental_change_ =
true;
764 mp_var_to_gurobi_var_.at(variable->
index()),
773 if (!had_nonincremental_change_) {
782 if (!had_nonincremental_change_) {
784 for (
const auto& entry :
solver_->objective_->coefficients_) {
793 update_branching_priorities_ =
true;
802 return static_cast<int64_t
>(iter);
810 LOG(DFATAL) <<
"Number of nodes only available for discrete problems.";
816 int gurobi_basis_status)
const {
817 switch (gurobi_basis_status) {
827 LOG(DFATAL) <<
"Unknown GRB basis status.";
833 int gurobi_basis_status,
int constraint_index)
const {
834 const int grb_index = mp_cons_to_gurobi_linear_cons_.at(constraint_index);
836 LOG(DFATAL) <<
"Basis status not available for nonlinear constraints.";
839 switch (gurobi_basis_status) {
844 double tolerance = 0.0;
849 VLOG(4) <<
"constraint " << constraint_index <<
" , slack = " << slack
850 <<
" , sense = " << sense;
851 if (fabs(slack) <= tolerance) {
872 LOG(DFATAL) <<
"Basis status only available after a solution has "
877 LOG(DFATAL) <<
"Basis status only available for continuous problems.";
880 const int grb_index = mp_cons_to_gurobi_linear_cons_.at(constraint_index);
882 LOG(DFATAL) <<
"Basis status not available for nonlinear constraints.";
885 const int gurobi_basis_status =
887 return TransformGRBConstraintBasisStatus(gurobi_basis_status,
895 LOG(DFATAL) <<
"Basis status only available after a solution has "
900 LOG(DFATAL) <<
"Basis status only available for continuous problems.";
903 const int grb_index = mp_var_to_gurobi_var_.at(variable_index);
904 const int gurobi_basis_status =
906 return TransformGRBVarBasisStatus(gurobi_basis_status);
911 const int total_num_vars =
solver_->variables_.size();
923 var->name().empty() ?
nullptr :
var->name().c_str()));
924 mp_var_to_gurobi_var_.push_back(num_gurobi_vars_++);
928 std::vector<int> grb_cons_ind;
929 std::vector<int> grb_var_ind;
930 std::vector<double>
coef;
937 const int grb_ct_idx = mp_cons_to_gurobi_linear_cons_.at(
ct->index());
938 DCHECK_GE(grb_ct_idx, 0);
939 DCHECK(
ct->indicator_variable() ==
nullptr);
940 for (
const auto& entry :
ct->coefficients_) {
941 const int var_index = entry.first->index();
945 grb_cons_ind.push_back(grb_ct_idx);
946 grb_var_ind.push_back(mp_var_to_gurobi_var_.at(var_index));
947 coef.push_back(entry.second);
951 if (!grb_cons_ind.empty()) {
952 CheckedGurobiCall(
GRBchgcoeffs(model_, grb_cons_ind.size(),
953 grb_cons_ind.data(), grb_var_ind.data(),
962 int total_num_rows =
solver_->constraints_.size();
968 const int size =
ct->coefficients_.size();
969 std::vector<int> grb_vars;
970 std::vector<double> coefs;
971 grb_vars.reserve(size);
973 for (
const auto& entry :
ct->coefficients_) {
974 const int var_index = entry.first->index();
976 grb_vars.push_back(mp_var_to_gurobi_var_.at(var_index));
977 coefs.push_back(entry.second);
980 ct->name().empty() ? nullptr :
const_cast<char*
>(
ct->name().c_str());
981 if (
ct->indicator_variable() !=
nullptr) {
982 const int grb_ind_var =
983 mp_var_to_gurobi_var_.at(
ct->indicator_variable()->index());
984 if (
ct->lb() > -std::numeric_limits<double>::infinity()) {
986 model_,
name, grb_ind_var,
ct->indicator_value(), size,
987 grb_vars.data(), coefs.data(),
990 if (
ct->ub() < std::numeric_limits<double>::infinity() &&
991 ct->lb() !=
ct->ub()) {
993 model_,
name, grb_ind_var,
ct->indicator_value(), size,
996 mp_cons_to_gurobi_linear_cons_.push_back(-1);
1000 if (
ct->lb() ==
ct->ub()) {
1001 CheckedGurobiCall(
GRBaddconstr(model_, size, grb_vars.data(),
1004 }
else if (
ct->lb() == -std::numeric_limits<double>::infinity()) {
1005 CheckedGurobiCall(
GRBaddconstr(model_, size, grb_vars.data(),
1008 }
else if (
ct->ub() == std::numeric_limits<double>::infinity()) {
1009 CheckedGurobiCall(
GRBaddconstr(model_, size, grb_vars.data(),
1014 coefs.data(),
ct->lb(),
ct->ub(),
1020 mp_cons_to_gurobi_linear_cons_.push_back(num_gurobi_linear_cons_++);
1042 bool GurobiInterface::SetSolverSpecificParametersAsString(
1047 void GurobiInterface::SetRelativeMipGap(
double value) {
1052 LOG(WARNING) <<
"The relative MIP gap is only available "
1053 <<
"for discrete problems.";
1063 void GurobiInterface::SetPrimalTolerance(
double value) {
1074 void GurobiInterface::SetDualTolerance(
double value) {
1079 void GurobiInterface::SetPresolveMode(
int value) {
1098 void GurobiInterface::SetScalingMode(
int value) {
1118 void GurobiInterface::SetLpAlgorithm(
int value) {
1138 int GurobiInterface::SolutionCount()
const {
1142 bool GurobiInterface::ModelIsNonincremental()
const {
1144 if (c->indicator_variable() !=
nullptr) {
1157 ModelIsNonincremental() || had_nonincremental_change_) {
1168 VLOG(1) << absl::StrFormat(
"Model built in %s.",
1172 for (
const std::pair<const MPVariable*, double>& p :
1175 mp_var_to_gurobi_var_.at(p.first->index()), p.second);
1179 if (update_branching_priorities_) {
1182 mp_var_to_gurobi_var_.at(
var->index()),
1183 var->branching_priority());
1185 update_branching_priorities_ =
false;
1200 SetParameters(param);
1202 solver_->solver_specific_parameter_string_);
1204 std::unique_ptr<GurobiMPCallbackContext> gurobi_context;
1205 MPCallbackWithGurobiContext mp_callback_with_context;
1206 int gurobi_precrush = 0;
1207 int gurobi_lazy_constraint = 0;
1208 if (callback_ ==
nullptr) {
1211 gurobi_context = std::make_unique<GurobiMPCallbackContext>(
1212 env_, &mp_var_to_gurobi_var_, num_gurobi_vars_,
1214 mp_callback_with_context.context = gurobi_context.get();
1215 mp_callback_with_context.callback = callback_;
1217 model_, CallbackImpl,
static_cast<void*
>(&mp_callback_with_context)));
1233 VLOG(1) << absl::StrFormat(
"Solved in %s.",
1239 VLOG(1) << absl::StrFormat(
"Solution status %d.\n", optimization_status);
1240 const int solution_count = SolutionCount();
1242 switch (optimization_status) {
1258 if (solution_count > 0) {
1271 LOG_IF(WARNING, error != 0)
1272 <<
"Best objective bound is not available, error=" << error
1279 current_solution_index_ = 0;
1285 const std::vector<double> grb_variable_values =
1287 for (
int i = 0; i <
solver_->variables_.size(); ++i) {
1289 const double val = grb_variable_values.at(mp_var_to_gurobi_var_.at(i));
1290 var->set_solution_value(val);
1291 VLOG(3) <<
var->name() <<
", value = " << val;
1296 const std::vector<double> grb_reduced_costs =
1298 for (
int i = 0; i <
solver_->variables_.size(); ++i) {
1300 const double rc = grb_reduced_costs.at(mp_var_to_gurobi_var_.at(i));
1301 var->set_reduced_cost(rc);
1302 VLOG(4) <<
var->name() <<
", reduced cost = " << rc;
1307 std::vector<double> grb_dual_values =
1309 for (
int i = 0; i <
solver_->constraints_.size(); ++i) {
1311 const double dual_value =
1312 grb_dual_values.at(mp_cons_to_gurobi_linear_cons_.at(i));
1313 ct->set_dual_value(dual_value);
1314 VLOG(4) <<
"row " <<
ct->index() <<
", dual value = " << dual_value;
1326 const MPModelRequest& request, std::atomic<bool>* interrupt) {
1328 if (interrupt !=
nullptr)
return std::nullopt;
1333 if (status_or.ok())
return status_or.value();
1336 if (absl::IsUnimplemented(status_or.status()))
return std::nullopt;
1338 if (request.enable_internal_solver_output()) {
1339 LOG(INFO) <<
"Invalid Gurobi status: " << status_or.status();
1342 response.set_status(MPSOLVER_NOT_SOLVED);
1343 response.set_status_str(status_or.status().ToString());
1349 if (!mip_)
return false;
1356 if (current_solution_index_ + 1 >= SolutionCount()) {
1359 current_solution_index_++;
1365 const std::vector<double> grb_variable_values =
1368 for (
int i = 0; i <
solver_->variables_.size(); ++i) {
1370 var->set_solution_value(
1371 grb_variable_values.at(mp_var_to_gurobi_var_.at(i)));
1385 VLOG(1) <<
"Writing Gurobi model file \"" << filename <<
"\".";
1397 callback_ = mp_callback;
absl::Duration GetDuration() const
void BranchingPriorityChangedForVariable(int var_index) override
void AddRowConstraint(MPConstraint *const ct) override
GurobiInterface(MPSolver *const solver, bool mip)
void Write(const std::string &filename) override
void * underlying_solver() override
std::optional< MPSolutionResponse > DirectlySolveProto(const MPModelRequest &request, std::atomic< bool > *interrupt) override
void ExtractObjective() override
bool IsContinuous() const override
void SetConstraintBounds(int row_index, double lb, double ub) override
bool InterruptSolve() override
MPSolver::ResultStatus Solve(const MPSolverParameters ¶m) override
void ClearConstraint(MPConstraint *const constraint) override
void SetObjectiveCoefficient(const MPVariable *const variable, double coefficient) override
~GurobiInterface() override
void SetCoefficient(MPConstraint *const constraint, const MPVariable *const variable, double new_value, double old_value) override
MPSolver::BasisStatus row_status(int constraint_index) const override
bool SupportsCallbacks() const override
double ComputeExactConditionNumber() const override
void SetVariableInteger(int var_index, bool integer) override
void SetCallback(MPCallback *mp_callback) override
void SetObjectiveOffset(double value) override
void ExtractNewConstraints() override
std::string SolverVersion() const override
void AddVariable(MPVariable *const var) override
void ExtractNewVariables() override
int64_t nodes() const override
void SetVariableBounds(int var_index, double lb, double ub) override
bool IsLP() const override
bool IsMIP() const override
int64_t iterations() const override
bool AddIndicatorConstraint(MPConstraint *const ct) override
bool NextSolution() override
void SetOptimizationDirection(bool maximize) override
MPSolver::BasisStatus column_status(int variable_index) const override
void ClearObjective() override
bool might_add_cuts() const
bool might_add_lazy_constraints() const
The class for constraints of a Mathematical Programming (MP) model.
int index() const
Returns the index of the constraint in the MPSolver::constraints_.
double offset() const
Gets the constant term in the objective.
This mathematical programming (MP) solver class is the main class though which users build and solve ...
const MPObjective & Objective() const
Returns the objective object.
ResultStatus
The status of solving the problem.
@ FEASIBLE
feasible, or stopped by limit.
@ NOT_SOLVED
not been solved yet.
@ INFEASIBLE
proven infeasible.
@ UNBOUNDED
proven unbounded.
const std::vector< MPConstraint * > & constraints() const
Returns the array of constraints handled by the MPSolver.
bool SetSolverSpecificParametersAsString(const std::string ¶meters)
Advanced usage: pass solver specific parameters in text format.
int64_t time_limit() const
double time_limit_in_secs() const
BasisStatus
Advanced usage: possible basis status values for a variable and the slack variable of a linear constr...
virtual void SetIntegerParamToUnsupportedValue(MPSolverParameters::IntegerParam param, int value)
friend class MPConstraint
void set_constraint_as_extracted(int ct_index, bool extracted)
MPSolver::ResultStatus result_status_
void InvalidateSolutionSynchronization()
void SetMIPParameters(const MPSolverParameters ¶m)
int last_constraint_index_
bool constraint_is_extracted(int ct_index) const
static constexpr int64_t kUnknownNumberOfNodes
double best_objective_bound_
bool CheckSolutionIsSynchronizedAndExists() const
bool CheckSolutionIsSynchronized() const
void ResetExtractionInformation()
bool variable_is_extracted(int var_index) const
static constexpr int64_t kUnknownNumberOfIterations
void set_variable_as_extracted(int var_index, bool extracted)
void SetCommonParameters(const MPSolverParameters ¶m)
SynchronizationStatus sync_status_
This class stores parameter settings for LP and MIP solvers.
@ INCREMENTALITY_OFF
Start solve from scratch.
@ SCALING_ON
Scaling is on.
@ SCALING_OFF
Scaling is off.
@ LP_ALGORITHM
Algorithm to solve linear programs.
@ PRESOLVE
Advanced usage: presolve mode.
@ INCREMENTALITY
Advanced usage: incrementality from one solve to the next.
@ BARRIER
Barrier algorithm.
@ PRESOLVE_ON
Presolve is on.
@ PRESOLVE_OFF
Presolve is off.
int GetIntegerParam(MPSolverParameters::IntegerParam param) const
Returns the value of an integer parameter.
The class for variables of a Mathematical Programming (MP) model.
int index() const
Returns the index of the variable in the MPSolver::variables_.
SharedResponseManager * response
#define GRB_INT_ATTR_BRANCHPRIORITY
#define GRB_DBL_ATTR_START
#define GRB_DBL_PAR_MIPGAP
#define GRB_DBL_PAR_FEASIBILITYTOL
#define GRB_NONBASIC_LOWER
#define GRB_INT_ATTR_MODELSENSE
#define GRB_INT_ATTR_VBASIS
#define GRB_GREATER_EQUAL
#define GRB_DBL_ATTR_NODECOUNT
#define GRB_INT_PAR_PRESOLVE
#define GRB_DBL_ATTR_ITERCOUNT
#define GRB_INT_PAR_THREADS
#define GRB_CB_MIPNODE_REL
#define GRB_INT_PAR_METHOD
#define GRB_DBL_ATTR_OBJVAL
#define GRB_DBL_ATTR_SLACK
#define GRB_INT_PAR_LAZYCONSTRAINTS
#define GRB_DBL_PAR_OPTIMALITYTOL
#define GRB_CB_MIPSOL_NODCNT
#define GRB_CB_MIPNODE_STATUS
#define GRB_INT_PAR_SCALEFLAG
#define GRB_METHOD_BARRIER
struct _GRBmodel GRBmodel
#define GRB_CHAR_ATTR_VTYPE
#define GRB_NONBASIC_UPPER
#define GRB_DBL_ATTR_OBJCON
#define GRB_DBL_PAR_INTFEASTOL
#define GRB_CHAR_ATTR_SENSE
#define GRB_INT_ATTR_NUMVARS
#define GRB_INT_ATTR_NUMCONSTRS
#define GRB_INT_ATTR_CBASIS
#define GRB_INT_ATTR_STATUS
#define GRB_DBL_ATTR_POOLOBJVAL
#define GRB_INT_PAR_SOLUTIONNUMBER
#define GRB_INT_ATTR_SOLCOUNT
#define GRB_METHOD_PRIMAL
#define GRB_INT_PAR_OUTPUTFLAG
#define GRB_DBL_PAR_TIMELIMIT
#define GRB_CB_MIPSOL_SOL
#define GRB_DBL_ATTR_OBJBOUND
#define GRB_INT_PAR_PRECRUSH
#define GRB_DBL_PAR_OBJSCALE
#define GRB_CB_MIPNODE_NODCNT
ABSL_FLAG(int, num_gurobi_threads, 0, "Number of threads available for Gurobi.")
void * gurobi_internal_callback_data
GurobiMPCallbackContext * context
A C++ wrapper that provides a simple and unified interface to several linear programming and mixed in...
Collection of objects used to extend the Constraint Solver library.
std::function< int(GRBmodel *model, const char *attrname, int element, char *valueP)> GRBgetcharattrelement
std::function< int(GRBmodel *model, int numnz, int *cind, double *cval, char sense, double rhs, const char *constrname)> GRBaddconstr
std::function< int(GRBmodel *model, const char *attrname, double *valueP)> GRBgetdblattr
MPSolverInterface * BuildGurobiInterface(bool mip, MPSolver *const solver)
std::function< int(GRBmodel *model, int numnz, int *vind, double *vval, double obj, double lb, double ub, char vtype, const char *varname)> GRBaddvar
const absl::string_view ToString(MPSolver::OptimizationProblemType optimization_problem_type)
std::function< void(int *majorP, int *minorP, int *technicalP)> GRBversion
std::function< int(GRBmodel *model, const char *attrname, int newvalue)> GRBsetintattr
absl::Status SetSolverSpecificParameters(absl::string_view parameters, GRBenv *gurobi)
std::function< int(void *cbdata, int lazylen, const int *lazyind, const double *lazyval, char lazysense, double lazyrhs)> GRBcblazy
std::function< int(GRBenv *env, const char *paramname, int value)> GRBsetintparam
std::function< int(void *cbdata, int where, int what, void *resultP)> GRBcbget
std::function< int(GRBmodel *model, const char *attrname, int element, int *valueP)> GRBgetintattrelement
std::function< int(GRBenv *dest, GRBenv *src)> GRBcopyparams
std::function< int(GRBmodel *model)> GRBfreemodel
std::function< void(GRBmodel *model)> GRBterminate
std::function< int(GRBenv *env, const char *paramname, double *valueP)> GRBgetdblparam
std::function< const char *(GRBenv *env)> GRBgeterrormsg
std::function< int(GRBmodel *model, int cnt, int *cind, int *vind, double *val)> GRBchgcoeffs
absl::StatusOr< GRBenv * > GetGurobiEnv()
std::function< GRBenv *(GRBmodel *model)> GRBgetenv
std::function< int(GRBmodel *model, const char *attrname, int element, double newvalue)> GRBsetdblattrelement
std::function< int(GRBenv *env)> GRBresetparams
std::function< int(GRBmodel *model, const char *attrname, int first, int len, double *values)> GRBgetdblattrarray
std::function< int(GRBmodel *model)> GRBupdatemodel
std::function< int(GRBmodel *model, int numnz, int *cind, double *cval, double lower, double upper, const char *constrname)> GRBaddrangeconstr
absl::StatusOr< MPSolutionResponse > GurobiSolveProto(const MPModelRequest &request, GRBenv *gurobi_env)
std::function< int(GRBmodel *model, const char *attrname, int element, char newvalue)> GRBsetcharattrelement
std::function< int(GRBmodel *model, const char *attrname, int element, int newvalue)> GRBsetintattrelement
std::function< int(GRBmodel *model, const char *attrname, int element, double *valueP)> GRBgetdblattrelement
std::function< int(void *cbdata, const double *solution, double *objvalP)> GRBcbsolution
std::function< int(GRBmodel *model)> GRBoptimize
std::function< int(GRBmodel *model, const char *filename)> GRBwrite
std::function< int(GRBenv *env, GRBmodel **modelP, const char *Pname, int numvars, double *obj, double *lb, double *ub, char *vtype, char **varnames)> GRBnewmodel
std::function< void(GRBenv *env)> GRBfreeenv
std::function< int(void *cbdata, int cutlen, const int *cutind, const double *cutval, char cutsense, double cutrhs)> GRBcbcut
std::function< int(GRBmodel *model, const char *attrname, double newvalue)> GRBsetdblattr
std::function< int(GRBmodel *model, int(GUROBI_STDCALL *cb)(CB_ARGS), void *usrdata)> GRBsetcallbackfunc
std::function< int(GRBmodel *model, const char *name, int binvar, int binval, int nvars, const int *vars, const double *vals, char sense, double rhs)> GRBaddgenconstrIndicator
std::function< int(GRBmodel *model, const char *attrname, int *valueP)> GRBgetintattr
std::function< int(GRBenv *env, const char *paramname, double value)> GRBsetdblparam
#define VLOG(verboselevel)