2 #ifndef OPENGM_LP_GURPBI_HXX 3 #define OPENGM_LP_GURPBI_HXX 12 #include "gurobi_c++.h" 37 template<
class GM,
class ACC>
54 template<
class _GM,
class _ACC>
99 integerConstraint_(p.integerConstraint_),
100 numberOfThreads_(p.numberOfThreads_),
101 verbose_(p.verbose_),
109 workMem_(p.workMem_),
110 treeMemoryLimit_(p.treeMemoryLimit_),
111 timeLimit_(p.timeLimit_),
112 probeingLevel_(p.probeingLevel_),
113 rootAlg_(p.rootAlg_),
114 nodeAlg_(p.nodeAlg_),
115 mipFocus_(p.mipFocus_),
116 presolve_(p.presolve_),
117 cutLevel_(p.cutLevel_),
118 cliqueCutLevel_(p.cliqueCutLevel_),
119 coverCutLevel_(p.coverCutLevel_),
120 gubCutLevel_(p.gubCutLevel_),
121 mirCutLevel_(p.mirCutLevel_),
122 iboundCutLevel_(p.iboundCutLevel_),
123 flowcoverCutLevel_(p.flowcoverCutLevel_),
124 flowpathCutLevel_(p.flowpathCutLevel_),
125 disjunctCutLevel_(p.disjunctCutLevel_),
126 gomoryCutLevel_(p.gomoryCutLevel_)
136 int numberOfThreads = 0
138 : numberOfThreads_(numberOfThreads),
142 treeMemoryLimit_(1e+75),
165 numberOfThreads_ = numberOfThreads;
166 integerConstraint_ =
false;
195 virtual std::string
name()
const 196 {
return "LPGurobi"; }
199 template<
class VisitorType>
206 typename GM::ValueType
bound()
const;
207 typename GM::ValueType
value()
const;
211 template<
class LABELING_ITERATOR>
212 size_t lpFactorVi(
const IndexType factorIndex,LABELING_ITERATOR labelingBegin,LABELING_ITERATOR labelingEnd)
const;
213 template<
class LPVariableIndexIterator,
class CoefficientIterator>
219 if( filename.size()!=0)
220 model_->write(filename);
222 catch(GRBException e) {
223 std::cout <<
"**Error code = " << e.getErrorCode() <<
"\n";
224 std::cout << e.getMessage() <<
"\n";
228 std::cout <<
"Exception during write" <<
"\n";
235 void updateIfDirty();
237 const GraphicalModelType& gm_;
239 std::vector<size_t> idNodesBegin_;
240 std::vector<size_t> idFactorsBegin_;
241 std::vector<std::vector<size_t> > unaryFactors_;
242 bool inferenceStarted_;
246 std::vector<double> lpArg_;
247 std::vector<LabelType> arg_;
261 template<
class GM,
class ACC>
264 const GraphicalModelType& gm,
269 idNodesBegin_(gm_.numberOfVariables()),
270 idFactorsBegin_(gm_.numberOfFactors()),
271 unaryFactors_(gm_.numberOfVariables()),
272 inferenceStarted_(
false),
275 arg_(gm_.numberOfVariables(),0),
284 ACC::neutral(value_);
285 ACC::ineutral(bound_);
289 env_->set(GRB_IntParam_LogToConsole,
int(param_.verbose_));
292 switch(param_.nodeAlg_) {
294 env_->set(GRB_IntParam_NodeMethod,1);
297 env_->set(GRB_IntParam_NodeMethod,0);
300 env_->set(GRB_IntParam_NodeMethod,1);
303 throw RuntimeError(
"Gurobi does not support Network Simplex");
306 env_->set(GRB_IntParam_NodeMethod,2);
312 throw RuntimeError(
"Gurobi does not concurrent solvers");
317 switch(param_.rootAlg_) {
319 env_->set(GRB_IntParam_Method,-1);
322 env_->set(GRB_IntParam_Method,0);
325 env_->set(GRB_IntParam_Method,1);
328 throw RuntimeError(
"Gurobi does not support Network Simplex");
331 env_->set(GRB_IntParam_Method,2);
334 env_->set(GRB_IntParam_Method,1);
335 env_->set(GRB_IntParam_SiftMethod,1);
338 env_->set(GRB_IntParam_Method,4);
343 switch(param_.presolve_) {
345 env_->set(GRB_IntParam_Presolve,-1);
348 env_->set(GRB_IntParam_Presolve,0);
351 env_->set(GRB_IntParam_Presolve,1);
354 env_->set(GRB_IntParam_Presolve,2);
359 switch(param_.mipFocus_) {
361 env_->set(GRB_IntParam_MIPFocus,0);
364 env_->set(GRB_IntParam_MIPFocus,1);
367 env_->set(GRB_IntParam_MIPFocus,2);
370 env_->set(GRB_IntParam_MIPFocus,3);
373 throw RuntimeError(
"Gurobi does not support hidden feasibility as MIP-focus");
378 env_->set(GRB_DoubleParam_Cutoff ,param_.cutUp_);
379 env_->set(GRB_DoubleParam_OptimalityTol ,param_.epOpt_);
380 env_->set(GRB_DoubleParam_IntFeasTol ,param_.epInt_);
381 env_->set(GRB_DoubleParam_MIPGapAbs ,param_.epAGap_);
382 env_->set(GRB_DoubleParam_MIPGap ,param_.epGap_);
383 env_->set(GRB_DoubleParam_FeasibilityTol,param_.epRHS_);
384 env_->set(GRB_DoubleParam_MarkowitzTol ,param_.epMrk_);
393 env_->set(GRB_DoubleParam_TimeLimit ,param_.timeLimit_);
396 if(param_.numberOfThreads_!=0)
397 env_->set(GRB_IntParam_Threads ,param_.numberOfThreads_);
404 env_->set(GRB_IntParam_Cuts ,param_.getCutLevel(param_.cutLevel_));
406 env_->set(GRB_IntParam_CliqueCuts ,param_.getCutLevel(param_.cliqueCutLevel_));
408 env_->set(GRB_IntParam_CoverCuts ,param_.getCutLevel(param_.coverCutLevel_));
410 env_->set(GRB_IntParam_GUBCoverCuts ,param_.getCutLevel(param_.gubCutLevel_));
412 env_->set(GRB_IntParam_MIRCuts ,param_.getCutLevel(param_.mirCutLevel_));
414 env_->set(GRB_IntParam_ImpliedCuts ,param_.getCutLevel(param_.iboundCutLevel_));
416 env_->set(GRB_IntParam_FlowCoverCuts ,param_.getCutLevel(param_.flowcoverCutLevel_));
418 env_->set(GRB_IntParam_FlowPathCuts ,param_.getCutLevel(param_.flowpathCutLevel_));
421 model_ =
new GRBModel(*env_);
423 catch(GRBException e) {
424 std::cout <<
"Error code = " << e.getErrorCode() <<
"\n";
425 std::cout << e.getMessage() <<
"\n";
428 std::cout <<
"Exception during construction of gurobi solver" <<
"\n";
434 throw RuntimeError(
"This implementation does only supports Min-Plus-Semiring");
438 idNodesBegin_.resize(gm_.numberOfVariables());
439 unaryFactors_.resize(gm_.numberOfVariables());
440 idFactorsBegin_.resize(gm_.numberOfFactors());
443 size_t numberOfElements = 0;
444 size_t numberOfVariableElements = 0;
445 size_t numberOfFactorElements = 0;
446 size_t maxLabel = 0 ;
447 size_t maxFacSize = 0;
449 size_t idCounter = 0;
450 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
451 numberOfVariableElements += gm_.numberOfLabels(node);
452 maxLabel=std::max(
size_t(gm_.numberOfLabels(node)),maxLabel);
454 idNodesBegin_[node] = idCounter;
455 idCounter += gm_.numberOfLabels(node);
458 for(
size_t f = 0; f < gm_.numberOfFactors(); ++f) {
459 if(gm_[f].numberOfVariables() == 1) {
460 size_t node = gm_[f].variableIndex(0);
461 unaryFactors_[node].push_back(f);
462 idFactorsBegin_[f] = idNodesBegin_[node];
465 idFactorsBegin_[f] = idCounter;
466 idCounter += gm_[f].size();
467 maxFacSize=std::max(
size_t(gm_[f].size()),maxFacSize);
468 numberOfFactorElements += gm_[f].size();
471 numberOfElements = numberOfVariableElements + numberOfFactorElements;
472 nLpVar_=numberOfElements;
477 throw RuntimeError(
"This implementation does only support Minimizer or Maximizer accumulators");
481 lpArg_.resize(nLpVar_);
482 std::vector<double> lb(numberOfElements,0.0);
483 std::vector<double> ub(numberOfElements,1.0);
484 std::vector<double> obj(numberOfElements);
485 std::vector<char> vtype(numberOfElements,GRB_CONTINUOUS);
487 if(param_.integerConstraint_) {
488 std::fill(vtype.begin(),vtype.begin()+numberOfVariableElements,GRB_BINARY);
492 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
493 for(
size_t i = 0; i < gm_.numberOfLabels(node); ++i) {
495 for(
size_t n=0; n<unaryFactors_[node].size();++n) {
496 t += gm_[unaryFactors_[node][n]](&i);
498 obj[idNodesBegin_[node]+i] = t;
502 for(
size_t f = 0; f < gm_.numberOfFactors(); ++f) {
503 if(gm_[f].numberOfVariables() == 2) {
505 size_t counter = idFactorsBegin_[f];
506 for(index[1]=0; index[1]<gm_[f].numberOfLabels(1);++index[1])
507 for(index[0]=0; index[0]<gm_[f].numberOfLabels(0);++index[0])
508 obj[counter++] = gm_[f](index);
510 else if(gm_[f].numberOfVariables() == 3) {
512 size_t counter = idFactorsBegin_[f] ;
513 for(index[2]=0; index[2]<gm_[f].numberOfLabels(2);++index[2])
514 for(index[1]=0; index[1]<gm_[f].numberOfLabels(1);++index[1])
515 for(index[0]=0; index[0]<gm_[f].numberOfLabels(0);++index[0])
516 obj[counter++] = gm_[f](index);
518 else if(gm_[f].numberOfVariables() == 4) {
520 size_t counter = idFactorsBegin_[f];
521 for(index[3]=0; index[3]<gm_[f].numberOfLabels(3);++index[3])
522 for(index[2]=0; index[2]<gm_[f].numberOfLabels(2);++index[2])
523 for(index[1]=0; index[1]<gm_[f].numberOfLabels(1);++index[1])
524 for(index[0]=0; index[0]<gm_[f].numberOfLabels(0);++index[0])
525 obj[counter++] = gm_[f](index);
527 else if(gm_[f].numberOfVariables() > 4) {
528 size_t counter = idFactorsBegin_[f];
529 std::vector<size_t> coordinate(gm_[f].numberOfVariables());
532 mit.coordinate(coordinate.begin());
533 obj[counter++] = gm_[f](coordinate.begin());
541 vars_ = model_->addVars(&lb[0],&ub[0],&obj[0],&vtype[0],NULL,numberOfElements);
545 catch(GRBException e) {
546 std::cout <<
"**Error code = " << e.getErrorCode() <<
"\n";
547 std::cout << e.getMessage() <<
"\n";
550 std::cout <<
"Exception during construction of gurobi model" <<
"\n";
556 size_t constraintCounter = 0;
558 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
563 for(
size_t f = 0; f < gm_.numberOfFactors(); ++f) {
564 if(gm_[f].numberOfVariables() > 1) {
565 for(
size_t n = 0; n < gm_[f].numberOfVariables(); ++n) {
566 size_t node = gm_[f].variableIndex(n);
567 for(
size_t i = 0; i < gm_.numberOfLabels(node); ++i) {
578 std::vector<GRBLinExpr> lhsExprs(constraintCounter);
579 std::vector<char> sense(constraintCounter,GRB_EQUAL);
580 std::vector<double> rhsVals(constraintCounter,0.0);
581 std::vector<std::string> names(constraintCounter,std::string());
583 std::fill(rhsVals.begin(),rhsVals.begin()+gm_.numberOfVariables(),1.0);
590 constraintCounter = 0;
593 const size_t buffferSize = std::max(maxLabel,
size_t(maxFacSize+1));
594 std::vector<GRBVar> localVars(buffferSize);
595 std::vector<double> localVal(buffferSize,1.0);
597 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
598 for(
size_t i = 0; i < gm_.numberOfLabels(node); ++i) {
599 localVars[i]=vars_[idNodesBegin_[node]+i];
601 lhsExprs[constraintCounter].addTerms(&localVal[0],&localVars[0],gm_.numberOfLabels(node));
608 for(
size_t f = 0; f < gm_.numberOfFactors(); ++f) {
609 if(gm_[f].numberOfVariables() > 1) {
611 size_t counter = idFactorsBegin_[f];
615 for(
size_t n = 0; n < gm_[f].numberOfVariables(); ++n) {
616 size_t node = gm_[f].variableIndex(n);
617 for(
size_t i = 0; i < gm_.numberOfLabels(node); ++i) {
622 size_t localCounter=1;
623 localVars[0]=vars_[idNodesBegin_[node]+i];
629 localVars[localCounter]=vars_[*vit];
632 lhsExprs[constraintCounter].addTerms(&localVal[0],&localVars[0],localCounter);
644 GRBConstr* constr = model_->addConstrs(&lhsExprs[0],&sense[0],&rhsVals[0],&names[0],constraintCounter);
647 catch(GRBException e) {
648 std::cout <<
"**Error code = " << e.getErrorCode() <<
"\n";
649 std::cout << e.getMessage() <<
"\n";
652 std::cout <<
"Exception during adding constring to gurobi model" <<
"\n";
660 template <
class GM,
class ACC>
667 template<
class GM,
class ACC>
668 template<
class VisitorType>
675 visitor.begin(*
this);
676 inferenceStarted_ =
true;
679 if(param_.integerConstraint_){
680 bound_ = model_->get(GRB_DoubleAttr_ObjBound);
683 bound_ = model_->get(GRB_DoubleAttr_ObjVal);
686 for(
size_t lpvi=0;lpvi<nLpVar_;++lpvi){
687 lpArg_[lpvi]=vars_[lpvi].get(GRB_DoubleAttr_X);
692 catch(GRBException e) {
693 std::cout <<
"Error code = " << e.getErrorCode() <<
"\n";
694 std::cout << e.getMessage() <<
"\n";
696 std::cout <<
"Exception during optimization" <<
"\n";
702 template <
class GM,
class ACC>
708 template <
class GM,
class ACC>
716 x.resize(gm_.numberOfVariables());
717 if(inferenceStarted_) {
718 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
721 for(
size_t i = 1; i < gm_.numberOfLabels(node); ++i) {
722 if(lpArg_[idNodesBegin_[node]+i] > value) {
723 value = lpArg_[idNodesBegin_[node]+i];
732 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
739 template <
class GM,
class ACC>
746 size_t var[] = {nodeId};
747 size_t shape[] = {gm_.numberOfLabels(nodeId)};
748 out.assign(var, var + 1, shape, shape + 1);
749 for(
size_t i = 0; i < gm_.numberOfLabels(nodeId); ++i) {
750 out(i) = lpArg_[idNodesBegin_[nodeId]+i];
756 template <
class GM,
class ACC>
759 const size_t factorId,
763 std::vector<size_t> var(gm_[factorId].numberOfVariables());
764 std::vector<size_t> shape(gm_[factorId].numberOfVariables());
765 for(
size_t i = 0; i < gm_[factorId].numberOfVariables(); ++i) {
766 var[i] = gm_[factorId].variableIndex(i);
767 shape[i] = gm_[factorId].shape(i);
769 out.assign(var.begin(), var.end(), shape.begin(), shape.end());
770 if(gm_[factorId].numberOfVariables() == 1) {
771 size_t nodeId = gm_[factorId].variableIndex(0);
776 for(
size_t n = idFactorsBegin_[factorId]; n<idFactorsBegin_[factorId]+gm_[factorId].size(); ++n) {
777 out(c++) = lpArg_[n];
783 template<
class GM,
class ACC>
790 template<
class GM,
class ACC>
792 std::vector<LabelType> states;
794 return gm_.evaluate(states);
797 template<
class GM,
class ACC>
800 if(param_.integerConstraint_) {
810 template <
class GM,
class ACC>
819 return idNodesBegin_[variableIndex]+label;
823 template <
class GM,
class ACC>
828 const size_t labelingIndex
832 return idFactorsBegin_[factorIndex]+labelingIndex;
836 template <
class GM,
class ACC>
837 template<
class LABELING_ITERATOR>
842 LABELING_ITERATOR labelingBegin,
843 LABELING_ITERATOR labelingEnd
846 OPENGM_ASSERT(std::distance(labelingBegin,labelingEnd)==gm_[factorIndex].numberOfVariables());
847 const size_t numVar=gm_[factorIndex].numberOfVariables();
848 size_t labelingIndex=labelingBegin[0];
849 size_t strides=gm_[factorIndex].numberOfLabels(0);
850 for(
size_t vi=1;vi<numVar;++vi){
851 OPENGM_ASSERT(labelingBegin[vi]<gm_[factorIndex].numberOfLabels(vi));
852 labelingIndex+=strides*labelingBegin[vi];
853 strides*=gm_[factorIndex].numberOfLabels(vi);
855 return idFactorsBegin_[factorIndex]+labelingIndex;
872 template<
class GM,
class ACC>
873 template<
class LPVariableIndexIterator,
class CoefficientIterator>
875 LPVariableIndexIterator viBegin,
876 LPVariableIndexIterator viEnd,
877 CoefficientIterator coefficient,
884 while(viBegin != viEnd) {
885 expr += vars_[*viBegin] * (*coefficient);
891 model_->addConstr(expr, GRB_LESS_EQUAL, upperBound, name);
892 model_->addConstr(expr, GRB_GREATER_EQUAL, lowerBound, name);
898 template<
class GM,
class ACC>
LPGurobi< _GM, _ACC > type
GM::ValueType bound() const
return a bound on the solution
virtual std::string name() const
STL-compliant random access iterator for View and Marray.
Addition as a binary operation.
static const double default_epRHS_
MIP_CUT flowpathCutLevel_
iterator end()
Get the end-iterator.
GM::ValueType value() const
return the solution (value)
static const double default_cutUp_
Optimization by Linear Programming (LP) or Integer LP using Guroi http://www.gurobi.com.
virtual InferenceTermination infer()
static const double default_epInt_
LPGurobi(const GraphicalModelType &, const Parameter &=Parameter())
Array-Interface to an interval of memory.
visitors::VerboseVisitor< LPGurobi< GM, ACC > > VerboseVisitorType
const GraphicalModelType & graphicalModel() const
#define OPENGM_ASSERT(expression)
size_t lpNodeVi(const IndexType variableIndex, const LabelType label) const
View< T, isConst, A > boundView(const size_t, const size_t=0) const
Get a View where one coordinate is bound to a value.
static const double default_epOpt_
static const double default_epAGap_
GraphicalModelType::OperatorType OperatorType
iterator begin()
Get an iterator to the beginning.
static const double default_epMrk_
void variable(const size_t, IndependentFactorType &out) const
virtual InferenceTermination args(std::vector< std::vector< LabelType > > &) const
void writeModelToDisk(const std::string &filename) const
visitors::TimingVisitor< LPGurobi< GM, ACC > > TimingVisitorType
GraphicalModelType::IndexType IndexType
static const double default_epGap_
void addConstraint(LPVariableIndexIterator, LPVariableIndexIterator, CoefficientIterator, const ValueType &, const ValueType &, const char *name=0)
add constraint
MIP_CUT flowcoverCutLevel_
LPGurobi< _GM, ACC > type
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 marginal(const size_t, IndependentFactorType &) const
output a solution for a marginal for a specific variable
Runtime-flexible multi-dimensional array.
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