OpenGM  2.3.x
Discrete Graphical Model Library
lp_solver_gurobi.hxx
Go to the documentation of this file.
1 #ifndef OPENGM_LP_SOLVER_GUROBI_HXX_
2 #define OPENGM_LP_SOLVER_GUROBI_HXX_
3 
4 #include <gurobi_c++.h>
5 
9 
10 /*********************
11  * class definition *
12  *********************/
13 namespace opengm {
14 
15 class LPSolverGurobi : public LPSolverInterface<LPSolverGurobi, double, int, std::vector<double>::const_iterator, double> {
16 public:
17  // typedefs
18  typedef double GurobiValueType;
19  typedef int GurobiIndexType;
20  typedef std::vector<GurobiValueType>::const_iterator GurobiSolutionIteratorType;
21  typedef double GurobiTimingType;
22 
24 
25  // constructor
26  LPSolverGurobi(const Parameter& parameter = Parameter());
27 
28  // destructor
30 
31 protected:
32  // Storage for Gurobi variables
34  mutable GRBModel gurobiModel_; // model is mutable as GRBModel::write() is not marked as const. However exporting a Model to file is expected to not change the model itself. Is the missing const intended by Gurobi?
35  std::vector<GRBVar> gurobiVariables_;
36  mutable std::vector<GurobiValueType> gurobiSolution_;
37  mutable bool gurobiSolutionValid_;
38 
39  // methods for class LPSolverInterface
40  // Gurobi infinity value
41  static GurobiValueType infinity_impl();
42 
43  // add Variables
44  void addContinuousVariables_impl(const GurobiIndexType numVariables, const GurobiValueType lowerBound, const GurobiValueType upperBound);
45  void addIntegerVariables_impl(const GurobiIndexType numVariables, const GurobiValueType lowerBound, const GurobiValueType upperBound);
46  void addBinaryVariables_impl(const GurobiIndexType numVariables);
47 
48  // objective function
49  void setObjective_impl(const Objective objective);
50  void setObjectiveValue_impl(const GurobiIndexType variable, const GurobiValueType value);
51  template<class ITERATOR_TYPE>
52  void setObjectiveValue_impl(ITERATOR_TYPE begin, const ITERATOR_TYPE end);
53  template<class VARIABLES_ITERATOR_TYPE, class COEFFICIENTS_ITERATOR_TYPE>
54  void setObjectiveValue_impl(VARIABLES_ITERATOR_TYPE variableIDsBegin, const VARIABLES_ITERATOR_TYPE variableIDsEnd, COEFFICIENTS_ITERATOR_TYPE coefficientsBegin);
55 
56  // constraints
57  template<class VARIABLES_ITERATOR_TYPE, class COEFFICIENTS_ITERATOR_TYPE>
58  void addEqualityConstraint_impl(VARIABLES_ITERATOR_TYPE variableIDsBegin, const VARIABLES_ITERATOR_TYPE variableIDsEnd, COEFFICIENTS_ITERATOR_TYPE coefficientsBegin, const GurobiValueType bound, const std::string& constraintName = "");
59  template<class VARIABLES_ITERATOR_TYPE, class COEFFICIENTS_ITERATOR_TYPE>
60  void addLessEqualConstraint_impl(VARIABLES_ITERATOR_TYPE variableIDsBegin, const VARIABLES_ITERATOR_TYPE variableIDsEnd, COEFFICIENTS_ITERATOR_TYPE coefficientsBegin, const GurobiValueType bound, const std::string& constraintName = "");
61  template<class VARIABLES_ITERATOR_TYPE, class COEFFICIENTS_ITERATOR_TYPE>
62  void addGreaterEqualConstraint_impl(VARIABLES_ITERATOR_TYPE variableIDsBegin, const VARIABLES_ITERATOR_TYPE variableIDsEnd, COEFFICIENTS_ITERATOR_TYPE coefficientsBegin, const GurobiValueType bound, const std::string& constraintName = "");
63 
65  void addConstraintsFinished_impl(GurobiTimingType& timing);
66 
67  // parameter
68  template <class PARAMETER_TYPE, class PARAMETER_VALUE_TYPE>
69  void setParameter_impl(const PARAMETER_TYPE parameter, const PARAMETER_VALUE_TYPE value);
70 
71  // solve
72  bool solve_impl();
73  bool solve_impl(GurobiTimingType& timing);
74 
75  // solution
76  GurobiSolutionIteratorType solutionBegin_impl() const;
77  GurobiSolutionIteratorType solutionEnd_impl() const;
78  GurobiValueType solution_impl(const GurobiIndexType variable) const;
79 
80  GurobiValueType objectiveFunctionValue_impl() const;
81  GurobiValueType objectiveFunctionValueBound_impl() const;
82 
83  // model export
84  void exportModel_impl(const std::string& filename) const;
85 
86  // helper functions
87  void updateSolution() const;
88  static int getCutLevelValue(const LPDef::MIP_CUT cutLevel);
89 
90  // friend
91  friend class LPSolverInterface<LPSolverGurobi, GurobiValueType, GurobiIndexType, GurobiSolutionIteratorType, GurobiTimingType>;
92 };
93 
94 } // namespace opengm
95 
96 /***********************
97  * class documentation *
98  ***********************/
466 /******************
467  * implementation *
468  ******************/
469 namespace opengm {
470 
471 inline LPSolverGurobi::LPSolverGurobi(const Parameter& parameter)
472  : LPSolverBaseClass(parameter), gurobiEnvironment_(),
473  gurobiModel_(gurobiEnvironment_), gurobiVariables_(), gurobiSolution_(),
474  gurobiSolutionValid_(false) {
475  // set parameter
476  try {
477  // multi-threading options
478  gurobiModel_.getEnv().set(GRB_IntParam_Threads, parameter_.numberOfThreads_);
479 
480  // verbose options
481  if(!parameter_.verbose_) {
482  gurobiModel_.getEnv().set(GRB_IntParam_OutputFlag, 0);
483  gurobiModel_.getEnv().set(GRB_IntParam_TuneOutput, 0);
484  gurobiModel_.getEnv().set(GRB_IntParam_LogToConsole, 0);
485  }
486 
487  // set hints
488  // CutUp is missing http://www.gurobi.com/resources/switching-to-gurobi/switching-from-cplex#setting
489 
490  // tolerance settings
491  //gurobiModel_.getEnv().set(GRB_DoubleParam_Cutoff, parameter_.cutUp_); // Optimality Tolerance
492  gurobiModel_.getEnv().set(GRB_DoubleParam_OptimalityTol, parameter_.epOpt_); // Optimality Tolerance
493  gurobiModel_.getEnv().set(GRB_DoubleParam_IntFeasTol, parameter_.epInt_); // amount by which an integer variable can differ from an integer
494  gurobiModel_.getEnv().set(GRB_DoubleParam_MIPGapAbs, parameter_.epAGap_); // Absolute MIP gap tolerance
495  gurobiModel_.getEnv().set(GRB_DoubleParam_MIPGap, parameter_.epGap_); // Relative MIP gap tolerance
496  gurobiModel_.getEnv().set(GRB_DoubleParam_FeasibilityTol, parameter_.epRHS_);
497  gurobiModel_.getEnv().set(GRB_DoubleParam_MarkowitzTol, parameter_.epMrk_);
498 
499  // memory setting
500  // missing
501 
502  // time limit
503  gurobiModel_.getEnv().set(GRB_DoubleParam_TimeLimit, parameter_.timeLimit_);
504 
505  // Root Algorithm
506  switch(parameter_.rootAlg_) {
507  case LPDef::LP_SOLVER_AUTO: {
508  gurobiModel_.getEnv().set(GRB_IntParam_Method, -1);
509  break;
510  }
512  gurobiModel_.getEnv().set(GRB_IntParam_Method, 0);
513  break;
514  }
516  gurobiModel_.getEnv().set(GRB_IntParam_Method, 1);
517  break;
518  }
520  throw std::runtime_error("Gurobi does not support Network Simplex");
521  break;
522  }
524  gurobiModel_.getEnv().set(GRB_IntParam_Method, 2);
525  break;
526  }
528  gurobiModel_.getEnv().set(GRB_IntParam_Method, 1);
529  gurobiModel_.getEnv().set(GRB_IntParam_SiftMethod, 1);
530  break;
531  }
533  gurobiModel_.getEnv().set(GRB_IntParam_Method, 4);
534  break;
535  }
536  default: {
537  throw std::runtime_error("Unknown Root Algorithm");
538  }
539  }
540 
541  // Node Algorithm
542  switch(parameter_.nodeAlg_) {
543  case LPDef::LP_SOLVER_AUTO: {
544  gurobiModel_.getEnv().set(GRB_IntParam_NodeMethod, 1);
545  break;
546  }
548  gurobiModel_.getEnv().set(GRB_IntParam_NodeMethod, 0);
549  break;
550  }
552  gurobiModel_.getEnv().set(GRB_IntParam_NodeMethod, 1);
553  break;
554  }
556  throw std::runtime_error("Gurobi does not support Network Simplex");
557  break;
558  }
560  gurobiModel_.getEnv().set(GRB_IntParam_NodeMethod, 2);
561  break;
562  }
564  throw std::runtime_error("Gurobi does not support Sifting as node algorithm");
565  break;
566  }
568  throw std::runtime_error("Gurobi does not support concurrent solvers as node algorithm");
569  break;
570  }
571  default: {
572  throw std::runtime_error("Unknown Node Algorithm");
573  }
574  }
575 
576  // presolve
577  switch(parameter_.presolve_) {
579  gurobiModel_.getEnv().set(GRB_IntParam_Presolve, -1);
580  break;
581  }
582  case LPDef::LP_PRESOLVE_OFF: {
583  gurobiModel_.getEnv().set(GRB_IntParam_Presolve, 0);
584  break;
585  }
587  gurobiModel_.getEnv().set(GRB_IntParam_Presolve, 1);
588  break;
589  }
591  gurobiModel_.getEnv().set(GRB_IntParam_Presolve, 2);
592  break;
593  }
594  default: {
595  throw std::runtime_error("Unknown Presolve Option");
596  }
597  }
598 
599  // MIP EMPHASIS
600  switch(parameter_.mipEmphasis_) {
602  gurobiModel_.getEnv().set(GRB_IntParam_MIPFocus, 0);
603  break;
604  }
606  gurobiModel_.getEnv().set(GRB_IntParam_MIPFocus, 1);
607  break;
608  }
610  gurobiModel_.getEnv().set(GRB_IntParam_MIPFocus, 2);
611  break;
612  }
614  gurobiModel_.getEnv().set(GRB_IntParam_MIPFocus, 3);
615  break;
616  }
618  throw std::runtime_error("Gurobi does not support hidden feasibility as MIP-focus");
619  break;
620  }
621  default: {
622  throw std::runtime_error("Unknown MIP Emphasis Option");
623  }
624  }
625 
626  // Tuning
627  // Probing missing
628  if(parameter_.cutLevel_ != LPDef::MIP_CUT_DEFAULT) {
629  gurobiModel_.getEnv().set(GRB_IntParam_Cuts, getCutLevelValue(parameter_.cutLevel_));
630  }
631  if(parameter_.cliqueCutLevel_ != LPDef::MIP_CUT_DEFAULT) {
632  gurobiModel_.getEnv().set(GRB_IntParam_CliqueCuts, getCutLevelValue(parameter_.cliqueCutLevel_));
633  }
634  if(parameter_.coverCutLevel_ != LPDef::MIP_CUT_DEFAULT) {
635  gurobiModel_.getEnv().set(GRB_IntParam_CoverCuts, getCutLevelValue(parameter_.coverCutLevel_));
636  }
637  if(parameter_.gubCutLevel_ != LPDef::MIP_CUT_DEFAULT) {
638  gurobiModel_.getEnv().set(GRB_IntParam_GUBCoverCuts, getCutLevelValue(parameter_.gubCutLevel_));
639  }
640  if(parameter_.mirCutLevel_ != LPDef::MIP_CUT_DEFAULT) {
641  gurobiModel_.getEnv().set(GRB_IntParam_MIRCuts, getCutLevelValue(parameter_.mirCutLevel_));
642  }
643  if(parameter_.iboundCutLevel_ != LPDef::MIP_CUT_DEFAULT) {
644  gurobiModel_.getEnv().set(GRB_IntParam_ImpliedCuts, getCutLevelValue(parameter_.iboundCutLevel_));
645  }
646  if(parameter_.flowcoverCutLevel_ != LPDef::MIP_CUT_DEFAULT) {
647  gurobiModel_.getEnv().set(GRB_IntParam_FlowCoverCuts, getCutLevelValue(parameter_.flowcoverCutLevel_));
648  }
649  if(parameter_.flowpathCutLevel_ != LPDef::MIP_CUT_DEFAULT) {
650  gurobiModel_.getEnv().set(GRB_IntParam_FlowPathCuts, getCutLevelValue(parameter_.flowpathCutLevel_));
651  }
652  // DisjCuts missing
653  // Gomory missing
654  } catch(const GRBException& e) {
655  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
656  std::cout << e.getMessage() << std::endl;
657  throw std::runtime_error(e.getMessage());
658  } catch(...) {
659  std::cout << "Exception while setting parameter for Gurobi model." << std::endl;
660  throw std::runtime_error("Exception while setting parameter for Gurobi model.");
661  }
662 }
663 
665 
666 }
667 
669  return GRB_INFINITY;
670 }
671 
672 inline void LPSolverGurobi::addContinuousVariables_impl(const GurobiIndexType numVariables, const GurobiValueType lowerBound, const GurobiValueType upperBound) {
673  gurobiVariables_.reserve(numVariables + gurobiVariables_.size());
674  // according to the Gurobi documentation, adding variables separately does not have any performance impact
675  try {
676  for(GurobiIndexType i = 0; i < numVariables; ++i) {
677  gurobiVariables_.push_back(gurobiModel_.addVar(lowerBound, upperBound, 0.0, GRB_CONTINUOUS));
678  }
679  gurobiSolution_.resize(gurobiVariables_.size());
680  gurobiSolutionValid_ = false;
681  gurobiModel_.update();
682  } catch(const GRBException& e) {
683  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
684  std::cout << e.getMessage() << std::endl;
685  throw std::runtime_error(e.getMessage());
686  } catch(...) {
687  std::cout << "Exception while adding continuous variables to Gurobi model." << std::endl;
688  throw std::runtime_error("Exception while adding continuous variables to Gurobi model.");
689  }
690 }
691 
692 inline void LPSolverGurobi::addIntegerVariables_impl(const GurobiIndexType numVariables, const GurobiValueType lowerBound, const GurobiValueType upperBound) {
693  gurobiVariables_.reserve(numVariables + gurobiVariables_.size());
694  // according to the Gurobi documentation, adding variables separately does not have any performance impact
695  try {
696  for(GurobiIndexType i = 0; i < numVariables; ++i) {
697  gurobiVariables_.push_back(gurobiModel_.addVar(lowerBound, upperBound, 0.0, GRB_INTEGER));
698  }
699  gurobiSolution_.resize(gurobiVariables_.size());
700  gurobiSolutionValid_ = false;
701  gurobiModel_.update();
702  } catch(const GRBException& e) {
703  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
704  std::cout << e.getMessage() << std::endl;
705  throw std::runtime_error(e.getMessage());
706  } catch(...) {
707  std::cout << "Exception while adding integer variables to Gurobi model." << std::endl;
708  throw std::runtime_error("Exception while adding integer variables to Gurobi model.");
709  }
710 }
711 
713  gurobiVariables_.reserve(numVariables + gurobiVariables_.size());
714  // according to the Gurobi documentation, adding variables separately does not have any performance impact
715  try {
716  for(GurobiIndexType i = 0; i < numVariables; ++i) {
717  gurobiVariables_.push_back(gurobiModel_.addVar(0.0, 1.0, 0.0, GRB_BINARY));
718  }
719  gurobiSolution_.resize(gurobiVariables_.size());
720  gurobiSolutionValid_ = false;
721  gurobiModel_.update();
722  } catch(const GRBException& e) {
723  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
724  std::cout << e.getMessage() << std::endl;
725  throw std::runtime_error(e.getMessage());
726  } catch(...) {
727  std::cout << "Exception while adding binary variables to Gurobi model." << std::endl;
728  throw std::runtime_error("Exception while adding binary variables to Gurobi model.");
729  }
730 }
731 
732 inline void LPSolverGurobi::setObjective_impl(const Objective objective) {
733  switch(objective) {
734  case Minimize: {
735  try {
736  gurobiModel_.set(GRB_IntAttr_ModelSense, 1);
737  } catch(const GRBException& e) {
738  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
739  std::cout << e.getMessage() << std::endl;
740  throw std::runtime_error(e.getMessage());
741  } catch(...) {
742  std::cout << "Exception while setting objective of Gurobi model." << std::endl;
743  throw std::runtime_error("Exception while setting objective of Gurobi model.");
744  }
745  break;
746  }
747  case Maximize: {
748  try {
749  gurobiModel_.set(GRB_IntAttr_ModelSense, -1);
750  } catch(const GRBException& e) {
751  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
752  std::cout << e.getMessage() << std::endl;
753  throw std::runtime_error(e.getMessage());
754  } catch(...) {
755  std::cout << "Exception while setting objective of Gurobi model." << std::endl;
756  throw std::runtime_error("Exception while setting objective of Gurobi model.");
757  }
758  break;
759  }
760  default: {
761  throw std::runtime_error("Unknown Objective");
762  }
763  }
764 }
765 
767  try {
768  gurobiVariables_[variable].set(GRB_DoubleAttr_Obj, value);
769  } catch(const GRBException& e) {
770  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
771  std::cout << e.getMessage() << std::endl;
772  throw std::runtime_error(e.getMessage());
773  } catch(...) {
774  std::cout << "Exception while setting objective value of Gurobi model." << std::endl;
775  throw std::runtime_error("Exception while setting objective value of Gurobi model.");
776  }
777 }
778 
779 template<class ITERATOR_TYPE>
780 inline void LPSolverGurobi::setObjectiveValue_impl(ITERATOR_TYPE begin, const ITERATOR_TYPE end) {
781  try {
782  GRBLinExpr objective;
783  objective.addTerms(&(*begin), &gurobiVariables_[0], gurobiVariables_.size());
784  gurobiModel_.setObjective(objective);
785  } catch(const GRBException& e) {
786  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
787  std::cout << e.getMessage() << std::endl;
788  throw std::runtime_error(e.getMessage());
789  } catch(...) {
790  std::cout << "Exception while setting objective value of Gurobi model." << std::endl;
791  throw std::runtime_error("Exception while setting objective value of Gurobi model.");
792  }
793 }
794 
795 template<class VARIABLES_ITERATOR_TYPE, class COEFFICIENTS_ITERATOR_TYPE>
796 inline void LPSolverGurobi::setObjectiveValue_impl(VARIABLES_ITERATOR_TYPE variableIDsBegin, const VARIABLES_ITERATOR_TYPE variableIDsEnd, COEFFICIENTS_ITERATOR_TYPE coefficientsBegin) {
797  try {
798  while(variableIDsBegin != variableIDsEnd) {
799  gurobiVariables_[*variableIDsBegin].set(GRB_DoubleAttr_Obj, *coefficientsBegin);
800  ++variableIDsBegin;
801  ++coefficientsBegin;
802  }
803  } catch(const GRBException& e) {
804  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
805  std::cout << e.getMessage() << std::endl;
806  throw std::runtime_error(e.getMessage());
807  } catch(...) {
808  std::cout << "Exception while setting objective value of Gurobi model." << std::endl;
809  throw std::runtime_error("Exception while setting objective value of Gurobi model.");
810  }
811 }
812 
813 template<class VARIABLES_ITERATOR_TYPE, class COEFFICIENTS_ITERATOR_TYPE>
814 inline void LPSolverGurobi::addEqualityConstraint_impl(VARIABLES_ITERATOR_TYPE variableIDsBegin, const VARIABLES_ITERATOR_TYPE variableIDsEnd, COEFFICIENTS_ITERATOR_TYPE coefficientsBegin, const GurobiValueType bound, const std::string& constraintName) {
815  const GurobiIndexType numConstraintVariables = std::distance(variableIDsBegin, variableIDsEnd);
816  std::vector<GRBVar> constraintVariables;
817  constraintVariables.reserve(numConstraintVariables);
818  while(variableIDsBegin != variableIDsEnd) {
819  constraintVariables.push_back(gurobiVariables_[*variableIDsBegin]);
820  ++variableIDsBegin;
821  }
822 
823  try {
824  GRBLinExpr constraint;
825  constraint.addTerms(&(*coefficientsBegin), &constraintVariables[0], numConstraintVariables);
826  gurobiModel_.addConstr(constraint, GRB_EQUAL, bound, constraintName);
827  } catch(const GRBException& e) {
828  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
829  std::cout << e.getMessage() << std::endl;
830  throw std::runtime_error(e.getMessage());
831  } catch(...) {
832  std::cout << "Exception while adding equality constraint to Gurobi model." << std::endl;
833  throw std::runtime_error("Exception while adding equality constraint to Gurobi model.");
834  }
835 }
836 
837 template<class VARIABLES_ITERATOR_TYPE, class COEFFICIENTS_ITERATOR_TYPE>
838 inline void LPSolverGurobi::addLessEqualConstraint_impl(VARIABLES_ITERATOR_TYPE variableIDsBegin, const VARIABLES_ITERATOR_TYPE variableIDsEnd, COEFFICIENTS_ITERATOR_TYPE coefficientsBegin, const GurobiValueType bound, const std::string& constraintName) {
839  const GurobiIndexType numConstraintVariables = std::distance(variableIDsBegin, variableIDsEnd);
840  std::vector<GRBVar> constraintVariables;
841  constraintVariables.reserve(numConstraintVariables);
842  while(variableIDsBegin != variableIDsEnd) {
843  constraintVariables.push_back(gurobiVariables_[*variableIDsBegin]);
844  ++variableIDsBegin;
845  }
846 
847  try {
848  GRBLinExpr constraint;
849  constraint.addTerms(&(*coefficientsBegin), &constraintVariables[0], numConstraintVariables);
850  gurobiModel_.addConstr(constraint, GRB_LESS_EQUAL, bound, constraintName);
851  } catch(const GRBException& e) {
852  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
853  std::cout << e.getMessage() << std::endl;
854  throw std::runtime_error(e.getMessage());
855  } catch(...) {
856  std::cout << "Exception while adding less equal constraint to Gurobi model." << std::endl;
857  throw std::runtime_error("Exception while adding less equal constraint to Gurobi model.");
858  }
859 }
860 
861 template<class VARIABLES_ITERATOR_TYPE, class COEFFICIENTS_ITERATOR_TYPE>
862 inline void LPSolverGurobi::addGreaterEqualConstraint_impl(VARIABLES_ITERATOR_TYPE variableIDsBegin, const VARIABLES_ITERATOR_TYPE variableIDsEnd, COEFFICIENTS_ITERATOR_TYPE coefficientsBegin, const GurobiValueType bound, const std::string& constraintName) {
863  const GurobiIndexType numConstraintVariables = std::distance(variableIDsBegin, variableIDsEnd);
864  std::vector<GRBVar> constraintVariables;
865  constraintVariables.reserve(numConstraintVariables);
866  while(variableIDsBegin != variableIDsEnd) {
867  constraintVariables.push_back(gurobiVariables_[*variableIDsBegin]);
868  ++variableIDsBegin;
869  }
870 
871  try {
872  GRBLinExpr constraint;
873  constraint.addTerms(&(*coefficientsBegin), &constraintVariables[0], numConstraintVariables);
874  gurobiModel_.addConstr(constraint, GRB_GREATER_EQUAL, bound, constraintName);
875  } catch(const GRBException& e) {
876  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
877  std::cout << e.getMessage() << std::endl;
878  throw std::runtime_error(e.getMessage());
879  } catch(...) {
880  std::cout << "Exception while adding greater equal constraint to Gurobi model." << std::endl;
881  throw std::runtime_error("Exception while adding greater equal constraint to Gurobi model.");
882  }
883 }
884 
886  try {
887  gurobiModel_.update();
888  } catch(const GRBException& e) {
889  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
890  std::cout << e.getMessage() << std::endl;
891  throw std::runtime_error(e.getMessage());
892  } catch(...) {
893  std::cout << "Exception while incorporating constraints into Gurobi model." << std::endl;
894  throw std::runtime_error("Exception while incorporating constraints into Gurobi model.");
895  }
896 }
897 
899  try {
900  Timer timer;
901  timer.tic();
902  gurobiModel_.update();
903  timer.toc();
904  timing = timer.elapsedTime();
905  } catch(const GRBException& e) {
906  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
907  std::cout << e.getMessage() << std::endl;
908  throw std::runtime_error(e.getMessage());
909  } catch(...) {
910  std::cout << "Exception while incorporating constraints into Gurobi model." << std::endl;
911  throw std::runtime_error("Exception while incorporating constraints into Gurobi model.");
912  }
913 }
914 
915 template <class PARAMETER_TYPE, class PARAMETER_VALUE_TYPE>
916 inline void LPSolverGurobi::setParameter_impl(const PARAMETER_TYPE parameter, const PARAMETER_VALUE_TYPE value) {
917  try {
918  gurobiModel_.getEnv().set(parameter, value);
919  } catch(const GRBException& e) {
920  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
921  std::cout << e.getMessage() << std::endl;
922  throw std::runtime_error(e.getMessage());
923  } catch(...) {
924  std::cout << "Exception while setting parameter for Gurobi model." << std::endl;
925  throw std::runtime_error("Exception while setting parameter for Gurobi model.");
926  }
927 }
928 
930  gurobiSolutionValid_ = false;
931  try {
932  gurobiModel_.optimize();
933  if(gurobiModel_.get(GRB_IntAttr_Status) == GRB_OPTIMAL) {
934  return true;
935  } else {
936  return false;
937  }
938  } catch(const GRBException& e) {
939  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
940  std::cout << e.getMessage() << std::endl;
941  throw std::runtime_error(e.getMessage());
942  } catch(...) {
943  std::cout << "Exception while solving Gurobi model." << std::endl;
944  throw std::runtime_error("Exception while solving Gurobi model.");
945  }
946 }
947 
949  gurobiSolutionValid_ = false;
950  try {
951  gurobiModel_.optimize();
952  timing = gurobiModel_.get(GRB_DoubleAttr_Runtime);
953  if(gurobiModel_.get(GRB_IntAttr_Status) == GRB_OPTIMAL) {
954  return true;
955  } else {
956  return false;
957  }
958  } catch(const GRBException& e) {
959  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
960  std::cout << e.getMessage() << std::endl;
961  throw std::runtime_error(e.getMessage());
962  } catch(...) {
963  std::cout << "Exception while solving Gurobi model." << std::endl;
964  throw std::runtime_error("Exception while solving Gurobi model.");
965  }
966 }
967 
969  updateSolution();
970  return gurobiSolution_.begin();
971 }
972 
974  updateSolution();
975  return gurobiSolution_.end();
976 }
977 
979  try {
980  return gurobiVariables_[variable].get(GRB_DoubleAttr_X);
981  } catch(const GRBException& e) {
982  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
983  std::cout << e.getMessage() << std::endl;
984  throw std::runtime_error(e.getMessage());
985  } catch(...) {
986  std::cout << "Exception while accessing Gurobi solution of variable." << std::endl;
987  throw std::runtime_error("Exception while accessing Gurobi solution of variable.");
988  }
989 }
990 
992  try {
993  return gurobiModel_.get(GRB_DoubleAttr_ObjVal);
994  } catch(const GRBException& e) {
995  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
996  std::cout << e.getMessage() << std::endl;
997  throw std::runtime_error(e.getMessage());
998  } catch(...) {
999  std::cout << "Exception while accessing Gurobi solution for objective function value." << std::endl;
1000  throw std::runtime_error("Exception while accessing Gurobi solution for objective function value.");
1001  }
1002 }
1003 
1005  try {
1006  if(gurobiModel_.get(GRB_IntAttr_IsMIP)) {
1007  return gurobiModel_.get(GRB_DoubleAttr_ObjBound);
1008  } else {
1009  return gurobiModel_.get(GRB_DoubleAttr_ObjVal);
1010  }
1011  } catch(const GRBException& e) {
1012  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
1013  std::cout << e.getMessage() << std::endl;
1014  throw std::runtime_error(e.getMessage());
1015  } catch(...) {
1016  std::cout << "Exception while accessing Gurobi bound for objective function value." << std::endl;
1017  throw std::runtime_error("Exception while accessing Gurobi bound for objective function value.");
1018  }
1019 }
1020 
1021 inline void LPSolverGurobi::exportModel_impl(const std::string& filename) const {
1022  try {
1023  gurobiModel_.write(filename);
1024  } catch(const GRBException& e) {
1025  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
1026  std::cout << e.getMessage() << std::endl;
1027  throw std::runtime_error(e.getMessage());
1028  } catch(...) {
1029  std::cout << "Exception while writing Gurobi model to file." << std::endl;
1030  throw std::runtime_error("Exception while writing Gurobi model to file.");
1031  }
1032 }
1033 
1034 inline void LPSolverGurobi::updateSolution() const {
1035  if(!gurobiSolutionValid_) {
1036  try {
1037  for(GurobiIndexType i = 0; i < static_cast<GurobiIndexType>(gurobiVariables_.size()); ++i) {
1038  gurobiSolution_[i] = gurobiVariables_[i].get(GRB_DoubleAttr_X);
1039  }
1040  gurobiSolutionValid_ = true;
1041  } catch(const GRBException& e) {
1042  std::cout << "Gurobi Error code = " << e.getErrorCode() << std::endl;
1043  std::cout << e.getMessage() << std::endl;
1044  throw std::runtime_error(e.getMessage());
1045  } catch(...) {
1046  std::cout << "Exception while updating Gurobi solution." << std::endl;
1047  throw std::runtime_error("Exception while updating Gurobi solution.");
1048  }
1049  }
1050 }
1051 
1053  switch(cutLevel){
1055  case LPDef::MIP_CUT_AUTO:
1056  return -1;
1057  case LPDef::MIP_CUT_OFF:
1058  return 0;
1059  case LPDef::MIP_CUT_ON:
1060  return 1;
1062  return 2;
1064  return 3;
1065  default:
1066  throw std::runtime_error("Unknown Cut level.");
1067  }
1068 }
1069 
1070 } // namespace opengm
1071 
1072 #endif /* OPENGM_LP_SOLVER_GUROBI_HXX_ */
void updateSolution() const
Update solution if required.
void setObjective_impl(const Objective objective)
Set objective to minimize or maximize.
The OpenGM namespace.
Definition: config.hxx:43
LPSolverInterface< LPSolverGurobi, GurobiValueType, GurobiIndexType, GurobiSolutionIteratorType, GurobiTimingType > LPSolverBaseClass
Defines the type of the base class.
void addContinuousVariables_impl(const GurobiIndexType numVariables, const GurobiValueType lowerBound, const GurobiValueType upperBound)
Add new continuous variables to the model.
Wrapper class for the Gurobi optimizer.
GurobiSolutionIteratorType solutionEnd_impl() const
Get an iterator which is pointing to the end of the solution computed by Gurobi.
void toc()
Definition: timer.hxx:109
Platform-independent runtime measurements.
Definition: timer.hxx:29
static GurobiValueType infinity_impl()
Get the value which is used by Gurobi to represent infinity.
void addBinaryVariables_impl(const GurobiIndexType numVariables)
Add new binary variables to the model.
Provides Interface definition for wrapper of LP Solvers like CPLEX and Gurobi.
GRBModel gurobiModel_
The Gurobi model of the LP/MIP problem.
GurobiValueType solution_impl(const GurobiIndexType variable) const
Get the solution value of a variable computed by Gurobi.
GurobiValueType objectiveFunctionValueBound_impl() const
Get the best known bound for the optimal solution of the current model.
void addConstraintsFinished_impl()
Join all constraints added via LPSolverGurobi::addEqualityConstraint, LPSolverGurobi::addLessEqualCon...
Interface definition for wrapper of LP Solvers like CPLEX and Gurobi.
double GurobiTimingType
Defines the timing type used by Gurobi.
void addLessEqualConstraint_impl(VARIABLES_ITERATOR_TYPE variableIDsBegin, const VARIABLES_ITERATOR_TYPE variableIDsEnd, COEFFICIENTS_ITERATOR_TYPE coefficientsBegin, const GurobiValueType bound, const std::string &constraintName="")
Add a new less equal constraint to the model.
int GurobiIndexType
Defines the index type used by Gurobi.
double elapsedTime() const
Definition: timer.hxx:130
void tic()
Definition: timer.hxx:96
void addGreaterEqualConstraint_impl(VARIABLES_ITERATOR_TYPE variableIDsBegin, const VARIABLES_ITERATOR_TYPE variableIDsEnd, COEFFICIENTS_ITERATOR_TYPE coefficientsBegin, const GurobiValueType bound, const std::string &constraintName="")
Add a new greater equal constraint to the model.
std::vector< GurobiValueType >::const_iterator GurobiSolutionIteratorType
Defines the iterator type which can be used to iterate over the solution of Gurobi.
~LPSolverGurobi()
Destructor for LPSolverGurobi.
double GurobiValueType
Defines the value type used by Gurobi.
std::vector< GRBVar > gurobiVariables_
The variables which are present in the model.
void addIntegerVariables_impl(const GurobiIndexType numVariables, const GurobiValueType lowerBound, const GurobiValueType upperBound)
Add new integer variables to the model.
void exportModel_impl(const std::string &filename) const
Export model to file.
bool solve_impl()
Solve the current model.
void setObjectiveValue_impl(const GurobiIndexType variable, const GurobiValueType value)
Set the coefficient of a variable in the objective function.
static int getCutLevelValue(const LPDef::MIP_CUT cutLevel)
Translate LPDef::MIP_CUT into corresponding Gurobi int value.
bool gurobiSolutionValid_
Tell if the currently stored solution is valid.
void addEqualityConstraint_impl(VARIABLES_ITERATOR_TYPE variableIDsBegin, const VARIABLES_ITERATOR_TYPE variableIDsEnd, COEFFICIENTS_ITERATOR_TYPE coefficientsBegin, const GurobiValueType bound, const std::string &constraintName="")
Add a new equality constraint to the model.
std::vector< GurobiValueType > gurobiSolution_
Storage for the solution computed by Gurobi.
GRBEnv gurobiEnvironment_
The Gurobi environment.
GurobiSolutionIteratorType solutionBegin_impl() const
Get an iterator which is pointing to the begin of the solution computed by Gurobi.
GurobiValueType objectiveFunctionValue_impl() const
Get the objective function value from Gurobi.
void setParameter_impl(const PARAMETER_TYPE parameter, const PARAMETER_VALUE_TYPE value)
Set Gurobi parameter.
LPSolverGurobi(const Parameter &parameter=Parameter())
Default constructor for LPSolverGurobi.