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 // CMakeLists.txt needs OSICBC_HOME defined 19 // #include <coin/CoinPackedVector.hpp> 20 // #include <coin/CoinPackedMatrix.hpp> 21 // #include <coin/CoinShallowPackedVector.hpp> 22 // #include <coin/CoinTime.hpp> 23 // #include <coin/OsiSolverInterface.hpp> 24 // #include <coin/OsiCbcSolverInterface.hpp> 25 #include <coin/CbcModel.hpp> 26 #include <coin/OsiClpSolverInterface.hpp> 27 // #include <coin/CbcSolver.hpp> 28 29 class MIPosicbcWrapper : public MIPWrapper { 30 // OsiCbcSolverInterface osi; // deprecated in Cbc 2.9.6 31 OsiClpSolverInterface _osi; 32 // CoinPackedMatrix* matrix = 0; 33 int _error; 34 std::string _osicbcBuffer; // [CBC_MESSAGEBUFSIZE]; 35 // string osicbc_status_buffer; // [CBC_MESSAGEBUFSIZE]; 36 37 std::vector<double> _x; 38 39 // To add constraints: 40 // vector<int> rowStarts, columns; 41 std::vector<CoinPackedVector> _rows; 42 std::vector<double> // element, 43 _rowlb, _rowub; 44 45 std::unordered_map<VarId, double> _warmstart; // this accumulates warmstart infos 46 47 public: 48 class FactoryOptions { 49 public: 50 // NOLINTNEXTLINE(readability-convert-member-functions-to-static) processOption(int & i,std::vector<std::string> & argv,const std::string & workingDir)51 bool processOption(int& i, std::vector<std::string>& argv, const std::string& workingDir) { 52 return false; 53 } 54 }; 55 56 class Options : public MiniZinc::SolverInstanceBase::Options { 57 public: 58 int nThreads = 1; 59 std::string sExportModel; 60 int nTimeout = 0; 61 long int nSolLimit = -1; 62 double nWorkMemLimit = -1; 63 std::string sReadParams; 64 std::string sWriteParams; 65 bool flagIntermediate = false; 66 67 double absGap = -1; 68 double relGap = 1e-8; 69 double intTol = 1e-8; 70 double objDiff = 1.0; 71 72 std::vector<std::string> cbcCmdOptions; 73 74 std::unordered_map<std::string, std::string> extraParams; 75 76 bool processOption(int& i, std::vector<std::string>& argv, 77 const std::string& workingDir = std::string()); 78 static void printHelp(std::ostream& os); 79 }; 80 81 private: 82 Options* _options = nullptr; 83 84 public: MIPosicbcWrapper(FactoryOptions & factoryOpt,Options * opt)85 MIPosicbcWrapper(FactoryOptions& factoryOpt, Options* opt) : _options(opt) { openOSICBC(); } ~MIPosicbcWrapper()86 ~MIPosicbcWrapper() override { closeOSICBC(); } 87 88 static std::string getDescription(FactoryOptions& factoryOpt, 89 MiniZinc::SolverInstanceBase::Options* opt = nullptr); 90 static std::string getVersion(FactoryOptions& factoryOpt, 91 MiniZinc::SolverInstanceBase::Options* opt = nullptr); 92 static std::string getId(); 93 static std::string getName(); 94 static std::vector<std::string> getTags(); 95 static std::vector<std::string> getStdFlags(); getRequiredFlags(FactoryOptions & factoryOpt)96 static std::vector<std::string> getRequiredFlags(FactoryOptions& factoryOpt) { return {}; }; getFactoryFlags()97 static std::vector<std::string> getFactoryFlags() { return {}; }; 98 99 static std::vector<MiniZinc::SolverConfig::ExtraFlag> getExtraFlags(FactoryOptions& factoryOpt); 100 101 void printVersion(std::ostream&); 102 void printHelp(std::ostream&); 103 // Statistics& getStatistics() { return _statistics; } 104 105 // IloConstraintArray *userCuts, *lazyConstraints; 106 107 /// derived should overload and call the ancestor 108 // virtual void cleanup(); openOSICBC()109 void openOSICBC() {} closeOSICBC()110 void closeOSICBC() {} 111 112 /// actual adding new variables to the solver 113 void doAddVars(size_t n, double* obj, double* lb, double* ub, VarType* vt, 114 std::string* names) override; 115 addPhase1Vars()116 void addPhase1Vars() override { 117 if (fVerbose) { 118 std::cerr << " MIPosicbcWrapper: delaying physical addition of variables..." << std::endl; 119 } 120 } 121 122 /// adding a linear constraint 123 void addRow(int nnz, int* rmatind, double* rmatval, LinConType sense, double rhs, 124 int mask = MaskConsType_Normal, const std::string& rowName = "") override; 125 /// adding an implication 126 // virtual void addImpl() = 0; 127 128 bool addWarmStart(const std::vector<VarId>& vars, const std::vector<double>& vals) override; 129 130 void setObjSense(int s) override; // +/-1 for max/min 131 getInfBound()132 double getInfBound() override { return _osi.getInfinity(); } 133 getNCols()134 int getNCols() override { 135 int nc = _osi.getNumCols(); 136 return nc != 0 ? nc : static_cast<int>(colLB.size()); 137 } getNColsModel()138 int getNColsModel() override { return _osi.getNumCols(); } getNRows()139 int getNRows() override { 140 if (!_rowlb.empty()) { 141 return _rowlb.size(); 142 } 143 return _osi.getNumRows(); 144 } 145 146 // void setObjUB(double ub) { objUB = ub; } 147 // void addQPUniform(double c) { qpu = c; } // also sets problem type to MIQP unless c=0 148 149 void solve() override; 150 151 /// OUTPUT: getValues()152 const double* getValues() override { return output.x; } getObjValue()153 double getObjValue() override { return output.objVal; } getBestBound()154 double getBestBound() override { return output.bestBound; } getCPUTime()155 double getCPUTime() override { return output.dCPUTime; } 156 getStatus()157 Status getStatus() override { return output.status; } getStatusName()158 std::string getStatusName() override { return output.statusName; } 159 getNNodes()160 int getNNodes() override { return output.nNodes; } getNOpen()161 int getNOpen() override { return output.nOpenNodes; } 162 163 // virtual int getNNodes() = 0; 164 // virtual double getTime() = 0; 165 166 protected: 167 // OsiSolverInterface& getOsiSolver() { return osi; } 168 169 void wrapAssert(bool cond, const std::string& msg, bool fTerm = true); 170 171 /// Need to consider the 100 status codes in OSICBC and change with every version? TODO 172 Status convertStatus(CbcModel* pModel); 173 Status convertStatus(); 174 }; 175