2 #ifndef OPENGM_LP_CPLEX_HXX 3 #define OPENGM_LP_CPLEX_HXX 12 #include <ilcplex/ilocplex.h> 37 template<
class GM,
class ACC>
53 template<
class _GM,
class _ACC>
103 integerConstraint_(p.integerConstraint_),
104 numberOfThreads_(p.numberOfThreads_),
105 verbose_(p.verbose_),
113 workMem_(p.workMem_),
114 treeMemoryLimit_(p.treeMemoryLimit_),
115 timeLimit_(p.timeLimit_),
116 probeingLevel_(p.probeingLevel_),
117 rootAlg_(p.rootAlg_),
118 nodeAlg_(p.nodeAlg_),
119 presolve_(p.presolve_),
120 mipEmphasis_(p.mipEmphasis_),
121 cutLevel_(p.cutLevel_),
122 cliqueCutLevel_(p.cliqueCutLevel_),
123 coverCutLevel_(p.coverCutLevel_),
124 gubCutLevel_(p.gubCutLevel_),
125 mirCutLevel_(p.mirCutLevel_),
126 iboundCutLevel_(p.iboundCutLevel_),
127 flowcoverCutLevel_(p.flowcoverCutLevel_),
128 flowpathCutLevel_(p.flowpathCutLevel_),
129 disjunctCutLevel_(p.disjunctCutLevel_),
130 gomoryCutLevel_(p.gomoryCutLevel_)
140 int numberOfThreads = 0
142 : numberOfThreads_(numberOfThreads),
146 treeMemoryLimit_(1e+75),
168 numberOfThreads_ = numberOfThreads;
169 integerConstraint_ =
false;
199 virtual std::string
name()
const 200 {
return "LPCplex"; }
203 template<
class VisitorType>
210 typename GM::ValueType
bound()
const;
211 typename GM::ValueType
value()
const;
217 template<
class LABELING_ITERATOR>
218 size_t lpFactorVi(
const IndexType factorIndex,LABELING_ITERATOR labelingBegin,LABELING_ITERATOR labelingEnd)
const;
219 template<
class LPVariableIndexIterator,
class CoefficientIterator>
223 const GraphicalModelType& gm_;
225 std::vector<size_t> idNodesBegin_;
226 std::vector<size_t> idFactorsBegin_;
227 std::vector<std::vector<size_t> > unaryFactors_;
228 bool inferenceStarted_;
240 template<
class GM,
class ACC>
243 const GraphicalModelType& gm,
246 : gm_(gm), inferenceStarted_(
false)
249 throw RuntimeError(
"This implementation does only supports Min-Plus-Semiring and Max-Plus-Semiring.");
252 idNodesBegin_.resize(gm_.numberOfVariables());
253 unaryFactors_.resize(gm_.numberOfVariables());
254 idFactorsBegin_.resize(gm_.numberOfFactors());
257 IloInt numberOfElements = 0;
258 IloInt numberOfVariableElements = 0;
259 IloInt numberOfFactorElements = 0;
261 size_t idCounter = 0;
262 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
263 numberOfVariableElements += gm_.numberOfLabels(node);
264 idNodesBegin_[node] = idCounter;
265 idCounter += gm_.numberOfLabels(node);
269 for(
size_t f = 0; f < gm_.numberOfFactors(); ++f) {
270 if(gm_[f].numberOfVariables() == 0) {
272 constValue_ += gm_[f](&l);
274 else if(gm_[f].numberOfVariables() == 1) {
275 size_t node = gm_[f].variableIndex(0);
276 unaryFactors_[node].push_back(f);
277 idFactorsBegin_[f] = idNodesBegin_[node];
280 idFactorsBegin_[f] = idCounter;
281 idCounter += gm_[f].size();
282 numberOfFactorElements += gm_[f].size();
285 numberOfElements = numberOfVariableElements + numberOfFactorElements;
287 model_ = IloModel(env_);
288 x_ = IloNumVarArray(env_);
289 c_ = IloRangeArray(env_);
290 sol_ = IloNumArray(env_);
293 obj_ = IloMinimize(env_);
295 obj_ = IloMaximize(env_);
297 throw RuntimeError(
"This implementation does only support Minimizer or Maximizer accumulators");
300 if(parameter_.integerConstraint_) {
301 x_.add(IloNumVarArray(env_, numberOfVariableElements, 0, 1, ILOBOOL));
304 x_.add(IloNumVarArray(env_, numberOfVariableElements, 0, 1));
306 x_.add(IloNumVarArray(env_, numberOfFactorElements, 0, 1));
307 IloNumArray obj(env_, numberOfElements);
309 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
310 for(
size_t i = 0; i < gm_.numberOfLabels(node); ++i) {
312 for(
size_t n=0; n<unaryFactors_[node].size();++n) {
313 t += gm_[unaryFactors_[node][n]](&i);
316 obj[idNodesBegin_[node]+i] = t;
319 for(
size_t f = 0; f < gm_.numberOfFactors(); ++f) {
320 if(gm_[f].numberOfVariables() == 2) {
322 size_t counter = idFactorsBegin_[f];
323 for(index[1]=0; index[1]<gm_[f].numberOfLabels(1);++index[1])
324 for(index[0]=0; index[0]<gm_[f].numberOfLabels(0);++index[0])
325 obj[counter++] = gm_[f](index);
327 else if(gm_[f].numberOfVariables() == 3) {
329 size_t counter = idFactorsBegin_[f] ;
330 for(index[2]=0; index[2]<gm_[f].numberOfLabels(2);++index[2])
331 for(index[1]=0; index[1]<gm_[f].numberOfLabels(1);++index[1])
332 for(index[0]=0; index[0]<gm_[f].numberOfLabels(0);++index[0])
333 obj[counter++] = gm_[f](index);
335 else if(gm_[f].numberOfVariables() == 4) {
337 size_t counter = idFactorsBegin_[f];
338 for(index[3]=0; index[3]<gm_[f].numberOfLabels(3);++index[3])
339 for(index[2]=0; index[2]<gm_[f].numberOfLabels(2);++index[2])
340 for(index[1]=0; index[1]<gm_[f].numberOfLabels(1);++index[1])
341 for(index[0]=0; index[0]<gm_[f].numberOfLabels(0);++index[0])
342 obj[counter++] = gm_[f](index);
344 else if(gm_[f].numberOfVariables() > 4) {
345 size_t counter = idFactorsBegin_[f];
346 std::vector<size_t> coordinate(gm_[f].numberOfVariables());
349 mit.coordinate(coordinate.begin());
350 obj[counter++] = gm_[f](coordinate.begin());
354 obj_.setLinearCoefs(x_, obj);
356 size_t constraintCounter = 0;
358 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
359 c_.add(IloRange(env_, 1, 1));
360 for(
size_t i = 0; i < gm_.numberOfLabels(node); ++i) {
361 c_[constraintCounter].setLinearCoef(x_[idNodesBegin_[node]+i], 1);
366 for(
size_t f = 0; f < gm_.numberOfFactors(); ++f) {
367 if(gm_[f].numberOfVariables() > 1) {
369 size_t counter = idFactorsBegin_[f];
373 for(
size_t n = 0; n < gm_[f].numberOfVariables(); ++n) {
374 size_t node = gm_[f].variableIndex(n);
375 for(
size_t i = 0; i < gm_.numberOfLabels(node); ++i) {
376 c_.add(IloRange(env_, 0, 0));
377 c_[constraintCounter].setLinearCoef(x_[idNodesBegin_[node]+i], -1);
380 c_[constraintCounter].setLinearCoef(x_[*vit], 1);
391 cplex_ = IloCplex(model_);
393 catch(IloCplex::Exception& e) {
394 throw std::runtime_error(
"CPLEX exception");
398 template <
class GM,
class ACC>
405 template<
class GM,
class ACC>
406 template<
class VisitorType>
412 visitor.begin(*
this);
413 inferenceStarted_ =
true;
416 switch(parameter_.rootAlg_) {
418 cplex_.setParam(IloCplex::RootAlg, 0);
421 cplex_.setParam(IloCplex::RootAlg, 1);
424 cplex_.setParam(IloCplex::RootAlg, 2);
427 cplex_.setParam(IloCplex::RootAlg, 3);
430 cplex_.setParam(IloCplex::RootAlg, 4);
433 cplex_.setParam(IloCplex::RootAlg, 5);
436 cplex_.setParam(IloCplex::RootAlg, 6);
441 switch(parameter_.nodeAlg_) {
443 cplex_.setParam(IloCplex::NodeAlg, 0);
446 cplex_.setParam(IloCplex::NodeAlg, 1);
449 cplex_.setParam(IloCplex::NodeAlg, 2);
452 cplex_.setParam(IloCplex::NodeAlg, 3);
455 cplex_.setParam(IloCplex::NodeAlg, 4);
458 cplex_.setParam(IloCplex::NodeAlg, 5);
461 cplex_.setParam(IloCplex::NodeAlg, 6);
466 switch(parameter_.presolve_) {
468 cplex_.setParam(IloCplex::PreInd, CPX_ON);
469 cplex_.setParam(IloCplex::RelaxPreInd, -1);
472 cplex_.setParam(IloCplex::PreInd, CPX_OFF);
473 cplex_.setParam(IloCplex::RelaxPreInd, 0);
476 cplex_.setParam(IloCplex::PreInd, CPX_ON);
477 cplex_.setParam(IloCplex::RelaxPreInd, -1);
480 cplex_.setParam(IloCplex::PreInd, CPX_ON);
481 cplex_.setParam(IloCplex::RelaxPreInd, 1);
486 switch(parameter_.mipEmphasis_) {
488 cplex_.setParam(IloCplex::MIPEmphasis, 0);
491 cplex_.setParam(IloCplex::MIPEmphasis, 1);
494 cplex_.setParam(IloCplex::MIPEmphasis, 2);
497 cplex_.setParam(IloCplex::MIPEmphasis, 3);
500 cplex_.setParam(IloCplex::MIPEmphasis, 4);
505 if(parameter_.verbose_ ==
false) {
506 cplex_.setParam(IloCplex::MIPDisplay, 0);
507 cplex_.setParam(IloCplex::BarDisplay, 0);
508 cplex_.setParam(IloCplex::SimDisplay, 0);
509 cplex_.setParam(IloCplex::NetDisplay, 0);
510 cplex_.setParam(IloCplex::SiftDisplay, 0);
514 cplex_.setParam(IloCplex::EpOpt, parameter_.epOpt_);
515 cplex_.setParam(IloCplex::EpMrk, parameter_.epMrk_);
516 cplex_.setParam(IloCplex::EpRHS, parameter_.epRHS_);
517 cplex_.setParam(IloCplex::EpInt, parameter_.epInt_);
518 cplex_.setParam(IloCplex::EpAGap, parameter_.epAGap_);
519 cplex_.setParam(IloCplex::EpGap, parameter_.epGap_);
522 cplex_.setParam(IloCplex::CutUp, parameter_.cutUp_);
525 cplex_.setParam(IloCplex::WorkMem, parameter_.workMem_);
526 cplex_.setParam(IloCplex::ClockType,2);
527 cplex_.setParam(IloCplex::TreLim,parameter_.treeMemoryLimit_);
528 cplex_.setParam(IloCplex::MemoryEmphasis, 1);
531 cplex_.setParam(IloCplex::TiLim, parameter_.timeLimit_);
534 cplex_.setParam(IloCplex::Threads, parameter_.numberOfThreads_);
537 cplex_.setParam(IloCplex::Probe, parameter_.probeingLevel_);
539 int cl = parameter_.getCutLevel(parameter_.cutLevel_);
540 cplex_.setParam(IloCplex::Covers, cl);
541 cplex_.setParam(IloCplex::Cliques, cl);
542 cplex_.setParam(IloCplex::DisjCuts, cl);
543 cplex_.setParam(IloCplex::Cliques, cl);
544 cplex_.setParam(IloCplex::MIRCuts, cl);
545 cplex_.setParam(IloCplex::GUBCovers, cl);
546 cplex_.setParam(IloCplex::FlowCovers, cl);
547 cplex_.setParam(IloCplex::FlowPaths, cl);
548 cplex_.setParam(IloCplex::ImplBd, cl);
549 cplex_.setParam(IloCplex::FracCuts, cl);
559 if(!cplex_.solve()) {
560 std::cout <<
"failed to optimize. " <<cplex_.getStatus() << std::endl;
561 inferenceStarted_ = 0;
564 cplex_.getValues(sol_, x_);
566 catch(IloCplex::Exception e) {
567 std::cout <<
"caught CPLEX exception: " << e << std::endl;
574 template <
class GM,
class ACC>
579 template <
class GM,
class ACC>
586 x.resize(gm_.numberOfVariables());
587 if(inferenceStarted_) {
588 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
591 for(
size_t i = 1; i < gm_.numberOfLabels(node); ++i) {
592 if(sol_[idNodesBegin_[node]+i] > value) {
593 value = sol_[idNodesBegin_[node]+i];
601 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
609 template <
class GM,
class ACC>
615 size_t var[] = {nodeId};
616 size_t shape[] = {gm_.numberOfLabels(nodeId)};
617 out.assign(var, var + 1, shape, shape + 1);
618 for(
size_t i = 0; i < gm_.numberOfLabels(nodeId); ++i) {
619 out(i) = sol_[idNodesBegin_[nodeId]+i];
624 template <
class GM,
class ACC>
627 const size_t factorId,
630 std::vector<size_t> var(gm_[factorId].numberOfVariables());
631 std::vector<size_t> shape(gm_[factorId].numberOfVariables());
632 for(
size_t i = 0; i < gm_[factorId].numberOfVariables(); ++i) {
633 var[i] = gm_[factorId].variableIndex(i);
634 shape[i] = gm_[factorId].shape(i);
636 out.assign(var.begin(), var.end(), shape.begin(), shape.end());
637 if(gm_[factorId].numberOfVariables() == 1) {
638 size_t nodeId = gm_[factorId].variableIndex(0);
643 for(
size_t n = idFactorsBegin_[factorId]; n<idFactorsBegin_[factorId]+gm_[factorId].size(); ++n) {
650 template<
class GM,
class ACC>
655 IloNumVarArray vars(env_);
656 IloNumArray values(env_);
657 for(
IndexType var=0; var<gm_.numberOfVariables(); ++var){
658 const IloNumVar lpvar = x_[
lpNodeVi(var,*(begin+var))];
662 cplex_.addMIPStart(vars, values);
667 template<
class GM,
class ACC>
674 template<
class GM,
class ACC>
676 std::vector<LabelType> states;
678 return gm_.evaluate(states);
681 template<
class GM,
class ACC>
683 if(inferenceStarted_) {
684 if(parameter_.integerConstraint_) {
685 return cplex_.getBestObjValue()+constValue_;
688 return cplex_.getObjValue()+constValue_;
692 return ACC::template ineutral<ValueType>();
697 template <
class GM,
class ACC>
706 return idNodesBegin_[variableIndex]+label;
710 template <
class GM,
class ACC>
715 const size_t labelingIndex
719 return idFactorsBegin_[factorIndex]+labelingIndex;
723 template <
class GM,
class ACC>
724 template<
class LABELING_ITERATOR>
729 LABELING_ITERATOR labelingBegin,
730 LABELING_ITERATOR labelingEnd
733 OPENGM_ASSERT(std::distance(labelingBegin,labelingEnd)==gm_[factorIndex].numberOfVariables());
734 const size_t numVar=gm_[factorIndex].numberOfVariables();
735 size_t labelingIndex=labelingBegin[0];
736 size_t strides=gm_[factorIndex].numberOfLabels(0);
737 for(
size_t vi=1;vi<numVar;++vi){
738 OPENGM_ASSERT(labelingBegin[vi]<gm_[factorIndex].numberOfLabels(vi));
739 labelingIndex+=strides*labelingBegin[vi];
740 strides*=gm_[factorIndex].numberOfLabels(vi);
742 return idFactorsBegin_[factorIndex]+labelingIndex;
759 template<
class GM,
class ACC>
760 template<
class LPVariableIndexIterator,
class CoefficientIterator>
762 LPVariableIndexIterator viBegin,
763 LPVariableIndexIterator viEnd,
764 CoefficientIterator coefficient,
769 IloRange constraint(env_, lowerBound, upperBound, name);
770 while(viBegin != viEnd) {
771 constraint.setLinearCoef(x_[*viBegin], *coefficient);
775 model_.add(constraint);
void setStartingPoint(typename std::vector< LabelType >::const_iterator)
set initial labeling
STL-compliant random access iterator for View and Marray.
Addition as a binary operation.
static const double default_epRHS_
visitors::VerboseVisitor< LPCplex< GM, ACC > > VerboseVisitorType
MIP_EMPHASIS mipEmphasis_
iterator end()
Get the end-iterator.
static const double default_cutUp_
static const double default_epInt_
LPCplex< _GM, _ACC > type
int getCutLevel(MIP_CUT cl)
Array-Interface to an interval of memory.
#define OPENGM_ASSERT(expression)
const GraphicalModelType & graphicalModel() 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
void variable(const size_t, IndependentFactorType &out) const
visitors::TimingVisitor< LPCplex< GM, ACC > > TimingVisitorType
MIP_CUT disjunctCutLevel_
iterator begin()
Get an iterator to the beginning.
virtual InferenceTermination arg(std::vector< LabelType > &, const size_t=1) const
output a solution
MIP_CUT flowpathCutLevel_
LPCplex(const GraphicalModelType &, const Parameter &=Parameter())
static const double default_epMrk_
GraphicalModelType::IndexType IndexType
static const double default_epGap_
#define OPENGM_ASSERT_OP(a, op, b)
runtime assertion
size_t lpNodeVi(const IndexType variableIndex, const LabelType label) const
MIP_CUT flowcoverCutLevel_
Optimization by Linear Programming (LP) or Integer LP using IBM ILOG CPLEX http://www.ilog.com/products/cplex/.
GraphicalModelType::ValueType ValueType
visitors::EmptyVisitor< LPCplex< GM, ACC > > EmptyVisitorType
Inference algorithm interface.
GM::ValueType value() const
return the solution (value)
virtual InferenceTermination marginal(const size_t, IndependentFactorType &) const
output a solution for a marginal for a specific variable
GM::ValueType bound() const
return a bound on the solution
Runtime-flexible multi-dimensional array.
GraphicalModelType::LabelType LabelType
virtual std::string name() const
Minimization as a unary accumulation.
Maximization as a unary accumulation.
virtual InferenceTermination args(std::vector< std::vector< LabelType > > &) const
void factorVariable(const size_t, IndependentFactorType &out) const
virtual InferenceTermination infer()
size_t lpFactorVi(const IndexType factorIndex, const size_t labelingIndex) const
void addConstraint(LPVariableIndexIterator, LPVariableIndexIterator, CoefficientIterator, const ValueType &, const ValueType &, const char *name=0)
add constraint
GraphicalModelType::IndependentFactorType IndependentFactorType