Limbo
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GurobiApi.h
Go to the documentation of this file.
1 
8 #ifndef LIMBO_SOLVERS_API_GUROBIAPI_H
9 #define LIMBO_SOLVERS_API_GUROBIAPI_H
10 
11 #include <iostream>
12 #include <string>
13 #include <vector>
14 #include <list>
15 #include <boost/lexical_cast.hpp>
16 #include <boost/shared_ptr.hpp>
17 #include <boost/assert.hpp>
18 #include <limbo/solvers/Solvers.h>
19 // make sure gurobi is configured properly
20 extern "C"
21 {
22 #include "gurobi_c.h"
23 }
24 
26 namespace limbo
27 {
29 namespace solvers
30 {
31 
34 {
35  public:
38  : m_outputFlag(0)
39  , m_numThreads(std::numeric_limits<int>::max())
40  {
41  }
43  virtual ~GurobiParameters() {}
46  virtual void operator()(GRBenv* env) const
47  {
48  // mute the log from the LP solver
49  GRBsetintparam(env, GRB_INT_PAR_OUTPUTFLAG, m_outputFlag);
51  GRBsetintparam(env, GRB_INT_PAR_THREADS, m_numThreads);
52  }
56  virtual void operator()(GRBmodel* /*model*/) const
57  {
58  }
59 
62  void setOutputFlag(int v) {m_outputFlag = v;}
65  void setNumThreads(int v) {m_numThreads = v;}
66 
67  protected:
70 };
71 
75 template <typename T, typename V>
77 {
78  public:
82  typedef typename model_type::coefficient_value_type coefficient_value_type;
83  typedef typename model_type::variable_value_type variable_value_type;
87  typedef typename model_type::term_type term_type;
91 
94  GurobiLinearApi(model_type* model)
95  : m_model(model)
96  , m_grbModel(NULL)
97  {
98  }
101  {
102  }
103 
106  SolverProperty operator()(parameter_type* param = NULL)
107  {
108  bool defaultParam = false;
109  if (param == NULL)
110  {
111  param = new GurobiParameters;
112  defaultParam = true;
113  }
114 
115  // ILP environment
116  GRBenv* env = NULL;
117  m_grbModel = NULL;
118  // Create environment
119  int error = GRBloadenv(&env, NULL);
120  errorHandler(env, error);
121  param->operator()(env);
122  // Create an empty model
123  error = GRBnewmodel(env, &m_grbModel, "GurobiLinearApi", m_model->numVariables(), NULL, NULL, NULL, NULL, NULL);
124  errorHandler(env, error);
125 
126  // create variables
127  error = GRBupdatemodel(m_grbModel);
128  errorHandler(env, error);
129  for (unsigned int i = 0, ie = m_model->numVariables(); i < ie; ++i)
130  {
131  variable_type var (i);
132  error = GRBsetdblattrelement(m_grbModel, GRB_DBL_ATTR_LB, var.id(), m_model->variableLowerBound(var));
133  errorHandler(env, error);
134  error = GRBsetdblattrelement(m_grbModel, GRB_DBL_ATTR_UB, var.id(), m_model->variableUpperBound(var));
135  errorHandler(env, error);
136  error = GRBsetdblattrelement(m_grbModel, GRB_DBL_ATTR_START, var.id(), m_model->variableSolution(var));
137  errorHandler(env, error);
138  error = GRBsetcharattrelement(m_grbModel, GRB_CHAR_ATTR_VTYPE, var.id(), m_model->variableNumericType(var) == CONTINUOUS? GRB_CONTINUOUS : GRB_INTEGER);
139  errorHandler(env, error);
140  error = GRBsetstrattrelement(m_grbModel, GRB_STR_ATTR_VARNAME, var.id(), m_model->variableName(var).c_str());
141  errorHandler(env, error);
142  }
143 
144  // create constraints
145  std::vector<int> vIdx;
146  std::vector<double> vValue;
147  for (unsigned int i = 0, ie = m_model->constraints().size(); i < ie; ++i)
148  {
149  constraint_type const& constr = m_model->constraints().at(i);
150 
151  vIdx.clear();
152  vValue.clear();
153  for (typename std::vector<term_type>::const_iterator it = constr.expression().terms().begin(), ite = constr.expression().terms().end(); it != ite; ++it)
154  {
155  vIdx.push_back(it->variable().id());
156  vValue.push_back(it->coefficient());
157  }
158 
159  error = GRBaddconstr(m_grbModel, constr.expression().terms().size(), &vIdx[0], &vValue[0], constr.sense(), constr.rightHandSide(), m_model->constraintName(constr).c_str());
160  errorHandler(env, error);
161  }
162 
163  // create objective
164  for (typename std::vector<term_type>::const_iterator it = m_model->objective().terms().begin(), ite = m_model->objective().terms().end(); it != ite; ++it)
165  {
166  error = GRBsetdblattrelement(m_grbModel, GRB_DBL_ATTR_OBJ, it->variable().id(), it->coefficient());
167  errorHandler(env, error);
168  }
169  error = GRBsetintattr(m_grbModel, GRB_INT_ATTR_MODELSENSE, m_model->optimizeType() == MIN? GRB_MINIMIZE : GRB_MAXIMIZE);
170  errorHandler(env, error);
171 
172  // call parameter setting before optimization
173  param->operator()(m_grbModel);
174  error = GRBupdatemodel(m_grbModel);
175  errorHandler(env, error);
176 
177 #ifdef DEBUG_GUROBIAPI
178  GRBwrite(m_grbModel, "problem.lp");
179 #endif
180  error = GRBoptimize(m_grbModel);
181 
182  int status = 0;
183  error = GRBgetintattr(m_grbModel, GRB_INT_ATTR_STATUS, &status);
184  errorHandler(env, error);
185 
186  if (status == GRB_INFEASIBLE)
187  {
188  error = GRBcomputeIIS(m_grbModel);
189  errorHandler(env, error);
190  GRBwrite(m_grbModel, "problem.ilp");
191  limboPrint(kERROR, "Model is infeasible, compute IIS and write to problem.ilp\n");
192  }
193 #ifdef DEBUG_GUROBIAPI
194  GRBwrite(m_grbModel, "problem.sol");
195 #endif
196 
197  for (unsigned int i = 0; i < m_model->numVariables(); ++i)
198  {
199  variable_type var = m_model->variable(i);
200  double value = 0;
201  error = GRBgetdblattrelement(m_grbModel, GRB_DBL_ATTR_X, var.id(), &value);
202  errorHandler(env, error);
204  }
205 
206  if (defaultParam)
207  delete param;
208  // Free model
209  GRBfreemodel(m_grbModel);
210  // Free environment
211  GRBfreeenv(env);
212 
213  switch (status)
214  {
215  case GRB_OPTIMAL:
216  return OPTIMAL;
217  case GRB_INFEASIBLE:
218  return INFEASIBLE;
219  case GRB_INF_OR_UNBD:
220  case GRB_UNBOUNDED:
221  return UNBOUNDED;
222  default:
223  limboAssertMsg(0, "unknown status %d", status);
224  }
225  }
226 
230  void errorHandler(GRBenv* env, int error) const;
231  protected:
234  GurobiLinearApi(GurobiLinearApi const& rhs);
238 
239  model_type* m_model;
240  GRBmodel* m_grbModel;
241 };
242 
243 template <typename T, typename V>
244 void GurobiLinearApi<T, V>::errorHandler(GRBenv* env, int error) const
245 {
246  // Error reporting
247  if (error)
248  limboAssertMsg(0, "%s", GRBgeterrormsg(env));
249 }
250 
251 #if GUROBIFILEAPI == 1
252 #include "gurobi_c++.h"
256 template <typename T>
257 struct GurobiFileApi
258 {
260  typedef T value_type;
261 
263  struct solution_type
264  {
265  value_type obj;
266  std::list<std::pair<std::string, value_type> > vVariable;
267  };
271  virtual boost::shared_ptr<solution_type> operator()(std::string const& fileName, bool = true) const
272  {
273  // better to use full path for file name
274  boost::shared_ptr<solution_type> pSol (new solution_type);
275  // remove previous solution file
276  std::cout << "rm -rf "+fileName+".sol" << std::endl;
277  std::cout << system(("rm -rf "+fileName+".sol").c_str()) << std::endl;;
278 
279  std::cout << "solve linear program "+fileName << std::endl;
280  this->solve_lp(fileName);
281 
282  // read rpt
283  {
284  std::ifstream solFile ((fileName+".sol").c_str(), std::ifstream::in);
285  if (!solFile.good()) BOOST_ASSERT_MSG(false, ("failed to open " + fileName + ".sol").c_str());
286 
287  std::string var;
288  double value;
289 
290  // read objective value
291  solFile >> var >> var >> var >> var >> value;
292  pSol->obj = value;
293 
294  while (!solFile.eof())
295  {
296  solFile >> var >> value;
297  pSol->vVariable.push_back(make_pair(var, value));
298  }
299  solFile.close();
300  }
301 
302  return pSol;
303  }
308  virtual void solve_lp(std::string fileName) const
309  {
310  try
311  {
312  GRBEnv env = GRBEnv();
313  GRBModel model = GRBModel(env, fileName+".lp");
314 
315  model.optimize();
316 
317  int optimstatus = model.get(GRB_IntAttr_Status);
318 
319  if (optimstatus == GRB_INF_OR_UNBD)
320  {
321  model.getEnv().set(GRB_IntParam_Presolve, 0);
322  model.optimize();
323  optimstatus = model.get(GRB_IntAttr_Status);
324  }
325 
326  if (optimstatus == GRB_OPTIMAL)
327  {
328  double objval = model.get(GRB_DoubleAttr_ObjVal);
329  std::cout << "Optimal objective: " << objval << std::endl;
330  // write result
331  model.write(fileName+".sol");
332  }
333  else if (optimstatus == GRB_INFEASIBLE)
334  {
335  std::cout << "Model is infeasible" << std::endl;
336 
337  // compute and write out IIS
338 
339  model.computeIIS();
340  model.write(fileName+".ilp");
341  }
342  else if (optimstatus == GRB_UNBOUNDED)
343  {
344  std::cout << "Model is unbounded" << std::endl;
345  }
346  else
347  {
348  std::cout << "Optimization was stopped with status = "
349  << optimstatus << std::endl;
350  }
351  }
352  catch(GRBException e)
353  {
354  std::cout << "Error code = " << e.getErrorCode() << std::endl;
355  std::cout << e.getMessage() << std::endl;
356  }
357  catch (...)
358  {
359  std::cout << "Error during optimization" << std::endl;
360  }
361  }
362 
363 };
364 #endif
365 
366 } // namespace solvers
367 } // namespace limbo
368 
369 #endif
Gurobi API with limbo::solvers::LinearModel.
Definition: GurobiApi.h:76
unsigned int id() const
Definition: Solvers.h:117
void setNumThreads(int v)
set number of threads
Definition: GurobiApi.h:65
variable_value_type variableSolution(variable_type const &var) const
Definition: Solvers.h:1376
Base class for custom Gurobi parameters.
Definition: GurobiApi.h:33
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
model_type * m_model
model for the problem
Definition: GurobiApi.h:239
Basic utilities such as variables and linear expressions in solvers.
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
T coefficient_value_type
T coefficient.
Definition: Solvers.h:1164
expression_type const & objective() const
Definition: Solvers.h:1292
Describe linear constraint.
Definition: Solvers.h:78
int m_numThreads
number of threads
Definition: GurobiApi.h:69
void setOutputFlag(int v)
set output flag
Definition: GurobiApi.h:62
std::vector< constraint_type > const & constraints() const
Definition: Solvers.h:1210
unsigned int numVariables() const
Definition: Solvers.h:1316
virtual void operator()(GRBmodel *) const
customize model
Definition: GurobiApi.h:56
virtual void operator()(GRBenv *env) const
customize environment
Definition: GurobiApi.h:46
GurobiLinearApi(model_type *model)
constructor
Definition: GurobiApi.h:94
the model is infeasible
Definition: Solvers.h:37
expression_type const & expression() const
Definition: Solvers.h:1028
variable_type variable(unsigned int id) const
Definition: Solvers.h:1318
void errorHandler(GRBenv *env, int error) const
error handler
Definition: GurobiApi.h:244
namespace for Limbo
Definition: GraphUtility.h:22
floating point number
Definition: Solvers.h:35
std::iterator_traits< Iterator >::value_type max(Iterator first, Iterator last)
get max of an array
Definition: Math.h:61
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
GurobiLinearApi & operator=(GurobiLinearApi const &rhs)
assignment, forbidden
int limboPrint(MessageType m, const char *format,...)
formatted print with prefix
Definition: PrintMsg.h:49
std::vector< term_type > const & terms() const
Definition: Solvers.h:655
optimally solved
Definition: Solvers.h:36
GRBmodel * m_grbModel
model for Gurobi
Definition: GurobiApi.h:240
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
model to describe an optimization problem
Definition: Solvers.h:80
int m_outputFlag
control log from Gurobi
Definition: GurobiApi.h:68
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
SolverProperty operator()(parameter_type *param=NULL)
API to run the algorithm.
Definition: GurobiApi.h:106
LinearModel< T, V > model_type
linear model type for the problem
Definition: GurobiApi.h:80
virtual ~GurobiParameters()
destructor
Definition: GurobiApi.h:43