Limbo 3.5.4
Loading...
Searching...
No Matches
GurobiApi.h
Go to the documentation of this file.
1
7
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>
19// make sure gurobi is configured properly
20extern "C"
21{
22#include "gurobi_c.h"
23}
24
26namespace limbo
27{
29namespace solvers
30{
31
34{
35 public:
38 : m_outputFlag(0)
39 , m_numThreads(std::numeric_limits<int>::max())
40 {
41 }
42
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);
50 if (m_numThreads > 0 && m_numThreads != std::numeric_limits<int>::max())
51 GRBsetintparam(env, GRB_INT_PAR_THREADS, m_numThreads);
52 }
53
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
74template <typename T, std::size_t = std::numeric_limits<T>::is_integer>
75struct SmartRound
76{
77 inline T operator()(double value) const
78 {
79 return value;
80 }
81};
82
83template <typename T>
84struct SmartRound<T, 1>
85{
86 inline T operator()(double value) const
87 {
88 return std::round(value);
89 }
90};
91
95template <typename T, typename V>
97{
98 public:
102 typedef typename model_type::coefficient_value_type coefficient_value_type;
103 typedef typename model_type::variable_value_type variable_value_type;
104 typedef typename model_type::variable_type variable_type;
105 typedef typename model_type::constraint_type constraint_type;
106 typedef typename model_type::expression_type expression_type;
107 typedef typename model_type::term_type term_type;
108 typedef typename model_type::property_type property_type;
109 typedef GurobiParameters parameter_type;
111
115 : m_model(model)
116 , m_grbModel(NULL)
117 {
118 }
119
121 {
122 }
123
126 SolverProperty operator()(parameter_type* param = NULL)
127 {
128 bool defaultParam = false;
129 if (param == NULL)
130 {
131 param = new GurobiParameters;
132 defaultParam = true;
133 }
134
135 // ILP environment
136 GRBenv* env = NULL;
137 m_grbModel = NULL;
138 // Create environment
139 int error = GRBloadenv(&env, NULL);
140 errorHandler(env, error);
141 param->operator()(env);
142 // Create an empty model
143 error = GRBnewmodel(env, &m_grbModel, "GurobiLinearApi", m_model->numVariables(), NULL, NULL, NULL, NULL, NULL);
144 errorHandler(env, error);
145
146 // create variables
147 error = GRBupdatemodel(m_grbModel);
148 errorHandler(env, error);
149 for (unsigned int i = 0, ie = m_model->numVariables(); i < ie; ++i)
150 {
151 variable_type var (i);
152 error = GRBsetdblattrelement(m_grbModel, GRB_DBL_ATTR_LB, var.id(), m_model->variableLowerBound(var));
153 errorHandler(env, error);
154 error = GRBsetdblattrelement(m_grbModel, GRB_DBL_ATTR_UB, var.id(), m_model->variableUpperBound(var));
155 errorHandler(env, error);
156 error = GRBsetdblattrelement(m_grbModel, GRB_DBL_ATTR_START, var.id(), m_model->variableSolution(var));
157 errorHandler(env, error);
158 error = GRBsetcharattrelement(m_grbModel, GRB_CHAR_ATTR_VTYPE, var.id(), m_model->variableNumericType(var) == CONTINUOUS? GRB_CONTINUOUS : GRB_INTEGER);
159 errorHandler(env, error);
160 limboAssertMsg(!(std::numeric_limits<V>::is_integer && m_model->variableNumericType(var) == CONTINUOUS),
161 "LinearModel<T, V> is declared as V = integer type, but variable %s is CONTINUOUS", m_model->variableName(var).c_str());
162 error = GRBsetstrattrelement(m_grbModel, GRB_STR_ATTR_VARNAME, var.id(), m_model->variableName(var).c_str());
163 errorHandler(env, error);
164 }
165
166 // create constraints
167 std::vector<int> vIdx;
168 std::vector<double> vValue;
169 for (unsigned int i = 0, ie = m_model->constraints().size(); i < ie; ++i)
170 {
171 constraint_type const& constr = m_model->constraints().at(i);
172
173 vIdx.clear();
174 vValue.clear();
175 for (typename std::vector<term_type>::const_iterator it = constr.expression().terms().begin(), ite = constr.expression().terms().end(); it != ite; ++it)
176 {
177 vIdx.push_back(it->variable().id());
178 vValue.push_back(it->coefficient());
179 }
180
181 error = GRBaddconstr(m_grbModel, constr.expression().terms().size(), &vIdx[0], &vValue[0], constr.sense(), constr.rightHandSide(), m_model->constraintName(constr).c_str());
182 errorHandler(env, error);
183 }
184
185 // create objective
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 error = GRBsetdblattrelement(m_grbModel, GRB_DBL_ATTR_OBJ, it->variable().id(), it->coefficient());
189 errorHandler(env, error);
190 }
191 error = GRBsetintattr(m_grbModel, GRB_INT_ATTR_MODELSENSE, m_model->optimizeType() == MIN? GRB_MINIMIZE : GRB_MAXIMIZE);
192 errorHandler(env, error);
193
194 // call parameter setting before optimization
195 param->operator()(m_grbModel);
196 error = GRBupdatemodel(m_grbModel);
197 errorHandler(env, error);
198
199#ifdef DEBUG_GUROBIAPI
200 GRBwrite(m_grbModel, "problem.lp");
201#endif
202 error = GRBoptimize(m_grbModel);
203
204 int status = 0;
205 error = GRBgetintattr(m_grbModel, GRB_INT_ATTR_STATUS, &status);
206 errorHandler(env, error);
207
208 if (status == GRB_INFEASIBLE)
209 {
210 error = GRBcomputeIIS(m_grbModel);
211 errorHandler(env, error);
212 GRBwrite(m_grbModel, "problem.ilp");
213 limboPrint(kERROR, "Model is infeasible, compute IIS and write to problem.ilp\n");
214 }
215#ifdef DEBUG_GUROBIAPI
216 GRBwrite(m_grbModel, "problem.sol");
217#endif
218
219 // round if the variable type is integer
220 SmartRound<V> sround;
221 for (unsigned int i = 0; i < m_model->numVariables(); ++i)
222 {
223 variable_type var = m_model->variable(i);
224 double value = 0;
225 error = GRBgetdblattrelement(m_grbModel, GRB_DBL_ATTR_X, var.id(), &value);
226 errorHandler(env, error);
227 m_model->setVariableSolution(m_model->variable(i), sround(value));
228 }
229
230 if (defaultParam)
231 delete param;
232 // Free model
233 GRBfreemodel(m_grbModel);
234 // Free environment
235 GRBfreeenv(env);
236
237 switch (status)
238 {
239 case GRB_OPTIMAL:
240 return OPTIMAL;
241 case GRB_INFEASIBLE:
242 return INFEASIBLE;
243 case GRB_INF_OR_UNBD:
244 case GRB_UNBOUNDED:
245 return UNBOUNDED;
246 default:
247 limboAssertMsg(0, "unknown status %d", status);
248 }
249 }
250
254 void errorHandler(GRBenv* env, int error) const;
255 protected:
262
264 GRBmodel* m_grbModel;
265};
266
267template <typename T, typename V>
268void GurobiLinearApi<T, V>::errorHandler(GRBenv* env, int error) const
269{
270 // Error reporting
271 if (error)
272 limboAssertMsg(0, "%s", GRBgeterrormsg(env));
273}
274
275#if GUROBIFILEAPI == 1
276#include "gurobi_c++.h"
280template <typename T>
281struct GurobiFileApi
282{
284 typedef T value_type;
285
287 struct solution_type
288 {
289 value_type obj;
290 std::list<std::pair<std::string, value_type> > vVariable;
291 };
295 virtual boost::shared_ptr<solution_type> operator()(std::string const& fileName, bool = true) const
296 {
297 // better to use full path for file name
298 boost::shared_ptr<solution_type> pSol (new solution_type);
299 // remove previous solution file
300 std::cout << "rm -rf "+fileName+".sol" << std::endl;
301 std::cout << system(("rm -rf "+fileName+".sol").c_str()) << std::endl;;
302
303 std::cout << "solve linear program "+fileName << std::endl;
304 this->solve_lp(fileName);
305
306 // read rpt
307 {
308 std::ifstream solFile ((fileName+".sol").c_str(), std::ifstream::in);
309 if (!solFile.good()) BOOST_ASSERT_MSG(false, ("failed to open " + fileName + ".sol").c_str());
310
311 std::string var;
312 double value;
313
314 // read objective value
315 solFile >> var >> var >> var >> var >> value;
316 pSol->obj = value;
317
318 while (!solFile.eof())
319 {
320 solFile >> var >> value;
321 pSol->vVariable.push_back(make_pair(var, value));
322 }
323 solFile.close();
324 }
325
326 return pSol;
327 }
332 virtual void solve_lp(std::string fileName) const
333 {
334 try
335 {
336 GRBEnv env = GRBEnv();
337 GRBModel model = GRBModel(env, fileName+".lp");
338
339 model.optimize();
340
341 int optimstatus = model.get(GRB_IntAttr_Status);
342
343 if (optimstatus == GRB_INF_OR_UNBD)
344 {
345 model.getEnv().set(GRB_IntParam_Presolve, 0);
346 model.optimize();
347 optimstatus = model.get(GRB_IntAttr_Status);
348 }
349
350 if (optimstatus == GRB_OPTIMAL)
351 {
352 double objval = model.get(GRB_DoubleAttr_ObjVal);
353 std::cout << "Optimal objective: " << objval << std::endl;
354 // write result
355 model.write(fileName+".sol");
356 }
357 else if (optimstatus == GRB_INFEASIBLE)
358 {
359 std::cout << "Model is infeasible" << std::endl;
360
361 // compute and write out IIS
362
363 model.computeIIS();
364 model.write(fileName+".ilp");
365 }
366 else if (optimstatus == GRB_UNBOUNDED)
367 {
368 std::cout << "Model is unbounded" << std::endl;
369 }
370 else
371 {
372 std::cout << "Optimization was stopped with status = "
373 << optimstatus << std::endl;
374 }
375 }
376 catch(GRBException e)
377 {
378 std::cout << "Error code = " << e.getErrorCode() << std::endl;
379 std::cout << e.getMessage() << std::endl;
380 }
381 catch (...)
382 {
383 std::cout << "Error during optimization" << std::endl;
384 }
385 }
386
387};
388#endif
389
390} // namespace solvers
391} // namespace limbo
392
393#endif
#define limboAssertMsg(condition, args...)
custom assertion with message
Definition AssertMsg.h:24
Basic utilities such as variables and linear expressions in solvers.
void errorHandler(GRBenv *env, int error) const
error handler
Definition GurobiApi.h:268
SolverProperty operator()(parameter_type *param=NULL)
API to run the algorithm.
Definition GurobiApi.h:126
LinearModel< model_type::coefficient_value_type, model_type::variable_value_type > model_type
Definition GurobiApi.h:100
GurobiLinearApi(model_type *model)
constructor
Definition GurobiApi.h:114
GurobiLinearApi & operator=(GurobiLinearApi const &rhs)
assignment, forbidden
GurobiLinearApi(GurobiLinearApi const &rhs)
copy constructor, forbidden
Base class for custom Gurobi parameters.
Definition GurobiApi.h:34
virtual ~GurobiParameters()
destructor
Definition GurobiApi.h:43
virtual void operator()(GRBenv *env) const
customize environment
Definition GurobiApi.h:46
void setNumThreads(int v)
set number of threads
Definition GurobiApi.h:65
virtual void operator()(GRBmodel *) const
customize model
Definition GurobiApi.h:56
void setOutputFlag(int v)
set output flag
Definition GurobiApi.h:62
int m_numThreads
number of threads
Definition GurobiApi.h:69
int m_outputFlag
control log from Gurobi
Definition GurobiApi.h:68
coefficient_value_type rightHandSide() const
Definition Solvers.h:1034
expression_type const & expression() const
Definition Solvers.h:1028
std::vector< term_type > const & terms() const
Definition Solvers.h:655
model to describe an optimization problem
Definition Solvers.h:1161
V variable_value_type
V variable.
Definition Solvers.h:1166
VariableProperty< variable_value_type > property_type
variable property type
Definition Solvers.h:1178
Variable< coefficient_value_type > variable_type
variable type
Definition Solvers.h:1170
T coefficient_value_type
T coefficient.
Definition Solvers.h:1164
LinearConstraint< coefficient_value_type > constraint_type
constraint type
Definition Solvers.h:1176
LinearExpression< coefficient_value_type > expression_type
expression type
Definition Solvers.h:1174
LinearTerm< coefficient_value_type > term_type
term type
Definition Solvers.h:1172
unsigned int id() const
Definition Solvers.h:117
namespace for Limbo.Solvers
SolverProperty
Some enums used in solver.
Definition Solvers.h:30
@ OPTIMAL
optimally solved
Definition Solvers.h:36
@ CONTINUOUS
floating point number
Definition Solvers.h:35
@ MIN
minimize objective
Definition Solvers.h:31
@ INFEASIBLE
the model is infeasible
Definition Solvers.h:37
@ UNBOUNDED
the model is unbounded
Definition Solvers.h:39
namespace for Limbo
std::iterator_traits< Iterator >::value_type max(Iterator first, Iterator last)
get max of an array
Definition Math.h:61
int limboPrint(MessageType m, const char *format,...)
formatted print with prefix
Definition PrintMsg.h:49
Round floating point solutions to integer if the variable type is integer. If not rounded,...
Definition CplexApi.h:89