57#include "absl/base/attributes.h"
58#include "absl/container/flat_hash_map.h"
59#include "absl/container/flat_hash_set.h"
60#include "absl/flags/flag.h"
61#include "absl/log/check.h"
62#include "absl/log/die_if_null.h"
63#include "absl/status/status.h"
64#include "absl/strings/str_format.h"
65#include "absl/synchronization/mutex.h"
66#include "absl/time/time.h"
79 "Number of threads available for Gurobi.");
98 return interrupt ==
nullptr;
101 std::atomic<bool>* interrupt)
override {
102 DCHECK_EQ(interrupt,
nullptr);
103 const bool log_error = request->enable_internal_solver_output();
112 void Write(
const std::string& filename)
override;
116 void Reset()
override;
130 double new_value,
double old_value)
override;
135 double coefficient)
override;
146 int64_t
nodes()
const override;
156 bool IsLP()
const override {
return !mip_; }
157 bool IsMIP()
const override {
return mip_; }
164 int major, minor, technical;
166 return absl::StrFormat(
"Gurobi library version %d.%d.%d\n", major, minor,
171 const absl::MutexLock lock(hold_interruptions_mutex_);
180 LOG(DFATAL) <<
"ComputeExactConditionNumber not implemented for"
181 <<
" GUROBI_MIXED_INTEGER_PROGRAMMING";
186 LOG(DFATAL) <<
"ComputeExactConditionNumber not implemented for"
187 <<
" GUROBI_LINEAR_PROGRAMMING";
221 bool SetSolverSpecificParametersAsString(
222 const std::string& parameters)
override;
224 void SetRelativeMipGap(
double value)
override;
225 void SetPrimalTolerance(
double value)
override;
226 void SetDualTolerance(
double value)
override;
227 void SetPresolveMode(
int value)
override;
228 void SetScalingMode(
int value)
override;
229 void SetLpAlgorithm(
int value)
override;
232 int gurobi_basis_status)
const;
234 int gurobi_basis_status,
int constraint_index)
const;
237 bool ModelIsNonincremental()
const;
239 void SetIntAttr(
const char* name,
int value);
240 int GetIntAttr(
const char* name)
const;
241 void SetDoubleAttr(
const char* name,
double value);
242 double GetDoubleAttr(
const char* name)
const;
243 void SetIntAttrElement(
const char* name,
int index,
int value);
244 int GetIntAttrElement(
const char* name,
int index)
const;
245 void SetDoubleAttrElement(
const char* name,
int index,
double value);
246 double GetDoubleAttrElement(
const char* name,
int index)
const;
247 std::vector<double> GetDoubleAttrArray(
const char* name,
int elements);
248 void SetCharAttrElement(
const char* name,
int index,
char value);
249 char GetCharAttrElement(
const char* name,
int index)
const;
251 void CheckedGurobiCall(
int err)
const;
253 int SolutionCount()
const;
262 int current_solution_index_;
264 bool update_branching_priorities_ =
false;
270 std::vector<int> mp_var_to_gurobi_var_;
275 std::vector<int> mp_cons_to_gurobi_linear_cons_;
277 int num_gurobi_vars_ = 0;
280 int num_gurobi_linear_cons_ = 0;
282 bool had_nonincremental_change_ =
false;
287 mutable absl::Mutex hold_interruptions_mutex_;
292constexpr int kGurobiOkCode = 0;
293void CheckedGurobiCall(
int err,
GRBenv*
const env) {
294 CHECK_EQ(kGurobiOkCode, err)
295 <<
"Fatal error with code " << err <<
", due to " <<
GRBgeterrormsg(env);
299struct GurobiInternalCallbackContext {
301 void* gurobi_internal_callback_data;
307 GurobiMPCallbackContext(
GRBenv* env,
308 const std::vector<int>* mp_var_to_gurobi_var,
309 int num_gurobi_vars,
bool might_add_cuts,
310 bool might_add_lazy_constraints);
314 bool CanQueryVariableValues()
override;
315 double VariableValue(
const MPVariable* variable)
override;
316 void AddCut(
const LinearRange& cutting_plane)
override;
317 void AddLazyConstraint(
const LinearRange& lazy_constraint)
override;
318 double SuggestSolution(
319 const absl::flat_hash_map<const MPVariable*, double>&
solution)
override;
320 int64_t NumExploredNodes()
override;
324 void UpdateFromGurobiState(
325 const GurobiInternalCallbackContext& gurobi_internal_context);
331 template <
typename T>
333 const GurobiInternalCallbackContext& gurobi_internal_context,
335 void CheckedGurobiCall(
int gurobi_error_code)
const;
337 template <
typename GRBConstra
intFunction>
338 void AddGeneratedConstraint(
const LinearRange& linear_range,
339 GRBConstraintFunction grb_constraint_function);
342 const std::vector<int>*
const mp_var_to_gurobi_var_;
343 const int num_gurobi_vars_;
345 const bool might_add_cuts_;
346 const bool might_add_lazy_constraints_;
349 GurobiInternalCallbackContext current_gurobi_internal_callback_context_;
350 bool variable_values_extracted_ =
false;
351 std::vector<double> gurobi_variable_values_;
354void GurobiMPCallbackContext::CheckedGurobiCall(
int gurobi_error_code)
const {
355 ::operations_research::CheckedGurobiCall(gurobi_error_code, env_);
358GurobiMPCallbackContext::GurobiMPCallbackContext(
359 GRBenv* env,
const std::vector<int>* mp_var_to_gurobi_var,
360 int num_gurobi_vars,
bool might_add_cuts,
bool might_add_lazy_constraints)
361 : env_(ABSL_DIE_IF_NULL(env)),
362 mp_var_to_gurobi_var_(ABSL_DIE_IF_NULL(mp_var_to_gurobi_var)),
363 num_gurobi_vars_(num_gurobi_vars),
364 might_add_cuts_(might_add_cuts),
365 might_add_lazy_constraints_(might_add_lazy_constraints) {}
367void GurobiMPCallbackContext::UpdateFromGurobiState(
368 const GurobiInternalCallbackContext& gurobi_internal_context) {
369 current_gurobi_internal_callback_context_ = gurobi_internal_context;
370 variable_values_extracted_ =
false;
373int64_t GurobiMPCallbackContext::NumExploredNodes() {
375 case MPCallbackEvent::kMipNode:
376 return static_cast<int64_t
>(GurobiCallbackGet<double>(
378 case MPCallbackEvent::kMipSolution:
379 return static_cast<int64_t
>(GurobiCallbackGet<double>(
382 LOG(FATAL) <<
"Node count is supported only for callback events MIP_NODE "
383 "and MIP_SOL, but was requested at: "
389T GurobiMPCallbackContext::GurobiCallbackGet(
390 const GurobiInternalCallbackContext& gurobi_internal_context,
391 const int callback_code) {
394 GRBcbget(gurobi_internal_context.gurobi_internal_callback_data,
395 gurobi_internal_context.where, callback_code,
396 static_cast<void*
>(&result)));
401 switch (current_gurobi_internal_callback_context_.where) {
403 return MPCallbackEvent::kPolling;
405 return MPCallbackEvent::kPresolve;
407 return MPCallbackEvent::kSimplex;
409 return MPCallbackEvent::kMip;
411 return MPCallbackEvent::kMipSolution;
413 return MPCallbackEvent::kMipNode;
415 return MPCallbackEvent::kMessage;
417 return MPCallbackEvent::kBarrier;
422 LOG_FIRST_N(ERROR, 1) <<
"Gurobi callback at unknown where="
423 << current_gurobi_internal_callback_context_.where;
424 return MPCallbackEvent::kUnknown;
428bool GurobiMPCallbackContext::CanQueryVariableValues() {
430 if (where == MPCallbackEvent::kMipSolution) {
433 if (where == MPCallbackEvent::kMipNode) {
434 const int gurobi_node_status = GurobiCallbackGet<int>(
441double GurobiMPCallbackContext::VariableValue(
const MPVariable* variable) {
442 CHECK(variable !=
nullptr);
443 if (!variable_values_extracted_) {
445 CHECK(where == MPCallbackEvent::kMipSolution ||
446 where == MPCallbackEvent::kMipNode)
447 <<
"You can only call VariableValue at "
448 <<
ToString(MPCallbackEvent::kMipSolution) <<
" or "
449 <<
ToString(MPCallbackEvent::kMipNode)
450 <<
" but called from: " <<
ToString(where);
451 const int gurobi_get_var_param = where == MPCallbackEvent::kMipNode
455 gurobi_variable_values_.resize(num_gurobi_vars_);
457 current_gurobi_internal_callback_context_.gurobi_internal_callback_data,
458 current_gurobi_internal_callback_context_.where, gurobi_get_var_param,
459 static_cast<void*
>(gurobi_variable_values_.data())));
460 variable_values_extracted_ =
true;
462 return gurobi_variable_values_[mp_var_to_gurobi_var_->at(variable->index())];
465template <
typename GRBConstra
intFunction>
466void GurobiMPCallbackContext::AddGeneratedConstraint(
467 const LinearRange& linear_range,
468 GRBConstraintFunction grb_constraint_function) {
469 std::vector<int> variable_indices;
470 std::vector<double> variable_coefficients;
471 const int num_terms = linear_range.linear_expr().terms().size();
472 variable_indices.reserve(num_terms);
473 variable_coefficients.reserve(num_terms);
474 for (
const auto& var_coef_pair : linear_range.linear_expr().terms()) {
475 variable_indices.push_back(
476 mp_var_to_gurobi_var_->at(var_coef_pair.first->index()));
477 variable_coefficients.push_back(var_coef_pair.second);
479 if (std::isfinite(linear_range.upper_bound())) {
480 CheckedGurobiCall(grb_constraint_function(
481 current_gurobi_internal_callback_context_.gurobi_internal_callback_data,
482 variable_indices.size(), variable_indices.data(),
484 linear_range.upper_bound()));
486 if (std::isfinite(linear_range.lower_bound())) {
487 CheckedGurobiCall(grb_constraint_function(
488 current_gurobi_internal_callback_context_.gurobi_internal_callback_data,
489 variable_indices.size(), variable_indices.data(),
491 linear_range.lower_bound()));
495void GurobiMPCallbackContext::AddCut(
const LinearRange& cutting_plane) {
496 CHECK(might_add_cuts_);
498 CHECK(where == MPCallbackEvent::kMipNode)
499 <<
"Cuts can only be added at MIP_NODE, tried to add cut at: "
501 AddGeneratedConstraint(cutting_plane, GRBcbcut);
504void GurobiMPCallbackContext::AddLazyConstraint(
505 const LinearRange& lazy_constraint) {
506 CHECK(might_add_lazy_constraints_);
508 CHECK(where == MPCallbackEvent::kMipNode ||
509 where == MPCallbackEvent::kMipSolution)
510 <<
"Lazy constraints can only be added at MIP_NODE or MIP_SOL, tried to "
511 "add lazy constraint at: "
513 AddGeneratedConstraint(lazy_constraint, GRBcblazy);
516double GurobiMPCallbackContext::SuggestSolution(
517 const absl::flat_hash_map<const MPVariable*, double>&
solution) {
519 CHECK(where == MPCallbackEvent::kMipNode)
520 <<
"Feasible solutions can only be added at MIP_NODE, tried to add "
524 std::vector<double> full_solution(num_gurobi_vars_,
GRB_UNDEFINED);
525 for (
const auto& variable_value : solution) {
526 const MPVariable* var = variable_value.first;
527 full_solution[mp_var_to_gurobi_var_->at(var->index())] =
528 variable_value.second;
533 current_gurobi_internal_callback_context_.gurobi_internal_callback_data,
534 full_solution.data(), &objval));
539struct MPCallbackWithGurobiContext {
540 GurobiMPCallbackContext* context;
541 MPCallback* callback;
548#define GUROBI_STDCALL __stdcall
550#define GUROBI_STDCALL
554 void* gurobi_internal_callback_data,
int where,
555 void* raw_model_and_callback) {
556 MPCallbackWithGurobiContext*
const callback_with_context =
557 static_cast<MPCallbackWithGurobiContext*
>(raw_model_and_callback);
558 CHECK(callback_with_context !=
nullptr);
559 CHECK(callback_with_context->context !=
nullptr);
560 CHECK(callback_with_context->callback !=
nullptr);
561 GurobiInternalCallbackContext gurobi_internal_context{
562 model, gurobi_internal_callback_data, where};
563 callback_with_context->context->UpdateFromGurobiState(
564 gurobi_internal_context);
565 callback_with_context->callback->RunCallback(callback_with_context->context);
571void GurobiInterface::CheckedGurobiCall(
int err)
const {
572 ::operations_research::CheckedGurobiCall(err, global_env_);
575void GurobiInterface::SetIntAttr(
const char* name,
int value) {
579int GurobiInterface::GetIntAttr(
const char* name)
const {
585void GurobiInterface::SetDoubleAttr(
const char* name,
double value) {
589double GurobiInterface::GetDoubleAttr(
const char* name)
const {
595void GurobiInterface::SetIntAttrElement(
const char* name,
int index,
600int GurobiInterface::GetIntAttrElement(
const char* name,
int index)
const {
606void GurobiInterface::SetDoubleAttrElement(
const char* name,
int index,
610double GurobiInterface::GetDoubleAttrElement(
const char* name,
617std::vector<double> GurobiInterface::GetDoubleAttrArray(
const char* name,
619 std::vector<double> results(elements);
625void GurobiInterface::SetCharAttrElement(
const char* name,
int index,
629char GurobiInterface::GetCharAttrElement(
const char* name,
int index)
const {
639 global_env_(nullptr),
641 current_solution_index_(0) {
654 absl::GetFlag(FLAGS_num_gurobi_threads)));
666 const absl::MutexLock lock(hold_interruptions_mutex_);
694 mp_var_to_gurobi_var_.clear();
695 mp_cons_to_gurobi_linear_cons_.clear();
696 num_gurobi_vars_ = 0;
697 num_gurobi_linear_cons_ = 0;
698 had_nonincremental_change_ =
false;
709 SetDoubleAttrElement(
GRB_DBL_ATTR_LB, mp_var_to_gurobi_var_.at(var_index),
711 SetDoubleAttrElement(
GRB_DBL_ATTR_UB, mp_var_to_gurobi_var_.at(var_index),
737 had_nonincremental_change_ =
true;
754 had_nonincremental_change_ =
true;
765 double new_value,
double old_value) {
770 int grb_var = mp_var_to_gurobi_var_.at(variable->
index());
771 int grb_cons = mp_cons_to_gurobi_linear_cons_.at(constraint->
index());
773 had_nonincremental_change_ =
true;
778 GRBchgcoeffs(model_, 1, &grb_cons, &grb_var, &new_value));
786 had_nonincremental_change_ =
true;
794 double coefficient) {
798 mp_var_to_gurobi_var_.at(variable->
index()),
807 if (!had_nonincremental_change_) {
816 if (!had_nonincremental_change_) {
818 for (
const auto& entry :
solver_->objective_->coefficients_) {
827 update_branching_priorities_ =
true;
836 return static_cast<int64_t
>(iter);
844 LOG(DFATAL) <<
"Number of nodes only available for discrete problems.";
850 int gurobi_basis_status)
const {
851 switch (gurobi_basis_status) {
861 LOG(DFATAL) <<
"Unknown GRB basis status.";
867 int gurobi_basis_status,
int constraint_index)
const {
868 const int grb_index = mp_cons_to_gurobi_linear_cons_.at(constraint_index);
870 LOG(DFATAL) <<
"Basis status not available for nonlinear constraints.";
873 switch (gurobi_basis_status) {
878 double tolerance = 0.0;
883 VLOG(4) <<
"constraint " << constraint_index <<
" , slack = " << slack
884 <<
" , sense = " << sense;
885 if (fabs(slack) <= tolerance) {
906 LOG(DFATAL) <<
"Basis status only available after a solution has "
911 LOG(DFATAL) <<
"Basis status only available for continuous problems.";
914 const int grb_index = mp_cons_to_gurobi_linear_cons_.at(constraint_index);
916 LOG(DFATAL) <<
"Basis status not available for nonlinear constraints.";
919 const int gurobi_basis_status =
921 return TransformGRBConstraintBasisStatus(gurobi_basis_status,
929 LOG(DFATAL) <<
"Basis status only available after a solution has "
934 LOG(DFATAL) <<
"Basis status only available for continuous problems.";
937 const int grb_index = mp_var_to_gurobi_var_.at(variable_index);
938 const int gurobi_basis_status =
940 return TransformGRBVarBasisStatus(gurobi_basis_status);
945 const int total_num_vars =
solver_->variables_.size();
955 solver_->objective_->GetCoefficient(var), var->
lb(), var->
ub(),
957 var->
name().empty() ?
nullptr : var->
name().c_str()));
958 mp_var_to_gurobi_var_.push_back(num_gurobi_vars_++);
962 std::vector<int> grb_cons_ind;
963 std::vector<int> grb_var_ind;
964 std::vector<double> coef;
971 const int grb_ct_idx = mp_cons_to_gurobi_linear_cons_.at(ct->
index());
972 DCHECK_GE(grb_ct_idx, 0);
974 for (
const auto& entry : ct->coefficients_) {
975 const int var_index = entry.first->index();
979 grb_cons_ind.push_back(grb_ct_idx);
980 grb_var_ind.push_back(mp_var_to_gurobi_var_.at(var_index));
981 coef.push_back(entry.second);
985 if (!grb_cons_ind.empty()) {
986 CheckedGurobiCall(
GRBchgcoeffs(model_, grb_cons_ind.size(),
987 grb_cons_ind.data(), grb_var_ind.data(),
996 int total_num_rows =
solver_->constraints_.size();
1002 const int size = ct->coefficients_.size();
1003 std::vector<int> grb_vars;
1004 std::vector<double> coefs;
1005 grb_vars.reserve(size);
1006 coefs.reserve(size);
1007 for (
const auto& entry : ct->coefficients_) {
1008 const int var_index = entry.first->index();
1010 grb_vars.push_back(mp_var_to_gurobi_var_.at(var_index));
1011 coefs.push_back(entry.second);
1014 ct->
name().empty() ? nullptr :
const_cast<char*
>(ct->
name().c_str());
1016 const int grb_ind_var =
1018 if (ct->
lb() > -std::numeric_limits<double>::infinity()) {
1021 grb_vars.data(), coefs.data(),
1024 if (ct->
ub() < std::numeric_limits<double>::infinity() &&
1025 ct->
lb() != ct->
ub()) {
1030 mp_cons_to_gurobi_linear_cons_.push_back(-1);
1034 if (ct->
lb() == ct->
ub()) {
1035 CheckedGurobiCall(
GRBaddconstr(model_, size, grb_vars.data(),
1038 }
else if (ct->
lb() == -std::numeric_limits<double>::infinity()) {
1039 CheckedGurobiCall(
GRBaddconstr(model_, size, grb_vars.data(),
1042 }
else if (ct->
ub() == std::numeric_limits<double>::infinity()) {
1043 CheckedGurobiCall(
GRBaddconstr(model_, size, grb_vars.data(),
1048 coefs.data(), ct->
lb(), ct->
ub(),
1054 mp_cons_to_gurobi_linear_cons_.push_back(num_gurobi_linear_cons_++);
1076bool GurobiInterface::SetSolverSpecificParametersAsString(
1077 const std::string& parameters) {
1081void GurobiInterface::SetRelativeMipGap(
double value) {
1086 LOG(WARNING) <<
"The relative MIP gap is only available "
1087 <<
"for discrete problems.";
1097void GurobiInterface::SetPrimalTolerance(
double value) {
1108void GurobiInterface::SetDualTolerance(
double value) {
1113void GurobiInterface::SetPresolveMode(
int value) {
1132void GurobiInterface::SetScalingMode(
int value) {
1152void GurobiInterface::SetLpAlgorithm(
int value) {
1172int GurobiInterface::SolutionCount()
const {
1176bool GurobiInterface::ModelIsNonincremental()
const {
1178 if (
c->indicator_variable() !=
nullptr) {
1191 ModelIsNonincremental() || had_nonincremental_change_) {
1202 VLOG(1) << absl::StrFormat(
"Model built in %s.",
1206 for (
const std::pair<const MPVariable*, double>& p :
1209 mp_var_to_gurobi_var_.at(p.first->index()), p.second);
1213 if (update_branching_priorities_) {
1216 mp_var_to_gurobi_var_.at(var->
index()),
1219 update_branching_priorities_ =
false;
1223 if (
solver_->time_limit() != 0) {
1224 VLOG(1) <<
"Setting time limit = " <<
solver_->time_limit() <<
" ms.";
1226 solver_->time_limit_in_secs()));
1234 SetParameters(param);
1235 solver_->SetSolverSpecificParametersAsString(
1236 solver_->solver_specific_parameter_string_);
1238 std::unique_ptr<GurobiMPCallbackContext> gurobi_context;
1239 MPCallbackWithGurobiContext mp_callback_with_context;
1240 int gurobi_precrush = 0;
1241 int gurobi_lazy_constraint = 0;
1242 if (callback_ ==
nullptr) {
1245 gurobi_context = std::make_unique<GurobiMPCallbackContext>(
1246 global_env_, &mp_var_to_gurobi_var_, num_gurobi_vars_,
1247 callback_->might_add_cuts(), callback_->might_add_lazy_constraints());
1248 mp_callback_with_context.context = gurobi_context.get();
1249 mp_callback_with_context.callback = callback_;
1251 model_, CallbackImpl,
static_cast<void*
>(&mp_callback_with_context)));
1252 gurobi_precrush = callback_->might_add_cuts();
1253 gurobi_lazy_constraint = callback_->might_add_lazy_constraints();
1271 VLOG(1) <<
"Failed to optimize MIP." <<
GRBgeterrormsg(global_env_);
1273 VLOG(1) << absl::StrFormat(
"Solved in %s.",
1279 VLOG(1) << absl::StrFormat(
"Solution status %d.\n", optimization_status);
1280 const int solution_count = SolutionCount();
1282 switch (optimization_status) {
1298 if (solution_count > 0) {
1311 LOG_IF(WARNING, error != 0)
1312 <<
"Best objective bound is not available, error=" << error
1319 current_solution_index_ = 0;
1325 const std::vector<double> grb_variable_values =
1327 for (
int i = 0; i <
solver_->variables_.size(); ++i) {
1329 const double val = grb_variable_values.at(mp_var_to_gurobi_var_.at(i));
1331 VLOG(3) << var->
name() <<
", value = " << val;
1336 const std::vector<double> grb_reduced_costs =
1338 for (
int i = 0; i <
solver_->variables_.size(); ++i) {
1340 const double rc = grb_reduced_costs.at(mp_var_to_gurobi_var_.at(i));
1342 VLOG(4) << var->
name() <<
", reduced cost = " << rc;
1347 std::vector<double> grb_dual_values =
1349 for (
int i = 0; i <
solver_->constraints_.size(); ++i) {
1351 const double dual_value =
1352 grb_dual_values.at(mp_cons_to_gurobi_linear_cons_.at(i));
1354 VLOG(4) <<
"row " << ct->
index() <<
", dual value = " << dual_value;
1367 if (!mip_)
return false;
1374 if (current_solution_index_ + 1 >= SolutionCount()) {
1377 current_solution_index_++;
1383 const std::vector<double> grb_variable_values =
1386 for (
int i = 0; i <
solver_->variables_.size(); ++i) {
1389 grb_variable_values.at(mp_var_to_gurobi_var_.at(i)));
1403 VLOG(1) <<
"Writing Gurobi model file \"" << filename <<
"\".";
1404 const int status =
GRBwrite(model_, filename.c_str());
1406 LOG(WARNING) <<
"Failed to write MIP." <<
GRBgeterrormsg(global_env_);
1411 callback_ = mp_callback;
1417const void*
const kRegisterGurobiLp ABSL_ATTRIBUTE_UNUSED = [] {
1426const void*
const kRegisterGurobiMip ABSL_ATTRIBUTE_UNUSED = [] {
absl::Duration GetDuration() const
bool IsMIP() const override
void Write(const std::string &filename) override
void ExtractObjective() override
bool InterruptSolve() override
bool SupportsCallbacks() const override
void * underlying_solver() override
void SetCoefficient(MPConstraint *constraint, const MPVariable *variable, double new_value, double old_value) override
GurobiInterface(MPSolver *solver, bool mip)
bool IsContinuous() const override
MPSolver::ResultStatus Solve(const MPSolverParameters ¶m) override
MPSolutionResponse DirectlySolveProto(LazyMutableCopy< MPModelRequest > request, std::atomic< bool > *interrupt) override
void SetVariableBounds(int var_index, double lb, double ub) override
void ClearConstraint(MPConstraint *constraint) override
void SetCallback(MPCallback *mp_callback) override
bool SupportsDirectlySolveProto(std::atomic< bool > *interrupt) const override
void ClearObjective() override
void SetObjectiveOffset(double value) override
int64_t nodes() const override
void ExtractNewConstraints() override
double ComputeExactConditionNumber() const override
void SetObjectiveCoefficient(const MPVariable *variable, double coefficient) override
void SetConstraintBounds(int row_index, double lb, double ub) override
MPSolver::BasisStatus column_status(int variable_index) const override
void SetVariableInteger(int var_index, bool integer) override
std::string SolverVersion() const override
void BranchingPriorityChangedForVariable(int var_index) override
void ExtractNewVariables() override
bool NextSolution() override
bool AddIndicatorConstraint(MPConstraint *ct) override
MPSolver::BasisStatus row_status(int constraint_index) const override
~GurobiInterface() override
int64_t iterations() const override
void SetOptimizationDirection(bool maximize) override
bool IsLP() const override
void AddVariable(MPVariable *var) override
void AddRowConstraint(MPConstraint *ct) override
void set_dual_value(double dual_value)
double lb() const
Returns the lower bound.
double ub() const
Returns the upper bound.
const MPVariable * indicator_variable() const
const std::string & name() const
Returns the name of the constraint.
int index() const
Returns the index of the constraint in the MPSolver::constraints_.
bool indicator_value() const
static MPSolverInterfaceFactoryRepository * GetInstance()
void Register(MPSolverInterfaceFactory factory, MPSolver::OptimizationProblemType problem_type, std::function< bool()> is_runtime_ready={})
void set_variable_as_extracted(int var_index, bool extracted)
bool CheckSolutionIsSynchronized() const
static constexpr int64_t kUnknownNumberOfIterations
friend class MPConstraint
void InvalidateSolutionSynchronization()
void set_constraint_as_extracted(int ct_index, bool extracted)
void ResetExtractionInformation()
virtual void SetIntegerParamToUnsupportedValue(MPSolverParameters::IntegerParam param, int value)
int last_constraint_index_
bool variable_is_extracted(int var_index) const
bool constraint_is_extracted(int ct_index) const
static constexpr int64_t kUnknownNumberOfNodes
double best_objective_bound_
void SetMIPParameters(const MPSolverParameters ¶m)
MPSolverInterface(MPSolver *solver)
void SetCommonParameters(const MPSolverParameters ¶m)
bool CheckSolutionIsSynchronizedAndExists() const
MPSolver::ResultStatus result_status_
SynchronizationStatus sync_status_
@ PRESOLVE_OFF
Presolve is off.
@ PRESOLVE_ON
Presolve is on.
@ BARRIER
Barrier algorithm.
@ INCREMENTALITY
Advanced usage: incrementality from one solve to the next.
@ PRESOLVE
Advanced usage: presolve mode.
@ LP_ALGORITHM
Algorithm to solve linear programs.
@ INCREMENTALITY_OFF
Start solve from scratch.
@ SCALING_ON
Scaling is on.
@ SCALING_OFF
Scaling is off.
int GetIntegerParam(MPSolverParameters::IntegerParam param) const
Returns the value of an integer parameter.
@ FEASIBLE
feasible, or stopped by limit.
@ NOT_SOLVED
not been solved yet.
@ INFEASIBLE
proven infeasible.
@ UNBOUNDED
proven unbounded.
@ GUROBI_MIXED_INTEGER_PROGRAMMING
@ GUROBI_LINEAR_PROGRAMMING
The class for variables of a Mathematical Programming (MP) model.
bool integer() const
Returns the integrality requirement of the variable.
double lb() const
Returns the lower bound.
double ub() const
Returns the upper bound.
const std::string & name() const
Returns the name of the variable.
int branching_priority() const
void set_reduced_cost(double reduced_cost)
void set_solution_value(double value)
int index() const
Returns the index of the variable in the MPSolver::variables_.
#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.")
dual_gradient T(y - `dual_solution`) class DiagonalTrustRegionProblemFromQp
std::function< int(GRBmodel *model, int numnz, int *cind, double *cval, char sense, double rhs, const char *constrname)> GRBaddconstr
std::function< void(GRBenv *env)> GRBfreeenv
std::function< int(GRBmodel *model, const char *attrname, double *valueP)> GRBgetdblattr
std::function< int(GRBmodel *model, const char *attrname, int first, int len, double *values)> GRBgetdblattrarray
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(GRBenv *dest, GRBenv *src)> GRBcopyparams
std::function< int(GRBmodel *model, int cnt, int *cind, int *vind, double *val)> GRBchgcoeffs
std::function< int(GRBenv *env, const char *paramname, double *valueP)> GRBgetdblparam
std::string GurobiParamInfoForLogging(GRBenv *grb, bool one_liner_output)
std::function< int(GRBmodel *model, const char *attrname, int newvalue)> GRBsetintattr
std::function< int(GRBmodel *model, const char *attrname, int element, int *valueP)> GRBgetintattrelement
Select next search node to expand Select next item_i to add this new search node to the search Generate a new search node where item_i is not in the knapsack Check validity of this new partial solution(using propagators) - If valid
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< int(GRBmodel *model, int numnz, int *vind, double *vval, double obj, double lb, double ub, char vtype, const char *varname)> GRBaddvar
std::function< int(GRBmodel *model)> GRBupdatemodel
std::function< void(int *majorP, int *minorP, int *technicalP)> GRBversion
std::function< GRBenv *(GRBmodel *model)> GRBgetenv
bool GurobiIsCorrectlyInstalled()
std::function< int(GRBmodel *model, const char *attrname, int element, double *valueP)> GRBgetdblattrelement
std::function< int(GRBmodel *model)> GRBfreemodel
std::function< int(void *cbdata, int where, int what, void *resultP)> GRBcbget
std::function< int(GRBenv *env, const char *paramname, int value)> GRBsetintparam
std::function< int(GRBmodel *model, int numnz, int *cind, double *cval, double lower, double upper, const char *constrname)> GRBaddrangeconstr
absl::StatusOr< MPSolutionResponse > GurobiSolveProto(LazyMutableCopy< MPModelRequest > request, GRBenv *gurobi_env)
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 element, char newvalue)> GRBsetcharattrelement
std::function< int(GRBmodel *model, const char *attrname, int element, int newvalue)> GRBsetintattrelement
std::function< int(GRBenv *env)> GRBresetparams
std::function< int(GRBmodel *model)> GRBoptimize
std::function< int(GRBmodel *model, const char *attrname, int *valueP)> GRBgetintattr
std::function< const char *(GRBenv *env)> GRBgeterrormsg
absl::StatusOr< GRBenv * > GetGurobiEnv()
std::function< int(GRBmodel *model, const char *filename)> GRBwrite
MPSolutionResponse ConvertStatusOrMPSolutionResponse(bool log_error, absl::StatusOr< MPSolutionResponse > response)
absl::string_view ToString(MPSolver::OptimizationProblemType optimization_problem_type)
absl::Status SetSolverSpecificParameters(absl::string_view parameters, GRBenv *gurobi)
std::function< int(GRBmodel *model, const char *attrname, int element, char *valueP)> GRBgetcharattrelement
std::function< int(void *cbdata, const double *solution, double *objvalP)> GRBcbsolution
std::function< void(GRBmodel *model)> GRBterminate
std::function< int(GRBenv *env, const char *paramname, double value)> GRBsetdblparam
std::function< int(GRBmodel *model, const char *attrname, int element, double newvalue)> GRBsetdblattrelement