1 2 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 3 4 /* 5 * Main authors: 6 * Gleb Belov <gleb.belov@monash.edu> 7 */ 8 9 /* This Source Code Form is subject to the terms of the Mozilla Public 10 * License, v. 2.0. If a copy of the MPL was not distributed with this 11 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 12 13 #pragma once 14 15 #include <minizinc/solver_config.hh> 16 #include <minizinc/solver_instance_base.hh> 17 #include <minizinc/solvers/MIP/MIP_wrap.hh> 18 19 extern "C" { 20 #include <gurobi_c.h> // need GUROBI_HOME defined 21 } 22 23 class MIPGurobiWrapper : public MIPWrapper { 24 GRBenv* _env = nullptr; 25 GRBmodel* _model = nullptr; 26 #ifdef GUROBI_PLUGIN 27 void* _gurobiDll; 28 #endif 29 int _error; 30 std::string _gurobiBuffer; // [GRB_MESSAGEBUFSIZE]; 31 std::string _gurobiStatusBuffer; // [GRB_MESSAGEBUFSIZE]; 32 33 std::vector<double> _x; 34 35 public: 36 class FactoryOptions { 37 public: 38 bool processOption(int& i, std::vector<std::string>& argv, 39 const std::string& workingDir = std::string()); 40 41 std::string gurobiDll; 42 }; 43 44 class Options : public MiniZinc::SolverInstanceBase::Options { 45 public: 46 int nMIPFocus = 0; 47 int nFreeSearch = 1; 48 int nThreads = 1; 49 std::string sExportModel; 50 int nTimeout1000 = -1; 51 int nTimeoutFeas1000 = -1; 52 int nSolLimit = -1; 53 int nSeed = -1; 54 double nWorkMemLimit = 0.5; 55 std::string sNodefileDir; 56 std::string sReadParams; 57 std::string sWriteParams; 58 std::vector<std::string> sConcurrentParamFiles; 59 bool flagIntermediate = false; 60 61 double absGap = -1; 62 double relGap = 1e-8; 63 double feasTol = 1e-8; 64 double intTol = 1e-8; 65 double objDiff = 1.0; 66 int nonConvex = 2; 67 68 std::unordered_map<std::string, std::string> extraParams; 69 70 bool processOption(int& i, std::vector<std::string>& argv, const std::string& workingDir); 71 static void printHelp(std::ostream& os); 72 }; 73 74 private: 75 FactoryOptions& _factoryOptions; 76 Options* _options = nullptr; 77 78 public: 79 // NOLINTNEXTLINE(readability-identifier-naming) 80 void(__stdcall* dll_GRBversion)(int*, int*, int*); 81 82 // NOLINTNEXTLINE(readability-identifier-naming) 83 int(__stdcall* dll_GRBaddconstr)(GRBmodel* model, int numnz, int* cind, double* cval, char sense, 84 double rhs, const char* constrname); 85 86 // NOLINTNEXTLINE(readability-identifier-naming) 87 int(__stdcall* dll_GRBaddgenconstrMin)(GRBmodel* model, const char* name, int resvar, int nvars, 88 const int* vars, double constant); 89 90 // NOLINTNEXTLINE(readability-identifier-naming) 91 int(__stdcall* dll_GRBaddqconstr)(GRBmodel* model, int numlnz, int* lind, double* lval, 92 int numqnz, int* qrow, int* qcol, double* qval, char sense, 93 double rhs, const char* QCname); 94 95 // NOLINTNEXTLINE(readability-identifier-naming) 96 int(__stdcall* dll_GRBaddgenconstrIndicator)(GRBmodel* model, const char* name, int binvar, 97 int binval, int nvars, const int* ind, 98 const double* val, char sense, double rhs); 99 100 // NOLINTNEXTLINE(readability-identifier-naming) 101 int(__stdcall* dll_GRBaddvars)(GRBmodel* model, int numvars, int numnz, int* vbeg, int* vind, 102 double* vval, double* obj, double* lb, double* ub, char* vtype, 103 char** varnames); 104 105 // NOLINTNEXTLINE(readability-identifier-naming) 106 int(__stdcall* dll_GRBcbcut)(void* cbdata, int cutlen, const int* cutind, const double* cutval, 107 char cutsense, double cutrhs); 108 109 // NOLINTNEXTLINE(readability-identifier-naming) 110 int(__stdcall* dll_GRBcbget)(void* cbdata, int where, int what, void* resultP); 111 112 // NOLINTNEXTLINE(readability-identifier-naming) 113 int(__stdcall* dll_GRBcblazy)(void* cbdata, int lazylen, const int* lazyind, 114 const double* lazyval, char lazysense, double lazyrhs); 115 116 // NOLINTNEXTLINE(readability-identifier-naming) 117 void(__stdcall* dll_GRBfreeenv)(GRBenv* env); 118 119 // NOLINTNEXTLINE(readability-identifier-naming) 120 int(__stdcall* dll_GRBfreemodel)(GRBmodel* model); 121 122 // NOLINTNEXTLINE(readability-identifier-naming) 123 int(__stdcall* dll_GRBgetdblattr)(GRBmodel* model, const char* attrname, double* valueP); 124 125 // NOLINTNEXTLINE(readability-identifier-naming) 126 int(__stdcall* dll_GRBgetdblattrarray)(GRBmodel* model, const char* attrname, int first, int len, 127 double* values); 128 129 // NOLINTNEXTLINE(readability-identifier-naming) 130 GRBenv*(__stdcall* dll_GRBgetenv)(GRBmodel* model); 131 132 // NOLINTNEXTLINE(readability-identifier-naming) 133 const char*(__stdcall* dll_GRBgeterrormsg)(GRBenv* env); 134 135 // NOLINTNEXTLINE(readability-identifier-naming) 136 int(__stdcall* dll_GRBgetintattr)(GRBmodel* model, const char* attrname, int* valueP); 137 138 // NOLINTNEXTLINE(readability-identifier-naming) 139 int(__stdcall* dll_GRBloadenv)(GRBenv** envP, const char* logfilename); 140 141 // NOLINTNEXTLINE(readability-identifier-naming) 142 GRBenv*(__stdcall* dll_GRBgetconcurrentenv)(GRBmodel* model, int num); 143 144 // NOLINTNEXTLINE(readability-identifier-naming) 145 int(__stdcall* dll_GRBnewmodel)(GRBenv* env, GRBmodel** modelP, const char* Pname, int numvars, 146 double* obj, double* lb, double* ub, char* vtype, 147 char** varnames); 148 149 // NOLINTNEXTLINE(readability-identifier-naming) 150 int(__stdcall* dll_GRBoptimize)(GRBmodel* model); 151 152 // NOLINTNEXTLINE(readability-identifier-naming) 153 int(__stdcall* dll_GRBreadparams)(GRBenv* env, const char* filename); 154 155 // NOLINTNEXTLINE(readability-identifier-naming) 156 int(__stdcall* dll_GRBsetcallbackfunc)(GRBmodel* model, int(__stdcall* cb)(CB_ARGS), 157 void* usrdata); 158 159 // NOLINTNEXTLINE(readability-identifier-naming) 160 int(__stdcall* dll_GRBsetdblparam)(GRBenv* env, const char* paramname, double value); 161 162 // NOLINTNEXTLINE(readability-identifier-naming) 163 int(__stdcall* dll_GRBsetintparam)(GRBenv* env, const char* paramname, int value); 164 165 // NOLINTNEXTLINE(readability-identifier-naming) 166 int(__stdcall* dll_GRBsetintattr)(GRBmodel* model, const char* attrname, int newvalue); 167 168 // NOLINTNEXTLINE(readability-identifier-naming) 169 int(__stdcall* dll_GRBsetdblattrelement)(GRBmodel* model, const char* attrname, int iv, double v); 170 171 // NOLINTNEXTLINE(readability-identifier-naming) 172 int(__stdcall* dll_GRBsetintattrlist)(GRBmodel* model, const char* attrname, int len, int* ind, 173 int* newvalues); 174 175 // NOLINTNEXTLINE(readability-identifier-naming) 176 int(__stdcall* dll_GRBsetdblattrlist)(GRBmodel* model, const char* attrname, int len, int* ind, 177 double* newvalues); 178 179 // NOLINTNEXTLINE(readability-identifier-naming) 180 int(__stdcall* dll_GRBsetobjectiven)(GRBmodel* model, int index, int priority, double weight, 181 double abstol, double reltol, const char* name, 182 double constant, int lnz, int* lind, double* lval); 183 184 // NOLINTNEXTLINE(readability-identifier-naming) 185 int(__stdcall* dll_GRBsetstrparam)(GRBenv* env, const char* paramname, const char* value); 186 187 // NOLINTNEXTLINE(readability-identifier-naming) 188 void(__stdcall* dll_GRBterminate)(GRBmodel* model); 189 190 // NOLINTNEXTLINE(readability-identifier-naming) 191 int(__stdcall* dll_GRBupdatemodel)(GRBmodel* model); 192 193 // NOLINTNEXTLINE(readability-identifier-naming) 194 int(__stdcall* dll_GRBwrite)(GRBmodel* model, const char* filename); 195 196 // NOLINTNEXTLINE(readability-identifier-naming) 197 int(__stdcall* dll_GRBwriteparams)(GRBenv* env, const char* filename); 198 199 // NOLINTNEXTLINE(readability-identifier-naming) 200 int(__stdcall* dll_GRBgetintparam)(GRBenv* env, const char* paramname, int* valueP); 201 202 // NOLINTNEXTLINE(readability-identifier-naming) 203 int(__stdcall* dll_GRBemptyenv)(GRBenv** envP); 204 205 // NOLINTNEXTLINE(readability-identifier-naming) 206 int(__stdcall* dll_GRBgetnumparams)(GRBenv* env); 207 208 // NOLINTNEXTLINE(readability-identifier-naming) 209 int(__stdcall* dll_GRBgetparamname)(GRBenv* env, int i, char** paramnameP); 210 211 // NOLINTNEXTLINE(readability-identifier-naming) 212 int(__stdcall* dll_GRBgetparamtype)(GRBenv* env, const char* paramname); 213 214 // NOLINTNEXTLINE(readability-identifier-naming) 215 int(__stdcall* dll_GRBgetintparaminfo)(GRBenv* env, const char* paramname, int* valueP, int* minP, 216 int* maxP, int* defP); 217 218 // NOLINTNEXTLINE(readability-identifier-naming) 219 int(__stdcall* dll_GRBgetdblparaminfo)(GRBenv* env, const char* paramname, double* valueP, 220 double* minP, double* maxP, double* defP); 221 222 // NOLINTNEXTLINE(readability-identifier-naming) 223 int(__stdcall* dll_GRBgetstrparaminfo)(GRBenv* env, const char* paramname, char* valueP, 224 char* defP); 225 MIPGurobiWrapper(FactoryOptions & factoryOpt,Options * opt)226 MIPGurobiWrapper(FactoryOptions& factoryOpt, Options* opt) 227 : _factoryOptions(factoryOpt), _options(opt) { 228 if (opt != nullptr) { 229 openGUROBI(); 230 } 231 } ~MIPGurobiWrapper()232 ~MIPGurobiWrapper() override { closeGUROBI(); } 233 234 static std::string getDescription(FactoryOptions& factoryOpt, 235 MiniZinc::SolverInstanceBase::Options* opt = nullptr); 236 static std::string getVersion(FactoryOptions& factoryOpt, 237 MiniZinc::SolverInstanceBase::Options* opt = nullptr); 238 static std::string getId(); 239 static std::string getName(); 240 static std::vector<std::string> getTags(); 241 static std::vector<std::string> getStdFlags(); 242 static std::vector<std::string> getRequiredFlags(FactoryOptions& factoryOpt); 243 static std::vector<std::string> getFactoryFlags(); 244 245 static std::vector<MiniZinc::SolverConfig::ExtraFlag> getExtraFlags(FactoryOptions& factoryOpt); 246 247 // Statistics& getStatistics() { return _statistics; } 248 249 // IloConstraintArray *userCuts, *lazyConstraints; 250 251 /// derived should overload and call the ancestor 252 // virtual void cleanup(); 253 254 void checkDLL(); 255 void openGUROBI(); 256 void closeGUROBI(); 257 258 /// actual adding new variables to the solver 259 void doAddVars(size_t n, double* obj, double* lb, double* ub, VarType* vt, 260 std::string* names) override; 261 262 /// adding a linear constraint 263 void addRow(int nnz, int* rmatind, double* rmatval, LinConType sense, double rhs, 264 int mask = MaskConsType_Normal, const std::string& rowName = "") override; 265 void setVarBounds(int iVar, double lb, double ub) override; 266 void setVarLB(int iVar, double lb) override; 267 void setVarUB(int iVar, double ub) override; 268 /// Indicator constraint: x[iBVar]==bVal -> lin constr 269 void addIndicatorConstraint(int iBVar, int bVal, int nnz, int* rmatind, double* rmatval, 270 LinConType sense, double rhs, 271 const std::string& rowName = "") override; 272 void addMinimum(int iResultVar, int nnz, int* ind, const std::string& rowName = "") override; 273 274 /// Times constraint: var[x]*var[y] == var[z] 275 void addTimes(int x, int y, int z, const std::string& rowName = "") override; 276 277 int getFreeSearch() override; 278 bool addSearch(const std::vector<VarId>& vars, const std::vector<int>& pri) override; 279 bool addWarmStart(const std::vector<VarId>& vars, const std::vector<double>& vals) override; 280 bool defineMultipleObjectives(const MultipleObjectives& mo) override; 281 282 int nRows = 0; // to count rows in order tp notice lazy constraints 283 std::vector<int> nLazyIdx; 284 std::vector<int> nLazyValue; 285 /// adding an implication 286 // virtual void addImpl() = 0; 287 void setObjSense(int s) override; // +/-1 for max/min 288 getInfBound()289 double getInfBound() override { return GRB_INFINITY; } 290 getNCols()291 int getNCols() override { 292 dll_GRBupdatemodel(_model); 293 int cols; 294 _error = dll_GRBgetintattr(_model, GRB_INT_ATTR_NUMVARS, &cols); 295 return cols; 296 } getNRows()297 int getNRows() override { 298 dll_GRBupdatemodel(_model); 299 int cols; 300 _error = dll_GRBgetintattr(_model, GRB_INT_ATTR_NUMCONSTRS, &cols); 301 return cols; 302 } 303 304 // void setObjUB(double ub) { objUB = ub; } 305 // void addQPUniform(double c) { qpu = c; } // also sets problem type to MIQP unless c=0 306 307 void solve() override; 308 309 /// OUTPUT: getValues()310 const double* getValues() override { return output.x; } getObjValue()311 double getObjValue() override { return output.objVal; } getBestBound()312 double getBestBound() override { return output.bestBound; } getCPUTime()313 double getCPUTime() override { return output.dCPUTime; } 314 getStatus()315 Status getStatus() override { return output.status; } getStatusName()316 std::string getStatusName() override { return output.statusName; } 317 getNNodes()318 int getNNodes() override { return output.nNodes; } getNOpen()319 int getNOpen() override { return output.nOpenNodes; } 320 321 // virtual int getNNodes() = 0; 322 // virtual double getTime() = 0; 323 324 protected: 325 void wrapAssert(bool cond, const std::string& msg, bool fTerm = true); 326 327 /// Need to consider the 100 status codes in GUROBI and change with every version? TODO 328 Status convertStatus(int gurobiStatus); 329 }; 330