solver  1.0
LPSolveSolver.cpp
1 /*
2  This file is part of the EnergyOptimizatorOfRoboticCells program.
3 
4  EnergyOptimizatorOfRoboticCells is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  EnergyOptimizatorOfRoboticCells is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with EnergyOptimizatorOfRoboticCells. If not, see <http://www.gnu.org/licenses/>.
16 */
17 
18 #include <cmath>
19 #include <string>
20 #include <stdexcept>
21 #include <vector>
22 #include <lpsolve/lp_lib.h>
24 
25 using namespace std;
26 
27 void throwExceptionIfError(const unsigned char& status, string errorMsg);
28 void generateProblem(const ILPModel& m, lprec* ilp);
29 
30 string solverIdentification() {
31  string identification = "LPSolve";
32  int major = -1, minor = -1, release = -1, build = -1;
33  lp_solve_version(&major, &minor, &release, &build);
34  if (major != -1 && minor != -1 && release != -1 && build != -1)
35  identification += " "+to_string(major)+"."+to_string(minor)+"."+to_string(release)+"."+to_string(build);
36  return identification;
37 }
38 
39 SolutionILP solveILP(const ILPModel& m, bool verbose, double gap, double timeLimit, int, int) {
40 
41  SolutionILP s;
42  lprec *model = nullptr;
43 
44  try {
45  model = make_lp(m.numberOfConstraints(), m.numberOfVariables());
46  if (model == nullptr)
47  throw ILPSolverException(caller(), "LPSolve - cannot initialize the ilp problem!");
48 
49  generateProblem(m, model);
50 
51  if (!verbose)
52  set_verbose(model, NEUTRAL);
53  if (gap != 0.0)
54  set_mip_gap(model, FALSE, gap);
55  if (timeLimit != 0.0)
56  set_timeout(model, static_cast<long>(ceil(timeLimit)));
57 
58  set_presolve(model, PRESOLVE_ROWS | PRESOLVE_BOUNDS, get_presolveloops(model));
59  switch (solve(model)) {
60  case OPTIMAL:
61  s.status = ILP_OPTIMAL;
62  break;
63  case SUBOPTIMAL:
64  s.status = ILP_FEASIBLE;
65  break;
66  case INFEASIBLE:
67  s.status = ILP_INFEASIBLE;
68  break;
69  case UNBOUNDED:
70  s.status = ILP_UNBOUNDED;
71  break;
72  default:
73  s.status = ILP_UNKNOWN;
74  }
75 
76  if (s.status == ILP_OPTIMAL || s.status == ILP_FEASIBLE) {
77  double *vars = nullptr;
78  get_ptr_variables(model, &vars);
79  if (vars != nullptr) {
80  s.criterion = get_objective(model);
81  for (unsigned long v = 0; v < m.numberOfVariables(); ++v)
82  s.solution.push_back(vars[v]);
83  } else {
84  throw ILPSolverException(caller(), "LPSolve - cannot obtain the variables!");
85  }
86 
87  }
88 
89  if (s.status == ILP_OPTIMAL) {
90  s.bound = s.criterion;
91  } else {
92  s.bound = 0.0;
93  for (unsigned long v = 0; v < m.numberOfVariables(); ++v) {
94  if (m.obj == MINIMIZE && m.c[v] > 0.0)
95  s.bound += m.c[v]*m.x[v].lowerBound;
96  else if (m.obj == MINIMIZE && m.c[v] < 0.0)
97  s.bound += m.c[v]*m.x[v].upperBound;
98  else if (m.obj == MAXIMIZE && m.c[v] > 0.0)
99  s.bound += m.c[v]*m.x[v].upperBound;
100  else if (m.obj == MAXIMIZE && m.c[v] < 0.0)
101  s.bound += m.c[v]*m.x[v].lowerBound;
102  }
103  }
104 
105  delete_lp(model);
106 
107  } catch (...) {
108  delete_lp(model);
109  throw_with_nested(ILPSolverException(caller(), "Error during solving the ILP problem!"));
110  }
111 
112  return s;
113 }
114 
115 void throwExceptionIfError(const unsigned char& status, string errorMsg) {
116  if (status != TRUE)
117  throw ILPSolverException(caller(), errorMsg);
118 }
119 
120 void generateProblem(const ILPModel& m, lprec* ilp) {
121 
122  if (m.obj == MINIMIZE)
123  set_minim(ilp);
124  else
125  set_maxim(ilp);
126 
127  vector<double> crit(1, 0.0);
128  crit.insert(crit.end(), m.c.cbegin(), m.c.cend());
129  throwExceptionIfError(set_obj_fn(ilp, crit.data()), "LPSolve - cannot set the objective function!");
130 
131  for (unsigned long v = 0; v < m.numberOfVariables(); ++v) {
132  if (m.x[v].type == BIN || m.x[v].type == INT)
133  throwExceptionIfError(set_int(ilp, v+1, TRUE), "LPSolve - cannot set the integer type of the variable!");
134 
135  throwExceptionIfError(set_bounds(ilp, v+1, m.x[v].lowerBound, m.x[v].upperBound), "LPSolve - cannot set variable bounds!");
136  throwExceptionIfError(set_col_name(ilp, v+1, (char*) m.varDesc[v].c_str()), "LPSolve - cannot set the variable name!");
137  }
138 
139  throwExceptionIfError(set_add_rowmode(ilp, TRUE), "LPSolve - 'rowmode' should be changed!");
140  for (unsigned long c = 0; c < m.numberOfConstraints(); ++c) {
141  vector<int> conIdx;
142  vector<double> conCoeff;
143  for (const pair<uint32_t, double>& p : m.A[c]) {
144  conIdx.push_back(p.first+1);
145  conCoeff.push_back(p.second);
146  }
147 
148  switch (m.ops[c]) {
149  case LESS_EQUAL:
150  throwExceptionIfError(add_constraintex(ilp, conIdx.size(), conCoeff.data(), conIdx.data(), LE, m.b[c]), "LPSolve - cannot add the constraint!");
151  break;
152  case EQUAL:
153  throwExceptionIfError(add_constraintex(ilp, conIdx.size(), conCoeff.data(), conIdx.data(), EQ, m.b[c]), "LPSolve - cannot add the constraint!");
154  break;
155  case GREATER_EQUAL:
156  throwExceptionIfError(add_constraintex(ilp, conIdx.size(), conCoeff.data(), conIdx.data(), GE, m.b[c]), "LPSolve - cannot add the constraint!");
157  }
158 
159  throwExceptionIfError(set_row_name(ilp, c+1, (char*) m.conDesc[c].c_str()), "LPSolve - cannot set the constraint name!");
160  }
161  throwExceptionIfError(set_add_rowmode(ilp, FALSE), "LPSolve - 'rowmode' should be turned off!");
162 }
163 
std::vector< double > b
Constants in the constraints, i.e. the right-hand side vector of .
Definition: ILPModel.h:87
SparseMatrix< double > A
Constraint matrix of the problem.
Definition: ILPModel.h:81
STL namespace.
Integer Linear Programming problem is stored in this data structure.
Definition: ILPModel.h:69
std::vector< double > solution
The best found solution.
Structure storing a solution of an Integer Linear Programming problem.
std::vector< std::string > varDesc
Optional description of the variables.
Definition: ILPModel.h:93
Solver-independent interface for solving Integer Linear Programming problems.
Exception dedicated to problems with Integer Linear Programming solvers.
Definition: Exceptions.h:127
double criterion
The criterion value of the solution.
std::vector< Operator > ops
Operators of the constraints, see Operator enum.
Definition: ILPModel.h:89
std::string solverIdentification()
Returns an identification of the used solver, e.g. 'Gurobi 6.0.4'.
Definition: CplexSolver.cpp:30
double bound
The best known lower or upper bound.
std::vector< double > c
Vector of the criterion coefficients.
Definition: ILPModel.h:83
Objective obj
Sense of the objective function (minimization/maximization).
Definition: ILPModel.h:79
Status status
Solution status, see Status enum.
std::vector< Variable > x
Variables of the problem.
Definition: ILPModel.h:91
SolutionILP solveILP(const ILPModel &m, bool verbose, double gap=0.0, double timeLimit=0.0, int numberOfThreads=1, int threadId=0)
Integer Linear Programming solver is called to solve the problem and the solution is returned...
Definition: CplexSolver.cpp:39
std::vector< std::string > conDesc
Optional description of the constraints.
Definition: ILPModel.h:95