2 #ifndef OPENGM_LP_CPLEX_HXX
3 #define OPENGM_LP_CPLEX_HXX
12 #include <ilcplex/ilocplex.h>
37 template<
class GM,
class ACC>
93 int numberOfThreads = 0
121 numberOfThreads_ = numberOfThreads;
122 integerConstraint_ =
false;
150 LPCplex(
const GraphicalModelType&,
const Parameter& = Parameter());
152 virtual std::string
name()
const
153 {
return "LPCplex"; }
156 template<
class VisitorType>
163 typename GM::ValueType
bound()
const;
164 typename GM::ValueType
value()
const;
170 template<
class LABELING_ITERATOR>
171 size_t lpFactorVi(
const IndexType factorIndex,LABELING_ITERATOR labelingBegin,LABELING_ITERATOR labelingEnd)
const;
172 template<
class LPVariableIndexIterator,
class CoefficientIterator>
176 const GraphicalModelType& gm_;
177 Parameter parameter_;
178 std::vector<size_t> idNodesBegin_;
179 std::vector<size_t> idFactorsBegin_;
180 std::vector<std::vector<size_t> > unaryFactors_;
181 bool inferenceStarted_;
193 template<
class GM,
class ACC>
196 const GraphicalModelType& gm,
199 : gm_(gm), inferenceStarted_(
false)
202 throw RuntimeError(
"This implementation does only supports Min-Plus-Semiring and Max-Plus-Semiring.");
205 idNodesBegin_.resize(gm_.numberOfVariables());
206 unaryFactors_.resize(gm_.numberOfVariables());
207 idFactorsBegin_.resize(gm_.numberOfFactors());
210 IloInt numberOfElements = 0;
211 IloInt numberOfVariableElements = 0;
212 IloInt numberOfFactorElements = 0;
214 size_t idCounter = 0;
215 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
216 numberOfVariableElements += gm_.numberOfLabels(node);
217 idNodesBegin_[node] = idCounter;
218 idCounter += gm_.numberOfLabels(node);
222 for(
size_t f = 0; f < gm_.numberOfFactors(); ++f) {
223 if(gm_[f].numberOfVariables() == 0) {
225 constValue_ += gm_[f](&l);
227 else if(gm_[f].numberOfVariables() == 1) {
228 size_t node = gm_[f].variableIndex(0);
229 unaryFactors_[node].push_back(f);
230 idFactorsBegin_[f] = idNodesBegin_[node];
233 idFactorsBegin_[f] = idCounter;
234 idCounter += gm_[f].size();
235 numberOfFactorElements += gm_[f].size();
238 numberOfElements = numberOfVariableElements + numberOfFactorElements;
240 model_ = IloModel(env_);
241 x_ = IloNumVarArray(env_);
242 c_ = IloRangeArray(env_);
243 sol_ = IloNumArray(env_);
246 obj_ = IloMinimize(env_);
248 obj_ = IloMaximize(env_);
250 throw RuntimeError(
"This implementation does only support Minimizer or Maximizer accumulators");
253 if(parameter_.integerConstraint_) {
254 x_.add(IloNumVarArray(env_, numberOfVariableElements, 0, 1, ILOBOOL));
257 x_.add(IloNumVarArray(env_, numberOfVariableElements, 0, 1));
259 x_.add(IloNumVarArray(env_, numberOfFactorElements, 0, 1));
260 IloNumArray obj(env_, numberOfElements);
262 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
263 for(
size_t i = 0; i < gm_.numberOfLabels(node); ++i) {
265 for(
size_t n=0; n<unaryFactors_[node].size();++n) {
266 t += gm_[unaryFactors_[node][n]](&i);
269 obj[idNodesBegin_[node]+i] = t;
272 for(
size_t f = 0; f < gm_.numberOfFactors(); ++f) {
273 if(gm_[f].numberOfVariables() == 2) {
275 size_t counter = idFactorsBegin_[f];
276 for(index[1]=0; index[1]<gm_[f].numberOfLabels(1);++index[1])
277 for(index[0]=0; index[0]<gm_[f].numberOfLabels(0);++index[0])
278 obj[counter++] = gm_[f](index);
280 else if(gm_[f].numberOfVariables() == 3) {
282 size_t counter = idFactorsBegin_[f] ;
283 for(index[2]=0; index[2]<gm_[f].numberOfLabels(2);++index[2])
284 for(index[1]=0; index[1]<gm_[f].numberOfLabels(1);++index[1])
285 for(index[0]=0; index[0]<gm_[f].numberOfLabels(0);++index[0])
286 obj[counter++] = gm_[f](index);
288 else if(gm_[f].numberOfVariables() == 4) {
290 size_t counter = idFactorsBegin_[f];
291 for(index[3]=0; index[3]<gm_[f].numberOfLabels(3);++index[3])
292 for(index[2]=0; index[2]<gm_[f].numberOfLabels(2);++index[2])
293 for(index[1]=0; index[1]<gm_[f].numberOfLabels(1);++index[1])
294 for(index[0]=0; index[0]<gm_[f].numberOfLabels(0);++index[0])
295 obj[counter++] = gm_[f](index);
297 else if(gm_[f].numberOfVariables() > 4) {
298 size_t counter = idFactorsBegin_[f];
299 std::vector<size_t> coordinate(gm_[f].numberOfVariables());
302 mit.coordinate(coordinate.begin());
303 obj[counter++] = gm_[f](coordinate.begin());
307 obj_.setLinearCoefs(x_, obj);
309 size_t constraintCounter = 0;
311 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
312 c_.add(IloRange(env_, 1, 1));
313 for(
size_t i = 0; i < gm_.numberOfLabels(node); ++i) {
314 c_[constraintCounter].setLinearCoef(x_[idNodesBegin_[node]+i], 1);
319 for(
size_t f = 0; f < gm_.numberOfFactors(); ++f) {
320 if(gm_[f].numberOfVariables() > 1) {
322 size_t counter = idFactorsBegin_[f];
326 for(
size_t n = 0; n < gm_[f].numberOfVariables(); ++n) {
327 size_t node = gm_[f].variableIndex(n);
328 for(
size_t i = 0; i < gm_.numberOfLabels(node); ++i) {
329 c_.add(IloRange(env_, 0, 0));
330 c_[constraintCounter].setLinearCoef(x_[idNodesBegin_[node]+i], -1);
333 c_[constraintCounter].setLinearCoef(x_[*vit], 1);
344 cplex_ = IloCplex(model_);
346 catch(IloCplex::Exception& e) {
347 throw std::runtime_error(
"CPLEX exception");
351 template <
class GM,
class ACC>
358 template<
class GM,
class ACC>
359 template<
class VisitorType>
365 visitor.begin(*
this);
366 inferenceStarted_ =
true;
369 switch(parameter_.rootAlg_) {
371 cplex_.setParam(IloCplex::RootAlg, 0);
373 case LP_SOLVER_PRIMAL_SIMPLEX:
374 cplex_.setParam(IloCplex::RootAlg, 1);
376 case LP_SOLVER_DUAL_SIMPLEX:
377 cplex_.setParam(IloCplex::RootAlg, 2);
379 case LP_SOLVER_NETWORK_SIMPLEX:
380 cplex_.setParam(IloCplex::RootAlg, 3);
382 case LP_SOLVER_BARRIER:
383 cplex_.setParam(IloCplex::RootAlg, 4);
385 case LP_SOLVER_SIFTING:
386 cplex_.setParam(IloCplex::RootAlg, 5);
388 case LP_SOLVER_CONCURRENT:
389 cplex_.setParam(IloCplex::RootAlg, 6);
394 switch(parameter_.nodeAlg_) {
396 cplex_.setParam(IloCplex::NodeAlg, 0);
398 case LP_SOLVER_PRIMAL_SIMPLEX:
399 cplex_.setParam(IloCplex::NodeAlg, 1);
401 case LP_SOLVER_DUAL_SIMPLEX:
402 cplex_.setParam(IloCplex::NodeAlg, 2);
404 case LP_SOLVER_NETWORK_SIMPLEX:
405 cplex_.setParam(IloCplex::NodeAlg, 3);
407 case LP_SOLVER_BARRIER:
408 cplex_.setParam(IloCplex::NodeAlg, 4);
410 case LP_SOLVER_SIFTING:
411 cplex_.setParam(IloCplex::NodeAlg, 5);
413 case LP_SOLVER_CONCURRENT:
414 cplex_.setParam(IloCplex::NodeAlg, 6);
419 switch(parameter_.presolve_) {
420 case LP_PRESOLVE_AUTO:
421 cplex_.setParam(IloCplex::PreInd, CPX_ON);
422 cplex_.setParam(IloCplex::RelaxPreInd, -1);
424 case LP_PRESOLVE_OFF:
425 cplex_.setParam(IloCplex::PreInd, CPX_OFF);
426 cplex_.setParam(IloCplex::RelaxPreInd, 0);
428 case LP_PRESOLVE_CONSERVATIVE:
429 cplex_.setParam(IloCplex::PreInd, CPX_ON);
430 cplex_.setParam(IloCplex::RelaxPreInd, -1);
432 case LP_PRESOLVE_AGGRESSIVE:
433 cplex_.setParam(IloCplex::PreInd, CPX_ON);
434 cplex_.setParam(IloCplex::RelaxPreInd, 1);
439 switch(parameter_.mipEmphasis_) {
440 case MIP_EMPHASIS_BALANCED:
441 cplex_.setParam(IloCplex::MIPEmphasis, 0);
443 case MIP_EMPHASIS_FEASIBILITY:
444 cplex_.setParam(IloCplex::MIPEmphasis, 1);
446 case MIP_EMPHASIS_OPTIMALITY:
447 cplex_.setParam(IloCplex::MIPEmphasis, 2);
449 case MIP_EMPHASIS_BESTBOUND:
450 cplex_.setParam(IloCplex::MIPEmphasis, 3);
452 case MIP_EMPHASIS_HIDDENFEAS:
453 cplex_.setParam(IloCplex::MIPEmphasis, 4);
458 if(parameter_.verbose_ ==
false) {
459 cplex_.setParam(IloCplex::MIPDisplay, 0);
460 cplex_.setParam(IloCplex::BarDisplay, 0);
461 cplex_.setParam(IloCplex::SimDisplay, 0);
462 cplex_.setParam(IloCplex::NetDisplay, 0);
463 cplex_.setParam(IloCplex::SiftDisplay, 0);
467 cplex_.setParam(IloCplex::EpOpt, parameter_.epOpt_);
468 cplex_.setParam(IloCplex::EpMrk, parameter_.epMrk_);
469 cplex_.setParam(IloCplex::EpRHS, parameter_.epRHS_);
470 cplex_.setParam(IloCplex::EpInt, parameter_.epInt_);
471 cplex_.setParam(IloCplex::EpAGap, parameter_.epAGap_);
472 cplex_.setParam(IloCplex::EpGap, parameter_.epGap_);
475 cplex_.setParam(IloCplex::CutUp, parameter_.cutUp_);
478 cplex_.setParam(IloCplex::WorkMem, parameter_.workMem_);
479 cplex_.setParam(IloCplex::ClockType,2);
480 cplex_.setParam(IloCplex::TreLim,parameter_.treeMemoryLimit_);
481 cplex_.setParam(IloCplex::MemoryEmphasis, 1);
484 cplex_.setParam(IloCplex::TiLim, parameter_.timeLimit_);
487 cplex_.setParam(IloCplex::Threads, parameter_.numberOfThreads_);
490 cplex_.setParam(IloCplex::Probe, parameter_.probeingLevel_);
491 if(parameter_.cutLevel_ != MIP_CUT_DEFAULT){
492 int cl = parameter_.getCutLevel(parameter_.cutLevel_);
493 cplex_.setParam(IloCplex::Covers, cl);
494 cplex_.setParam(IloCplex::Cliques, cl);
495 cplex_.setParam(IloCplex::DisjCuts, cl);
496 cplex_.setParam(IloCplex::Cliques, cl);
497 cplex_.setParam(IloCplex::MIRCuts, cl);
498 cplex_.setParam(IloCplex::GUBCovers, cl);
499 cplex_.setParam(IloCplex::FlowCovers, cl);
500 cplex_.setParam(IloCplex::FlowPaths, cl);
501 cplex_.setParam(IloCplex::ImplBd, cl);
502 cplex_.setParam(IloCplex::FracCuts, cl);
511 if(!cplex_.solve()) {
512 std::cout <<
"failed to optimize. " <<cplex_.getStatus() << std::endl;
515 cplex_.getValues(sol_, x_);
517 catch(IloCplex::Exception e) {
518 std::cout <<
"caught CPLEX exception: " << e << std::endl;
525 template <
class GM,
class ACC>
530 template <
class GM,
class ACC>
537 x.resize(gm_.numberOfVariables());
538 if(inferenceStarted_) {
539 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
540 ValueType value = sol_[idNodesBegin_[node]];
542 for(
size_t i = 1; i < gm_.numberOfLabels(node); ++i) {
543 if(sol_[idNodesBegin_[node]+i] > value) {
544 value = sol_[idNodesBegin_[node]+i];
552 for(
size_t node = 0; node < gm_.numberOfVariables(); ++node) {
560 template <
class GM,
class ACC>
566 size_t var[] = {nodeId};
567 size_t shape[] = {gm_.numberOfLabels(nodeId)};
568 out.assign(var, var + 1, shape, shape + 1);
569 for(
size_t i = 0; i < gm_.numberOfLabels(nodeId); ++i) {
570 out(i) = sol_[idNodesBegin_[nodeId]+i];
575 template <
class GM,
class ACC>
578 const size_t factorId,
581 std::vector<size_t> var(gm_[factorId].numberOfVariables());
582 std::vector<size_t> shape(gm_[factorId].numberOfVariables());
583 for(
size_t i = 0; i < gm_[factorId].numberOfVariables(); ++i) {
584 var[i] = gm_[factorId].variableIndex(i);
585 shape[i] = gm_[factorId].shape(i);
587 out.assign(var.begin(), var.end(), shape.begin(), shape.end());
588 if(gm_[factorId].numberOfVariables() == 1) {
589 size_t nodeId = gm_[factorId].variableIndex(0);
590 marginal(nodeId, out);
594 for(
size_t n = idFactorsBegin_[factorId]; n<idFactorsBegin_[factorId]+gm_[factorId].size(); ++n) {
601 template<
class GM,
class ACC>
606 IloNumVarArray vars(env_);
607 IloNumArray values(env_);
608 for(
IndexType var=0; var<gm_.numberOfVariables(); ++var){
609 const IloNumVar lpvar = x_[lpNodeVi(var,*(begin+var))];
613 cplex_.addMIPStart(vars, values);
618 template<
class GM,
class ACC>
625 template<
class GM,
class ACC>
627 std::vector<LabelType> states;
629 return gm_.evaluate(states);
632 template<
class GM,
class ACC>
634 if(inferenceStarted_) {
635 if(parameter_.integerConstraint_) {
636 return cplex_.getBestObjValue()+constValue_;
639 return cplex_.getObjValue()+constValue_;
643 return ACC::template ineutral<ValueType>();
648 template <
class GM,
class ACC>
657 return idNodesBegin_[variableIndex]+label;
661 template <
class GM,
class ACC>
666 const size_t labelingIndex
670 return idFactorsBegin_[factorIndex]+labelingIndex;
674 template <
class GM,
class ACC>
675 template<
class LABELING_ITERATOR>
680 LABELING_ITERATOR labelingBegin,
681 LABELING_ITERATOR labelingEnd
684 OPENGM_ASSERT(std::distance(labelingBegin,labelingEnd)==gm_[factorIndex].numberOfVariables());
685 const size_t numVar=gm_[factorIndex].numberOfVariables();
686 size_t labelingIndex=labelingBegin[0];
687 size_t strides=gm_[factorIndex].numberOfLabels(0);
688 for(
size_t vi=1;vi<numVar;++vi){
689 OPENGM_ASSERT(labelingBegin[vi]<gm_[factorIndex].numberOfLabels(vi));
690 labelingIndex+=strides*labelingBegin[vi];
691 strides*=gm_[factorIndex].numberOfLabels(vi);
693 return idFactorsBegin_[factorIndex]+labelingIndex;
710 template<
class GM,
class ACC>
711 template<
class LPVariableIndexIterator,
class CoefficientIterator>
713 LPVariableIndexIterator viBegin,
714 LPVariableIndexIterator viEnd,
715 CoefficientIterator coefficient,
720 IloRange constraint(env_, lowerBound, upperBound, name);
721 while(viBegin != viEnd) {
722 constraint.setLinearCoef(x_[*viBegin], *coefficient);
726 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_
GM::ValueType bound() const
return a bound on the solution
visitors::VerboseVisitor< LPCplex< GM, ACC > > VerboseVisitorType
MIP_EMPHASIS mipEmphasis_
const GraphicalModelType & graphicalModel() const
static const double default_cutUp_
virtual InferenceTermination args(std::vector< std::vector< LabelType > > &) const
static const double default_epInt_
int getCutLevel(MIP_CUT cl)
Array-Interface to an interval of memory.
#define OPENGM_ASSERT(expression)
static const double default_epOpt_
static const double default_epAGap_
GraphicalModelType::OperatorType OperatorType
visitors::TimingVisitor< LPCplex< GM, ACC > > TimingVisitorType
MIP_CUT disjunctCutLevel_
GM::ValueType value() const
return the solution (value)
MIP_CUT flowpathCutLevel_
LPCplex(const GraphicalModelType &, const Parameter &=Parameter())
virtual InferenceTermination arg(std::vector< LabelType > &, const size_t=1) const
output a solution
static const double default_epMrk_
GraphicalModelType::IndexType IndexType
static const double default_epGap_
View< T, isConst, A > boundView(const size_t, const size_t=0) const
#define OPENGM_ASSERT_OP(a, op, b)
runtime assertion
size_t lpFactorVi(const IndexType factorIndex, const size_t labelingIndex) const
MIP_CUT flowcoverCutLevel_
void variable(const size_t, IndependentFactorType &out) const
Optimization by Linear Programming (LP) or Integer LP using IBM ILOG CPLEX http://www.ilog.com/products/cplex/.
void factorVariable(const size_t, IndependentFactorType &out) const
GraphicalModelType::ValueType ValueType
visitors::EmptyVisitor< LPCplex< GM, ACC > > EmptyVisitorType
Inference algorithm interface.
Runtime-flexible multi-dimensional array.
size_t lpNodeVi(const IndexType variableIndex, const LabelType label) const
GraphicalModelType::LabelType LabelType
Minimization as a unary accumulation.
Maximization as a unary accumulation.
Parameter(int numberOfThreads=0)
constructor
virtual InferenceTermination infer()
virtual std::string name() const
void addConstraint(LPVariableIndexIterator, LPVariableIndexIterator, CoefficientIterator, const ValueType &, const ValueType &, const char *name=0)
add constraint
GraphicalModelType::IndependentFactorType IndependentFactorType