2 #ifndef OPENGM_LP_GURPBI_HXX
3 #define OPENGM_LP_GURPBI_HXX
12 #include "gurobi_c++.h"
37 template<
class GM,
class ACC>
90 int numberOfThreads = 0
119 numberOfThreads_ = numberOfThreads;
120 integerConstraint_ =
false;
147 LPGurobi(
const GraphicalModelType&,
const Parameter& = Parameter());
149 virtual std::string
name()
const
150 {
return "LPGurobi"; }
153 template<
class VisitorType>
160 typename GM::ValueType
bound()
const;
161 typename GM::ValueType
value()
const;
165 template<
class LABELING_ITERATOR>
166 size_t lpFactorVi(
const IndexType factorIndex,LABELING_ITERATOR labelingBegin,LABELING_ITERATOR labelingEnd)
const;
167 template<
class LPVariableIndexIterator,
class CoefficientIterator>
173 if( filename.size()!=0)
174 model_->write(filename);
176 catch(GRBException e) {
177 std::cout <<
"**Error code = " << e.getErrorCode() <<
"\n";
178 std::cout << e.getMessage() <<
"\n";
182 std::cout <<
"Exception during write" <<
"\n";
189 void updateIfDirty();
191 const GraphicalModelType& gm_;
193 std::vector<size_t> idNodesBegin_;
194 std::vector<size_t> idFactorsBegin_;
195 std::vector<std::vector<size_t> > unaryFactors_;
196 bool inferenceStarted_;
200 std::vector<double> lpArg_;
201 std::vector<LabelType> arg_;
215 template<
class GM,
class ACC>
218 const GraphicalModelType& gm,
223 idNodesBegin_(gm_.numberOfVariables()),
224 idFactorsBegin_(gm_.numberOfFactors()),
225 unaryFactors_(gm_.numberOfVariables()),
226 inferenceStarted_(
false),
229 arg_(gm_.numberOfVariables(),0),
238 ACC::neutral(value_);
239 ACC::ineutral(bound_);
243 env_->set(GRB_IntParam_LogToConsole,
int(param_.verbose_));
246 switch(param_.nodeAlg_) {
248 env_->set(GRB_IntParam_NodeMethod,1);
250 case LP_SOLVER_PRIMAL_SIMPLEX:
251 env_->set(GRB_IntParam_NodeMethod,0);
253 case LP_SOLVER_DUAL_SIMPLEX:
254 env_->set(GRB_IntParam_NodeMethod,1);
256 case LP_SOLVER_NETWORK_SIMPLEX:
257 throw RuntimeError(
"Gurobi does not support Network Simplex");
259 case LP_SOLVER_BARRIER:
260 env_->set(GRB_IntParam_NodeMethod,2);
262 case LP_SOLVER_SIFTING:
265 case LP_SOLVER_CONCURRENT:
266 throw RuntimeError(
"Gurobi does not concurrent solvers");
271 switch(param_.rootAlg_) {
273 env_->set(GRB_IntParam_Method,-1);
275 case LP_SOLVER_PRIMAL_SIMPLEX:
276 env_->set(GRB_IntParam_Method,0);
278 case LP_SOLVER_DUAL_SIMPLEX:
279 env_->set(GRB_IntParam_Method,1);
281 case LP_SOLVER_NETWORK_SIMPLEX:
282 throw RuntimeError(
"Gurobi does not support Network Simplex");
284 case LP_SOLVER_BARRIER:
285 env_->set(GRB_IntParam_Method,2);
287 case LP_SOLVER_SIFTING:
288 env_->set(GRB_IntParam_Method,1);
289 env_->set(GRB_IntParam_SiftMethod,1);
291 case LP_SOLVER_CONCURRENT:
292 env_->set(GRB_IntParam_Method,4);
297 switch(param_.presolve_) {
298 case LP_PRESOLVE_AUTO:
299 env_->set(GRB_IntParam_Presolve,-1);
301 case LP_PRESOLVE_OFF:
302 env_->set(GRB_IntParam_Presolve,0);
304 case LP_PRESOLVE_CONSERVATIVE:
305 env_->set(GRB_IntParam_Presolve,1);
307 case LP_PRESOLVE_AGGRESSIVE:
308 env_->set(GRB_IntParam_Presolve,2);
313 switch(param_.mipFocus_) {
314 case MIP_EMPHASIS_BALANCED:
315 env_->set(GRB_IntParam_MIPFocus,0);
317 case MIP_EMPHASIS_FEASIBILITY:
318 env_->set(GRB_IntParam_MIPFocus,1);
320 case MIP_EMPHASIS_OPTIMALITY:
321 env_->set(GRB_IntParam_MIPFocus,2);
323 case MIP_EMPHASIS_BESTBOUND:
324 env_->set(GRB_IntParam_MIPFocus,3);
326 case MIP_EMPHASIS_HIDDENFEAS:
327 throw RuntimeError(
"Gurobi does not support hidden feasibility as MIP-focus");
332 env_->set(GRB_DoubleParam_Cutoff ,param_.cutUp_);
333 env_->set(GRB_DoubleParam_OptimalityTol ,param_.epOpt_);
334 env_->set(GRB_DoubleParam_IntFeasTol ,param_.epInt_);
335 env_->set(GRB_DoubleParam_MIPGapAbs ,param_.epAGap_);
336 env_->set(GRB_DoubleParam_MIPGap ,param_.epGap_);
337 env_->set(GRB_DoubleParam_FeasibilityTol,param_.epRHS_);
338 env_->set(GRB_DoubleParam_MarkowitzTol ,param_.epMrk_);
347 env_->set(GRB_DoubleParam_TimeLimit ,param_.timeLimit_);
350 if(param_.numberOfThreads_!=0)
351 env_->set(GRB_IntParam_Threads ,param_.numberOfThreads_);
357 if(param_.cutLevel_ != MIP_CUT_DEFAULT)
358 env_->set(GRB_IntParam_Cuts ,param_.getCutLevel(param_.cutLevel_));
359 if(param_.cliqueCutLevel_ != MIP_CUT_DEFAULT)
360 env_->set(GRB_IntParam_CliqueCuts ,param_.getCutLevel(param_.cliqueCutLevel_));
361 if(param_.coverCutLevel_ != MIP_CUT_DEFAULT)
362 env_->set(GRB_IntParam_CoverCuts ,param_.getCutLevel(param_.coverCutLevel_));
363 if(param_.gubCutLevel_ != MIP_CUT_DEFAULT)
364 env_->set(GRB_IntParam_GUBCoverCuts ,param_.getCutLevel(param_.gubCutLevel_));
365 if(param_.mirCutLevel_ != MIP_CUT_DEFAULT)
366 env_->set(GRB_IntParam_MIRCuts ,param_.getCutLevel(param_.mirCutLevel_));
367 if(param_.iboundCutLevel_ != MIP_CUT_DEFAULT)
368 env_->set(GRB_IntParam_ImpliedCuts ,param_.getCutLevel(param_.iboundCutLevel_));
369 if(param_.flowcoverCutLevel_ != MIP_CUT_DEFAULT)
370 env_->set(GRB_IntParam_FlowCoverCuts ,param_.getCutLevel(param_.flowcoverCutLevel_));
371 if(param_.flowpathCutLevel_ != MIP_CUT_DEFAULT)
372 env_->set(GRB_IntParam_FlowPathCuts ,param_.getCutLevel(param_.flowpathCutLevel_));
375 model_ =
new GRBModel(*env_);
377 catch(GRBException e) {
378 std::cout <<
"Error code = " << e.getErrorCode() <<
"\n";
379 std::cout << e.getMessage() <<
"\n";
382 std::cout <<
"Exception during construction of gurobi solver" <<
"\n";
388 throw RuntimeError(
"This implementation does only supports Min-Plus-Semiring");
392 idNodesBegin_.resize(gm_.numberOfVariables());
393 unaryFactors_.resize(gm_.numberOfVariables());
394 idFactorsBegin_.resize(gm_.numberOfFactors());
397 size_t numberOfElements = 0;
398 size_t numberOfVariableElements = 0;
399 size_t numberOfFactorElements = 0;
400 size_t maxLabel = 0 ;
401 size_t maxFacSize = 0;
403 size_t idCounter = 0;
404 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
405 numberOfVariableElements += gm_.numberOfLabels(node);
406 maxLabel=std::max(
size_t(gm_.numberOfLabels(node)),maxLabel);
408 idNodesBegin_[node] = idCounter;
409 idCounter += gm_.numberOfLabels(node);
412 for(
size_t f = 0; f < gm_.numberOfFactors(); ++f) {
413 if(gm_[f].numberOfVariables() == 1) {
414 size_t node = gm_[f].variableIndex(0);
415 unaryFactors_[node].push_back(f);
416 idFactorsBegin_[f] = idNodesBegin_[node];
419 idFactorsBegin_[f] = idCounter;
420 idCounter += gm_[f].size();
421 maxFacSize=std::max(
size_t(gm_[f].size()),maxFacSize);
422 numberOfFactorElements += gm_[f].size();
425 numberOfElements = numberOfVariableElements + numberOfFactorElements;
426 nLpVar_=numberOfElements;
431 throw RuntimeError(
"This implementation does only support Minimizer or Maximizer accumulators");
435 lpArg_.resize(nLpVar_);
436 std::vector<double> lb(numberOfElements,0.0);
437 std::vector<double> ub(numberOfElements,1.0);
438 std::vector<double> obj(numberOfElements);
439 std::vector<char> vtype(numberOfElements,GRB_CONTINUOUS);
441 if(param_.integerConstraint_) {
442 std::fill(vtype.begin(),vtype.begin()+numberOfVariableElements,GRB_BINARY);
446 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
447 for(
size_t i = 0; i < gm_.numberOfLabels(node); ++i) {
449 for(
size_t n=0; n<unaryFactors_[node].size();++n) {
450 t += gm_[unaryFactors_[node][n]](&i);
452 obj[idNodesBegin_[node]+i] = t;
456 for(
size_t f = 0; f < gm_.numberOfFactors(); ++f) {
457 if(gm_[f].numberOfVariables() == 2) {
459 size_t counter = idFactorsBegin_[f];
460 for(index[1]=0; index[1]<gm_[f].numberOfLabels(1);++index[1])
461 for(index[0]=0; index[0]<gm_[f].numberOfLabels(0);++index[0])
462 obj[counter++] = gm_[f](index);
464 else if(gm_[f].numberOfVariables() == 3) {
466 size_t counter = idFactorsBegin_[f] ;
467 for(index[2]=0; index[2]<gm_[f].numberOfLabels(2);++index[2])
468 for(index[1]=0; index[1]<gm_[f].numberOfLabels(1);++index[1])
469 for(index[0]=0; index[0]<gm_[f].numberOfLabels(0);++index[0])
470 obj[counter++] = gm_[f](index);
472 else if(gm_[f].numberOfVariables() == 4) {
474 size_t counter = idFactorsBegin_[f];
475 for(index[3]=0; index[3]<gm_[f].numberOfLabels(3);++index[3])
476 for(index[2]=0; index[2]<gm_[f].numberOfLabels(2);++index[2])
477 for(index[1]=0; index[1]<gm_[f].numberOfLabels(1);++index[1])
478 for(index[0]=0; index[0]<gm_[f].numberOfLabels(0);++index[0])
479 obj[counter++] = gm_[f](index);
481 else if(gm_[f].numberOfVariables() > 4) {
482 size_t counter = idFactorsBegin_[f];
483 std::vector<size_t> coordinate(gm_[f].numberOfVariables());
486 mit.coordinate(coordinate.begin());
487 obj[counter++] = gm_[f](coordinate.begin());
495 vars_ = model_->addVars(&lb[0],&ub[0],&obj[0],&vtype[0],NULL,numberOfElements);
499 catch(GRBException e) {
500 std::cout <<
"**Error code = " << e.getErrorCode() <<
"\n";
501 std::cout << e.getMessage() <<
"\n";
504 std::cout <<
"Exception during construction of gurobi model" <<
"\n";
510 size_t constraintCounter = 0;
512 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
517 for(
size_t f = 0; f < gm_.numberOfFactors(); ++f) {
518 if(gm_[f].numberOfVariables() > 1) {
519 for(
size_t n = 0; n < gm_[f].numberOfVariables(); ++n) {
520 size_t node = gm_[f].variableIndex(n);
521 for(
size_t i = 0; i < gm_.numberOfLabels(node); ++i) {
532 std::vector<GRBLinExpr> lhsExprs(constraintCounter);
533 std::vector<char> sense(constraintCounter,GRB_EQUAL);
534 std::vector<double> rhsVals(constraintCounter,0.0);
535 std::vector<std::string> names(constraintCounter,std::string());
537 std::fill(rhsVals.begin(),rhsVals.begin()+gm_.numberOfVariables(),1.0);
544 constraintCounter = 0;
547 const size_t buffferSize = std::max(maxLabel,
size_t(maxFacSize+1));
548 std::vector<GRBVar> localVars(buffferSize);
549 std::vector<double> localVal(buffferSize,1.0);
551 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
552 for(
size_t i = 0; i < gm_.numberOfLabels(node); ++i) {
553 localVars[i]=vars_[idNodesBegin_[node]+i];
555 lhsExprs[constraintCounter].addTerms(&localVal[0],&localVars[0],gm_.numberOfLabels(node));
562 for(
size_t f = 0; f < gm_.numberOfFactors(); ++f) {
563 if(gm_[f].numberOfVariables() > 1) {
565 size_t counter = idFactorsBegin_[f];
569 for(
size_t n = 0; n < gm_[f].numberOfVariables(); ++n) {
570 size_t node = gm_[f].variableIndex(n);
571 for(
size_t i = 0; i < gm_.numberOfLabels(node); ++i) {
576 size_t localCounter=1;
577 localVars[0]=vars_[idNodesBegin_[node]+i];
583 localVars[localCounter]=vars_[*vit];
586 lhsExprs[constraintCounter].addTerms(&localVal[0],&localVars[0],localCounter);
598 GRBConstr* constr = model_->addConstrs(&lhsExprs[0],&sense[0],&rhsVals[0],&names[0],constraintCounter);
601 catch(GRBException e) {
602 std::cout <<
"**Error code = " << e.getErrorCode() <<
"\n";
603 std::cout << e.getMessage() <<
"\n";
606 std::cout <<
"Exception during adding constring to gurobi model" <<
"\n";
614 template <
class GM,
class ACC>
621 template<
class GM,
class ACC>
622 template<
class VisitorType>
629 visitor.begin(*
this);
630 inferenceStarted_ =
true;
633 if(param_.integerConstraint_){
634 bound_ = model_->get(GRB_DoubleAttr_ObjBound);
637 bound_ = model_->get(GRB_DoubleAttr_ObjVal);
640 for(
size_t lpvi=0;lpvi<nLpVar_;++lpvi){
641 lpArg_[lpvi]=vars_[lpvi].get(GRB_DoubleAttr_X);
646 catch(GRBException e) {
647 std::cout <<
"Error code = " << e.getErrorCode() <<
"\n";
648 std::cout << e.getMessage() <<
"\n";
650 std::cout <<
"Exception during optimization" <<
"\n";
656 template <
class GM,
class ACC>
662 template <
class GM,
class ACC>
670 x.resize(gm_.numberOfVariables());
671 if(inferenceStarted_) {
672 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
673 ValueType value = lpArg_[idNodesBegin_[node]];
675 for(
size_t i = 1; i < gm_.numberOfLabels(node); ++i) {
676 if(lpArg_[idNodesBegin_[node]+i] > value) {
677 value = lpArg_[idNodesBegin_[node]+i];
686 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
693 template <
class GM,
class ACC>
700 size_t var[] = {nodeId};
701 size_t shape[] = {gm_.numberOfLabels(nodeId)};
702 out.assign(var, var + 1, shape, shape + 1);
703 for(
size_t i = 0; i < gm_.numberOfLabels(nodeId); ++i) {
704 out(i) = lpArg_[idNodesBegin_[nodeId]+i];
710 template <
class GM,
class ACC>
713 const size_t factorId,
717 std::vector<size_t> var(gm_[factorId].numberOfVariables());
718 std::vector<size_t> shape(gm_[factorId].numberOfVariables());
719 for(
size_t i = 0; i < gm_[factorId].numberOfVariables(); ++i) {
720 var[i] = gm_[factorId].variableIndex(i);
721 shape[i] = gm_[factorId].shape(i);
723 out.assign(var.begin(), var.end(), shape.begin(), shape.end());
724 if(gm_[factorId].numberOfVariables() == 1) {
725 size_t nodeId = gm_[factorId].variableIndex(0);
726 marginal(nodeId, out);
730 for(
size_t n = idFactorsBegin_[factorId]; n<idFactorsBegin_[factorId]+gm_[factorId].size(); ++n) {
731 out(c++) = lpArg_[n];
737 template<
class GM,
class ACC>
744 template<
class GM,
class ACC>
746 std::vector<LabelType> states;
748 return gm_.evaluate(states);
751 template<
class GM,
class ACC>
754 if(param_.integerConstraint_) {
764 template <
class GM,
class ACC>
773 return idNodesBegin_[variableIndex]+label;
777 template <
class GM,
class ACC>
782 const size_t labelingIndex
786 return idFactorsBegin_[factorIndex]+labelingIndex;
790 template <
class GM,
class ACC>
791 template<
class LABELING_ITERATOR>
796 LABELING_ITERATOR labelingBegin,
797 LABELING_ITERATOR labelingEnd
800 OPENGM_ASSERT(std::distance(labelingBegin,labelingEnd)==gm_[factorIndex].numberOfVariables());
801 const size_t numVar=gm_[factorIndex].numberOfVariables();
802 size_t labelingIndex=labelingBegin[0];
803 size_t strides=gm_[factorIndex].numberOfLabels(0);
804 for(
size_t vi=1;vi<numVar;++vi){
805 OPENGM_ASSERT(labelingBegin[vi]<gm_[factorIndex].numberOfLabels(vi));
806 labelingIndex+=strides*labelingBegin[vi];
807 strides*=gm_[factorIndex].numberOfLabels(vi);
809 return idFactorsBegin_[factorIndex]+labelingIndex;
826 template<
class GM,
class ACC>
827 template<
class LPVariableIndexIterator,
class CoefficientIterator>
829 LPVariableIndexIterator viBegin,
830 LPVariableIndexIterator viEnd,
831 CoefficientIterator coefficient,
838 while(viBegin != viEnd) {
839 expr += vars_[*viBegin] * (*coefficient);
845 model_->addConstr(expr, GRB_LESS_EQUAL, upperBound, name);
846 model_->addConstr(expr, GRB_GREATER_EQUAL, lowerBound, name);
852 template<
class GM,
class ACC>
GM::ValueType bound() const
return a bound on the solution
STL-compliant random access iterator for View and Marray.
Addition as a binary operation.
static const double default_epRHS_
MIP_CUT flowpathCutLevel_
size_t lpNodeVi(const IndexType variableIndex, const LabelType label) const
static const double default_cutUp_
Optimization by Linear Programming (LP) or Integer LP using Guroi http://www.gurobi.com.
virtual InferenceTermination infer()
const GraphicalModelType & graphicalModel() const
static const double default_epInt_
LPGurobi(const GraphicalModelType &, const Parameter &=Parameter())
Array-Interface to an interval of memory.
visitors::VerboseVisitor< LPGurobi< GM, ACC > > VerboseVisitorType
#define OPENGM_ASSERT(expression)
static const double default_epOpt_
static const double default_epAGap_
GraphicalModelType::OperatorType OperatorType
Parameter(int numberOfThreads=0)
constructor
static const double default_epMrk_
void variable(const size_t, IndependentFactorType &out) const
GM::ValueType value() const
return the solution (value)
visitors::TimingVisitor< LPGurobi< GM, ACC > > TimingVisitorType
GraphicalModelType::IndexType IndexType
static const double default_epGap_
void writeModelToDisk(const std::string &filename) const
void addConstraint(LPVariableIndexIterator, LPVariableIndexIterator, CoefficientIterator, const ValueType &, const ValueType &, const char *name=0)
add constraint
View< T, isConst, A > boundView(const size_t, const size_t=0) const
MIP_CUT flowcoverCutLevel_
GraphicalModelType::ValueType ValueType
Inference algorithm interface.
visitors::EmptyVisitor< LPGurobi< GM, ACC > > EmptyVisitorType
MIP_CUT disjunctCutLevel_
int getCutLevel(MIP_CUT cl)
void factorVariable(const size_t, IndependentFactorType &out) const
virtual InferenceTermination args(std::vector< std::vector< LabelType > > &) const
Runtime-flexible multi-dimensional array.
virtual std::string name() const
GraphicalModelType::LabelType LabelType
Minimization as a unary accumulation.
size_t lpFactorVi(const IndexType factorIndex, const size_t labelingIndex) const
GraphicalModelType::IndependentFactorType IndependentFactorType
virtual InferenceTermination arg(std::vector< LabelType > &, const size_t=1) const
output a solution