20#include "absl/status/status.h"
21#include "absl/status/statusor.h"
22#include "absl/strings/str_format.h"
31constexpr int kGrbOk = 0;
33struct UserCallbackData {
35 absl::Status
status = absl::OkStatus();
40 void*
const usrdata) {
41 CHECK(usrdata !=
nullptr);
43 auto user_cb_data =
static_cast<UserCallbackData*
>(usrdata);
46 if (!user_cb_data->status.ok()) {
49 const Gurobi::CallbackContext
context(user_cb_data->gurobi, cbdata,
where);
50 user_cb_data->status = user_cb_data->user_cb(
context);
51 if (!user_cb_data->status.ok()) {
52 user_cb_data->gurobi->Terminate();
67 const std::optional<GurobiIsvKey>& isv_key) {
68 GRBenv* naked_master_env =
nullptr;
70 std::string_view init_env_method;
71 if (isv_key.has_value()) {
72 err =
GRBisqp(&naked_master_env,
73 nullptr, isv_key->name.c_str(),
74 isv_key->application_name.c_str(), isv_key->expiration,
75 isv_key->key.c_str());
76 init_env_method =
"GRBisqp()";
79 init_env_method =
"GRBloadenv()";
90 <<
"failed to create Gurobi master environment, " << init_env_method
91 <<
" returned the error (" << err
98 GRBenv*
const master_env) {
99 CHECK(master_env !=
nullptr);
100 return New(
nullptr, master_env);
105 if (master_env ==
nullptr) {
108 GRBenv*
const raw_master_env = master_env.get();
109 return New(std::move(master_env), raw_master_env);
114 : owned_master_env_(
std::move(optional_owned_master_env)),
118absl::StatusOr<std::unique_ptr<Gurobi>>
Gurobi::New(
120 CHECK(master_env !=
nullptr);
130 <<
"Error creating gurobi model on GRBnewmodel(), error code: "
137 int gurobi_major, gurobi_minor, gurobi_technical;
138 GRBversion(&gurobi_major, &gurobi_minor, &gurobi_technical);
139 VLOG(3) << absl::StrFormat(
140 "Successfully created model for Gurobi v%d.%d.%d (%s)", gurobi_major,
143 return absl::WrapUnique(
144 new Gurobi(std::move(optional_owned_master_env),
model, model_env));
150 LOG(
ERROR) <<
"Error freeing gurobi model, code: " << err
155absl::Status Gurobi::ToStatus(
const int grb_err,
const absl::StatusCode code,
157 if (grb_err == kGrbOk) {
158 return absl::OkStatus();
162 <<
"Gurobi error code: " << grb_err
167 const absl::Span<const double> lb,
168 const absl::Span<const double> ub,
169 const absl::Span<const char> vtype,
170 const absl::Span<const std::string> names) {
171 return AddVars({}, {}, {}, obj, lb, ub, vtype, names);
175 const absl::Span<const int> vind,
176 const absl::Span<const double> vval,
177 const absl::Span<const double> obj,
178 const absl::Span<const double> lb,
179 const absl::Span<const double> ub,
180 const absl::Span<const char> vtype,
181 const absl::Span<const std::string> names) {
183 const int num_vars = lb.size();
186 double* c_obj =
nullptr;
189 c_obj =
const_cast<double*
>(obj.data());
191 if (!vbegin.empty()) {
194 char** c_names =
nullptr;
195 std::vector<char*> c_names_data;
196 if (!names.empty()) {
198 for (
const std::string&
name : names) {
199 c_names_data.push_back(
const_cast<char*
>(
name.c_str()));
201 c_names = c_names_data.data();
203 return ToStatus(
GRBaddvars(gurobi_model_, num_vars,
205 const_cast<int*
>(vbegin.data()),
206 const_cast<int*
>(vind.data()),
207 const_cast<double*
>(vval.data()),
209 const_cast<double*
>(lb.data()),
210 const_cast<double*
>(ub.data()),
211 const_cast<char*
>(vtype.data()),
217 GRBdelvars(gurobi_model_, ind.size(),
const_cast<int*
>(ind.data())));
221 const absl::Span<const double> rhs,
222 const absl::Span<const std::string> names) {
223 const int num_cons = sense.size();
225 char** c_names =
nullptr;
226 std::vector<char*> c_names_data;
227 if (!names.empty()) {
229 for (
const std::string&
name : names) {
230 c_names_data.push_back(
const_cast<char*
>(
name.c_str()));
232 c_names = c_names_data.data();
238 nullptr,
const_cast<char*
>(sense.data()),
239 const_cast<double*
>(rhs.data()), c_names));
244 GRBdelconstrs(gurobi_model_, ind.size(),
const_cast<int*
>(ind.data())));
248 const absl::Span<const int> qcol,
249 const absl::Span<const double> qval) {
250 const int numqnz = qrow.size();
254 gurobi_model_, numqnz,
const_cast<int*
>(qcol.data()),
255 const_cast<int*
>(qrow.data()),
const_cast<double*
>(qval.data())));
261 const absl::Span<const int> vind,
262 const absl::Span<const double> val) {
263 const int num_changes = cind.size();
267 gurobi_model_, num_changes,
const_cast<int*
>(cind.data()),
268 const_cast<int*
>(vind.data()),
const_cast<double*
>(val.data())));
274 nullptr, first_var, num_vars)));
279 const absl::Span<int> vind,
280 const absl::Span<double> vval,
const int first_var,
281 const int num_vars) {
286 ToStatus(
GRBgetvars(gurobi_model_, &nnz, vbegin.data(), vind.data(),
287 vval.data(), first_var, num_vars)));
289 return absl::OkStatus();
293 const int num_vars) {
296 result.
begins.resize(num_vars);
297 result.
inds.resize(nnz);
298 result.
vals.resize(nnz);
302 result.
inds.data(), result.
vals.data(), first_var, num_vars)));
312 bool needs_cb_cleanup =
false;
313 UserCallbackData user_cb_data;
315 user_cb_data.user_cb = std::move(cb);
316 user_cb_data.gurobi =
this;
319 needs_cb_cleanup =
true;
325 if (needs_cb_cleanup) {
327 if (error != kGrbOk) {
328 LOG(
ERROR) <<
"Error cleaning up callback";
332 absl::Status solve_status = ToStatus(
GRBoptimize(gurobi_model_));
335 if (needs_cb_cleanup) {
336 needs_cb_cleanup =
false;
340 return absl::OkStatus();
350 <<
"Error getting Gurobi int attribute: " <<
name;
357 <<
"Error getting Gurobi double attribute: " <<
name;
362 const char*
const name)
const {
365 char* result =
nullptr;
367 <<
"Error getting Gurobi string attribute: " <<
name;
368 if (result ==
nullptr) {
369 return std::string();
371 return std::string(result);
375 const std::string&
value) {
384 const double value) {
389 const absl::Span<const int> new_values) {
391 const_cast<int*
>(new_values.data())));
395 const char*
const name,
const absl::Span<const double> new_values) {
397 const_cast<double*
>(new_values.data())));
401 const absl::Span<const char> new_values) {
403 const_cast<char*
>(new_values.data())));
407 const absl::Span<int> attr_out)
const {
409 gurobi_model_,
name, 0, attr_out.size(), attr_out.data())))
410 <<
"Error getting Gurobi int array attribute: " <<
name;
411 return absl::OkStatus();
415 const int len)
const {
416 std::vector<int> result(len);
422 const char*
const name,
const absl::Span<double> attr_out)
const {
424 gurobi_model_,
name, 0, attr_out.size(), attr_out.data())))
425 <<
"Error getting Gurobi double array attribute: " <<
name;
426 return absl::OkStatus();
430 const char*
const name,
const int len)
const {
431 std::vector<double> result(len);
437 const absl::Span<char> attr_out)
const {
439 gurobi_model_,
name, 0, attr_out.size(), attr_out.data())))
440 <<
"Error getting Gurobi char array attribute: " <<
name;
441 return absl::OkStatus();
445 const char*
const name,
const int len)
const {
446 std::vector<char> result(len);
452 const absl::Span<const int> ind,
453 const absl::Span<const int> new_values) {
454 const int len = ind.size();
457 const_cast<int*
>(ind.data()),
458 const_cast<int*
>(new_values.data())));
462 const char*
const name,
const absl::Span<const int> ind,
463 const absl::Span<const double> new_values) {
464 const int len = ind.size();
467 const_cast<int*
>(ind.data()),
468 const_cast<double*
>(new_values.data())));
472 const absl::Span<const int> ind,
473 const absl::Span<const char> new_values) {
474 const int len = ind.size();
477 const_cast<int*
>(ind.data()),
478 const_cast<char*
>(new_values.data())));
482 const std::string&
value) {
491 const double value) {
496 const std::string&
value) {
515 return std::string(result.data());
525 void*
const cb_data,
const int where)
531 GRBcbget(cb_data_, where_, what,
static_cast<void*
>(&result))));
536 const int what)
const {
539 GRBcbget(cb_data_, where_, what,
static_cast<void*
>(&result))));
544 const int what,
const absl::Span<double> result)
const {
545 return gurobi_->ToStatus(
546 GRBcbget(cb_data_, where_, what,
static_cast<void*
>(result.data())));
550 char* result =
nullptr;
553 if (result ==
nullptr) {
554 return std::string();
556 return std::string(result);
560 const absl::Span<const int> cutind,
const absl::Span<const double> cutval,
561 const char cutsense,
const double cutrhs)
const {
562 const int cut_len = cutind.size();
564 return gurobi_->ToStatus(
565 GRBcbcut(cb_data_, cut_len,
const_cast<int*
>(cutind.data()),
566 const_cast<double*
>(cutval.data()), cutsense, cutrhs));
570 const absl::Span<const int> lazyind,
const absl::Span<const double> lazyval,
571 const char lazysense,
const double lazyrhs)
const {
572 const int lazy_len = lazyind.size();
574 return gurobi_->ToStatus(
575 GRBcblazy(cb_data_, lazy_len,
const_cast<int*
>(lazyind.data()),
576 const_cast<double*
>(lazyval.data()), lazysense, lazyrhs));
580 const absl::Span<const double> solution)
const {
583 GRBcbsolution(cb_data_,
const_cast<double*
>(solution.data()), &result)));
#define CHECK_EQ(val1, val2)
#define VLOG(verboselevel)
#define ASSIGN_OR_RETURN(lhs, rexpr)
#define RETURN_IF_ERROR(expr)
absl::StatusOr< double > CbGetDouble(int what) const
absl::StatusOr< double > CbSolution(absl::Span< const double > solution) const
CallbackContext(Gurobi *gurobi, void *cb_data, int where)
absl::Status CbGetDoubleArray(int what, absl::Span< double > result) const
absl::Status CbCut(absl::Span< const int > cutind, absl::Span< const double > cutval, char cutsense, double cutrhs) const
absl::StatusOr< std::string > CbGetMessage() const
absl::StatusOr< int > CbGetInt(int what) const
absl::Status CbLazy(absl::Span< const int > lazyind, absl::Span< const double > lazyval, char lazysense, double lazyrhs) const
absl::Status GetVars(absl::Span< int > vbegin, absl::Span< int > vind, absl::Span< double > vval, int first_var, int num_vars)
absl::Status GetIntAttrArray(const char *name, absl::Span< int > attr_out) const
static absl::StatusOr< std::unique_ptr< Gurobi > > New(GRBenvUniquePtr master_env=nullptr)
absl::Status AddConstrs(absl::Span< const char > sense, absl::Span< const double > rhs, absl::Span< const std::string > names)
absl::StatusOr< double > GetDoubleParam(const char *name)
absl::Status Optimize(Callback cb=nullptr)
absl::Status ChgCoeffs(absl::Span< const int > cind, absl::Span< const int > vind, absl::Span< const double > val)
absl::StatusOr< int > GetIntParam(const char *name)
absl::Status SetDoubleAttr(const char *attr_name, double value)
absl::Status AddQpTerms(absl::Span< const int > qrow, absl::Span< const int > qcol, absl::Span< const double > qval)
absl::StatusOr< int > GetNnz(int first_var, int num_vars)
absl::Status SetDoubleParam(const char *name, double value)
std::function< absl::Status(const CallbackContext &)> Callback
absl::Status UpdateModel()
static absl::StatusOr< std::unique_ptr< Gurobi > > NewWithSharedMasterEnv(GRBenv *master_env)
absl::Status SetIntAttr(const char *attr_name, int value)
absl::StatusOr< std::string > GetStringParam(const char *name)
absl::Status GetCharAttrArray(const char *name, absl::Span< char > attr_out) const
absl::Status SetCharAttrArray(const char *name, absl::Span< const char > new_values)
absl::StatusOr< int > GetIntAttr(const char *name) const
absl::Status DelVars(absl::Span< const int > ind)
absl::StatusOr< std::string > GetStringAttr(const char *name) const
absl::Status SetIntAttrList(const char *name, absl::Span< const int > ind, absl::Span< const int > new_values)
absl::Status GetDoubleAttrArray(const char *name, absl::Span< double > attr_out) const
absl::Status SetDoubleAttrArray(const char *name, absl::Span< const double > new_values)
absl::Status SetParam(const char *name, const std::string &value)
bool IsAttrAvailable(const char *name) const
absl::Status SetDoubleAttrList(const char *name, absl::Span< const int > ind, absl::Span< const double > new_values)
absl::StatusOr< double > GetDoubleAttr(const char *name) const
absl::Status ResetParameters()
absl::Status SetIntParam(const char *name, int value)
absl::Status SetIntAttrArray(const char *name, absl::Span< const int > new_values)
absl::Status SetStringParam(const char *name, const std::string &value)
absl::Status DelConstrs(absl::Span< const int > ind)
absl::Status SetStringAttr(const char *attr_name, const std::string &value)
absl::Status AddVars(absl::Span< const double > obj, absl::Span< const double > lb, absl::Span< const double > ub, absl::Span< const char > vtype, absl::Span< const std::string > names)
absl::Status SetCharAttrList(const char *name, absl::Span< const int > ind, absl::Span< const char > new_values)
#define GRB_ERROR_CALLBACK
#define GRB_CB_MSG_STRING
struct _GRBmodel GRBmodel
GurobiMPCallbackContext * context
absl::Cleanup< absl::decay_t< Callback > > MakeCleanup(Callback &&callback)
absl::StatusOr< GRBenvUniquePtr > GurobiNewMasterEnv(const std::optional< GurobiIsvKey > &isv_key)
std::unique_ptr< GRBenv, GurobiFreeEnv > GRBenvUniquePtr
std::function< int(GRBenv *env, const char *paramname, int *valueP)> GRBgetintparam
std::function< int(GRBmodel *model, const char *attrname, double *valueP)> GRBgetdblattr
std::function< int(GRBmodel *model, const char *attrname, int len, int *ind, double *newvalues)> GRBsetdblattrlist
std::function< char *(void)> GRBplatform
std::function< void(int *majorP, int *minorP, int *technicalP)> GRBversion
std::function< int(GRBenv *env, const char *paramname, const char *value)> GRBsetparam
std::function< int(GRBmodel *model, const char *attrname, int newvalue)> GRBsetintattr
std::function< int(GRBenv *env, const char *paramname, char *valueP)> GRBgetstrparam
std::function< int(void *cbdata, int lazylen, const int *lazyind, const double *lazyval, char lazysense, double lazyrhs)> GRBcblazy
std::function< int(GRBmodel *model, const char *attrname, int first, int len, int *values)> GRBgetintattrarray
std::function< int(GRBmodel *model, int numconstrs, int numnz, int *cbeg, int *cind, double *cval, char *sense, double *rhs, char **constrnames)> GRBaddconstrs
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 first, int len, char *values)> GRBgetcharattrarray
std::function< int(GRBenv **envP, const char *logfilename)> GRBloadenv
std::function< int(GRBmodel *model, const char *attrname, int first, int len, double *newvalues)> GRBsetdblattrarray
std::function< int(GRBmodel *model)> GRBfreemodel
std::function< void(GRBmodel *model)> GRBterminate
std::function< int(GRBmodel *model, int numqnz, int *qrow, int *qcol, double *qval)> GRBaddqpterms
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
std::function< GRBenv *(GRBmodel *model)> GRBgetenv
std::function< int(GRBmodel *model, int len, int *ind)> GRBdelconstrs
std::function< int(GRBenv *env, const char *paramname, const char *value)> GRBsetstrparam
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)> GRBdelq
std::function< int(GRBmodel *model, const char *attrname, const char *newvalue)> GRBsetstrattr
std::function< int(void *cbdata, const double *solution, double *objvalP)> GRBcbsolution
std::function< int(GRBmodel *model, const char *attrname)> GRBisattravailable
std::function< int(GRBmodel *model)> GRBoptimize
std::function< int(GRBenv **, const char *, const char *, const char *, int, const char *)> GRBisqp
std::function< int(GRBmodel *model, int len, int *ind)> GRBdelvars
std::function< int(GRBmodel *model, const char *attrname, int len, int *ind, char *newvalues)> GRBsetcharattrlist
std::function< int(GRBmodel *model, const char *attrname, char **valueP)> GRBgetstrattr
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(GRBmodel *model, const char *attrname, int len, int *ind, int *newvalues)> GRBsetintattrlist
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, const char *attrname, int first, int len, int *newvalues)> GRBsetintattrarray
std::function< int(GRBmodel *model, int(GUROBI_STDCALL *cb)(CB_ARGS), void *usrdata)> GRBsetcallbackfunc
std::function< int(GRBmodel *model, int *numnzP, int *vbeg, int *vind, double *vval, int start, int len)> GRBgetvars
std::function< int(GRBmodel *model, int numvars, int numnz, int *vbeg, int *vind, double *vval, double *obj, double *lb, double *ub, char *vtype, char **varnames)> GRBaddvars
std::function< int(GRBmodel *model, const char *attrname, int first, int len, char *newvalues)> GRBsetcharattrarray
std::function< int(GRBmodel *model, const char *attrname, int *valueP)> GRBgetintattr
std::function< int(GRBenv *env, const char *paramname, double value)> GRBsetdblparam
StatusBuilder InvalidArgumentErrorBuilder()
std::vector< double > vals
std::vector< int > begins
void operator()(GRBenv *const env) const
#define VLOG_IS_ON(verboselevel)