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;
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(
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;
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;
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);
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 {
305class GurobiMPCallbackContext :
public MPCallbackContext {
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)
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 {
548 void* raw_model_and_callback) {
549 MPCallbackWithGurobiContext*
const callback_with_context =
550 static_cast<MPCallbackWithGurobiContext*
>(raw_model_and_callback);
551 CHECK(callback_with_context !=
nullptr);
552 CHECK(callback_with_context->context !=
nullptr);
553 CHECK(callback_with_context->callback !=
nullptr);
554 GurobiInternalCallbackContext gurobi_internal_context{
556 callback_with_context->context->UpdateFromGurobiState(
557 gurobi_internal_context);
558 callback_with_context->callback->RunCallback(callback_with_context->context);
564void GurobiInterface::CheckedGurobiCall(
int err)
const {
565 ::operations_research::CheckedGurobiCall(err, global_env_);
568void GurobiInterface::SetIntAttr(
const char*
name,
int value) {
572int GurobiInterface::GetIntAttr(
const char*
name)
const {
578void GurobiInterface::SetDoubleAttr(
const char*
name,
double value) {
582double GurobiInterface::GetDoubleAttr(
const char*
name)
const {
588void GurobiInterface::SetIntAttrElement(
const char*
name,
int index,
593int GurobiInterface::GetIntAttrElement(
const char*
name,
int index)
const {
599void GurobiInterface::SetDoubleAttrElement(
const char*
name,
int index,
603double GurobiInterface::GetDoubleAttrElement(
const char*
name,
610std::vector<double> GurobiInterface::GetDoubleAttrArray(
const char*
name,
612 std::vector<double> results(elements);
618void GurobiInterface::SetCharAttrElement(
const char*
name,
int index,
622char GurobiInterface::GetCharAttrElement(
const char*
name,
int index)
const {
629GurobiInterface::GurobiInterface(
MPSolver*
const solver,
bool mip)
632 global_env_(nullptr),
634 current_solution_index_(0) {
647 absl::GetFlag(FLAGS_num_gurobi_threads)));
659 const absl::MutexLock lock(&hold_interruptions_mutex_);
687 mp_var_to_gurobi_var_.clear();
688 mp_cons_to_gurobi_linear_cons_.clear();
689 num_gurobi_vars_ = 0;
690 num_gurobi_linear_cons_ = 0;
691 had_nonincremental_change_ =
false;
730 had_nonincremental_change_ =
true;
747 had_nonincremental_change_ =
true;
758 double new_value,
double old_value) {
763 int grb_var = mp_var_to_gurobi_var_.at(variable->
index());
764 int grb_cons = mp_cons_to_gurobi_linear_cons_.at(constraint->
index());
766 had_nonincremental_change_ =
true;
771 GRBchgcoeffs(model_, 1, &grb_cons, &grb_var, &new_value));
779 had_nonincremental_change_ =
true;
791 mp_var_to_gurobi_var_.at(variable->
index()),
800 if (!had_nonincremental_change_) {
809 if (!had_nonincremental_change_) {
811 for (
const auto& entry :
solver_->objective_->coefficients_) {
820 update_branching_priorities_ =
true;
829 return static_cast<int64_t
>(iter);
837 LOG(DFATAL) <<
"Number of nodes only available for discrete problems.";
843 int gurobi_basis_status)
const {
844 switch (gurobi_basis_status) {
854 LOG(DFATAL) <<
"Unknown GRB basis status.";
863 LOG(DFATAL) <<
"Basis status not available for nonlinear constraints.";
866 switch (gurobi_basis_status) {
871 double tolerance = 0.0;
877 <<
" , sense = " << sense;
878 if (fabs(slack) <= tolerance) {
899 LOG(DFATAL) <<
"Basis status only available after a solution has "
904 LOG(DFATAL) <<
"Basis status only available for continuous problems.";
909 LOG(DFATAL) <<
"Basis status not available for nonlinear constraints.";
912 const int gurobi_basis_status =
914 return TransformGRBConstraintBasisStatus(gurobi_basis_status,
922 LOG(DFATAL) <<
"Basis status only available after a solution has "
927 LOG(DFATAL) <<
"Basis status only available for continuous problems.";
930 const int grb_index = mp_var_to_gurobi_var_.at(variable_index);
931 const int gurobi_basis_status =
933 return TransformGRBVarBasisStatus(gurobi_basis_status);
938 const int total_num_vars =
solver_->variables_.size();
950 var->name().empty() ?
nullptr :
var->name().c_str()));
951 mp_var_to_gurobi_var_.push_back(num_gurobi_vars_++);
955 std::vector<int> grb_cons_ind;
956 std::vector<int> grb_var_ind;
957 std::vector<double>
coef;
964 const int grb_ct_idx = mp_cons_to_gurobi_linear_cons_.at(
ct->index());
965 DCHECK_GE(grb_ct_idx, 0);
966 DCHECK(
ct->indicator_variable() ==
nullptr);
967 for (
const auto& entry :
ct->coefficients_) {
968 const int var_index = entry.first->index();
972 grb_cons_ind.push_back(grb_ct_idx);
973 grb_var_ind.push_back(mp_var_to_gurobi_var_.at(
var_index));
974 coef.push_back(entry.second);
978 if (!grb_cons_ind.empty()) {
979 CheckedGurobiCall(
GRBchgcoeffs(model_, grb_cons_ind.size(),
980 grb_cons_ind.data(), grb_var_ind.data(),
989 int total_num_rows =
solver_->constraints_.size();
995 const int size =
ct->coefficients_.size();
996 std::vector<int> grb_vars;
997 std::vector<double> coefs;
998 grb_vars.reserve(
size);
1000 for (
const auto& entry :
ct->coefficients_) {
1001 const int var_index = entry.first->index();
1003 grb_vars.push_back(mp_var_to_gurobi_var_.at(
var_index));
1004 coefs.push_back(entry.second);
1007 ct->name().empty() ? nullptr :
const_cast<char*
>(
ct->name().c_str());
1008 if (
ct->indicator_variable() !=
nullptr) {
1009 const int grb_ind_var =
1010 mp_var_to_gurobi_var_.at(
ct->indicator_variable()->index());
1011 if (
ct->lb() > -std::numeric_limits<double>::infinity()) {
1013 model_,
name, grb_ind_var,
ct->indicator_value(),
size,
1014 grb_vars.data(), coefs.data(),
1017 if (
ct->ub() < std::numeric_limits<double>::infinity() &&
1018 ct->lb() !=
ct->ub()) {
1020 model_,
name, grb_ind_var,
ct->indicator_value(),
size,
1023 mp_cons_to_gurobi_linear_cons_.push_back(-1);
1027 if (
ct->lb() ==
ct->ub()) {
1031 }
else if (
ct->lb() == -std::numeric_limits<double>::infinity()) {
1035 }
else if (
ct->ub() == std::numeric_limits<double>::infinity()) {
1041 coefs.data(),
ct->lb(),
ct->ub(),
1047 mp_cons_to_gurobi_linear_cons_.push_back(num_gurobi_linear_cons_++);
1069bool GurobiInterface::SetSolverSpecificParametersAsString(
1074void GurobiInterface::SetRelativeMipGap(
double value) {
1079 LOG(WARNING) <<
"The relative MIP gap is only available "
1080 <<
"for discrete problems.";
1090void GurobiInterface::SetPrimalTolerance(
double value) {
1101void GurobiInterface::SetDualTolerance(
double value) {
1106void GurobiInterface::SetPresolveMode(
int value) {
1125void GurobiInterface::SetScalingMode(
int value) {
1145void GurobiInterface::SetLpAlgorithm(
int value) {
1165int GurobiInterface::SolutionCount()
const {
1169bool GurobiInterface::ModelIsNonincremental()
const {
1171 if (
c->indicator_variable() !=
nullptr) {
1184 ModelIsNonincremental() || had_nonincremental_change_) {
1195 VLOG(1) << absl::StrFormat(
"Model built in %s.",
1199 for (
const std::pair<const MPVariable*, double>& p :
1202 mp_var_to_gurobi_var_.at(p.first->index()), p.second);
1206 if (update_branching_priorities_) {
1209 mp_var_to_gurobi_var_.at(
var->index()),
1210 var->branching_priority());
1212 update_branching_priorities_ =
false;
1227 SetParameters(param);
1229 solver_->solver_specific_parameter_string_);
1231 std::unique_ptr<GurobiMPCallbackContext> gurobi_context;
1232 MPCallbackWithGurobiContext mp_callback_with_context;
1233 int gurobi_precrush = 0;
1234 int gurobi_lazy_constraint = 0;
1235 if (callback_ ==
nullptr) {
1238 gurobi_context = std::make_unique<GurobiMPCallbackContext>(
1239 global_env_, &mp_var_to_gurobi_var_, num_gurobi_vars_,
1241 mp_callback_with_context.context = gurobi_context.get();
1242 mp_callback_with_context.callback = callback_;
1244 model_, CallbackImpl,
static_cast<void*
>(&mp_callback_with_context)));
1264 VLOG(1) <<
"Failed to optimize MIP." <<
GRBgeterrormsg(global_env_);
1266 VLOG(1) << absl::StrFormat(
"Solved in %s.",
1272 VLOG(1) << absl::StrFormat(
"Solution status %d.\n", optimization_status);
1273 const int solution_count = SolutionCount();
1275 switch (optimization_status) {
1291 if (solution_count > 0) {
1304 LOG_IF(WARNING, error != 0)
1305 <<
"Best objective bound is not available, error=" << error
1312 current_solution_index_ = 0;
1318 const std::vector<double> grb_variable_values =
1320 for (
int i = 0; i <
solver_->variables_.size(); ++i) {
1322 const double val = grb_variable_values.at(mp_var_to_gurobi_var_.at(i));
1323 var->set_solution_value(val);
1324 VLOG(3) <<
var->name() <<
", value = " << val;
1329 const std::vector<double> grb_reduced_costs =
1331 for (
int i = 0; i <
solver_->variables_.size(); ++i) {
1333 const double rc = grb_reduced_costs.at(mp_var_to_gurobi_var_.at(i));
1334 var->set_reduced_cost(rc);
1335 VLOG(4) <<
var->name() <<
", reduced cost = " << rc;
1340 std::vector<double> grb_dual_values =
1342 for (
int i = 0; i <
solver_->constraints_.size(); ++i) {
1344 const double dual_value =
1345 grb_dual_values.at(mp_cons_to_gurobi_linear_cons_.at(i));
1346 ct->set_dual_value(dual_value);
1347 VLOG(4) <<
"row " <<
ct->index() <<
", dual value = " << dual_value;
1360 if (!mip_)
return false;
1367 if (current_solution_index_ + 1 >= SolutionCount()) {
1370 current_solution_index_++;
1376 const std::vector<double> grb_variable_values =
1379 for (
int i = 0; i <
solver_->variables_.size(); ++i) {
1381 var->set_solution_value(
1382 grb_variable_values.at(mp_var_to_gurobi_var_.at(i)));
1396 VLOG(1) <<
"Writing Gurobi model file \"" << filename <<
"\".";
1399 LOG(WARNING) <<
"Failed to write MIP." <<
GRBgeterrormsg(global_env_);
1408 callback_ = mp_callback;
absl::Duration GetDuration() const
void Start()
When Start() is called multiple times, only the most recent is used.
bool IsMIP() const override
Returns true if the problem is discrete and linear.
void Write(const std::string &filename) override
Writes the model.
void ExtractObjective() override
Extracts the objective.
bool InterruptSolve() override
bool SupportsCallbacks() const override
void * underlying_solver() override
Returns the underlying solver.
void SetCoefficient(MPConstraint *constraint, const MPVariable *variable, double new_value, double old_value) override
Changes a coefficient in a constraint.
GurobiInterface(MPSolver *solver, bool mip)
Constructor that takes a name for the underlying GRB solver.
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
Modifies bounds.
void ClearConstraint(MPConstraint *constraint) override
Clears a constraint from all its terms.
void SetCallback(MPCallback *mp_callback) override
See MPSolver::SetCallback() for details.
bool SupportsDirectlySolveProto(std::atomic< bool > *interrupt) const override
--— Directly solve proto is supported without interrupt —
void ClearObjective() override
Clears the objective from all its terms.
void SetObjectiveOffset(double value) override
Changes the constant term in the linear objective.
int64_t nodes() const override
Number of branch-and-bound nodes. Only available for discrete problems.
void ExtractNewConstraints() override
Extracts the constraints that have not been extracted yet.
void Reset() override
---— Model modifications and extraction --—
double ComputeExactConditionNumber() const override
void SetObjectiveCoefficient(const MPVariable *variable, double coefficient) override
Changes a coefficient in the linear objective.
void SetConstraintBounds(int row_index, double lb, double ub) override
Modify bounds of an extracted variable.
MPSolver::BasisStatus column_status(int variable_index) const override
Returns the basis status of a column.
void SetVariableInteger(int var_index, bool integer) override
Modifies integrality of an extracted variable.
std::string SolverVersion() const override
Returns a string describing the underlying solver and its version.
void BranchingPriorityChangedForVariable(int var_index) override
void ExtractNewVariables() override
Extracts new variables.
bool NextSolution() override
Iterates through the solutions in Gurobi's solution pool.
bool AddIndicatorConstraint(MPConstraint *ct) override
MPSolver::BasisStatus row_status(int constraint_index) const override
Returns the basis status of a row.
~GurobiInterface() override
int64_t iterations() const override
---— Query statistics on the solution and the solve ---—
void SetOptimizationDirection(bool maximize) override
Sets the optimization direction (min/max).
bool IsLP() const override
Returns true if the problem is continuous and linear.
void AddVariable(MPVariable *var) override
Adds variable incrementally.
void AddRowConstraint(MPConstraint *ct) override
Adds Constraint incrementally.
bool might_add_lazy_constraints() const
bool might_add_cuts() const
int index() const
Returns the index of the constraint in the MPSolver::constraints_.
double offset() const
Gets the constant term in the objective.
void set_variable_as_extracted(int var_index, bool extracted)
bool CheckSolutionIsSynchronized() const
static constexpr int64_t kUnknownNumberOfIterations
friend class MPConstraint
To access the maximize_ bool and the MPSolver.
void InvalidateSolutionSynchronization()
void set_constraint_as_extracted(int ct_index, bool extracted)
void ResetExtractionInformation()
Resets the extraction information.
int last_variable_index_
Index in MPSolver::constraints_ of last variable extracted.
virtual void SetIntegerParamToUnsupportedValue(MPSolverParameters::IntegerParam param, int value)
Sets a supported integer parameter to an unsupported value.
int last_constraint_index_
Index in MPSolver::variables_ of last constraint extracted.
bool variable_is_extracted(int var_index) const
bool quiet() const
Returns the boolean indicating the verbosity of the solver output.
bool constraint_is_extracted(int ct_index) const
static constexpr int64_t kUnknownNumberOfNodes
void ExtractModel()
Extracts model stored in MPSolver.
double objective_value_
The value of the objective function.
double best_objective_bound_
The value of the best objective bound. Used only for MIP solvers.
bool maximize_
Optimization direction.
void SetMIPParameters(const MPSolverParameters ¶m)
Sets MIP specific parameters in the underlying solver.
bool quiet_
Boolean indicator for the verbosity of the solver output.
void SetCommonParameters(const MPSolverParameters ¶m)
Sets parameters common to LP and MIP in the underlying solver.
bool CheckSolutionIsSynchronizedAndExists() const
Handy shortcut to do both checks above (it is often used).
MPSolver::ResultStatus result_status_
SynchronizationStatus sync_status_
Indicates whether the model and the solution are synchronized.
@ 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.
int64_t time_limit() const
double time_limit_in_secs() const
@ FEASIBLE
feasible, or stopped by limit.
@ NOT_SOLVED
not been solved yet.
@ INFEASIBLE
proven infeasible.
@ UNBOUNDED
proven unbounded.
const MPObjective & Objective() const
bool SetSolverSpecificParametersAsString(const std::string ¶meters)
const std::vector< MPConstraint * > & constraints() const
The class for variables of a Mathematical Programming (MP) model.
int index() const
Returns the index of the variable in the MPSolver::variables_.
const std::string name
A name for logging purposes.
#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
In SWIG mode, we don't want anything besides these top-level includes.
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
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
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
MPSolverInterface * BuildGurobiInterface(bool mip, MPSolver *const solver)
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