Limbo
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
LPSolveApi.h
Go to the documentation of this file.
1 
8 #ifndef LIMBO_SOLVERS_API_LPSOLVEAPI_H
9 #define LIMBO_SOLVERS_API_LPSOLVEAPI_H
10 
11 #include <iostream>
12 #include <string>
13 #include <vector>
14 #include <list>
15 #include <limbo/solvers/Solvers.h>
16 // make sure lpsolve is configured properly
17 extern "C"
18 {
19 #include "lp_lib.h" // use lpsolve as ILP solver
20 }
21 
22 // lpsolve has macro definitions that cause conflicts
23 // temporarily uncomment them
24 #undef OPTIMAL
25 #undef SUBOPTIMAL
26 #undef INFEASIBLE
27 #undef UNBOUNDED
32 {
33  switch (status)
34  {
35  case 0: // OPTIMAL
36  case 8: // PRESOLVED
38  case 1: // SUBOPTIMAL
39  case 6: // USERABORT
40  case 7: // TIMEOUT
42  case 2: // INFEASIBLE
43  case 4: // DEGENERATE
44  case 5: // NUMFAILURE, numerical failure
45  case 25: // NUMFAILURE, accuracy error encountered
47  case 3: // UNBOUNDED
49  default:
50  limboAssertMsg(0, "unknown status %d", status);
51  }
52 }
53 
55 namespace limbo
56 {
58 namespace solvers
59 {
60 
63 {
64  public:
67  : m_verbose(SEVERE)
68  , m_bbRule(NODE_PSEUDONONINTSELECT|NODE_RCOSTFIXING)
69  // various options in presolve to tune
70  // I found PRESOLVE_COLDOMINATE may result in INFEASIBLE model, which may be a bug in lpsolve
71  // PRESOLVE_COLDOMINATE is buggy, do not use it
72  , m_presolve(PRESOLVE_ROWS+PRESOLVE_COLS+PRESOLVE_LINDEP+PRESOLVE_SOS+PRESOLVE_REDUCEMIP+PRESOLVE_KNAPSACK
73  +PRESOLVE_ELIMEQ2+PRESOLVE_IMPLIEDFREE+PRESOLVE_REDUCEGCD+PRESOLVE_PROBEFIX+PRESOLVE_PROBEREDUCE
74  +PRESOLVE_ROWDOMINATE/*+PRESOLVE_COLDOMINATE*/+PRESOLVE_MERGEROWS+PRESOLVE_COLFIXDUAL
75  +PRESOLVE_BOUNDS/*+PRESOLVE_DUALS+PRESOLVE_SENSDUALS*/)
76  {
77  }
79  virtual ~LPSolveParameters() {}
82  virtual void operator()(lprec* lp) const
83  {
84  set_verbose(lp, m_verbose);
85  // various options in presolve to tune
86  set_bb_rule(lp, m_bbRule);
87  set_presolve(lp, m_presolve, get_presolveloops(lp));
88  }
89 
92  void setVerbose(int v) {m_verbose = v;}
95  void setBbRule(int v) {m_bbRule = v;}
98  void setPresolve(int v) {m_presolve = v;}
99 
100  protected:
101  int m_verbose;
102  int m_bbRule;
104 };
108 template <typename T, typename V>
110 {
111  public:
115  typedef typename model_type::coefficient_value_type coefficient_value_type;
116  typedef typename model_type::variable_value_type variable_value_type;
117  typedef typename model_type::variable_type variable_type;
120  typedef typename model_type::term_type term_type;
121  typedef typename model_type::property_type property_type;
124 
127  LPSolveLinearApi(model_type* model)
128  : m_model(model)
129  , m_lpModel(NULL)
130  {
131  }
134  {
135  }
136 
139  SolverProperty operator()(parameter_type* param = NULL)
140  {
141  bool defaultParam = false;
142  if (param == NULL)
143  {
144  param = new LPSolveParameters;
145  defaultParam = true;
146  }
147 
148  // column indices
149  std::vector<int> vIdx;
150  // coefficients
151  std::vector<double> vValue;
152  // buffer for name
153  char buf[64];
154 
155  m_lpModel = make_lp(m_model->constraints().size(), m_model->numVariables());
156 
157  set_lp_name(m_lpModel, (char*)"LPSolveLinearApi");
158  // set verbose level
159  set_verbose(m_lpModel, SEVERE);
160 
161  // create variables
162  for (unsigned int i = 0, ie = m_model->numVariables(); i < ie; ++i)
163  {
164  variable_type var (i);
165  limboAssertMsg(set_bounds(m_lpModel, i+1, m_model->variableLowerBound(var), m_model->variableUpperBound(var)), "failed to set bounds of variable for LP");
166  sprintf(buf, "%s", m_model->variableName(var).c_str());
167  limboAssertMsg(set_col_name(m_lpModel, i+1, buf), "failed to set name of variable %s", m_model->variableName(var).c_str());
168  switch (m_model->variableNumericType(var))
169  {
170  case CONTINUOUS:
171  break;
172  case BINARY:
173  limboAssertMsg(set_binary(m_lpModel, i+1, TRUE), "failed to set binary variable for LP");
174  break;
175  case INTEGER:
176  limboAssertMsg(set_int(m_lpModel, i+1, TRUE), "failed to set integer variable for LP");
177  break;
178  default:
179  limboAssertMsg(0, "unknown numeric type");
180  }
181  }
182 
183  // create objective
184  vIdx.clear();
185  vValue.clear();
186  for (typename std::vector<term_type>::const_iterator it = m_model->objective().terms().begin(), ite = m_model->objective().terms().end(); it != ite; ++it)
187  {
188  vIdx.push_back(it->variable().id()+1); // variable id starts from 1 for LPSolve
189  vValue.push_back(it->coefficient());
190  }
191  limboAssertMsg(set_obj_fnex(m_lpModel, vIdx.size(), &vValue[0], &vIdx[0]), "failed to set objective for LP");
192  if (m_model->optimizeType() == MIN)
193  {
194  set_minim(m_lpModel);
195  }
196  else
197  {
198  set_maxim(m_lpModel);
199  }
200 
201  // create constraints
202  for (unsigned int i = 0, ie = m_model->constraints().size(); i < ie; ++i)
203  {
204  constraint_type const& constr = m_model->constraints().at(i);
205 
206  vIdx.clear();
207  vValue.clear();
208  for (typename std::vector<term_type>::const_iterator it = constr.expression().terms().begin(), ite = constr.expression().terms().end(); it != ite; ++it)
209  {
210  vIdx.push_back(it->variable().id()+1); // variable id starts from 1 for LPSolve
211  vValue.push_back(it->coefficient());
212  }
213 
214  limboAssertMsg(set_rowex(m_lpModel, i+1, vIdx.size(), &vValue[0], &vIdx[0]), "failed to set constraint for LP");
215  switch (constr.sense())
216  {
217  case '>':
218  limboAssertMsg(set_constr_type(m_lpModel, i+1, GE), "failed to set constraint type for LP");
219  break;
220  case '<':
221  limboAssertMsg(set_constr_type(m_lpModel, i+1, LE), "failed to set constraint type for LP");
222  break;
223  case '=':
224  limboAssertMsg(set_constr_type(m_lpModel, i+1, EQ), "failed to set constraint type for LP");
225  break;
226  default:
227  limboAssertMsg(0, "unknown sense");
228  }
229  limboAssertMsg(set_rh(m_lpModel, i+1, constr.rightHandSide()), "failed to set constraint right-hand side for LP");
230  sprintf(buf, "%s", m_model->constraintName(constr).c_str());
231  limboAssertMsg(set_row_name(m_lpModel, i+1, buf), "failed to set constraint name %s for LP", m_model->constraintName(constr).c_str());
232  }
233 
234  // solve LP
235 #ifdef DEBUG_LPSOLVEAPI
236  write_lp(m_lpModel, (char*)"problem.lp");
237 #endif
238  set_scaling(m_lpModel, SCALE_RANGE);
239  // call parameter setting before optimization
240  param->operator()(m_lpModel);
241  int status = solve(m_lpModel);
242 
243  // apply solution
244  for (unsigned int i = 0; i < m_model->numVariables(); ++i)
245  {
246  REAL value = get_var_primalresult(m_lpModel, m_model->constraints().size()+1+i);
248  }
249 
250 #ifdef DEBUG_LPSOLVEAPI
251  std::vector<REAL> vSol (1+m_model->constraints().size()+m_model->numVariables());
252  limboAssertMsg(get_primal_solution(m_lpModel, &vSol[0]), "failed to get_primal_solution for LP");
253  std::ofstream out ("problem.sol");
254  limboAssertMsg(out.good(), "failed to open %s for write", "problem.sol");
255  out << "# Solution for model " << get_lp_name(m_lpModel) << "\n";
256  out << "# Objective value = " << get_objective(m_lpModel) << "\n";
257  for (unsigned int i = 0; i < m_model->numVariables(); ++i)
258  {
259  out << get_col_name(m_lpModel, i+1) << " " << vSol[1+m_model->constraints().size()+i] << "\n";
260  }
261  out.close();
262 #endif
263 
264  if (defaultParam)
265  delete param;
266  delete_lp(m_lpModel);
267 
268  return getSolveStatus(status);
269  //switch (status)
270  //{
271  // case 0: // OPTIMAL
272  // case 8: // PRESOLVED
273  // return OPTIMAL;
274  // case 1: // SUBOPTIMAL
275  // case 6: // USERABORT
276  // case 7: // TIMEOUT
277  // return SUBOPTIMAL;
278  // case 2: // INFEASIBLE
279  // case 4: // DEGENERATE
280  // case 5: // NUMFAILURE, numerical failure
281  // case 25: // NUMFAILURE, accuracy error encountered
282  // return INFEASIBLE;
283  // case 3: // UNBOUNDED
284  // return UNBOUNDED;
285  // default:
286  // limboAssertMsg(0, "unknown status %d", status);
287  //}
288  }
289  protected:
296 
297  model_type* m_model;
298  lprec* m_lpModel;
299 };
300 
301 } // namespace solvers
302 } // namespace limbo
303 
304 #endif
Describe properties of a variable.
Definition: Solvers.h:72
SolverProperty
Some enums used in solver.
Definition: Solvers.h:29
SolverProperty optimizeType() const
Definition: Solvers.h:1308
Basic utilities such as variables and linear expressions in solvers.
model_type * m_model
model for the problem
Definition: LPSolveApi.h:297
std::string const & constraintName(constraint_type const &constr) const
Definition: Solvers.h:1286
SolverProperty variableNumericType(variable_type const &var)
Definition: Solvers.h:1354
V variable_value_type
V variable.
Definition: Solvers.h:1166
limbo::solvers::SolverProperty getSolveStatus(int status)
convert lpsolve status to limbo::solvers status
Definition: LPSolveApi.h:31
T coefficient_value_type
T coefficient.
Definition: Solvers.h:1164
expression_type const & objective() const
Definition: Solvers.h:1292
LPSolveLinearApi(model_type *model)
constructor
Definition: LPSolveApi.h:127
Describe linear constraint.
Definition: Solvers.h:78
lprec * m_lpModel
model for LPSolve
Definition: LPSolveApi.h:298
std::vector< constraint_type > const & constraints() const
Definition: Solvers.h:1210
LinearModel< T, V > model_type
linear model type for the problem
Definition: LPSolveApi.h:113
unsigned int numVariables() const
Definition: Solvers.h:1316
virtual ~LPSolveParameters()
destructor
Definition: LPSolveApi.h:79
int m_bbRule
branch and bound rule
Definition: LPSolveApi.h:102
the model is infeasible
Definition: Solvers.h:37
LPSolve API with limbo::solvers::LinearModel.
Definition: LPSolveApi.h:109
void setPresolve(int v)
set presolve strategy
Definition: LPSolveApi.h:98
expression_type const & expression() const
Definition: Solvers.h:1028
variable_type variable(unsigned int id) const
Definition: Solvers.h:1318
void setVerbose(int v)
set verbose level
Definition: LPSolveApi.h:92
the model is suboptimal
Definition: Solvers.h:38
binary number
Definition: Solvers.h:33
int m_presolve
presolve strategy
Definition: LPSolveApi.h:103
Base class for custom LPSolve parameters.
Definition: LPSolveApi.h:62
namespace for Limbo
Definition: GraphUtility.h:22
floating point number
Definition: Solvers.h:35
std::string variableName(variable_type const &var) const
Definition: Solvers.h:1320
coefficient_value_type rightHandSide() const
Definition: Solvers.h:1034
the model is unbounded
Definition: Solvers.h:39
SolverProperty operator()(parameter_type *param=NULL)
API to run the algorithm.
Definition: LPSolveApi.h:139
std::vector< term_type > const & terms() const
Definition: Solvers.h:655
optimally solved
Definition: Solvers.h:36
void setVariableSolution(variable_type const &var, variable_value_type v)
Definition: Solvers.h:1379
variable_value_type variableLowerBound(variable_type const &var)
Definition: Solvers.h:1334
integer number
Definition: Solvers.h:34
model to describe an optimization problem
Definition: Solvers.h:80
LPSolveLinearApi & operator=(LPSolveLinearApi const &rhs)
assignment, forbidden
variable_value_type variableUpperBound(variable_type const &var)
Definition: Solvers.h:1344
minimize objective
Definition: Solvers.h:31
#define limboAssertMsg(condition, args...)
custom assertion with message
Definition: AssertMsg.h:52
void setBbRule(int v)
set branch and bound rule
Definition: LPSolveApi.h:95
virtual void operator()(lprec *lp) const
customize environment
Definition: LPSolveApi.h:82