5#ifndef IDOL_OSIIDOLCGLSOLVERINTERFACE_H
6#define IDOL_OSIIDOLCGLSOLVERINTERFACE_H
9#include <OsiSolverInterface.hpp>
12#define THROW_CALLED { throw Exception("Function " + std::string(__FUNCTION__) + " was called by Cgl."); }
14template<
class NodeInfoT>
15class idol::CglCutCallback<NodeInfoT>::Strategy::OsiIdolCglSolverInterface :
public OsiSolverInterface {
17 std::unique_ptr<CoinPackedMatrix> m_matrix;
18 std::vector<double> m_col_lower;
19 std::vector<double> m_col_upper;
20 std::vector<char> m_row_sense;
21 std::vector<double> m_rhs;
22 std::vector<double> m_row_lower;
23 std::vector<double> m_row_upper;
24 std::vector<double> m_current_solution;
25 std::vector<double> m_row_activity;
27 OsiIdolCglSolverInterface(
Strategy& parent) : m_parent(parent) {
31 void update_current_solution() {
32 m_row_activity.clear();
33 const auto& model = m_parent.original_model();
34 const unsigned int n_cols = model.vars().size();
35 m_current_solution = std::vector<double>(n_cols);
36 const auto& current_solution = m_parent.node().info().primal_solution();
37 for (
unsigned int index = 0 ; index < n_cols ; ++index) {
38 const auto& var = model.get_var_by_index(index);
39 m_current_solution[index] = current_solution.get(var);
43 void initialSolve() override THROW_CALLED
44 void resolve() override THROW_CALLED
45 void branchAndBound() override THROW_CALLED
46 bool isAbandoned() const override THROW_CALLED
47 bool isProvenOptimal() const override THROW_CALLED
48 bool isProvenPrimalInfeasible() const override THROW_CALLED
49 bool isProvenDualInfeasible() const override THROW_CALLED
50 CoinWarmStart* getEmptyWarmStart() const override THROW_CALLED
51 CoinWarmStart* getWarmStart() const override THROW_CALLED
52 bool setWarmStart(const CoinWarmStart* warmstart) override THROW_CALLED
53 int getNumCols()
const override {
return m_parent.original_model().vars().size(); }
54 int getNumRows()
const override {
return m_parent.original_model().ctrs().size(); }
55 CoinBigIndex getNumElements() const override THROW_CALLED
57 const
double* getColLower()
const override {
59 if (m_col_lower.empty()) {
60 auto& me = const_cast<OsiIdolCglSolverInterface&>(*this);
61 const auto& model = m_parent.original_model();
62 const auto n_cols = model.vars().size();
63 me.m_col_lower = std::vector<double>(n_cols);
64 for (unsigned int index = 0 ; index < n_cols ; ++index) {
65 const auto& var = model.get_var_by_index(index);
66 me.m_col_lower[index] = model.get_var_lb(var);
70 assert(m_col_lower.size() == m_parent.original_model().vars().size());
71 return m_col_lower.data();
74 const double* getColUpper()
const override {
76 if (m_col_upper.empty()) {
77 auto& me =
const_cast<OsiIdolCglSolverInterface&
>(*this);
78 const auto& model = m_parent.original_model();
79 const auto n_cols = model.vars().size();
80 me.m_col_upper = std::vector<double>(n_cols);
81 for (
unsigned int index = 0 ; index < n_cols; ++index) {
82 const auto& var = model.get_var_by_index(index);
83 me.m_col_upper[index] = model.get_var_ub(var);
87 assert(m_col_upper.size() == m_parent.original_model().vars().size());
88 return m_col_upper.data();
91 const char* getRowSense()
const override {
93 if (m_row_sense.empty()) {
94 auto& me =
const_cast<OsiIdolCglSolverInterface&
>(*this);
95 const auto& model = m_parent.original_model();
96 const auto n_rows = model.ctrs().size();
97 me.m_row_sense = std::vector<char>(n_rows);
98 for (
unsigned int index = 0 ; index < n_rows ; ++index) {
99 const auto ctr = model.get_ctr_by_index(index);
100 const auto type = model.get_ctr_type(ctr);
103 me.m_row_sense[index] =
'L';
106 me.m_row_sense[index] =
'G';
109 me.m_row_sense[index] =
'E';
112 throw Exception(
"Constraint type out of bounds.");
117 assert(m_row_sense.size() == m_parent.original_model().ctrs().size());
118 return m_row_sense.data();
121 const double* getRightHandSide()
const override {
124 auto& me =
const_cast<OsiIdolCglSolverInterface&
>(*this);
125 const auto& model = m_parent.original_model();
126 const auto n_rows = model.ctrs().size();
127 me.m_rhs = std::vector<double>(n_rows);
128 for (
unsigned int index = 0 ; index < n_rows ; ++index) {
129 const auto ctr = model.get_ctr_by_index(index);
130 me.m_rhs[index] = model.get_ctr_rhs(ctr);
134 assert(m_rhs.size() == m_parent.original_model().ctrs().size());
138 const double* getRowRange() const override THROW_CALLED
140 const
double* getRowLower()
const override {
142 if (m_row_lower.empty()) {
143 auto& me = const_cast<OsiIdolCglSolverInterface&>(*this);
144 const auto& model = m_parent.original_model();
145 const unsigned int n_rows = model.ctrs().size();
146 me.m_row_lower = std::vector<double>(n_rows);
147 for (int i = 0 ; i < n_rows ; ++i) {
148 const auto ctr = model.get_ctr_by_index(i);
149 const auto rhs = model.get_ctr_rhs(ctr);
150 const auto type = model.get_ctr_type(ctr);
153 me.m_row_lower[i] = -Inf;
156 me.m_row_lower[i] = rhs;
159 me.m_row_lower[i] = rhs;
162 throw Exception(
"Constraint type out of bounds.");
167 assert(m_row_lower.size() == m_parent.original_model().ctrs().size());
168 return m_row_lower.data();
171 const double* getRowUpper()
const override {
173 if (m_row_upper.empty()) {
174 auto& me =
const_cast<OsiIdolCglSolverInterface&
>(*this);
175 const auto& model = m_parent.original_model();
176 const unsigned int n_rows = model.ctrs().size();
177 me.m_row_upper = std::vector<double>(n_rows);
178 for (
int i = 0 ; i < n_rows ; ++i) {
179 const auto ctr = model.get_ctr_by_index(i);
180 const auto rhs = model.get_ctr_rhs(ctr);
181 const auto type = model.get_ctr_type(ctr);
183 case idol::LessOrEqual:
184 me.m_row_upper[i] = rhs;
186 case idol::GreaterOrEqual:
187 me.m_row_upper[i] = Inf;
190 me.m_row_upper[i] = rhs;
193 throw Exception(
"Constraint type out of bounds.");
198 assert(m_row_upper.size() == m_parent.original_model().ctrs().size());
199 return m_row_upper.data();
202 const double* getObjCoefficients() const override THROW_CALLED
203 double getObjSense() const override THROW_CALLED
205 bool isContinuous(
int colIndex)
const override {
206 const auto& model = m_parent.original_model();
207 assert(colIndex < model.vars().size());
208 const auto& var = model.get_var_by_index(colIndex);
209 return model.get_var_type(var) == Continuous;
212 const CoinPackedMatrix* getMatrixByRow()
const override {
216 const auto& model = m_parent.original_model();
217 const auto n_rows = model.ctrs().size();
218 const auto n_cols = model.vars().size();
239 CoinBigIndex nnz = 0;
240 std::vector<int> row_lengths(n_rows);
242 for (
int i = 0; i < n_rows; ++i) {
243 const auto ctr = model.get_ctr_by_index(i);
244 const auto& row = model.get_ctr_row(ctr);
246 row_lengths[i] = row.size();
247 nnz += row_lengths[i];
251 std::vector<double> elem(nnz);
252 std::vector<int> ind(nnz);
253 std::vector<CoinBigIndex> start(n_rows);
256 CoinBigIndex pos = 0;
258 for (
int i = 0; i < n_rows; ++i) {
261 const auto ctr = model.get_ctr_by_index(i);
262 const auto& row = model.get_ctr_row(ctr);
264 for (
const auto& [var, constant] : row) {
265 const int index = (int) model.get_var_index(var);
266 assert(index >= 0 && index < n_cols);
269 elem[pos] = constant;
274 auto* me =
const_cast<OsiIdolCglSolverInterface*
>(
this);
275 me->m_matrix.reset(
new CoinPackedMatrix(
288 assert(m_matrix->getNumCols() == m_parent.original_model().vars().size());
289 assert(m_matrix->getNumRows() == m_parent.original_model().ctrs().size());
291 return m_matrix.get();
294 const CoinPackedMatrix* getMatrixByCol() const override THROW_CALLED
296 double getInfinity()
const override {
return Inf; }
298 const double* getColSolution()
const override {
299 assert(m_current_solution.size() == m_parent.original_model().vars().size());
300 return m_current_solution.data();
303 const double* getRowPrice() const override THROW_CALLED
304 const
double* getReducedCost() const override THROW_CALLED
306 const
double* getRowActivity()
const override {
308 if (m_row_activity.empty()) {
309 auto& me = const_cast<OsiIdolCglSolverInterface&>(*this);
310 const auto& model = m_parent.original_model();
311 const unsigned int n_rows = model.ctrs().size();
312 me.m_row_activity = std::vector<double>(n_rows);
313 const auto& current_solution = m_parent.node().info().primal_solution();
314 for (unsigned int index = 0 ; index < n_rows ; ++index) {
315 const auto& ctr = model.get_ctr_by_index(index);
316 const auto& row = model.get_ctr_row(ctr);
317 me.m_row_activity[index] = evaluate(row, current_solution);
321 assert(m_row_activity.size() == m_parent.original_model().ctrs().size());
322 return m_row_activity.data();
325 std::vector<double*> getDualRays(
int maxNumRays,
bool fullRay)
const override THROW_CALLED
326 std::vector<double*> getPrimalRays(
int maxNumRays)
const override THROW_CALLED
327 void setObjCoeff(
int elementIndex,
double elementValue)
override THROW_CALLED
328 void setColLower(
int elementIndex,
double elementValue)
override THROW_CALLED
329 void setColUpper(
int elementIndex,
double elementValue)
override THROW_CALLED
330 void setRowLower(
int elementIndex,
double elementValue)
override THROW_CALLED
331 void setRowUpper(
int elementIndex,
double elementValue)
override THROW_CALLED
332 void setColSolution(
const double* colsol)
override THROW_CALLED
333 void setRowPrice(
const double* rowprice)
override THROW_CALLED
334 void setContinuous(
int index)
override THROW_CALLED
335 void setInteger(
int index)
override THROW_CALLED
336 void addCol(
const CoinPackedVectorBase& vec,
const double collb,
const double colub,
const double obj)
override THROW_CALLED
337 void addRow(
const CoinPackedVectorBase& vec,
const double rowlb,
const double rowub)
override THROW_CALLED
338 void deleteRows(
const int num,
const int* rowIndices)
override THROW_CALLED
339 void loadProblem(
const CoinPackedMatrix& matrix,
const double* collb,
const double* colub,
const double* obj,
const double* rowlb,
const double* rowub)
override THROW_CALLED
340 void assignProblem(CoinPackedMatrix*& matrix,
double*& collb,
double*& colub,
double*& obj,
double*& rowlb,
double*& rowub)
override THROW_CALLED
341 void loadProblem(
const CoinPackedMatrix& matrix,
const double* collb,
const double* colub,
const double* obj,
const char* rowsen,
const double* rowrhs,
const double* rowrng)
override THROW_CALLED
342 void assignProblem(CoinPackedMatrix*& matrix,
double*& collb,
double*& colub,
double*& obj,
char*& rowsen,
double*& rowrhs,
double*& rowrng)
override THROW_CALLED
343 void loadProblem(
const int numcols,
const int numrows,
const CoinBigIndex* start,
const int* index,
const double* value,
const double* collb,
const double* colub,
const double* obj,
const double* rowlb,
const double* rowub)
override THROW_CALLED
344 void loadProblem(
const int numcols,
const int numrows,
const CoinBigIndex* start,
const int* index,
const double* value,
const double* collb,
const double* colub,
const double* obj,
const char* rowsen,
const double* rowrhs,
const double* rowrng)
override THROW_CALLED
345 void writeMps(
const char* filename,
const char* extension,
double objSense)
const override THROW_CALLED
346 OsiSolverInterface* clone(
bool copyData)
const override THROW_CALLED
347 bool isIterationLimitReached() const override THROW_CALLED
348 double getObjValue() const override THROW_CALLED
349 int getIterationCount() const override THROW_CALLED
350 void setObjSense(
double s) override THROW_CALLED
351 void setRowType(
int index,
char sense,
double rightHandSide,
double range) override THROW_CALLED
352 void deleteCols(const
int num, const
int* colIndices) override THROW_CALLED
353 void addRow(const CoinPackedVectorBase& vec, const
char rowsen, const
double rowrhs, const
double rowrng) override THROW_CALLED
356 void applyRowCut(const OsiRowCut& rc) override THROW_CALLED
357 void applyColCut(const OsiColCut& cc) override THROW_CALLED