OpenGM  2.3.x
Discrete Graphical Model Library
lp_inference_base.hxx
Go to the documentation of this file.
1 #ifndef OPENGM_LP_INFERENCE_BASE_HXX_
2 #define OPENGM_LP_INFERENCE_BASE_HXX_
3 
4 #include <utility>
5 #include <vector>
6 #include <map>
7 #include <list>
8 #include <typeinfo>
9 #include <limits>
10 
19 
20 namespace opengm {
21 
22 /********************
23  * class definition *
24  *******************/
25 template <class LP_INFERENCE_TYPE>
27 
28 template <class LP_INFERENCE_TYPE>
29 class LPInferenceBase : public Inference<typename LPInferenceTraits<LP_INFERENCE_TYPE>::GraphicalModelType, typename LPInferenceTraits<LP_INFERENCE_TYPE>::AccumulationType> {
30 public:
31  // typedefs
32  typedef LP_INFERENCE_TYPE LPInferenceType;
35  typedef typename LPInferenceTraitsType::AccumulationType AccumulationType;
36  typedef typename LPInferenceTraitsType::GraphicalModelType GraphicalModelType;
38 
42 
44  typedef std::vector<LinearConstraintType> LinearConstraintsContainerType;
45  typedef typename LinearConstraintsContainerType::const_iterator LinearConstraintsIteratorType;
50 
52 
53  typedef typename LPInferenceTraitsType::SolverType SolverType;
54  typedef typename LPInferenceTraitsType::SolverIndexType SolverIndexType;
55  typedef typename LPInferenceTraitsType::SolverValueType SolverValueType;
56  typedef typename LPInferenceTraitsType::SolverSolutionIteratorType SolverSolutionIteratorType;
57  typedef typename LPInferenceTraitsType::SolverTimingType SolverTimingType;
58  typedef typename LPInferenceTraitsType::SolverParameterType SolverParameterType;
59 
62 
63  struct Parameter : public SolverParameterType {
64  // LocalPolytope will add a first order local polytope approximation of the marginal polytope, i.e. the affine instead of the convex hull.
65  // LoosePolytope will add no constraints at all. All linear constraints will be added iteratively only if they are violated.
66  // TightPolytope will add all constraints of the LocalPolytope relaxation and furthermore all constraints that are present in the model via constraint functions. Thus all constraints will be added before the first run of lp inference which leads to solving the problem in only one iteration.
69 
70  Parameter();
71 
72  // general options
73  bool integerConstraintNodeVar_; // use integer constraints for node variables
74  bool integerConstraintFactorVar_; // use integer constraints for factor variables
75  bool useSoftConstraints_; // if constraint factors are present in the model add them as soft constraints e.g. treat them as normal factors
76  bool useFunctionTransfer_; // use function transfer if available to generate more efficient lp models
77  bool mergeParallelFactors_; // merge factors which are connected to the same set of variables
78  bool nameConstraints_; // create unique names for the linear constraints added to the model (might be helpful for debugging models)
79  Relaxation relaxation_; // relaxation method
80  size_t maxNumIterations_; // maximum number of tightening iterations (infinite if set to 0)
81  size_t maxNumConstraintsPerIter_; // maximum number of added constraints per tightening iteration (all if set to 0)
82  ChallengeHeuristic challengeHeuristic_; // heuristic on how to select violated constraints
83  ValueType tolerance_; // tolerance for violation of linear constraints
84  };
85 
86  // public member functions
87  virtual const GraphicalModelType& graphicalModel() const;
88  virtual InferenceTermination infer();
89  template<class VISITOR_TYPE>
90  InferenceTermination infer(VISITOR_TYPE& visitor);
91  virtual ValueType bound() const;
92  virtual ValueType value() const;
93  virtual InferenceTermination arg(std::vector<LabelType>& x, const size_t N = 1) const;
94 
95 protected:
96  // structs
98  std::vector<SolverIndexType> variableIDs_;
99  std::vector<SolverValueType> coefficients_;
100  SolverValueType bound_;
102  std::string name_;
103  };
104 
105  // protected typedefs
106  typedef typename std::list<ConstraintStorage> InactiveConstraintsListType;
107  typedef typename InactiveConstraintsListType::iterator InactiveConstraintsListIteratorType;
108  typedef std::pair<IndexType, const LinearConstraintType*> FactorIndexConstraintPointerPairType;
109  typedef std::pair<InactiveConstraintsListIteratorType, FactorIndexConstraintPointerPairType> InactiveConstraintFactorConstraintPairType;
110  typedef std::multimap<double, InactiveConstraintFactorConstraintPairType> SortedViolatedConstraintsListType;
111 
112  // functors
114  // storage
115  IndicatorVariablesIteratorType indicatorVariablesOrderBegin_;
116  // operator()
117  template<class LINEAR_CONSTRAINT_FUNCTION_TYPE>
118  void operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE& linearConstraintFunction);
119  // helper
120  template<class FUNCTION_TYPE, bool IS_LINEAR_CONSTRAINT_FUNCTION>
122  static void getIndicatorVariablesOrderBeginFunctor_impl(GetIndicatorVariablesOrderBeginFunctor& myself, const FUNCTION_TYPE& function);
123  };
124  template<class FUNCTION_TYPE>
125  struct GetIndicatorVariablesOrderBeginFunctor_impl<FUNCTION_TYPE, true> {
126  static void getIndicatorVariablesOrderBeginFunctor_impl(GetIndicatorVariablesOrderBeginFunctor& myself, const FUNCTION_TYPE& function);
127  };
128  };
130  // storage
131  IndicatorVariablesIteratorType indicatorVariablesOrderEnd_;
132  // operator()
133  template<class LINEAR_CONSTRAINT_FUNCTION_TYPE>
134  void operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE& linearConstraintFunction);
135  // helper
136  template<class FUNCTION_TYPE, bool IS_LINEAR_CONSTRAINT_FUNCTION>
138  static void getIndicatorVariablesOrderEndFunctor_impl(GetIndicatorVariablesOrderEndFunctor& myself, const FUNCTION_TYPE& function);
139  };
140  template<class FUNCTION_TYPE>
141  struct GetIndicatorVariablesOrderEndFunctor_impl<FUNCTION_TYPE, true> {
142  static void getIndicatorVariablesOrderEndFunctor_impl(GetIndicatorVariablesOrderEndFunctor& myself, const FUNCTION_TYPE& function);
143  };
144  };
146  // storage
147  LinearConstraintsIteratorType linearConstraintsBegin_;
148  // operator()
149  template<class LINEAR_CONSTRAINT_FUNCTION_TYPE>
150  void operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE& linearConstraintFunction);
151  // helper
152  template<class FUNCTION_TYPE, bool IS_LINEAR_CONSTRAINT_FUNCTION>
154  static void getLinearConstraintsBeginFunctor_impl(GetLinearConstraintsBeginFunctor& myself, const FUNCTION_TYPE& function);
155  };
156  template<class FUNCTION_TYPE>
157  struct GetLinearConstraintsBeginFunctor_impl<FUNCTION_TYPE, true> {
158  static void getLinearConstraintsBeginFunctor_impl(GetLinearConstraintsBeginFunctor& myself, const FUNCTION_TYPE& function);
159  };
160  };
162  // storage
163  LinearConstraintsIteratorType linearConstraintsEnd_;
164  // operator()
165  template<class LINEAR_CONSTRAINT_FUNCTION_TYPE>
166  void operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE& linearConstraintFunction);
167  // helper
168  template<class FUNCTION_TYPE, bool IS_LINEAR_CONSTRAINT_FUNCTION>
170  static void getLinearConstraintsEndFunctor_impl(GetLinearConstraintsEndFunctor& myself, const FUNCTION_TYPE& function);
171  };
172  template<class FUNCTION_TYPE>
173  struct GetLinearConstraintsEndFunctor_impl<FUNCTION_TYPE, true> {
174  static void getLinearConstraintsEndFunctor_impl(GetLinearConstraintsEndFunctor& myself, const FUNCTION_TYPE& function);
175  };
176  };
178  // storage
180  IntegerSolutionSubsequenceIterator labelingBegin_;
182  LPInferenceBaseType* lpInference_;
184  // operator()
185  template<class LINEAR_CONSTRAINT_FUNCTION_TYPE>
186  void operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE& linearConstraintFunction);
187  // helper
188  template<class FUNCTION_TYPE, bool IS_LINEAR_CONSTRAINT_FUNCTION>
190  static void addAllViolatedLinearConstraintsFunctor_impl(AddAllViolatedLinearConstraintsFunctor& myself, const FUNCTION_TYPE& function);
191  };
192  template<class FUNCTION_TYPE>
193  struct AddAllViolatedLinearConstraintsFunctor_impl<FUNCTION_TYPE, true> {
194  static void addAllViolatedLinearConstraintsFunctor_impl(AddAllViolatedLinearConstraintsFunctor& myself, const FUNCTION_TYPE& function);
195  };
196  };
198  // storage
200  RelaxedSolutionSubsequenceIterator labelingBegin_;
202  LPInferenceBaseType* lpInference_;
204  // operator()
205  template<class LINEAR_CONSTRAINT_FUNCTION_TYPE>
206  void operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE& linearConstraintFunction);
207  // helper
208  template<class FUNCTION_TYPE, bool IS_LINEAR_CONSTRAINT_FUNCTION>
211  };
212  template<class FUNCTION_TYPE>
215  };
216  };
217 
218  // meta
219  // note: LinearConstraintFunctionTypeList might be an empty type list containing only meta::ListEnd elements.
220  // This happens if GM::FunctionTypeList does not contain any linear constraint function
221  typedef typename meta::GetLinearConstraintFunctionTypeList<typename GraphicalModelType::FunctionTypeList>::type LinearConstraintFunctionTypeList;
222 
223  // storage
224  const GraphicalModelType& gm_;
225  const Parameter parameter_;
227  std::vector<IndexType> unaryFactors_;
228  std::vector<IndexType> higherOrderFactors_;
229  std::vector<IndexType> linearConstraintFactors_;
230  std::vector<IndexType> transferableFactors_;
232  SolverIndexType numLPVariables_;
233  SolverIndexType numNodesLPVariables_;
234  SolverIndexType numFactorsLPVariables_;
237  SolverIndexType numSlackVariables_;
238 
239  // lookup tables
240  std::vector<SolverIndexType> nodesLPVariablesOffset_;
241  std::vector<SolverIndexType> factorsLPVariablesOffset_;
242  // TODO The lookups might be faster by using hashmaps instead of std::map (requires C++11)
243  std::vector<std::map<const IndicatorVariableType, SolverIndexType> > linearConstraintsLPVariablesIndicesLookupTable_;
244  std::vector<std::map<const IndicatorVariableType, SolverIndexType> > transferedFactorsLPVariablesIndicesLookupTable_;
245  std::vector<std::vector<size_t> > linearConstraintLPVariablesSubsequenceIndices_;
246 
247  // cache
250  InactiveConstraintsListType inactiveConstraints_;
251 
252  // protected member functions
253  // construction
254  LPInferenceBase(const GraphicalModelType& gm, const Parameter& parameter = Parameter()); // no instance of LPInferenceBase is allowed
255  virtual ~LPInferenceBase();
256 
257  // initialization
258  void sortFactors();
259  void countLPVariables();
261  void setAccumulation();
262  void addLPVariables();
267 
268  // LP variables mapping functions
269  SolverIndexType nodeLPVariableIndex(const IndexType nodeID, const LabelType label) const;
270  SolverIndexType factorLPVariableIndex(const IndexType factorID, const size_t labelingIndex) const;
271  template<class LABELING_ITERATOR_TYPE>
272  SolverIndexType factorLPVariableIndex(const IndexType factorID, LABELING_ITERATOR_TYPE labelingBegin, const LABELING_ITERATOR_TYPE labelingEnd) const;
273  template <class HIGHER_ORDER_FACTORS_MAP_TYPE, class INDICATOR_VARIABLES_MAP_TYPE>
274  bool getLPVariableIndexFromIndicatorVariable(const HIGHER_ORDER_FACTORS_MAP_TYPE& higherOrderFactorVariablesLookupTable, const INDICATOR_VARIABLES_MAP_TYPE& indicatorVariablesLookupTable, const IndicatorVariableType& indicatorVariable, const IndexType linearConstraintFactorIndex, SolverIndexType& lpVariableIndex) const;
275 
276  // constraints creation helper
277  void addLocalPolytopeVariableConstraint(const IndexType variableID, const bool addToModel);
278  void addLocalPolytopeFactorConstraint(const IndexType factor, const IndexType variable, const LabelType label, const bool addToModel);
279  void addIndicatorVariableConstraints(const IndexType factor, const IndicatorVariableType& indicatorVariable, const SolverIndexType indicatorVariableLPVariable, const bool addToModel);
280  void addLinearConstraint(const IndexType linearConstraintFactor, const LinearConstraintType& constraint);
281 
282  // inference helper
283  template <class VISITOR_TYPE>
284  InferenceTermination infer_impl_selectRelaxation(VISITOR_TYPE& visitor);
285  template <class VISITOR_TYPE, typename Parameter::Relaxation RELAXATION>
286  InferenceTermination infer_impl_selectHeuristic(VISITOR_TYPE& visitor);
287  template <class VISITOR_TYPE, typename Parameter::Relaxation RELAXATION, typename Parameter::ChallengeHeuristic HEURISTIC>
288  InferenceTermination infer_impl_selectIterations(VISITOR_TYPE& visitor);
289  template <class VISITOR_TYPE, typename Parameter::Relaxation RELAXATION, typename Parameter::ChallengeHeuristic HEURISTIC, bool USE_INFINITE_ITERATIONS>
291  template <class VISITOR_TYPE, typename Parameter::Relaxation RELAXATION, typename Parameter::ChallengeHeuristic HEURISTIC, bool USE_INFINITE_ITERATIONS, bool ADD_ALL_VIOLATED_CONSTRAINTS>
292  InferenceTermination infer_impl_selectLPType(VISITOR_TYPE& visitor);
293  template <class VISITOR_TYPE, typename Parameter::Relaxation RELAXATION, typename Parameter::ChallengeHeuristic HEURISTIC, bool USE_INFINITE_ITERATIONS, bool ADD_ALL_VIOLATED_CONSTRAINTS, bool USE_INTEGER_CONSTRAINTS>
294  InferenceTermination infer_impl(VISITOR_TYPE& visitor);
295  template <typename Parameter::Relaxation RELAXATION, typename Parameter::ChallengeHeuristic HEURISTIC, bool ADD_ALL_VIOLATED_CONSTRAINTS>
296  bool tightenPolytope();
297  template <typename Parameter::Relaxation RELAXATION, typename Parameter::ChallengeHeuristic HEURISTIC, bool ADD_ALL_VIOLATED_CONSTRAINTS>
298  bool tightenPolytopeRelaxed();
299  void checkInactiveConstraint(const ConstraintStorage& constraint, double& weight) const;
300  void addInactiveConstraint(const ConstraintStorage& constraint);
301 
302  // friends
303  template <class LP_INFERENCE_BASE_TYPE, typename LP_INFERENCE_BASE_TYPE::Parameter::ChallengeHeuristic HEURISTIC>
305  template <class LP_INFERENCE_BASE_TYPE, typename LP_INFERENCE_BASE_TYPE::Parameter::ChallengeHeuristic HEURISTIC>
307 };
308 
309 template <class LP_INFERENCE_BASE_TYPE, typename LP_INFERENCE_BASE_TYPE::Parameter::ChallengeHeuristic HEURISTIC>
311  // storage
312  typename LP_INFERENCE_BASE_TYPE::ValueType tolerance_;
313  typename LP_INFERENCE_BASE_TYPE::IntegerSolutionSubsequenceIterator labelingBegin_;
315  LP_INFERENCE_BASE_TYPE* lpInference_;
316  typename LP_INFERENCE_BASE_TYPE::IndexType linearConstraintID_;
317  typename LP_INFERENCE_BASE_TYPE::SortedViolatedConstraintsListType* sortedViolatedConstraintsList_;
318  // operator()
319  template<class LINEAR_CONSTRAINT_FUNCTION_TYPE>
320  void operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE& linearConstraintFunction);
321  // helper
322  template<class FUNCTION_TYPE, bool IS_LINEAR_CONSTRAINT_FUNCTION>
325  };
326  template<class FUNCTION_TYPE>
327  struct AddViolatedLinearConstraintsFunctor_impl<FUNCTION_TYPE, true> {
329  };
330 };
331 template <class LP_INFERENCE_BASE_TYPE, typename LP_INFERENCE_BASE_TYPE::Parameter::ChallengeHeuristic HEURISTIC>
333  // storage
334  typename LP_INFERENCE_BASE_TYPE::ValueType tolerance_;
335  typename LP_INFERENCE_BASE_TYPE::RelaxedSolutionSubsequenceIterator labelingBegin_;
337  LP_INFERENCE_BASE_TYPE* lpInference_;
338  typename LP_INFERENCE_BASE_TYPE::IndexType linearConstraintID_;
339  typename LP_INFERENCE_BASE_TYPE::SortedViolatedConstraintsListType* sortedViolatedConstraintsList_;
340  // operator()
341  template<class LINEAR_CONSTRAINT_FUNCTION_TYPE>
342  void operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE& linearConstraintFunction);
343  // helper
344  template<class FUNCTION_TYPE, bool IS_LINEAR_CONSTRAINT_FUNCTION>
347  };
348  template<class FUNCTION_TYPE>
351  };
352 };
353 
354 /***********************
355  * class documentation *
356  **********************/
1748 /******************
1749  * implementation *
1750  *****************/
1751 template <class LP_INFERENCE_TYPE>
1753  : SolverParameterType(), integerConstraintNodeVar_(false),
1754  integerConstraintFactorVar_(false), useSoftConstraints_(false),
1755  useFunctionTransfer_(false), mergeParallelFactors_(false),
1756  nameConstraints_(false), relaxation_(LocalPolytope),
1757  maxNumIterations_(1000), maxNumConstraintsPerIter_(0),
1758  challengeHeuristic_(Random), tolerance_(OPENGM_FLOAT_TOL) {
1759 
1760 }
1761 
1762 template <class LP_INFERENCE_TYPE>
1764  return gm_;
1765 }
1766 
1767 template <class LP_INFERENCE_TYPE>
1769  EmptyVisitorType visitor;
1770  return infer(visitor);
1771 }
1772 
1773 template <class LP_INFERENCE_TYPE>
1774 template<class VISITOR_TYPE>
1776  // Inference is performed in the method infer_impl(). Therefore appropriate
1777  // template parameters have to be selected. This is done by the
1778  // infer_impl_select... methods.
1779  return infer_impl_selectRelaxation(visitor);
1780 }
1781 
1782 template <class LP_INFERENCE_TYPE>
1784  if(inferenceStarted_) {
1785  return static_cast<const LPInferenceType*>(this)->objectiveFunctionValueBound() + constValue_;
1786  }
1787  else{
1788  return AccumulationType::template ineutral<ValueType>();
1789  }
1790 }
1791 
1792 template <class LP_INFERENCE_TYPE>
1794  std::vector<LabelType> states;
1795  arg(states);
1796  return gm_.evaluate(states);
1797 }
1798 
1799 template <class LP_INFERENCE_TYPE>
1800 inline InferenceTermination LPInferenceBase<LP_INFERENCE_TYPE>::arg(std::vector<LabelType>& x, const size_t N) const {
1801  x.resize(gm_.numberOfVariables());
1802  if(inferenceStarted_) {
1803  SolverSolutionIteratorType solutionIterator = static_cast<const LPInferenceType*>(this)->solutionBegin();
1804  for(IndexType node = 0; node < gm_.numberOfVariables(); ++node) {
1805  SolverIndexType currentNodeLPVariable = nodesLPVariablesOffset_[node];
1806  SolverValueType bestValue = solutionIterator[currentNodeLPVariable];
1807  LabelType state = 0;
1808  for(LabelType i = 1; i < gm_.numberOfLabels(node); ++i) {
1809  ++currentNodeLPVariable;
1810  const SolverValueType currentValue = solutionIterator[currentNodeLPVariable];
1811  if(currentValue > bestValue) {
1812  bestValue = currentValue;
1813  state = i;
1814  }
1815  }
1816  x[node] = state;
1817  }
1818  return NORMAL;
1819  } else {
1820  for(IndexType node = 0; node < gm_.numberOfVariables(); ++node) {
1821  x[node] = 0;
1822  }
1823  return UNKNOWN;
1824  }
1825 }
1826 
1827 template <class LP_INFERENCE_TYPE>
1828 inline LPInferenceBase<LP_INFERENCE_TYPE>::LPInferenceBase(const GraphicalModelType& gm, const Parameter& parameter)
1829  : gm_(gm), parameter_(parameter), constValue_(0.0), unaryFactors_(),
1830  higherOrderFactors_(), linearConstraintFactors_(), transferableFactors_(),
1831  inferenceStarted_(false), numLPVariables_(0), numNodesLPVariables_(0),
1832  numFactorsLPVariables_(0), numLinearConstraintsLPVariables_(0),
1833  numTransferedFactorsLPVariables(0), numSlackVariables_(0),
1834  nodesLPVariablesOffset_(gm_.numberOfVariables()),
1835  factorsLPVariablesOffset_(gm_.numberOfFactors()),
1836  linearConstraintsLPVariablesIndicesLookupTable_(),
1837  transferedFactorsLPVariablesIndicesLookupTable_(),
1838  linearConstraintLPVariablesSubsequenceIndices_(),
1839  addLocalPolytopeFactorConstraintCachePreviousFactorID_(gm_.numberOfFactors()),
1840  addLocalPolytopeFactorConstraintCacheFactorLPVariableIDs_(),
1841  inactiveConstraints_() {
1842  if(!opengm::meta::Compare<OperatorType, opengm::Adder>::value) {
1843  throw RuntimeError("This implementation does only supports Min-Sum-Semiring and Max-Sum-Semiring.");
1844  }
1845 
1846  // sort factors
1847  sortFactors();
1848 
1849  // count number of required LP variables
1850  countLPVariables();
1851 
1852  // fill subsequence look up table for linear constraints
1854 
1855  // set accumulation
1856  setAccumulation();
1857 
1858  // add variables
1859  addLPVariables();
1860 
1861  // create objective function
1863 
1864  // add constraints
1865  switch(parameter_.relaxation_){
1866  case Parameter::LocalPolytope : {
1868  break;
1869  }
1870  case Parameter::LoosePolytope : {
1872  break;
1873  }
1874  case Parameter::TightPolytope: {
1876  break;
1877  }
1878  default : {
1879  throw RuntimeError("Unknown Relaxation");
1880  }
1881  }
1882 
1883  // Tell child class we are finished with adding constraints
1884  static_cast<LPInferenceType*>(this)->addConstraintsFinished();
1885 
1886  // clear cache (only needed durig construction)
1887  addLocalPolytopeFactorConstraintCacheFactorLPVariableIDs_ = marray::Marray<SolverIndexType>();
1888  addLocalPolytopeFactorConstraintCachePreviousFactorID_ = gm_.numberOfFactors();
1889 }
1890 
1891 template <class LP_INFERENCE_TYPE>
1893 
1894 }
1895 
1896 template <class LP_INFERENCE_TYPE>
1898  typename LPFunctionTransferType::IsTransferableFunctor isTransferableFunctor;
1899  for(IndexType factorIndex = 0; factorIndex < gm_.numberOfFactors(); ++factorIndex){
1900  gm_[factorIndex].callFunctor(isTransferableFunctor);
1901  if((!parameter_.useSoftConstraints_) && gm_[factorIndex].isLinearConstraint()) {
1902  linearConstraintFactors_.push_back(factorIndex);
1903  } else if(parameter_.useFunctionTransfer_ && isTransferableFunctor.isTransferable_) {
1904  transferableFactors_.push_back(factorIndex);
1905  } else if(gm_[factorIndex].numberOfVariables() == 0) {
1906  const LabelType l = 0;
1907  constValue_ += gm_[factorIndex](&l);
1908  } else if(gm_[factorIndex].numberOfVariables() == 1) {
1909  unaryFactors_.push_back(factorIndex);
1910  } else if(gm_[factorIndex].numberOfVariables() > 1) {
1911  higherOrderFactors_.push_back(factorIndex);
1912  }
1913  }
1914 }
1915 
1916 template <class LP_INFERENCE_TYPE>
1918  // number of node LP variables
1919  for(IndexType node = 0; node < gm_.numberOfVariables(); ++node){
1920  numNodesLPVariables_ += gm_.numberOfLabels(node);
1921  nodesLPVariablesOffset_[node] = numLPVariables_;
1922  numLPVariables_ += gm_.numberOfLabels(node);
1923  }
1924 
1925  // set unary factors offset
1926  for(IndexType i = 0; i < unaryFactors_.size(); ++i) {
1927  const IndexType factorIndex = unaryFactors_[i];
1928  const IndexType node = gm_[factorIndex].variableIndex(0);
1929  factorsLPVariablesOffset_[factorIndex] = nodesLPVariablesOffset_[node];
1930  }
1931 
1932  // number of factor LP variables
1933  // lookup table to search for parallel factors
1934  // TODO The lookup might be faster by using a hashmap (requires C++11)
1935  std::map<std::vector<IndexType>, IndexType> higherOrderFactorVariablesLookupTable;
1936  for(IndexType i = 0; i < higherOrderFactors_.size(); ++i) {
1937  const IndexType factorIndex = higherOrderFactors_[i];
1938  bool duplicate = false;
1939  if(parameter_.mergeParallelFactors_) {
1940  // check if factor with same variables is already present in the model
1941  std::vector<IndexType> currentFactorVariables(gm_[factorIndex].numberOfVariables());
1942  for(IndexType j = 0; j < gm_[factorIndex].numberOfVariables(); ++j) {
1943  currentFactorVariables[j] = gm_[factorIndex].variableIndex(j);
1944  }
1945  const typename std::map<std::vector<IndexType>, IndexType>::const_iterator iter = higherOrderFactorVariablesLookupTable.find(currentFactorVariables);
1946  if(iter != higherOrderFactorVariablesLookupTable.end()) {
1947  // parallel factor found
1948  factorsLPVariablesOffset_[factorIndex] = factorsLPVariablesOffset_[iter->second];
1949  duplicate = true;
1950  } else {
1951  higherOrderFactorVariablesLookupTable[currentFactorVariables] = factorIndex;
1952  }
1953  }
1954  if(!duplicate) {
1955  const size_t currentSize = gm_[factorIndex].size();
1956  numFactorsLPVariables_ += currentSize;
1957  factorsLPVariablesOffset_[factorIndex] = numLPVariables_;
1958  numLPVariables_ += currentSize;
1959  }
1960  }
1961 
1962  OPENGM_ASSERT(numLPVariables_ == numNodesLPVariables_ + numFactorsLPVariables_);
1963 
1964  // count linear constraint variables
1965  // lookup table to search for parallel indicator variables
1966  // TODO The lookup might be faster by using a hashmap (requires C++11)
1967  std::map<std::pair<typename IndicatorVariableType::LogicalOperatorType, std::vector<std::pair<IndexType, LabelType> > >, SolverIndexType> linearConstraintIndicatorVariablesLookupTable;
1968  GetIndicatorVariablesOrderBeginFunctor getIndicatorVariablesOrderBegin;
1969  GetIndicatorVariablesOrderEndFunctor getIndicatorVariablesOrderEnd;
1970  for(IndexType i = 0; i < linearConstraintFactors_.size(); ++i) {
1971  const IndexType currentLinearConstraintFactorIndex = linearConstraintFactors_[i];
1972  factorsLPVariablesOffset_[currentLinearConstraintFactorIndex] = numLPVariables_;
1973  gm_[currentLinearConstraintFactorIndex].callFunctor(getIndicatorVariablesOrderBegin);
1974  IndicatorVariablesIteratorType currentIndicatorVariablesBegin = getIndicatorVariablesOrderBegin.indicatorVariablesOrderBegin_;
1975  gm_[currentLinearConstraintFactorIndex].callFunctor(getIndicatorVariablesOrderEnd);
1976  const IndicatorVariablesIteratorType currentIndicatorVariablesEnd = getIndicatorVariablesOrderEnd.indicatorVariablesOrderEnd_;
1977 
1978  linearConstraintsLPVariablesIndicesLookupTable_.push_back(std::map<const IndicatorVariableType, SolverIndexType>());
1979  const size_t numIndicatorVariables = std::distance(currentIndicatorVariablesBegin, currentIndicatorVariablesEnd);
1980  for(size_t j = 0; j < numIndicatorVariables; ++j) {
1981  const IndicatorVariableType& currentIndicatorVariable = *currentIndicatorVariablesBegin;
1982 
1983  SolverIndexType lpVariableIndex = std::numeric_limits<SolverIndexType>::max();
1984  const bool matchingLPVariableIndexFound = getLPVariableIndexFromIndicatorVariable(higherOrderFactorVariablesLookupTable, linearConstraintIndicatorVariablesLookupTable, currentIndicatorVariable, currentLinearConstraintFactorIndex, lpVariableIndex);
1985 
1986  if(matchingLPVariableIndexFound) {
1987  linearConstraintsLPVariablesIndicesLookupTable_.back()[currentIndicatorVariable] = lpVariableIndex;
1988  } else {
1989  // new LP variable required
1990  linearConstraintsLPVariablesIndicesLookupTable_.back()[currentIndicatorVariable] = numLPVariables_;
1991  const size_t currentIndicatorVariableSize = std::distance(currentIndicatorVariable.begin(), currentIndicatorVariable.end());
1992  std::vector<std::pair<IndexType, LabelType> > currentVariableLabelPairs(currentIndicatorVariableSize);
1993  for(size_t k = 0; k < currentIndicatorVariableSize; ++k) {
1994  currentVariableLabelPairs[k] = std::pair<IndexType, LabelType>(gm_[currentLinearConstraintFactorIndex].variableIndex((currentIndicatorVariable.begin() + k)->first), (currentIndicatorVariable.begin() + k)->second);
1995  }
1996  linearConstraintIndicatorVariablesLookupTable[make_pair(currentIndicatorVariable.getLogicalOperatorType(), currentVariableLabelPairs)] = numLPVariables_;
1997  ++numLinearConstraintsLPVariables_;
1998  ++numLPVariables_;
1999  }
2000  ++currentIndicatorVariablesBegin;
2001  }
2002  OPENGM_ASSERT(currentIndicatorVariablesBegin == currentIndicatorVariablesEnd);
2003  }
2004 
2005  OPENGM_ASSERT(linearConstraintFactors_.size() == linearConstraintsLPVariablesIndicesLookupTable_.size());
2006  OPENGM_ASSERT(numLPVariables_ == numNodesLPVariables_ + numFactorsLPVariables_ + numLinearConstraintsLPVariables_);
2007 
2008  // count lp variables for transferable factors
2009  typename LPFunctionTransferType::NumSlackVariablesFunctor numSlackVariablesFunctor;
2010  typename LPFunctionTransferType::GetIndicatorVariablesFunctor getIndicatorVariablesFunctor;
2011  for(IndexType i = 0; i < transferableFactors_.size(); ++i) {
2012  const IndexType currentTransferableFactorIndex = transferableFactors_[i];
2013  factorsLPVariablesOffset_[currentTransferableFactorIndex] = numLPVariables_;
2014 
2015  // get number of slack variables
2016  gm_[currentTransferableFactorIndex].callFunctor(numSlackVariablesFunctor);
2017 
2018  IndexType currentNumSlackVariables = 0;
2019 
2020  transferedFactorsLPVariablesIndicesLookupTable_.push_back(std::map<const IndicatorVariableType, SolverIndexType>());
2021 
2022  // get indicator variables of
2023  IndicatorVariablesContainerType currentIndicatorVariables;
2024  getIndicatorVariablesFunctor.variables_ = &currentIndicatorVariables;
2025  gm_[currentTransferableFactorIndex].callFunctor(getIndicatorVariablesFunctor);
2026 
2027  // fill transferedFactorsLPVariablesIndicesLookupTable_
2028  for(IndicatorVariablesIteratorType iter = currentIndicatorVariables.begin(); iter != currentIndicatorVariables.end(); ++iter) {
2029  const IndicatorVariableType& currentIndicatorVariable = *iter;
2030  const size_t currentIndicatorVariableSize = std::distance(currentIndicatorVariable.begin(), currentIndicatorVariable.end());
2031 
2032  if(currentIndicatorVariableSize == 1) {
2033  if(currentIndicatorVariable.begin()->first >= gm_[currentTransferableFactorIndex].numberOfVariables()) {
2034  // slack variable
2035  transferedFactorsLPVariablesIndicesLookupTable_.back()[currentIndicatorVariable] = numSlackVariables_ + currentNumSlackVariables; // note: slack variables indices will be shifted to the end of the indices later
2036  ++currentNumSlackVariables;
2037  continue;
2038  }
2039  }
2040 
2041  SolverIndexType lpVariableIndex;
2042  const bool matchingLPVariableIndexFound = getLPVariableIndexFromIndicatorVariable(higherOrderFactorVariablesLookupTable, linearConstraintIndicatorVariablesLookupTable, currentIndicatorVariable, currentTransferableFactorIndex, lpVariableIndex);
2043 
2044  if(matchingLPVariableIndexFound) {
2045  transferedFactorsLPVariablesIndicesLookupTable_.back()[currentIndicatorVariable] = lpVariableIndex;
2046  } else {
2047  // new LP variable required
2048  transferedFactorsLPVariablesIndicesLookupTable_.back()[currentIndicatorVariable] = numLPVariables_;
2049  const size_t currentIndicatorVariableSize = std::distance(currentIndicatorVariable.begin(), currentIndicatorVariable.end());
2050  std::vector<std::pair<IndexType, LabelType> > currentVariableLabelPairs(currentIndicatorVariableSize);
2051  for(size_t j = 0; j < currentIndicatorVariableSize; ++j) {
2052  currentVariableLabelPairs[j] = std::pair<IndexType, LabelType>(gm_[currentTransferableFactorIndex].variableIndex((currentIndicatorVariable.begin() + j)->first), (currentIndicatorVariable.begin() + j)->second);
2053  }
2054  linearConstraintIndicatorVariablesLookupTable[make_pair(currentIndicatorVariable.getLogicalOperatorType(), currentVariableLabelPairs)] = numLPVariables_;
2055  ++numTransferedFactorsLPVariables;
2056  ++numLPVariables_;
2057  }
2058  }
2059 
2060  OPENGM_ASSERT(currentNumSlackVariables == numSlackVariablesFunctor.numSlackVariables_);
2061  numSlackVariables_ += numSlackVariablesFunctor.numSlackVariables_;
2062  }
2063 
2064  // update slack variables indices to shift their indices to the end (indices >= numLPVariables_)
2065  typename LPFunctionTransferType::GetSlackVariablesOrderFunctor getSlackVariablesOrderFunctor;
2066  for(IndexType i = 0; i < transferableFactors_.size(); ++i) {
2067  const IndexType currentTransferableFactorIndex = transferableFactors_[i];
2068 
2069  // get slack variables
2070  IndicatorVariablesContainerType slackVariables;
2071  getSlackVariablesOrderFunctor.order_ = &slackVariables;
2072  gm_[currentTransferableFactorIndex].callFunctor(getSlackVariablesOrderFunctor);
2073 
2074  // shift indices
2075  for(IndicatorVariablesIteratorType iter = slackVariables.begin(); iter != slackVariables.end(); ++iter) {
2076  const IndicatorVariableType& currentSlackVariable = *iter;
2077  transferedFactorsLPVariablesIndicesLookupTable_[i][currentSlackVariable] += numLPVariables_;
2078  }
2079  }
2080 
2081  OPENGM_ASSERT(transferableFactors_.size() == transferedFactorsLPVariablesIndicesLookupTable_.size());
2082  OPENGM_ASSERT(numLPVariables_ == numNodesLPVariables_ + numFactorsLPVariables_ + numLinearConstraintsLPVariables_ + numTransferedFactorsLPVariables);
2083 }
2084 
2085 template <class LP_INFERENCE_TYPE>
2087  linearConstraintLPVariablesSubsequenceIndices_.resize(linearConstraintFactors_.size());
2088  if(parameter_.integerConstraintNodeVar_ || parameter_.integerConstraintFactorVar_) {
2089  for(size_t i = 0; i < linearConstraintFactors_.size(); ++i) {
2090  const IndexType currentFactor = linearConstraintFactors_[i];
2091  const size_t numVariables = gm_[currentFactor].numberOfVariables();
2092  linearConstraintLPVariablesSubsequenceIndices_[i].resize(numVariables);
2093  for(size_t j = 0; j < numVariables; ++j) {
2094  linearConstraintLPVariablesSubsequenceIndices_[i][j] = gm_[currentFactor].variableIndex(j);
2095  }
2096  }
2097  } else {
2098  GetIndicatorVariablesOrderBeginFunctor getIndicatorVariablesOrderBegin;
2099  GetIndicatorVariablesOrderEndFunctor getIndicatorVariablesOrderEnd;
2100  for(size_t i = 0; i < linearConstraintFactors_.size(); ++i) {
2101  const IndexType currentFactor = linearConstraintFactors_[i];
2102  gm_[currentFactor].callFunctor(getIndicatorVariablesOrderBegin);
2103  gm_[currentFactor].callFunctor(getIndicatorVariablesOrderEnd);
2104  const IndicatorVariablesIteratorType currentIndicatorVariablesEnd = getIndicatorVariablesOrderEnd.indicatorVariablesOrderEnd_;
2105  for(IndicatorVariablesIteratorType iter = getIndicatorVariablesOrderBegin.indicatorVariablesOrderBegin_; iter != currentIndicatorVariablesEnd; ++iter) {
2106  linearConstraintLPVariablesSubsequenceIndices_[i].push_back(linearConstraintsLPVariablesIndicesLookupTable_[i][*iter]);
2107  }
2108  }
2109  }
2110 }
2111 
2112 template <class LP_INFERENCE_TYPE>
2114  if(meta::Compare<AccumulationType, Minimizer>::value) {
2115  static_cast<LPInferenceType*>(this)->setObjective(LPInferenceType::Minimize);
2116  } else if(meta::Compare<AccumulationType, Maximizer>::value) {
2117  static_cast<LPInferenceType*>(this)->setObjective(LPInferenceType::Maximize);
2118  } else {
2119  throw RuntimeError("This implementation of lp inference does only support Minimizer or Maximizer accumulators");
2120  }
2121 }
2122 
2123 template <class LP_INFERENCE_TYPE>
2125  if(parameter_.integerConstraintNodeVar_) {
2126  static_cast<LPInferenceType*>(this)->addBinaryVariables(numNodesLPVariables_);
2127  } else {
2128  static_cast<LPInferenceType*>(this)->addContinuousVariables(numNodesLPVariables_, 0.0, 1.0);
2129  }
2130 
2131  if(parameter_.integerConstraintFactorVar_) {
2132  static_cast<LPInferenceType*>(this)->addBinaryVariables(numFactorsLPVariables_);
2133  static_cast<LPInferenceType*>(this)->addBinaryVariables(numLinearConstraintsLPVariables_);
2134  static_cast<LPInferenceType*>(this)->addBinaryVariables(numTransferedFactorsLPVariables);
2135  } else {
2136  static_cast<LPInferenceType*>(this)->addContinuousVariables(numFactorsLPVariables_, 0.0, 1.0);
2137  static_cast<LPInferenceType*>(this)->addContinuousVariables(numLinearConstraintsLPVariables_, 0.0, 1.0);
2138  static_cast<LPInferenceType*>(this)->addContinuousVariables(numTransferedFactorsLPVariables, 0.0, 1.0);
2139  }
2140 
2141  // add slack variables
2142  static_cast<LPInferenceType*>(this)->addContinuousVariables(numSlackVariables_, 0.0, LPInferenceType::infinity());
2143 }
2144 
2145 template <class LP_INFERENCE_TYPE>
2147  std::vector<SolverValueType> objective(numNodesLPVariables_ + numFactorsLPVariables_ + numLinearConstraintsLPVariables_ + numTransferedFactorsLPVariables + numSlackVariables_, 0.0);
2148 
2149  // node lp variables coefficients
2150  for(IndexType i = 0; i < unaryFactors_.size(); i++) {
2151  const IndexType factorIndex = unaryFactors_[i];
2152  const IndexType node = gm_[factorIndex].variableIndex(0);
2153  for(LabelType j = 0; j < gm_.numberOfLabels(node); j++) {
2154  objective[nodeLPVariableIndex(node, j)] += static_cast<SolverValueType>(gm_[factorIndex](&j));
2155  }
2156  }
2157 
2158  // factor lp variables coefficients
2159  for(IndexType i = 0; i < higherOrderFactors_.size(); i++) {
2160  const IndexType factorIndex = higherOrderFactors_[i];
2161  // copy values
2162  std::vector<ValueType> tempValues(gm_[factorIndex].size());
2163  gm_[factorIndex].copyValues(tempValues.begin());
2164  for(size_t j = 0; j < tempValues.size(); ++j) {
2165  objective[factorLPVariableIndex(factorIndex, j)] += static_cast<SolverValueType>(tempValues[j]);
2166  }
2167  }
2168 
2169  // slack variables of transformed factors
2170  typename LPFunctionTransferType::GetSlackVariablesOrderFunctor getSlackVariablesOrderFunctor;
2171  typename LPFunctionTransferType::GetSlackVariablesObjectiveCoefficientsFunctor getSlackVariablesObjectiveCoefficientsFunctor;
2172  for(IndexType i = 0; i < transferableFactors_.size(); ++i) {
2173  const IndexType currentTransferableFactorIndex = transferableFactors_[i];
2174 
2175  // get slack variables
2176  IndicatorVariablesContainerType slackVariables;
2177  getSlackVariablesOrderFunctor.order_ = &slackVariables;
2178  gm_[currentTransferableFactorIndex].callFunctor(getSlackVariablesOrderFunctor);
2179 
2180  // get coefficients
2182  getSlackVariablesObjectiveCoefficientsFunctor.coefficients_ = &coefficients;
2183  gm_[currentTransferableFactorIndex].callFunctor(getSlackVariablesObjectiveCoefficientsFunctor);
2184 
2185  OPENGM_ASSERT(coefficients.size() == slackVariables.size());
2186 
2187  // add coefficients
2188  for(size_t j = 0; j < slackVariables.size(); ++j) {
2189  const IndicatorVariableType& currentSlackVariable = slackVariables[j];
2190  const ValueType currentCoefficient = coefficients[j];
2191  const SolverIndexType currentSlackVariableLPVariableIndex = transferedFactorsLPVariablesIndicesLookupTable_[i][currentSlackVariable];
2192  objective[currentSlackVariableLPVariableIndex] += static_cast<SolverValueType>(currentCoefficient);
2193  }
2194  }
2195  static_cast<LPInferenceType*>(this)->setObjectiveValue(objective.begin(), objective.end());
2196 }
2197 
2198 template <class LP_INFERENCE_TYPE>
2200  // \sum_i \mu_i = 1
2201  for(IndexType i = 0; i < gm_.numberOfVariables(); ++i) {
2202  addLocalPolytopeVariableConstraint(i, true);
2203  }
2204 
2205  // \sum_i \mu_{f;i_1,...,i_n} - \mu{b;j}= 0
2206  for(IndexType i = 0; i < higherOrderFactors_.size(); ++i) {
2207  const IndexType factorIndex = higherOrderFactors_[i];
2208  for(IndexType j = 0; j < gm_[factorIndex].numberOfVariables(); ++j) {
2209  const IndexType node = gm_[factorIndex].variableIndex(j);
2210  for(LabelType k = 0; k < gm_.numberOfLabels(node); k++) {
2211  addLocalPolytopeFactorConstraint(i, j, k, true);
2212  }
2213  }
2214  }
2215 
2216  // add constraints for linear constraint factor variables
2217  GetIndicatorVariablesOrderBeginFunctor getIndicatorVariablesOrderBegin;
2218  GetIndicatorVariablesOrderEndFunctor getIndicatorVariablesOrderEnd;
2219  for(IndexType i = 0; i < linearConstraintFactors_.size(); ++i) {
2220  gm_[linearConstraintFactors_[i]].callFunctor(getIndicatorVariablesOrderBegin);
2221  gm_[linearConstraintFactors_[i]].callFunctor(getIndicatorVariablesOrderEnd);
2222  const size_t linearConstraintNumIndicatorVariables = std::distance(getIndicatorVariablesOrderBegin.indicatorVariablesOrderBegin_, getIndicatorVariablesOrderEnd.indicatorVariablesOrderEnd_);
2223  for(size_t j = 0; j < linearConstraintNumIndicatorVariables; ++j) {
2224  const IndexType currentFactor = linearConstraintFactors_[i];
2225  const IndicatorVariableType& currentIndicatorVariable = getIndicatorVariablesOrderBegin.indicatorVariablesOrderBegin_[j];
2226  const SolverIndexType currentLPVariable = linearConstraintsLPVariablesIndicesLookupTable_[i][currentIndicatorVariable];
2227  addIndicatorVariableConstraints(currentFactor, currentIndicatorVariable, currentLPVariable, true);
2228  }
2229  }
2230 
2231  // add constraints for transfered factor variables
2232  typename LPFunctionTransferType::GetIndicatorVariablesFunctor getIndicatorVariablesFunctor;
2233  for(IndexType i = 0; i < transferableFactors_.size(); ++i) {
2234  typename LPFunctionTransferType::IndicatorVariablesContainerType currentIndicatorVariables;
2235  getIndicatorVariablesFunctor.variables_ = &currentIndicatorVariables;
2236  gm_[transferableFactors_[i]].callFunctor(getIndicatorVariablesFunctor);
2237  const size_t transformedFactorsNumIndicatorVariables = currentIndicatorVariables.size();
2238  for(size_t j = 0; j < transformedFactorsNumIndicatorVariables; ++j) {
2239  const IndexType currentFactor = transferableFactors_[i];
2240  const IndicatorVariableType& currentIndicatorVariable = currentIndicatorVariables[j];
2241  const SolverIndexType currentLPVariable = transferedFactorsLPVariablesIndicesLookupTable_[i][currentIndicatorVariable];
2242  addIndicatorVariableConstraints(currentFactor, currentIndicatorVariable, currentLPVariable, true);
2243  }
2244  }
2245 
2246  // add constraints for transfered factors
2247  typename LPFunctionTransferType::GetLinearConstraintsFunctor getLinearConstraintsFunctor;
2248  for(IndexType i = 0; i < transferableFactors_.size(); ++i) {
2249  const IndexType currentTransferableFactorIndex = transferableFactors_[i];
2250  // get constraints
2252  getLinearConstraintsFunctor.constraints_ = &constraints;
2253  gm_[currentTransferableFactorIndex].callFunctor(getLinearConstraintsFunctor);
2254  for(size_t j = 0; j < constraints.size(); ++j) {
2255  const LinearConstraintType& currentConstraint = constraints[j];
2256  std::vector<SolverIndexType> lpVariables(std::distance(currentConstraint.indicatorVariablesBegin(), currentConstraint.indicatorVariablesEnd()));
2257  for(size_t k = 0; k < lpVariables.size(); ++k) {
2258  lpVariables[k] = transferedFactorsLPVariablesIndicesLookupTable_[i][currentConstraint.indicatorVariablesBegin()[k]];
2259  }
2260  switch(currentConstraint.getConstraintOperator()) {
2261  case LinearConstraintType::LinearConstraintOperatorType::LessEqual : {
2262  static_cast<LPInferenceType*>(this)->addLessEqualConstraint(lpVariables.begin(), lpVariables.end(), currentConstraint.coefficientsBegin(), static_cast<const SolverValueType>(currentConstraint.getBound()));
2263  break;
2264  }
2265  case LinearConstraintType::LinearConstraintOperatorType::Equal : {
2266  static_cast<LPInferenceType*>(this)->addEqualityConstraint(lpVariables.begin(), lpVariables.end(), currentConstraint.coefficientsBegin(), static_cast<const SolverValueType>(currentConstraint.getBound()));
2267  break;
2268  }
2269  default: {
2270  // default corresponds to LinearConstraintType::LinearConstraintOperatorType::GreaterEqual case
2271  static_cast<LPInferenceType*>(this)->addGreaterEqualConstraint(lpVariables.begin(), lpVariables.end(), currentConstraint.coefficientsBegin(), static_cast<const SolverValueType>(currentConstraint.getBound()));
2272  }
2273  }
2274  }
2275  }
2276 }
2277 
2278 template <class LP_INFERENCE_TYPE>
2280  // \sum_i \mu_i = 1
2281  for(IndexType i = 0; i < gm_.numberOfVariables(); ++i) {
2282  addLocalPolytopeVariableConstraint(i, true);
2283  }
2284 
2285  // \sum_i \mu_{f;i_1,...,i_n} - \mu{b;j}= 0
2286  for(IndexType i = 0; i < higherOrderFactors_.size(); ++i) {
2287  const IndexType factorIndex = higherOrderFactors_[i];
2288  for(IndexType j = 0; j < gm_[factorIndex].numberOfVariables(); ++j) {
2289  const IndexType node = gm_[factorIndex].variableIndex(j);
2290  for(LabelType k = 0; k < gm_.numberOfLabels(node); k++) {
2291  addLocalPolytopeFactorConstraint(i, j, k, false);
2292  }
2293  }
2294  }
2295 
2296  // add constraints for linear constraint factor variables
2297  GetIndicatorVariablesOrderBeginFunctor getIndicatorVariablesOrderBegin;
2298  GetIndicatorVariablesOrderEndFunctor getIndicatorVariablesOrderEnd;
2299  for(IndexType i = 0; i < linearConstraintFactors_.size(); ++i) {
2300  gm_[linearConstraintFactors_[i]].callFunctor(getIndicatorVariablesOrderBegin);
2301  gm_[linearConstraintFactors_[i]].callFunctor(getIndicatorVariablesOrderEnd);
2302  const size_t linearConstraintNumIndicatorVariables = std::distance(getIndicatorVariablesOrderBegin.indicatorVariablesOrderBegin_, getIndicatorVariablesOrderEnd.indicatorVariablesOrderEnd_);
2303  for(size_t j = 0; j < linearConstraintNumIndicatorVariables; ++j) {
2304  const IndexType currentFactor = linearConstraintFactors_[i];
2305  const IndicatorVariableType& currentIndicatorVariable = getIndicatorVariablesOrderBegin.indicatorVariablesOrderBegin_[j];
2306  const SolverIndexType currentLPVariable = linearConstraintsLPVariablesIndicesLookupTable_[i][currentIndicatorVariable];
2307  addIndicatorVariableConstraints(currentFactor, currentIndicatorVariable, currentLPVariable, false);
2308  }
2309  }
2310 
2311  // add constraints for transfered factor variables
2312  typename LPFunctionTransferType::GetIndicatorVariablesFunctor getIndicatorVariablesFunctor;
2313  for(IndexType i = 0; i < transferableFactors_.size(); ++i) {
2314  typename LPFunctionTransferType::IndicatorVariablesContainerType currentIndicatorVariables;
2315  getIndicatorVariablesFunctor.variables_ = &currentIndicatorVariables;
2316  gm_[transferableFactors_[i]].callFunctor(getIndicatorVariablesFunctor);
2317  const size_t transformedFactorsNumIndicatorVariables = currentIndicatorVariables.size();
2318  for(size_t j = 0; j < transformedFactorsNumIndicatorVariables; ++j) {
2319  const IndexType currentFactor = transferableFactors_[i];
2320  const IndicatorVariableType& currentIndicatorVariable = currentIndicatorVariables[j];
2321  const SolverIndexType currentLPVariable = transferedFactorsLPVariablesIndicesLookupTable_[i][currentIndicatorVariable];
2322  addIndicatorVariableConstraints(currentFactor, currentIndicatorVariable, currentLPVariable, false);
2323  }
2324  }
2325 
2326  // add constraints for transfered factors
2327  typename LPFunctionTransferType::GetLinearConstraintsFunctor getLinearConstraintsFunctor;
2328  for(IndexType i = 0; i < transferableFactors_.size(); ++i) {
2329  const IndexType currentTransferableFactorIndex = transferableFactors_[i];
2330  // get constraints
2332  getLinearConstraintsFunctor.constraints_ = &constraints;
2333  gm_[currentTransferableFactorIndex].callFunctor(getLinearConstraintsFunctor);
2334  for(size_t j = 0; j < constraints.size(); ++j) {
2335  const LinearConstraintType& currentConstraint = constraints[j];
2336  std::vector<SolverIndexType> lpVariables(std::distance(currentConstraint.indicatorVariablesBegin(), currentConstraint.indicatorVariablesEnd()));
2337  for(size_t k = 0; k < lpVariables.size(); ++k) {
2338  lpVariables[k] = transferedFactorsLPVariablesIndicesLookupTable_[i][currentConstraint.indicatorVariablesBegin()[k]];
2339  }
2340 
2341  std::stringstream constraintName;
2342  if(parameter_.nameConstraints_) {
2343  constraintName << "transfered factor " << currentTransferableFactorIndex << " constraint " << j << " of " << constraints.size();
2344  }
2345  ConstraintStorage constraint;
2346  constraint.variableIDs_ = lpVariables;
2347  constraint.coefficients_ = std::vector<SolverValueType>(currentConstraint.coefficientsBegin(), currentConstraint.coefficientsEnd());
2348  constraint.bound_ = currentConstraint.getBound();
2349  constraint.operator_ = currentConstraint.getConstraintOperator();
2350  constraint.name_ = constraintName.str();
2351  inactiveConstraints_.push_back(constraint);
2352  }
2353  }
2354 }
2355 
2356 template <class LP_INFERENCE_TYPE>
2358  addLocalPolytopeConstraints();
2359 
2360  // Add all linear constraints from all linear constraint functions
2361  GetLinearConstraintsBeginFunctor getLinearConstraintsBegin;
2362  GetLinearConstraintsEndFunctor getLinearConstraintsEnd;
2363  for(IndexType i = 0; i < linearConstraintFactors_.size(); ++i) {
2364  const IndexType currentLinearConstraintFactorIndex = linearConstraintFactors_[i];
2365  gm_[currentLinearConstraintFactorIndex].callFunctor(getLinearConstraintsBegin);
2366  LinearConstraintsIteratorType currentLinearConstraintsBegin = getLinearConstraintsBegin.linearConstraintsBegin_;
2367  gm_[currentLinearConstraintFactorIndex].callFunctor(getLinearConstraintsEnd);
2368  const LinearConstraintsIteratorType currentLinearConstraintsEnd = getLinearConstraintsEnd.linearConstraintsEnd_;
2369  while(currentLinearConstraintsBegin != currentLinearConstraintsEnd) {
2370  addLinearConstraint(i, *currentLinearConstraintsBegin);
2371  ++currentLinearConstraintsBegin;
2372  }
2373  }
2374 }
2375 
2376 template <class LP_INFERENCE_TYPE>
2378  OPENGM_ASSERT(nodeID < gm_.numberOfVariables());
2379  OPENGM_ASSERT(label < gm_.numberOfLabels(nodeID));
2380  return nodesLPVariablesOffset_[nodeID] + label;
2381 }
2382 
2383 template <class LP_INFERENCE_TYPE>
2385  OPENGM_ASSERT(factorID < gm_.numberOfFactors());
2386  OPENGM_ASSERT(labelingIndex < gm_[factorID].size());
2387 
2388  return factorsLPVariablesOffset_[factorID] + labelingIndex;
2389 }
2390 
2391 template <class LP_INFERENCE_TYPE>
2392 template<class LABELING_ITERATOR_TYPE>
2393 inline typename LPInferenceBase<LP_INFERENCE_TYPE>::SolverIndexType LPInferenceBase<LP_INFERENCE_TYPE>::factorLPVariableIndex(const IndexType factorID, LABELING_ITERATOR_TYPE labelingBegin, const LABELING_ITERATOR_TYPE labelingEnd) const {
2394  OPENGM_ASSERT(factorID < gm_.numberOfFactors());
2395  OPENGM_ASSERT(static_cast<IndexType>(std::distance(labelingBegin, labelingEnd)) == gm_[factorID].numberOfVariables());
2396 
2397  const size_t numVar = gm_[factorID].numberOfVariables();
2398  size_t labelingIndex = *labelingBegin;
2399  labelingBegin++;
2400  size_t strides = gm_[factorID].numberOfLabels(0);
2401  for(size_t i = 1; i < numVar; i++){
2402  OPENGM_ASSERT(*labelingBegin < gm_[factorID].numberOfLabels(i));
2403  labelingIndex += strides * (*labelingBegin);
2404  strides *= gm_[factorID].numberOfLabels(i);
2405  labelingBegin++;
2406  }
2407 
2408  OPENGM_ASSERT(labelingBegin == labelingEnd);
2409 
2410  return factorLPVariableIndex(factorID, labelingIndex);
2411 }
2412 
2413 template <class LP_INFERENCE_TYPE>
2414 template <class HIGHER_ORDER_FACTORS_MAP_TYPE, class INDICATOR_VARIABLES_MAP_TYPE>
2415 inline bool LPInferenceBase<LP_INFERENCE_TYPE>::getLPVariableIndexFromIndicatorVariable(const HIGHER_ORDER_FACTORS_MAP_TYPE& higherOrderFactorVariablesLookupTable, const INDICATOR_VARIABLES_MAP_TYPE& indicatorVariablesLookupTable, const IndicatorVariableType& indicatorVariable, const IndexType linearConstraintFactorIndex, SolverIndexType& lpVariableIndex) const {
2416  const size_t indicatorVariableSize = std::distance(indicatorVariable.begin(), indicatorVariable.end());
2417  OPENGM_ASSERT(indicatorVariableSize > 0);
2418 
2419  if(indicatorVariableSize == 1) {
2420  const IndexType currentNode = gm_[linearConstraintFactorIndex].variableIndex(indicatorVariable.begin()->first);
2421  const LabelType currentLabel = indicatorVariable.begin()->second;
2422  if(indicatorVariable.getLogicalOperatorType() == IndicatorVariableType::Not) {
2423  if(gm_.numberOfLabels(currentNode) == 2) {
2424  OPENGM_ASSERT(currentLabel < 2);
2425  // use second label as not variable
2426  lpVariableIndex = nodeLPVariableIndex(currentNode, currentLabel == 0 ? LabelType(1) : LabelType(0));
2427  return true;
2428  } else {
2429  return false;
2430  }
2431  } else {
2432  lpVariableIndex = nodeLPVariableIndex(currentNode, currentLabel);
2433  return true;
2434  }
2435  } else {
2436  // search if any factor has the same variable combination
2437  if(indicatorVariable.getLogicalOperatorType() == IndicatorVariableType::And) {
2438  std::vector<IndexType> currentVariables(indicatorVariableSize);
2439  std::vector<LabelType> currentLabeling(indicatorVariableSize);
2440  for(size_t i = 0; i < indicatorVariableSize; ++i) {
2441  currentVariables[i] = gm_[linearConstraintFactorIndex].variableIndex((indicatorVariable.begin() + i)->first);
2442  currentLabeling[i] = (indicatorVariable.begin() + i)->second;
2443  }
2444  const typename HIGHER_ORDER_FACTORS_MAP_TYPE::const_iterator iter = higherOrderFactorVariablesLookupTable.find(currentVariables);
2445  if(iter != higherOrderFactorVariablesLookupTable.end()) {
2446  // matching factor found
2447  lpVariableIndex = factorLPVariableIndex(iter->second, currentLabeling.begin(), currentLabeling.end());
2448  return true;
2449  }
2450  }
2451  // search if any previous linear constraint has the same variable combination
2452  std::vector<std::pair<IndexType, LabelType> > currentVariableLabelPairs(indicatorVariableSize);
2453  for(size_t i = 0; i < indicatorVariableSize; ++i) {
2454  currentVariableLabelPairs[i] = std::pair<IndexType, LabelType>(gm_[linearConstraintFactorIndex].variableIndex((indicatorVariable.begin() + i)->first), (indicatorVariable.begin() + i)->second);
2455  }
2456  const typename INDICATOR_VARIABLES_MAP_TYPE::const_iterator iter = indicatorVariablesLookupTable.find(make_pair(indicatorVariable.getLogicalOperatorType(), currentVariableLabelPairs));
2457  if(iter != indicatorVariablesLookupTable.end()) {
2458  // indicator variable with same variable label combination found
2459  lpVariableIndex = iter->second;
2460  return true;
2461  } else {
2462  return false;
2463  }
2464  }
2465 }
2466 
2467 template <class LP_INFERENCE_TYPE>
2468 inline void LPInferenceBase<LP_INFERENCE_TYPE>::addLocalPolytopeVariableConstraint(const IndexType variableID, const bool addToModel) {
2469  OPENGM_ASSERT(variableID < gm_.numberOfVariables());
2470  static std::vector<SolverIndexType> variableIDs;
2471  static std::vector<SolverValueType> coefficients;
2472 
2473  // \sum_i \mu_i = 1
2474  const LabelType size = gm_.numberOfLabels(variableID);
2475  if(variableIDs.size() != size) {
2476  variableIDs.resize(size);
2477  coefficients.resize(size, 1.0);
2478  }
2479  for(LabelType j = 0; j < size; j++) {
2480  variableIDs[j] = nodeLPVariableIndex(variableID, j);
2481  }
2482 
2483  std::stringstream constraintName;
2484  if(parameter_.nameConstraints_) {
2485  constraintName << "local polytope variable constraint of variable " << variableID;
2486  }
2487  if(addToModel) {
2488  static_cast<LPInferenceType*>(this)->addEqualityConstraint(variableIDs.begin(), variableIDs.end(), coefficients.begin(), 1.0, constraintName.str());
2489  } else {
2490  ConstraintStorage constraint;
2491  constraint.variableIDs_ = variableIDs;
2492  constraint.coefficients_ = coefficients;
2493  constraint.bound_ = 1.0;
2494  constraint.operator_ = LinearConstraintType::LinearConstraintOperatorType::Equal;
2495  constraint.name_ = constraintName.str();
2496  inactiveConstraints_.push_back(constraint);
2497  }
2498 }
2499 
2500 template <class LP_INFERENCE_TYPE>
2501 inline void LPInferenceBase<LP_INFERENCE_TYPE>::addLocalPolytopeFactorConstraint(const IndexType factor, const IndexType variable, const LabelType label, const bool addToModel) {
2502  OPENGM_ASSERT(factor < higherOrderFactors_.size());
2503  OPENGM_ASSERT(variable < gm_[higherOrderFactors_[factor]].numberOfVariables());
2504  OPENGM_ASSERT(label < gm_[higherOrderFactors_[factor]].shape(variable));
2505 
2506  static std::vector<SolverIndexType> variableIDs;
2507  static std::vector<SolverValueType> coefficients;
2508  if(addLocalPolytopeFactorConstraintCachePreviousFactorID_ != higherOrderFactors_[factor]) {
2509  // update lookup table
2510  addLocalPolytopeFactorConstraintCachePreviousFactorID_ = higherOrderFactors_[factor];
2511  addLocalPolytopeFactorConstraintCacheFactorLPVariableIDs_.resize(gm_[higherOrderFactors_[factor]].shapeBegin(), gm_[higherOrderFactors_[factor]].shapeEnd());
2512  SolverIndexType counter = factorLPVariableIndex(higherOrderFactors_[factor], 0);
2513  for(typename marray::Marray<SolverIndexType>::iterator factorLPVariableIDsIter = addLocalPolytopeFactorConstraintCacheFactorLPVariableIDs_.begin(); factorLPVariableIDsIter != addLocalPolytopeFactorConstraintCacheFactorLPVariableIDs_.end(); ++factorLPVariableIDsIter) {
2514  *factorLPVariableIDsIter = counter++;
2515  }
2516  }
2517 
2518  marray::View<SolverIndexType> view = addLocalPolytopeFactorConstraintCacheFactorLPVariableIDs_.boundView(variable, label);
2519  const IndexType node = gm_[higherOrderFactors_[factor]].variableIndex(variable);
2520  const size_t size = view.size() + 1;
2521  const size_t containerSize = variableIDs.size();
2522  if(containerSize != size) {
2523  variableIDs.resize(size);
2524  // reset coefficients
2525  if(containerSize > 0) {
2526  coefficients[containerSize - 1] = 1.0;
2527  }
2528  coefficients.resize(size, 1.0);
2529  coefficients[size - 1] = -1.0;
2530  }
2531  SolverIndexType currentVariableIDsIndex = 0;
2532  for(typename marray::View<SolverIndexType>::iterator viewIter = view.begin(); viewIter != view.end(); ++viewIter) {
2533  variableIDs[currentVariableIDsIndex] = *viewIter;
2534  currentVariableIDsIndex++;
2535  }
2536  OPENGM_ASSERT(static_cast<size_t>(currentVariableIDsIndex) == size - 1);
2537  variableIDs[size - 1] = nodeLPVariableIndex(node, label);
2538 
2539  std::stringstream constraintName;
2540  if(parameter_.nameConstraints_) {
2541  constraintName << "local polytope factor constraint of higher order factor " << factor << " variable " << variable << " and label " << label;
2542  }
2543  if(addToModel) {
2544  static_cast<LPInferenceType*>(this)->addEqualityConstraint(variableIDs.begin(), variableIDs.end(), coefficients.begin(), 0.0, constraintName.str());
2545  } else {
2546  ConstraintStorage constraint;
2547  constraint.variableIDs_ = variableIDs;
2548  constraint.coefficients_ = coefficients;
2549  constraint.bound_ = 0.0;
2550  constraint.operator_ = LinearConstraintType::LinearConstraintOperatorType::Equal;
2551  constraint.name_ = constraintName.str();
2552  inactiveConstraints_.push_back(constraint);
2553  }
2554 }
2555 
2556 template <class LP_INFERENCE_TYPE>
2557 inline void LPInferenceBase<LP_INFERENCE_TYPE>::addIndicatorVariableConstraints(const IndexType factor, const IndicatorVariableType& indicatorVariable, const SolverIndexType indicatorVariableLPVariable, const bool addToModel) {
2558  OPENGM_ASSERT(factor < gm_.numberOfFactors());
2559  OPENGM_ASSERT(indicatorVariableLPVariable < numLPVariables_ + numSlackVariables_);
2560  if(indicatorVariableLPVariable >= numLPVariables_) {
2561  // slack variable nothing to do.
2562  } else {
2563  if(indicatorVariableLPVariable >= factorsLPVariablesOffset_[factor]) {
2564  // new constraints needed
2565  OPENGM_ASSERT(std::distance(indicatorVariable.begin(), indicatorVariable.end()) > 0);
2566 
2567  const SolverIndexType numVariables = static_cast<const SolverIndexType>(std::distance(indicatorVariable.begin(), indicatorVariable.end()));
2568  if(numVariables == 1) {
2569  // Only Not requires a new variable if the IndicatorVariable has size 1
2570  OPENGM_ASSERT(indicatorVariable.getLogicalOperatorType() == IndicatorVariableType::Not);
2571  // Not: currentLPVariable + lpNodeVar(node; label) == 1.0
2572  std::vector<SolverValueType> coefficients(2, 1.0);
2573  std::vector<SolverIndexType> lpVariableIDs(2, indicatorVariableLPVariable);
2574  lpVariableIDs[0] = nodeLPVariableIndex(gm_[factor].variableIndex(indicatorVariable.begin()->first), indicatorVariable.begin()->second);
2575  std::stringstream constraintName;
2576  if(parameter_.nameConstraints_) {
2577  constraintName << "indicator variable constraint of factor " << factor << "of type Not for node" << indicatorVariable.begin()->first << " and label " << indicatorVariable.begin()->second;
2578  }
2579  if(addToModel) {
2580  static_cast<LPInferenceType*>(this)->addEqualityConstraint(lpVariableIDs.begin(), lpVariableIDs.end(), coefficients.begin(), 1.0, constraintName.str());
2581  } else {
2582  ConstraintStorage constraint;
2583  constraint.variableIDs_ = lpVariableIDs;
2584  constraint.coefficients_ = coefficients;
2585  constraint.bound_ = 1.0;
2586  constraint.operator_ = LinearConstraintType::LinearConstraintOperatorType::Equal;
2587  constraint.name_ = constraintName.str();
2588  inactiveConstraints_.push_back(constraint);
2589  }
2590  } else {
2591  OPENGM_ASSERT((indicatorVariable.getLogicalOperatorType() == IndicatorVariableType::And) || (indicatorVariable.getLogicalOperatorType() == IndicatorVariableType::Or) || (indicatorVariable.getLogicalOperatorType() == IndicatorVariableType::Not) )
2592 
2593  // And: currentLPVariable - lpNodeVar(node; label) <= 0.0 for all node label pairs of the indicator variable
2594  // Or: currentLPVariable - lpNodeVar(node; label) >= 0.0 for all node label pairs of the indicator variable
2595  // Not: currentLPVariable + lpNodeVar(node; label) <= 1.0 for all node label pairs of the indicator variable
2596  std::vector<SolverValueType> coefficients(2, 1.0);
2597  if((indicatorVariable.getLogicalOperatorType() == IndicatorVariableType::And) || (indicatorVariable.getLogicalOperatorType() == IndicatorVariableType::Or)) {
2598  coefficients.back() = -1.0;
2599  }
2600  std::vector<SolverIndexType> lpVariableIDs(2, indicatorVariableLPVariable);
2601  for(VariableLabelPairsIteratorType iter = indicatorVariable.begin(); iter != indicatorVariable.end(); ++iter) {
2602  lpVariableIDs[1] = nodeLPVariableIndex(gm_[factor].variableIndex(iter->first), iter->second);
2603  std::stringstream constraintName;
2604  if(parameter_.nameConstraints_) {
2605  constraintName << "indicator variable constraint of factor " << factor << "of type ";
2606  switch(indicatorVariable.getLogicalOperatorType()) {
2607  case IndicatorVariableType::And : {
2608  constraintName << "And";
2609  break;
2610  }
2611  case IndicatorVariableType::Or : {
2612  constraintName << "Or";
2613  break;
2614  }
2615  default : {
2616  // default corresponds to IndicatorVariableType::Not
2617  constraintName << "Not";
2618  }
2619  }
2620  constraintName << " for node" << iter->first << " and label " << iter->second;
2621  }
2622 
2623  if(addToModel) {
2624  switch(indicatorVariable.getLogicalOperatorType()) {
2625  case IndicatorVariableType::And : {
2626  static_cast<LPInferenceType*>(this)->addLessEqualConstraint(lpVariableIDs.begin(), lpVariableIDs.end(), coefficients.begin(), 0.0, constraintName.str());
2627  break;
2628  }
2629  case IndicatorVariableType::Or : {
2630  static_cast<LPInferenceType*>(this)->addGreaterEqualConstraint(lpVariableIDs.begin(), lpVariableIDs.end(), coefficients.begin(), 0.0, constraintName.str());
2631  break;
2632  }
2633  default : {
2634  // default corresponds to IndicatorVariableType::Not
2635  static_cast<LPInferenceType*>(this)->addLessEqualConstraint(lpVariableIDs.begin(), lpVariableIDs.end(), coefficients.begin(), 1.0, constraintName.str());
2636  }
2637  }
2638  } else {
2639  ConstraintStorage constraint;
2640  constraint.variableIDs_ = lpVariableIDs;
2641  constraint.coefficients_ = coefficients;
2642  switch(indicatorVariable.getLogicalOperatorType()) {
2643  case IndicatorVariableType::And : {
2644  constraint.bound_ = 0.0;
2645  constraint.operator_ = LinearConstraintType::LinearConstraintOperatorType::LessEqual;
2646  break;
2647  }
2648  case IndicatorVariableType::Or : {
2649  constraint.bound_ = 0.0;
2650  constraint.operator_ = LinearConstraintType::LinearConstraintOperatorType::GreaterEqual;
2651  break;
2652  }
2653  default : {
2654  // default corresponds to IndicatorVariableType::Not
2655  constraint.bound_ = 1.0;
2656  constraint.operator_ = LinearConstraintType::LinearConstraintOperatorType::LessEqual;
2657  }
2658  }
2659  constraint.name_ = constraintName.str();
2660  inactiveConstraints_.push_back(constraint);
2661  }
2662  }
2663 
2664  // And: \sum_i lpNodeVar(node_i; label_i) - currentLPVariable <= n - 1.0
2665  // Or: \sum_i lpNodeVar(node_i; label_i) - currentLPVariable >= 0.0
2666  // Not: \sum_i lpNodeVar(node_i; label_i) + currentLPVariable >= 1.0
2667  if((indicatorVariable.getLogicalOperatorType() == IndicatorVariableType::And) || (indicatorVariable.getLogicalOperatorType() == IndicatorVariableType::Or)) {
2668  coefficients.back() = 1.0;
2669  }
2670  coefficients.resize(numVariables + 1, 1.0);
2671  if((indicatorVariable.getLogicalOperatorType() == IndicatorVariableType::And) || (indicatorVariable.getLogicalOperatorType() == IndicatorVariableType::Or)) {
2672  coefficients.back() = -1.0;
2673  }
2674  lpVariableIDs.clear();
2675  for(VariableLabelPairsIteratorType iter = indicatorVariable.begin(); iter != indicatorVariable.end(); ++iter) {
2676  lpVariableIDs.push_back(nodeLPVariableIndex(gm_[factor].variableIndex(iter->first), iter->second));
2677  }
2678  lpVariableIDs.push_back(indicatorVariableLPVariable);
2679  std::stringstream constraintName;
2680  if(parameter_.nameConstraints_) {
2681  constraintName << "indicator variable sum constraint of factor " << factor << "of type ";
2682  switch(indicatorVariable.getLogicalOperatorType()) {
2683  case IndicatorVariableType::And : {
2684  constraintName << "And";
2685  break;
2686  }
2687  case IndicatorVariableType::Or : {
2688  constraintName << "Or";
2689  break;
2690  }
2691  default : {
2692  // default corresponds to IndicatorVariableType::Not
2693  constraintName << "Not";
2694  }
2695  }
2696  constraintName << " for lp variable" << indicatorVariableLPVariable;
2697  }
2698  if(addToModel) {
2699  switch(indicatorVariable.getLogicalOperatorType()) {
2700  case IndicatorVariableType::And : {
2701  static_cast<LPInferenceType*>(this)->addLessEqualConstraint(lpVariableIDs.begin(), lpVariableIDs.end(), coefficients.begin(), static_cast<const SolverValueType>(numVariables - 1.0), constraintName.str());
2702  break;
2703  }
2704  case IndicatorVariableType::Or : {
2705  static_cast<LPInferenceType*>(this)->addGreaterEqualConstraint(lpVariableIDs.begin(), lpVariableIDs.end(), coefficients.begin(), static_cast<const SolverValueType>(0.0), constraintName.str());
2706  break;
2707  }
2708  default : {
2709  // default corresponds to IndicatorVariableType::Not
2710  static_cast<LPInferenceType*>(this)->addGreaterEqualConstraint(lpVariableIDs.begin(), lpVariableIDs.end(), coefficients.begin(), static_cast<const SolverValueType>(1.0), constraintName.str());
2711  }
2712  }
2713  } else {
2714  ConstraintStorage constraint;
2715  constraint.variableIDs_ = lpVariableIDs;
2716  constraint.coefficients_ = coefficients;
2717  switch(indicatorVariable.getLogicalOperatorType()) {
2718  case IndicatorVariableType::And : {
2719  constraint.bound_ = static_cast<const SolverValueType>(numVariables - 1.0);
2720  constraint.operator_ = LinearConstraintType::LinearConstraintOperatorType::LessEqual;
2721  break;
2722  }
2723  case IndicatorVariableType::Or : {
2724  constraint.bound_ = static_cast<const SolverValueType>(0.0);
2725  constraint.operator_ = LinearConstraintType::LinearConstraintOperatorType::GreaterEqual;
2726  break;
2727  }
2728  default : {
2729  // default corresponds to IndicatorVariableType::Not
2730  constraint.bound_ = static_cast<const SolverValueType>(1.0);
2731  constraint.operator_ = LinearConstraintType::LinearConstraintOperatorType::GreaterEqual;
2732  }
2733  }
2734  constraint.name_ = constraintName.str();
2735  inactiveConstraints_.push_back(constraint);
2736  }
2737  }
2738  }
2739  }
2740 }
2741 
2742 template <class LP_INFERENCE_TYPE>
2743 inline void LPInferenceBase<LP_INFERENCE_TYPE>::addLinearConstraint(const IndexType linearConstraintFactor, const LinearConstraintType& constraint) {
2744  OPENGM_ASSERT(linearConstraintFactor < linearConstraintsLPVariablesIndicesLookupTable_.size());
2745  std::vector<SolverIndexType> lpVariables(std::distance(constraint.indicatorVariablesBegin(), constraint.indicatorVariablesEnd()));
2746  for(size_t i = 0; i < lpVariables.size(); ++i) {
2747  lpVariables[i] = linearConstraintsLPVariablesIndicesLookupTable_[linearConstraintFactor][constraint.indicatorVariablesBegin()[i]];
2748  }
2749  switch(constraint.getConstraintOperator()) {
2750  case LinearConstraintType::LinearConstraintOperatorType::LessEqual : {
2751  static_cast<LPInferenceType*>(this)->addLessEqualConstraint(lpVariables.begin(), lpVariables.end(), constraint.coefficientsBegin(), static_cast<const SolverValueType>(constraint.getBound()));
2752  break;
2753  }
2754  case LinearConstraintType::LinearConstraintOperatorType::Equal : {
2755  static_cast<LPInferenceType*>(this)->addEqualityConstraint(lpVariables.begin(), lpVariables.end(), constraint.coefficientsBegin(), static_cast<const SolverValueType>(constraint.getBound()));
2756  break;
2757  }
2758  default: {
2759  // default corresponds to LinearConstraintOperatorType::LinearConstraintOperator::GreaterEqual case
2760  static_cast<LPInferenceType*>(this)->addGreaterEqualConstraint(lpVariables.begin(), lpVariables.end(), constraint.coefficientsBegin(), static_cast<const SolverValueType>(constraint.getBound()));
2761  }
2762  }
2763 }
2764 
2765 template <class LP_INFERENCE_TYPE>
2766 template <class VISITOR_TYPE>
2768  switch(parameter_.relaxation_){
2769  case Parameter::LocalPolytope : {
2770  return infer_impl_selectHeuristic<VISITOR_TYPE, Parameter::LocalPolytope>(visitor);
2771  }
2772  case Parameter::LoosePolytope : {
2773  return infer_impl_selectHeuristic<VISITOR_TYPE, Parameter::LoosePolytope>(visitor);
2774  }
2775  case Parameter::TightPolytope: {
2776  return infer_impl_selectHeuristic<VISITOR_TYPE, Parameter::TightPolytope>(visitor);
2777  }
2778  default : {
2779  throw RuntimeError("Unknown Relaxation");
2780  }
2781  }
2782 }
2783 
2784 template <class LP_INFERENCE_TYPE>
2785 template <class VISITOR_TYPE, typename LPInferenceBase<LP_INFERENCE_TYPE>::Parameter::Relaxation RELAXATION>
2787  switch(parameter_.challengeHeuristic_){
2788  case Parameter::Random : {
2789  return infer_impl_selectIterations<VISITOR_TYPE, RELAXATION, Parameter::Random>(visitor);
2790  }
2791  case Parameter::Weighted : {
2792  return infer_impl_selectIterations<VISITOR_TYPE, RELAXATION, Parameter::Weighted>(visitor);
2793  }
2794  default : {
2795  throw RuntimeError("Unknown Heuristic");
2796  }
2797  }
2798 }
2799 
2800 template <class LP_INFERENCE_TYPE>
2801 template <class VISITOR_TYPE, typename LPInferenceBase<LP_INFERENCE_TYPE>::Parameter::Relaxation RELAXATION, typename LPInferenceBase<LP_INFERENCE_TYPE>::Parameter::ChallengeHeuristic HEURISTIC>
2803  if(parameter_.maxNumIterations_ == 0) {
2804  return infer_impl_selectViolatedConstraints<VISITOR_TYPE, RELAXATION, HEURISTIC, true>(visitor);
2805  } else {
2806  return infer_impl_selectViolatedConstraints<VISITOR_TYPE, RELAXATION, HEURISTIC, false>(visitor);
2807  }
2808 }
2809 
2810 template <class LP_INFERENCE_TYPE>
2811 template <class VISITOR_TYPE, typename LPInferenceBase<LP_INFERENCE_TYPE>::Parameter::Relaxation RELAXATION, typename LPInferenceBase<LP_INFERENCE_TYPE>::Parameter::ChallengeHeuristic HEURISTIC, bool USE_INFINITE_ITERATIONS>
2813  if(parameter_.maxNumConstraintsPerIter_ == 0) {
2814  return infer_impl_selectLPType<VISITOR_TYPE, RELAXATION, HEURISTIC, USE_INFINITE_ITERATIONS, true>(visitor);
2815  } else {
2816  return infer_impl_selectLPType<VISITOR_TYPE, RELAXATION, HEURISTIC, USE_INFINITE_ITERATIONS, false>(visitor);
2817  }
2818 }
2819 
2820 template <class LP_INFERENCE_TYPE>
2821 template <class VISITOR_TYPE, typename LPInferenceBase<LP_INFERENCE_TYPE>::Parameter::Relaxation RELAXATION, typename LPInferenceBase<LP_INFERENCE_TYPE>::Parameter::ChallengeHeuristic HEURISTIC, bool USE_INFINITE_ITERATIONS, bool ADD_ALL_VIOLATED_CONSTRAINTS>
2823  if(parameter_.integerConstraintNodeVar_ || parameter_.integerConstraintFactorVar_) {
2824  return infer_impl<VISITOR_TYPE, RELAXATION, HEURISTIC, USE_INFINITE_ITERATIONS, ADD_ALL_VIOLATED_CONSTRAINTS, true>(visitor);
2825  } else {
2826  return infer_impl<VISITOR_TYPE, RELAXATION, HEURISTIC, USE_INFINITE_ITERATIONS, ADD_ALL_VIOLATED_CONSTRAINTS, false>(visitor);
2827  }
2828 }
2829 
2830 template <class LP_INFERENCE_TYPE>
2831 template <class VISITOR_TYPE, typename LPInferenceBase<LP_INFERENCE_TYPE>::Parameter::Relaxation RELAXATION, typename LPInferenceBase<LP_INFERENCE_TYPE>::Parameter::ChallengeHeuristic HEURISTIC, bool USE_INFINITE_ITERATIONS, bool ADD_ALL_VIOLATED_CONSTRAINTS, bool USE_INTEGER_CONSTRAINTS>
2833  if(meta::Compare<VISITOR_TYPE, TimingVisitorType>::value) {
2834  visitor.addLog("LP Solver Time");
2835  visitor.addLog("Search Violated Constraints Time");
2836  visitor.addLog("Add Violated Constraints Time");
2837  }
2838 
2839  visitor.begin(*this);
2840  inferenceStarted_ = true;
2841  for(size_t i = 0; USE_INFINITE_ITERATIONS || (i < parameter_.maxNumIterations_);) {
2842  // solve problem
2843  if(meta::Compare<VISITOR_TYPE, TimingVisitorType>::value) {
2844  SolverTimingType solverTime;
2845  const bool solveSuccess = static_cast<LPInferenceType*>(this)->solve(solverTime);
2846  if(!solveSuccess) {
2847  // LPSOLVER failed to optimize
2848  return UNKNOWN;
2849  }
2850  const size_t visitorReturnFlag = visitor(*this);
2851  visitor.log("LP Solver Time", solverTime);
2852  if(visitorReturnFlag != visitors::VisitorReturnFlag::ContinueInf) {
2853  // timeout or bound reached
2854  break;
2855  }
2856  } else {
2857  if(!static_cast<LPInferenceType*>(this)->solve()) {
2858  // LPSOLVER failed to optimize
2859  return UNKNOWN;
2860  }
2861  if(visitor(*this) != visitors::VisitorReturnFlag::ContinueInf) {
2862  // timeout or bound reached
2863  break;
2864  }
2865  }
2866  // search violated constraints
2867  if(meta::Compare<VISITOR_TYPE, TimingVisitorType>::value) {
2868  static Timer searchViolatedConstraintsTimer;
2869  searchViolatedConstraintsTimer.reset();
2870  searchViolatedConstraintsTimer.tic();
2871  const bool newViolatedConstraintsFound = USE_INTEGER_CONSTRAINTS ? tightenPolytope<RELAXATION, HEURISTIC, ADD_ALL_VIOLATED_CONSTRAINTS>() : tightenPolytopeRelaxed<RELAXATION, HEURISTIC, ADD_ALL_VIOLATED_CONSTRAINTS>();
2872  searchViolatedConstraintsTimer.toc();
2873  visitor.log("Search Violated Constraints Time", searchViolatedConstraintsTimer.elapsedTime());
2874  if(newViolatedConstraintsFound){
2875  SolverTimingType addConstraintsTime;
2876  static_cast<LPInferenceType*>(this)->addConstraintsFinished(addConstraintsTime);
2877  visitor.log("Add Violated Constraints Time", addConstraintsTime);
2878  } else {
2879  // all constraints are satisfied
2880  break;
2881  }
2882  } else {
2883  if(USE_INTEGER_CONSTRAINTS ? tightenPolytope<RELAXATION, HEURISTIC, ADD_ALL_VIOLATED_CONSTRAINTS>() : tightenPolytopeRelaxed<RELAXATION, HEURISTIC, ADD_ALL_VIOLATED_CONSTRAINTS>()){
2884  static_cast<LPInferenceType*>(this)->addConstraintsFinished();
2885  } else {
2886  // all constraints are satisfied
2887  break;
2888  }
2889  }
2890  if(!USE_INFINITE_ITERATIONS) {
2891  ++i;
2892  }
2893  }
2894  visitor.end(*this);
2895  return NORMAL;
2896 }
2897 
2898 template <class LP_INFERENCE_TYPE>
2899 template <typename LPInferenceBase<LP_INFERENCE_TYPE>::Parameter::Relaxation RELAXATION, typename LPInferenceBase<LP_INFERENCE_TYPE>::Parameter::ChallengeHeuristic HEURISTIC, bool ADD_ALL_VIOLATED_CONSTRAINTS>
2901  if(RELAXATION == Parameter::TightPolytope) {
2902  // nothing to tighten!
2903  return false;
2904  }
2905 
2906  // get current solution
2907  static std::vector<LabelType> currentArg;
2908  arg(currentArg);
2909 
2910  if(ADD_ALL_VIOLATED_CONSTRAINTS) {
2911  bool violatedConstraintAdded = false;
2912  if(RELAXATION == Parameter::LoosePolytope) {
2913  double currentWeight;
2914  InactiveConstraintsListIteratorType inactiveConstraintsBegin = inactiveConstraints_.begin();
2915  InactiveConstraintsListIteratorType inactiveConstraintsEnd = inactiveConstraints_.end();
2916  while(inactiveConstraintsBegin != inactiveConstraintsEnd) {
2917  checkInactiveConstraint(*inactiveConstraintsBegin, currentWeight);
2918  if(currentWeight > parameter_.tolerance_) {
2919  addInactiveConstraint(*inactiveConstraintsBegin);
2920  violatedConstraintAdded = true;
2921  const InactiveConstraintsListIteratorType removeInactiveConstraintIterator = inactiveConstraintsBegin;
2922  ++inactiveConstraintsBegin;
2923  inactiveConstraints_.erase(removeInactiveConstraintIterator);
2924  break;
2925  } else {
2926  ++inactiveConstraintsBegin;
2927  }
2928  }
2929  while(inactiveConstraintsBegin != inactiveConstraintsEnd) {
2930  checkInactiveConstraint(*inactiveConstraintsBegin, currentWeight);
2931  if(currentWeight > parameter_.tolerance_) {
2932  addInactiveConstraint(*inactiveConstraintsBegin);
2933  const InactiveConstraintsListIteratorType removeInactiveConstraintIterator = inactiveConstraintsBegin;
2934  ++inactiveConstraintsBegin;
2935  inactiveConstraints_.erase(removeInactiveConstraintIterator);
2936  } else {
2937  ++inactiveConstraintsBegin;
2938  }
2939  }
2940  }
2941 
2942  // add violated linear constraints from linear constraint factors
2943  size_t i = 0;
2944  AddAllViolatedLinearConstraintsFunctor addAllViolatedLinearConstraintsFunctor;
2945  addAllViolatedLinearConstraintsFunctor.tolerance_ = parameter_.tolerance_;
2946  addAllViolatedLinearConstraintsFunctor.lpInference_ = this;
2947  addAllViolatedLinearConstraintsFunctor.violatedConstraintAdded_ = false;
2948  if(!violatedConstraintAdded) {
2949  for(; i < linearConstraintFactors_.size(); ++i) {
2950  addAllViolatedLinearConstraintsFunctor.labelingBegin_ = IntegerSolutionSubsequenceIterator(currentArg.begin(), linearConstraintLPVariablesSubsequenceIndices_[i].begin());
2951  addAllViolatedLinearConstraintsFunctor.linearConstraintID_ = i;
2952  const IndexType currentFactor = linearConstraintFactors_[i];
2953  gm_[currentFactor].callFunctor(addAllViolatedLinearConstraintsFunctor);
2954  if(addAllViolatedLinearConstraintsFunctor.violatedConstraintAdded_) {
2955  violatedConstraintAdded = true;
2956  break;
2957  }
2958  }
2959  }
2960  for(; i < linearConstraintFactors_.size(); ++i) {
2961  for(; i < linearConstraintFactors_.size(); ++i) {
2962  addAllViolatedLinearConstraintsFunctor.labelingBegin_ = IntegerSolutionSubsequenceIterator(currentArg.begin(), linearConstraintLPVariablesSubsequenceIndices_[i].begin());
2963  addAllViolatedLinearConstraintsFunctor.linearConstraintID_ = i;
2964  const IndexType currentFactor = linearConstraintFactors_[i];
2965  gm_[currentFactor].callFunctor(addAllViolatedLinearConstraintsFunctor);
2966  }
2967  }
2968  return violatedConstraintAdded;
2969  } else {
2970  size_t numConstraintsAdded = 0;
2971  SortedViolatedConstraintsListType sortedViolatedConstraints;
2972 
2973  if(RELAXATION == Parameter::LoosePolytope) {
2974  double currentWeight;
2975  InactiveConstraintsListIteratorType inactiveConstraintsBegin = inactiveConstraints_.begin();
2976  InactiveConstraintsListIteratorType inactiveConstraintsEnd = inactiveConstraints_.end();
2977  while(inactiveConstraintsBegin != inactiveConstraintsEnd) {
2978  checkInactiveConstraint(*inactiveConstraintsBegin, currentWeight);
2979  if(currentWeight > parameter_.tolerance_) {
2980  if(HEURISTIC == Parameter::Random) {
2981  addInactiveConstraint(*inactiveConstraintsBegin);
2982  ++numConstraintsAdded;
2983  const InactiveConstraintsListIteratorType removeInactiveConstraintIterator = inactiveConstraintsBegin;
2984  ++inactiveConstraintsBegin;
2985  inactiveConstraints_.erase(removeInactiveConstraintIterator);
2986  if(numConstraintsAdded == parameter_.maxNumConstraintsPerIter_) {
2987  break;
2988  }
2989  } else {
2990  sortedViolatedConstraints.insert(typename SortedViolatedConstraintsListType::value_type(currentWeight, std::make_pair(inactiveConstraintsBegin, std::make_pair(linearConstraintFactors_.size(), static_cast<const LinearConstraintType*>(NULL)))));
2991  if(sortedViolatedConstraints.size() > parameter_.maxNumConstraintsPerIter_) {
2992  // remove constraints with to small weight
2993  sortedViolatedConstraints.erase(sortedViolatedConstraints.begin());
2994  OPENGM_ASSERT(sortedViolatedConstraints.size() == parameter_.maxNumConstraintsPerIter_);
2995  }
2996  ++inactiveConstraintsBegin;
2997  }
2998  } else {
2999  ++inactiveConstraintsBegin;
3000  }
3001  }
3002  }
3003 
3004  // add violated linear constraints from linear constraint factors
3005  AddViolatedLinearConstraintsFunctor<LPInferenceBaseType, HEURISTIC> addViolatedLinearConstraintsFunctor;
3006  addViolatedLinearConstraintsFunctor.tolerance_ = parameter_.tolerance_;
3007  addViolatedLinearConstraintsFunctor.lpInference_ = this;
3008  addViolatedLinearConstraintsFunctor.numConstraintsAdded_ = numConstraintsAdded;
3009  addViolatedLinearConstraintsFunctor.sortedViolatedConstraintsList_ = &sortedViolatedConstraints;
3010  for(size_t i = 0; i < linearConstraintFactors_.size(); ++i) {
3011  addViolatedLinearConstraintsFunctor.labelingBegin_ = IntegerSolutionSubsequenceIterator(currentArg.begin(), linearConstraintLPVariablesSubsequenceIndices_[i].begin());
3012  addViolatedLinearConstraintsFunctor.linearConstraintID_ = i;
3013  const IndexType currentFactor = linearConstraintFactors_[i];
3014  gm_[currentFactor].callFunctor(addViolatedLinearConstraintsFunctor);
3015  if(addViolatedLinearConstraintsFunctor.numConstraintsAdded_ == parameter_.maxNumConstraintsPerIter_) {
3016  break;
3017  }
3018  }
3019 
3020  numConstraintsAdded = addViolatedLinearConstraintsFunctor.numConstraintsAdded_;
3021  typename SortedViolatedConstraintsListType::reverse_iterator sortedViolatedConstraintsListRBegin = sortedViolatedConstraints.rbegin();
3022  const typename SortedViolatedConstraintsListType::reverse_iterator sortedViolatedConstraintsListREnd = sortedViolatedConstraints.rend();
3023  OPENGM_ASSERT(sortedViolatedConstraints.size() <= parameter_.maxNumConstraintsPerIter_);
3024  while(sortedViolatedConstraintsListRBegin != sortedViolatedConstraintsListREnd) {
3025  if(sortedViolatedConstraintsListRBegin->second.first == inactiveConstraints_.end()) {
3026  addLinearConstraint(sortedViolatedConstraintsListRBegin->second.second.first, *(sortedViolatedConstraintsListRBegin->second.second.second));
3027  } else {
3028  addInactiveConstraint(*(sortedViolatedConstraintsListRBegin->second.first));
3029  inactiveConstraints_.erase(sortedViolatedConstraintsListRBegin->second.first);
3030  }
3031  ++numConstraintsAdded;
3032  ++sortedViolatedConstraintsListRBegin;
3033  }
3034  if(numConstraintsAdded == 0) {
3035  return false;
3036  } else {
3037  return true;
3038  }
3039  }
3040 }
3041 
3042 template <class LP_INFERENCE_TYPE>
3043 template <typename LPInferenceBase<LP_INFERENCE_TYPE>::Parameter::Relaxation RELAXATION, typename LPInferenceBase<LP_INFERENCE_TYPE>::Parameter::ChallengeHeuristic HEURISTIC, bool ADD_ALL_VIOLATED_CONSTRAINTS>
3045  if(RELAXATION == Parameter::TightPolytope) {
3046  // nothing to tighten!
3047  return false;
3048  }
3049 
3050  // get current solution
3051  SolverSolutionIteratorType relaxedArgBegin = static_cast<const LPInferenceType*>(this)->solutionBegin();
3052 
3053  if(ADD_ALL_VIOLATED_CONSTRAINTS) {
3054  bool violatedConstraintAdded = false;
3055  if(RELAXATION == Parameter::LoosePolytope) {
3056  double currentWeight;
3057  InactiveConstraintsListIteratorType inactiveConstraintsBegin = inactiveConstraints_.begin();
3058  InactiveConstraintsListIteratorType inactiveConstraintsEnd = inactiveConstraints_.end();
3059  while(inactiveConstraintsBegin != inactiveConstraintsEnd) {
3060  checkInactiveConstraint(*inactiveConstraintsBegin, currentWeight);
3061  if(currentWeight > parameter_.tolerance_) {
3062  addInactiveConstraint(*inactiveConstraintsBegin);
3063  violatedConstraintAdded = true;
3064  const InactiveConstraintsListIteratorType removeInactiveConstraintIterator = inactiveConstraintsBegin;
3065  ++inactiveConstraintsBegin;
3066  inactiveConstraints_.erase(removeInactiveConstraintIterator);
3067  break;
3068  } else {
3069  ++inactiveConstraintsBegin;
3070  }
3071  }
3072  while(inactiveConstraintsBegin != inactiveConstraintsEnd) {
3073  checkInactiveConstraint(*inactiveConstraintsBegin, currentWeight);
3074  if(currentWeight > parameter_.tolerance_) {
3075  addInactiveConstraint(*inactiveConstraintsBegin);
3076  const InactiveConstraintsListIteratorType removeInactiveConstraintIterator = inactiveConstraintsBegin;
3077  ++inactiveConstraintsBegin;
3078  inactiveConstraints_.erase(removeInactiveConstraintIterator);
3079  } else {
3080  ++inactiveConstraintsBegin;
3081  }
3082  }
3083  }
3084 
3085  // add violated linear constraints from linear constraint factors
3086  size_t i = 0;
3087  AddAllViolatedLinearConstraintsRelaxedFunctor addAllViolatedLinearConstraintsRelaxedFunctor;
3088  addAllViolatedLinearConstraintsRelaxedFunctor.tolerance_ = parameter_.tolerance_;
3089  addAllViolatedLinearConstraintsRelaxedFunctor.lpInference_ = this;
3090  addAllViolatedLinearConstraintsRelaxedFunctor.violatedConstraintAdded_ = false;
3091  if(!violatedConstraintAdded) {
3092  for(; i < linearConstraintFactors_.size(); ++i) {
3093  addAllViolatedLinearConstraintsRelaxedFunctor.labelingBegin_ = RelaxedSolutionSubsequenceIterator(relaxedArgBegin, linearConstraintLPVariablesSubsequenceIndices_[i].begin());
3094  addAllViolatedLinearConstraintsRelaxedFunctor.linearConstraintID_ = i;
3095  const IndexType currentFactor = linearConstraintFactors_[i];
3096  gm_[currentFactor].callFunctor(addAllViolatedLinearConstraintsRelaxedFunctor);
3097  if(addAllViolatedLinearConstraintsRelaxedFunctor.violatedConstraintAdded_) {
3098  violatedConstraintAdded = true;
3099  break;
3100  }
3101  }
3102  }
3103  for(; i < linearConstraintFactors_.size(); ++i) {
3104  for(; i < linearConstraintFactors_.size(); ++i) {
3105  addAllViolatedLinearConstraintsRelaxedFunctor.labelingBegin_ = RelaxedSolutionSubsequenceIterator(relaxedArgBegin, linearConstraintLPVariablesSubsequenceIndices_[i].begin());
3106  addAllViolatedLinearConstraintsRelaxedFunctor.linearConstraintID_ = i;
3107  const IndexType currentFactor = linearConstraintFactors_[i];
3108  gm_[currentFactor].callFunctor(addAllViolatedLinearConstraintsRelaxedFunctor);
3109  }
3110  }
3111  return violatedConstraintAdded;
3112  } else {
3113  size_t numConstraintsAdded = 0;
3114  SortedViolatedConstraintsListType sortedViolatedConstraints;
3115 
3116  if(RELAXATION == Parameter::LoosePolytope) {
3117  double currentWeight;
3118  InactiveConstraintsListIteratorType inactiveConstraintsBegin = inactiveConstraints_.begin();
3119  InactiveConstraintsListIteratorType inactiveConstraintsEnd = inactiveConstraints_.end();
3120  while(inactiveConstraintsBegin != inactiveConstraintsEnd) {
3121  checkInactiveConstraint(*inactiveConstraintsBegin, currentWeight);
3122  if(currentWeight > parameter_.tolerance_) {
3123  if(HEURISTIC == Parameter::Random) {
3124  addInactiveConstraint(*inactiveConstraintsBegin);
3125  ++numConstraintsAdded;
3126  const InactiveConstraintsListIteratorType removeInactiveConstraintIterator = inactiveConstraintsBegin;
3127  ++inactiveConstraintsBegin;
3128  inactiveConstraints_.erase(removeInactiveConstraintIterator);
3129  if(numConstraintsAdded == parameter_.maxNumConstraintsPerIter_) {
3130  break;
3131  }
3132  } else {
3133  sortedViolatedConstraints.insert(typename SortedViolatedConstraintsListType::value_type(currentWeight, std::make_pair(inactiveConstraintsBegin, std::make_pair(linearConstraintFactors_.size(), static_cast<LinearConstraintType*>(NULL)))));
3134  if(sortedViolatedConstraints.size() > parameter_.maxNumConstraintsPerIter_) {
3135  // remove constraints with to small weight
3136  sortedViolatedConstraints.erase(sortedViolatedConstraints.begin());
3137  OPENGM_ASSERT(sortedViolatedConstraints.size() == parameter_.maxNumConstraintsPerIter_);
3138  }
3139  ++inactiveConstraintsBegin;
3140  }
3141  } else {
3142  ++inactiveConstraintsBegin;
3143  }
3144  }
3145  }
3146 
3147  // add violated linear constraints from linear constraint factors
3148  AddViolatedLinearConstraintsRelaxedFunctor<LPInferenceBaseType, HEURISTIC> addViolatedLinearConstraintsRelaxedFunctor;
3149  addViolatedLinearConstraintsRelaxedFunctor.tolerance_ = parameter_.tolerance_;
3150  addViolatedLinearConstraintsRelaxedFunctor.lpInference_ = this;
3151  addViolatedLinearConstraintsRelaxedFunctor.numConstraintsAdded_ = numConstraintsAdded;
3152  addViolatedLinearConstraintsRelaxedFunctor.sortedViolatedConstraintsList_ = &sortedViolatedConstraints;
3153  for(size_t i = 0; i < linearConstraintFactors_.size(); ++i) {
3154  addViolatedLinearConstraintsRelaxedFunctor.labelingBegin_ = RelaxedSolutionSubsequenceIterator(relaxedArgBegin, linearConstraintLPVariablesSubsequenceIndices_[i].begin());
3155  addViolatedLinearConstraintsRelaxedFunctor.linearConstraintID_ = i;
3156  const IndexType currentFactor = linearConstraintFactors_[i];
3157  gm_[currentFactor].callFunctor(addViolatedLinearConstraintsRelaxedFunctor);
3158  if(addViolatedLinearConstraintsRelaxedFunctor.numConstraintsAdded_ == parameter_.maxNumConstraintsPerIter_) {
3159  break;
3160  }
3161  }
3162 
3163  numConstraintsAdded = addViolatedLinearConstraintsRelaxedFunctor.numConstraintsAdded_;
3164  typename SortedViolatedConstraintsListType::reverse_iterator sortedViolatedConstraintsListRBegin = sortedViolatedConstraints.rbegin();
3165  const typename SortedViolatedConstraintsListType::reverse_iterator sortedViolatedConstraintsListREnd = sortedViolatedConstraints.rend();
3166  OPENGM_ASSERT(sortedViolatedConstraints.size() <= parameter_.maxNumConstraintsPerIter_);
3167  while(sortedViolatedConstraintsListRBegin != sortedViolatedConstraintsListREnd) {
3168  if(sortedViolatedConstraintsListRBegin->second.first == inactiveConstraints_.end()) {
3169  addLinearConstraint(sortedViolatedConstraintsListRBegin->second.second.first, *(sortedViolatedConstraintsListRBegin->second.second.second));
3170  } else {
3171  addInactiveConstraint(*(sortedViolatedConstraintsListRBegin->second.first));
3172  inactiveConstraints_.erase(sortedViolatedConstraintsListRBegin->second.first);
3173  }
3174  ++numConstraintsAdded;
3175  if(numConstraintsAdded == parameter_.maxNumConstraintsPerIter_) {
3176  break;
3177  }
3178  ++sortedViolatedConstraintsListRBegin;
3179  }
3180  if(numConstraintsAdded == 0) {
3181  return false;
3182  } else {
3183  return true;
3184  }
3185  }
3186 }
3187 
3188 template <class LP_INFERENCE_TYPE>
3189 inline void LPInferenceBase<LP_INFERENCE_TYPE>::checkInactiveConstraint(const ConstraintStorage& constraint, double& weight) const {
3190  const SolverSolutionIteratorType currentSolution = static_cast<const LPInferenceType*>(this)->solutionBegin();
3191  double sum = 0.0;
3192  for(size_t i = 0; i < constraint.variableIDs_.size(); ++i) {
3193  sum += constraint.coefficients_[i] * currentSolution[constraint.variableIDs_[i]];
3194  }
3195  switch(constraint.operator_) {
3196  case LinearConstraintType::LinearConstraintOperatorType::LessEqual : {
3197  if(sum <= constraint.bound_) {
3198  weight = 0.0;
3199  } else {
3200  weight = sum - constraint.bound_;
3201  }
3202  break;
3203  }
3204  case LinearConstraintType::LinearConstraintOperatorType::Equal : {
3205  if(sum == constraint.bound_) {
3206  weight = 0.0;
3207  } else {
3208  weight = std::abs(sum - constraint.bound_);
3209  }
3210  break;
3211  }
3212  default: {
3213  // default corresponds to LinearConstraintType::LinearConstraintOperatorType::GreaterEqual case
3214  if(sum >= constraint.bound_) {
3215  weight = 0.0;
3216  } else {
3217  weight = constraint.bound_ - sum;
3218  }
3219  break;
3220  }
3221  }
3222 }
3223 
3224 template <class LP_INFERENCE_TYPE>
3226  switch(constraint.operator_) {
3227  case LinearConstraintType::LinearConstraintOperatorType::LessEqual : {
3228  static_cast<LPInferenceType*>(this)->addLessEqualConstraint(constraint.variableIDs_.begin(), constraint.variableIDs_.end(), constraint.coefficients_.begin(), constraint.bound_, constraint.name_);
3229  break;
3230  }
3231  case LinearConstraintType::LinearConstraintOperatorType::Equal : {
3232  static_cast<LPInferenceType*>(this)->addEqualityConstraint(constraint.variableIDs_.begin(), constraint.variableIDs_.end(), constraint.coefficients_.begin(), constraint.bound_, constraint.name_);
3233  break;
3234  }
3235  default: {
3236  // default corresponds to LinearConstraintType::LinearConstraintOperatorType::GreaterEqual case
3237  static_cast<LPInferenceType*>(this)->addGreaterEqualConstraint(constraint.variableIDs_.begin(), constraint.variableIDs_.end(), constraint.coefficients_.begin(), constraint.bound_, constraint.name_);
3238  break;
3239  }
3240  }
3241 }
3242 
3243 template <class LP_INFERENCE_TYPE>
3244 template<class LINEAR_CONSTRAINT_FUNCTION_TYPE>
3245 inline void LPInferenceBase<LP_INFERENCE_TYPE>::GetIndicatorVariablesOrderBeginFunctor::operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE& linearConstraintFunction) {
3247 }
3248 
3249 template <class LP_INFERENCE_TYPE>
3250 template<class FUNCTION_TYPE, bool IS_LINEAR_CONSTRAINT_FUNCTION>
3252  throw RuntimeError(std::string("GetIndicatorVariablesOrderBeginFunctor: Unsupported linear constraint function type") + typeid(FUNCTION_TYPE).name());
3253 }
3254 
3255 template <class LP_INFERENCE_TYPE>
3256 template<class FUNCTION_TYPE>
3258  myself.indicatorVariablesOrderBegin_ = function.indicatorVariablesOrderBegin();
3259 }
3260 
3261 template <class LP_INFERENCE_TYPE>
3262 template<class LINEAR_CONSTRAINT_FUNCTION_TYPE>
3263 inline void LPInferenceBase<LP_INFERENCE_TYPE>::GetIndicatorVariablesOrderEndFunctor::operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE& linearConstraintFunction) {
3265 }
3266 
3267 template <class LP_INFERENCE_TYPE>
3268 template<class FUNCTION_TYPE, bool IS_LINEAR_CONSTRAINT_FUNCTION>
3270  throw RuntimeError(std::string("GetIndicatorVariablesOrderEnd: Unsupported linear constraint function type") + typeid(FUNCTION_TYPE).name());
3271 }
3272 
3273 template <class LP_INFERENCE_TYPE>
3274 template<class FUNCTION_TYPE>
3276  myself.indicatorVariablesOrderEnd_ = function.indicatorVariablesOrderEnd();
3277 }
3278 
3279 template <class LP_INFERENCE_TYPE>
3280 template<class LINEAR_CONSTRAINT_FUNCTION_TYPE>
3281 inline void LPInferenceBase<LP_INFERENCE_TYPE>::GetLinearConstraintsBeginFunctor::operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE& linearConstraintFunction) {
3283 }
3284 
3285 template <class LP_INFERENCE_TYPE>
3286 template<class FUNCTION_TYPE, bool IS_LINEAR_CONSTRAINT_FUNCTION>
3288  throw RuntimeError(std::string("GetLinearConstraintsBeginFunctor: Unsupported linear constraint function type") + typeid(FUNCTION_TYPE).name());
3289 }
3290 
3291 template <class LP_INFERENCE_TYPE>
3292 template<class FUNCTION_TYPE>
3294  myself.linearConstraintsBegin_ = function.linearConstraintsBegin();
3295 }
3296 
3297 template <class LP_INFERENCE_TYPE>
3298 template<class LINEAR_CONSTRAINT_FUNCTION_TYPE>
3299 inline void LPInferenceBase<LP_INFERENCE_TYPE>::GetLinearConstraintsEndFunctor::operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE& linearConstraintFunction) {
3301 }
3302 
3303 template <class LP_INFERENCE_TYPE>
3304 template<class FUNCTION_TYPE, bool IS_LINEAR_CONSTRAINT_FUNCTION>
3306  throw RuntimeError(std::string("GetLinearConstraintsEndFunctor: Unsupported linear constraint function type") + typeid(FUNCTION_TYPE).name());
3307 }
3308 
3309 template <class LP_INFERENCE_TYPE>
3310 template<class FUNCTION_TYPE>
3312  myself.linearConstraintsEnd_ = function.linearConstraintsEnd();
3313 }
3314 
3315 template <class LP_INFERENCE_TYPE>
3316 template<class LINEAR_CONSTRAINT_FUNCTION_TYPE>
3317 inline void LPInferenceBase<LP_INFERENCE_TYPE>::AddAllViolatedLinearConstraintsFunctor::operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE& linearConstraintFunction) {
3319 }
3320 
3321 template <class LP_INFERENCE_TYPE>
3322 template<class FUNCTION_TYPE, bool IS_LINEAR_CONSTRAINT_FUNCTION>
3324  throw RuntimeError(std::string("AddAllViolatedLinearConstraintsFunctor: Unsupported linear constraint function type") + typeid(FUNCTION_TYPE).name());
3325 }
3326 
3327 template <class LP_INFERENCE_TYPE>
3328 template<class FUNCTION_TYPE>
3330  typename FUNCTION_TYPE::ViolatedLinearConstraintsIteratorType violatedConstraintsBegin;
3331  typename FUNCTION_TYPE::ViolatedLinearConstraintsIteratorType violatedConstraintsEnd;
3332  typename FUNCTION_TYPE::ViolatedLinearConstraintsWeightsIteratorType violatedConstraintsWeightsBegin;
3333  function.challenge(violatedConstraintsBegin, violatedConstraintsEnd, violatedConstraintsWeightsBegin, myself.labelingBegin_, myself.tolerance_);
3334  if(std::distance(violatedConstraintsBegin, violatedConstraintsEnd) > 0) {
3335  while(violatedConstraintsBegin != violatedConstraintsEnd) {
3336  myself.lpInference_->addLinearConstraint(myself.linearConstraintID_, *violatedConstraintsBegin);
3337  ++violatedConstraintsBegin;
3338  }
3339  myself.violatedConstraintAdded_ = true;
3340  }
3341 }
3342 
3343 template <class LP_INFERENCE_TYPE>
3344 template<class LINEAR_CONSTRAINT_FUNCTION_TYPE>
3345 inline void LPInferenceBase<LP_INFERENCE_TYPE>::AddAllViolatedLinearConstraintsRelaxedFunctor::operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE& linearConstraintFunction) {
3347 }
3348 
3349 template <class LP_INFERENCE_TYPE>
3350 template<class FUNCTION_TYPE, bool IS_LINEAR_CONSTRAINT_FUNCTION>
3352  throw RuntimeError(std::string("AddAllViolatedLinearConstraintsRelaxedFunctor: Unsupported linear constraint function type") + typeid(FUNCTION_TYPE).name());
3353 }
3354 
3355 template <class LP_INFERENCE_TYPE>
3356 template<class FUNCTION_TYPE>
3358  typename FUNCTION_TYPE::ViolatedLinearConstraintsIteratorType violatedConstraintsBegin;
3359  typename FUNCTION_TYPE::ViolatedLinearConstraintsIteratorType violatedConstraintsEnd;
3360  typename FUNCTION_TYPE::ViolatedLinearConstraintsWeightsIteratorType violatedConstraintsWeightsBegin;
3361  function.challengeRelaxed(violatedConstraintsBegin, violatedConstraintsEnd, violatedConstraintsWeightsBegin, myself.labelingBegin_, myself.tolerance_);
3362  if(std::distance(violatedConstraintsBegin, violatedConstraintsEnd) > 0) {
3363  while(violatedConstraintsBegin != violatedConstraintsEnd) {
3364  myself.lpInference_->addLinearConstraint(myself.linearConstraintID_, *violatedConstraintsBegin);
3365  ++violatedConstraintsBegin;
3366  }
3367  myself.violatedConstraintAdded_ = true;
3368  }
3369 }
3370 
3371 template <class LP_INFERENCE_BASE_TYPE, typename LP_INFERENCE_BASE_TYPE::Parameter::ChallengeHeuristic HEURISTIC>
3372 template<class LINEAR_CONSTRAINT_FUNCTION_TYPE>
3373 inline void AddViolatedLinearConstraintsFunctor<LP_INFERENCE_BASE_TYPE, HEURISTIC>::operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE& linearConstraintFunction) {
3375 }
3376 
3377 template <class LP_INFERENCE_BASE_TYPE, typename LP_INFERENCE_BASE_TYPE::Parameter::ChallengeHeuristic HEURISTIC>
3378 template<class FUNCTION_TYPE, bool IS_LINEAR_CONSTRAINT_FUNCTION>
3380  throw RuntimeError(std::string("AddViolatedLinearConstraintsFunctor: Unsupported linear constraint function type") + typeid(FUNCTION_TYPE).name());
3381 }
3382 
3383 template <class LP_INFERENCE_BASE_TYPE, typename LP_INFERENCE_BASE_TYPE::Parameter::ChallengeHeuristic HEURISTIC>
3384 template<class FUNCTION_TYPE>
3386  typename FUNCTION_TYPE::ViolatedLinearConstraintsIteratorType violatedConstraintsBegin;
3387  typename FUNCTION_TYPE::ViolatedLinearConstraintsIteratorType violatedConstraintsEnd;
3388  typename FUNCTION_TYPE::ViolatedLinearConstraintsWeightsIteratorType violatedConstraintsWeightsBegin;
3389  function.challenge(violatedConstraintsBegin, violatedConstraintsEnd, violatedConstraintsWeightsBegin, myself.labelingBegin_, myself.tolerance_);
3390  if(std::distance(violatedConstraintsBegin, violatedConstraintsEnd) > 0) {
3391  while(violatedConstraintsBegin != violatedConstraintsEnd) {
3392  if(HEURISTIC == LP_INFERENCE_BASE_TYPE::Parameter::Random) {
3393  myself.lpInference_->addLinearConstraint(myself.linearConstraintID_, *violatedConstraintsBegin);
3394  ++violatedConstraintsBegin;
3395  ++myself.numConstraintsAdded_;
3396  if(myself.numConstraintsAdded_ == myself.lpInference_->parameter_.maxNumConstraintsPerIter_) {
3397  break;
3398  }
3399  } else {
3400  myself.sortedViolatedConstraintsList_->insert(typename LP_INFERENCE_BASE_TYPE::SortedViolatedConstraintsListType::value_type(*violatedConstraintsWeightsBegin, std::make_pair(myself.lpInference_->inactiveConstraints_.end(), std::make_pair(myself.linearConstraintID_, &(*violatedConstraintsBegin)))));
3401  if(myself.sortedViolatedConstraintsList_->size() > myself.lpInference_->parameter_.maxNumConstraintsPerIter_) {
3402  // remove constraints with to small weight
3403  myself.sortedViolatedConstraintsList_->erase(myself.sortedViolatedConstraintsList_->begin());
3404  OPENGM_ASSERT(myself.sortedViolatedConstraintsList_->size() == myself.lpInference_->parameter_.maxNumConstraintsPerIter_);
3405  }
3406  ++violatedConstraintsBegin;
3407  ++violatedConstraintsWeightsBegin;
3408  }
3409  }
3410  }
3411 }
3412 
3413 template <class LP_INFERENCE_BASE_TYPE, typename LP_INFERENCE_BASE_TYPE::Parameter::ChallengeHeuristic HEURISTIC>
3414 template<class LINEAR_CONSTRAINT_FUNCTION_TYPE>
3415 inline void AddViolatedLinearConstraintsRelaxedFunctor<LP_INFERENCE_BASE_TYPE, HEURISTIC>::operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE& linearConstraintFunction) {
3417 }
3418 
3419 template <class LP_INFERENCE_BASE_TYPE, typename LP_INFERENCE_BASE_TYPE::Parameter::ChallengeHeuristic HEURISTIC>
3420 template<class FUNCTION_TYPE, bool IS_LINEAR_CONSTRAINT_FUNCTION>
3422  throw RuntimeError(std::string("AddViolatedLinearConstraintsRelaxedFunctor: Unsupported linear constraint function type") + typeid(FUNCTION_TYPE).name());
3423 }
3424 
3425 template <class LP_INFERENCE_BASE_TYPE, typename LP_INFERENCE_BASE_TYPE::Parameter::ChallengeHeuristic HEURISTIC>
3426 template<class FUNCTION_TYPE>
3428  typename FUNCTION_TYPE::ViolatedLinearConstraintsIteratorType violatedConstraintsBegin;
3429  typename FUNCTION_TYPE::ViolatedLinearConstraintsIteratorType violatedConstraintsEnd;
3430  typename FUNCTION_TYPE::ViolatedLinearConstraintsWeightsIteratorType violatedConstraintsWeightsBegin;
3431  function.challengeRelaxed(violatedConstraintsBegin, violatedConstraintsEnd, violatedConstraintsWeightsBegin, myself.labelingBegin_, myself.tolerance_);
3432  if(std::distance(violatedConstraintsBegin, violatedConstraintsEnd) > 0) {
3433  while(violatedConstraintsBegin != violatedConstraintsEnd) {
3434  if(HEURISTIC == LP_INFERENCE_BASE_TYPE::Parameter::Random) {
3435  myself.lpInference_->addLinearConstraint(myself.linearConstraintID_, *violatedConstraintsBegin);
3436  ++violatedConstraintsBegin;
3437  ++myself.numConstraintsAdded_;
3438  if(myself.numConstraintsAdded_ == myself.lpInference_->parameter_.maxNumConstraintsPerIter_) {
3439  break;
3440  }
3441  } else {
3442  myself.sortedViolatedConstraintsList_->insert(typename LP_INFERENCE_BASE_TYPE::SortedViolatedConstraintsListType::value_type(*violatedConstraintsWeightsBegin, std::make_pair(myself.lpInference_->inactiveConstraints_.end(), std::make_pair(myself.linearConstraintID_, &(*violatedConstraintsBegin)))));
3443  if(myself.sortedViolatedConstraintsList_->size() > myself.lpInference_->parameter_.maxNumConstraintsPerIter_) {
3444  // remove constraints with to small weight
3445  myself.sortedViolatedConstraintsList_->erase(myself.sortedViolatedConstraintsList_->begin());
3446  OPENGM_ASSERT(myself.sortedViolatedConstraintsList_->size() == myself.lpInference_->parameter_.maxNumConstraintsPerIter_);
3447  }
3448  ++violatedConstraintsBegin;
3449  ++violatedConstraintsWeightsBegin;
3450  }
3451  }
3452  }
3453 }
3454 
3455 } // namespace opengm
3456 
3457 #endif /* OPENGM_LP_INFERENCE_BASE_HXX_ */
LPInferenceBase(const GraphicalModelType &gm, const Parameter &parameter=Parameter())
LPInferenceBase constructor.
#define OPENGM_FLOAT_TOL
InactiveConstraintsListType::iterator InactiveConstraintsListIteratorType
Typedef of the iterator type used to iterate over a set of LPInferenceBase::ConstraintStorage objects...
void operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE &linearConstraintFunction)
Operator used to access the method linearConstraintsBegin() of the underlying linear constraint funct...
Helper struct to distinguish between linear constraint functions and other function types...
LPInferenceTraitsType::SolverIndexType SolverIndexType
Typedef of the index type used by the LP/MIP solver.
Functor to call LPFunctionTransfer::getLinearConstraints() for a factor of the graphical model...
Functor used to access the method challengeRelaxed() of the underlying linear constraint function of ...
LinearConstraintsContainerType::const_iterator LinearConstraintsIteratorType
Typedef of the iterator type used to iterate over a set of linear constraints.
static void getLinearConstraintsBeginFunctor_impl(GetLinearConstraintsBeginFunctor &myself, const FUNCTION_TYPE &function)
Actual access to the method linearConstraintsBegin() of the underlying linear constraint function of ...
void operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE &linearConstraintFunction)
Operator used to access the method indicatorVariablesOrderBegin() of the underlying linear constraint...
IndexType linearConstraintID_
Index of the linear constraint factor.
LinearConstraintType::IndicatorVariableType IndicatorVariableType
Typedef of the indicator variable type used within linear constraints.
LPInferenceTraitsType::GraphicalModelType GraphicalModelType
Typedef of the graphical model type.
LPInferenceBase< LPInferenceType > LPInferenceBaseType
Typedef of the opengm::LPInferenceBase class with appropriate template parameter. ...
The OpenGM namespace.
Definition: config.hxx:43
IndicatorVariablesIteratorType indicatorVariablesOrderEnd_
Storage for the iterator returned by the method indicatorVariablesOrderEnd().
LinearConstraintType::IndicatorVariablesIteratorType IndicatorVariablesIteratorType
Typedef of the iterator type used to iterate over a set of indicator variables.
Base class for Linear Programming based inference.
LocalPolytope will use a first order local polytope approximation of the marginal polytope...
InferenceTermination infer_impl_selectHeuristic(VISITOR_TYPE &visitor)
Helper function for LPInferenceBase::infer_impl to select the challenge heuristic template parameter...
std::vector< IndexType > linearConstraintFactors_
List of all linear constraint factors.
std::vector< SolverIndexType > variableIDs_
The variables of the LP/MIP model which are used in the constraint.
STL-compliant random access iterator for View and Marray.
Definition: marray.hxx:49
void reset()
Definition: timer.hxx:124
LinearConstraintType::IndicatorVariablesContainerType IndicatorVariablesContainerType
Typedef of the container type used to store a set of indicator variables.
IndicatorVariablesContainerType * order_
Pointer to the storage for the return value of the LPFunctionTransfer::getSlackVariablesOrder() metho...
LoosePolytope will add no constraints at all. All linear constraints will be added iteratively only i...
LPInferenceTraitsType::SolverValueType SolverValueType
Typedef of the value type used by the LP/MIP solver.
TightPolytope will add all constraints of the LocalPolytope relaxation and furthermore all constraint...
IndicatorVariablesContainerType::const_iterator IndicatorVariablesIteratorType
Defines the const iterator type to iterate over the set of indicator variables.
bool useFunctionTransfer_
Use function transfer if available to generate more efficient LP/MIP models.
static void addAllViolatedLinearConstraintsFunctor_impl(AddAllViolatedLinearConstraintsFunctor &myself, const FUNCTION_TYPE &function)
Actual access to the method challenge() of the underlying linear constraint function of a graphical m...
void addLoosePolytopeConstraints()
Add all constraints to the lp model which are required by the loose polytope relaxation.
SolverIndexType numSlackVariables_
The number of slack variables for the transferable factors of the graphical model.
static void getIndicatorVariablesOrderBeginFunctor_impl(GetIndicatorVariablesOrderBeginFunctor &myself, const FUNCTION_TYPE &function)
Actual access to the method indicatorVariablesOrderBegin() of the underlying linear constraint functi...
Provides interface for liner constraint functions.
void addLinearConstraint(const IndexType linearConstraintFactor, const LinearConstraintType &constraint)
Add a new linear constraint from a linear constraint function to the lp model.
static void addViolatedLinearConstraintsRelaxedFunctor_impl(AddViolatedLinearConstraintsRelaxedFunctor< LP_INFERENCE_BASE_TYPE, HEURISTIC > &myself, const FUNCTION_TYPE &function)
Actual access to the method challengeRelaxed() of the underlying linear constraint function of a grap...
IndicatorVariableType::IteratorType VariableLabelPairsIteratorType
Defines the const iterator type to iterate over the variable label pairs of an indicator variable...
void operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE &linearConstraintFunction)
Operator used to access the method linearConstraintsEnd() of the underlying linear constraint functio...
static void getLinearConstraintsEndFunctor_impl(GetLinearConstraintsEndFunctor &myself, const FUNCTION_TYPE &function)
Actual access to the method linearConstraintsEnd() of the underlying linear constraint function of a ...
virtual ~LPInferenceBase()
LPInferenceBase destructor.
Helper struct to distinguish between linear constraint functions and other function types...
const GraphicalModelType & gm_
Reference to the graphical model.
Functor used to access the method linearConstraintsBegin() of the underlying linear constraint functi...
iterator end()
Get the end-iterator.
Definition: marray.hxx:2727
LP_INFERENCE_BASE_TYPE::RelaxedSolutionSubsequenceIterator labelingBegin_
Iterator used to iterate over the current solution.
Helper struct to distinguish between linear constraint functions and other function types...
void operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE &linearConstraintFunction)
Operator used to access the method indicatorVariablesOrderEnd() of the underlying linear constraint f...
std::vector< LinearConstraintType > LinearConstraintsContainerType
Typedef of the container type used to store a set of linear constraints.
bool tightenPolytope()
Search for linear constraints which are violated by the current integer solution and add them to the ...
std::vector< IndexType > higherOrderFactors_
List of all higher order factors.
void addLPVariables()
Add the number of lp variables computed by LPInferenceBase::countLPVariables to the lp model...
IteratorType begin() const
Get the iterator over the sequence of variable label pairs from the indicator variable.
void toc()
Definition: timer.hxx:109
std::vector< IndicatorVariableType > IndicatorVariablesContainerType
Defines the storage type for the set of indicator variables.
void addInactiveConstraint(const ConstraintStorage &constraint)
Add a linear constraint from the local polytope constraint to the LP/MIP model.
LP_INFERENCE_BASE_TYPE::ValueType tolerance_
The tolerance used for the method challenge() of the underlying linear constraint function of a graph...
Helper struct to distinguish between linear constraint functions and other function types...
static void getIndicatorVariablesOrderEndFunctor_impl(GetIndicatorVariablesOrderEndFunctor &myself, const FUNCTION_TYPE &function)
Actual access to the method indicatorVariablesOrderEnd() of the underlying linear constraint function...
SolverIndexType factorLPVariableIndex(const IndexType factorID, const size_t labelingIndex) const
Get the lp variable which corresponds to the labeling of the factor.
LP_INFERENCE_BASE_TYPE * lpInference_
Pointer pointing to the instance of opengm::LPInferenceBase to get access to the LP/MIP model...
Array-Interface to an interval of memory.
Definition: marray.hxx:44
void countLPVariables()
Count the number of lp variables required to build a lp model for inference of the graphical model...
Defines the const iterator type to iterate over the subset of a sequence.
Platform-independent runtime measurements.
Definition: timer.hxx:29
BoundType getBound() const
Get the bound of the linear constraint.
Functor used to access the method linearConstraintsEnd() of the underlying linear constraint function...
Helper struct to distinguish between linear constraint functions and other function types...
size_t numConstraintsAdded_
Indicator used to tell how many constraints were added to the LP/MIP model.
IteratorType end() const
Get the end iterator of the sequence of variable label pairs from the indicator variable.
visitors::TimingVisitor< LPInferenceBaseType > TimingVisitorType
Typedef of the opengm::visitors::TimingVisitor class with appropriate template parameter.
Functor to call LPFunctionTransfer::numSlackVariables() for a graphical model factor.
LPInferenceTraitsType::SolverType SolverType
Typedef of the solver type used to solve the LP or MIP which is generated from the graphical model...
SolverIndexType nodeLPVariableIndex(const IndexType nodeID, const LabelType label) const
Get the lp variable which corresponds to the variable label pair of the graphical model...
bool mergeParallelFactors_
Merge factors which are connected to the same set of variables. Might increase construction time but ...
#define OPENGM_ASSERT(expression)
Definition: opengm.hxx:77
visitors::VerboseVisitor< LPInferenceBaseType > VerboseVisitorType
Typedef of the opengm::visitors::VerboseVisitor class with appropriate template parameter.
SolverIndexType numTransferedFactorsLPVariables
The number of lp variables for the transferable factors of the graphical model.
virtual InferenceTermination infer()
Run inference with empty visitor.
ValueType tolerance_
Tolerance for violation of linear constraints.
std::list< ConstraintStorage > InactiveConstraintsListType
Typedef of the container type used to sore a set of LPInferenceBase::ConstraintStorage objects...
InferenceTermination infer_impl_selectLPType(VISITOR_TYPE &visitor)
Helper function for LPInferenceBase::infer_impl to select the use integer constraints template parame...
LP_INFERENCE_BASE_TYPE::IndexType linearConstraintID_
Index of the linear constraint factor.
Storage class for linear constraints representing the local polytope constraints. They are generated ...
std::vector< ValueType > SlackVariablesObjectiveCoefficientsContainerType
Defines the container type which is used to store the coefficients of the slack variables for the obj...
void setAccumulation()
Set the accumulation for the lp solver.
Relaxation
This enum defines the type of the linear programming model which is used for inference.
virtual ValueType bound() const
Get the current bound.
LPInferenceTraitsType::SolverTimingType SolverTimingType
Typedef of the type used by the LP/MIP solver to measure timings.
LPInferenceTraitsType::SolverParameterType SolverParameterType
Typedef of the parameter class used by the LP/MIP solver.
void createObjectiveFunction()
Create the objective function for the lp model.
visitors::EmptyVisitor< LPInferenceBaseType > EmptyVisitorType
Typedef of the opengm::visitors::EmptyVisitor class with appropriate template parameter.
LP_INFERENCE_TYPE LPInferenceType
Typedef of the child class which inherits from opengm::LPInferenceBase.
std::string name_
The name of the constraint.
bool tightenPolytopeRelaxed()
Search for linear constraints which are violated by the current relaxed solution and add them to the ...
iterator begin()
Get an iterator to the beginning.
Definition: marray.hxx:2714
size_t maxNumIterations_
Maximum number of tightening iterations (infinite if set to 0).
ChallengeHeuristic challengeHeuristic_
Heuristic on how to select violated constraints.
InactiveConstraintsListType inactiveConstraints_
Storage for all linear constraints representing the local polytope constraints. They are generated an...
Helper struct to distinguish between linear constraint functions and other function types...
static void addViolatedLinearConstraintsFunctor_impl(AddViolatedLinearConstraintsFunctor< LP_INFERENCE_BASE_TYPE, HEURISTIC > &myself, const FUNCTION_TYPE &function)
Actual access to the method challenge() of the underlying linear constraint function of a graphical m...
IndicatorVariablesIteratorType indicatorVariablesOrderBegin_
Storage for the iterator returned by the method indicatorVariablesOrderBegin().
IndicatorVariablesIteratorType indicatorVariablesBegin() const
Get the begin iterator to the set of indicator variables.
LinearConstraintsContainerType * constraints_
Pointer to the storage for the return value of the LPFunctionTransfer::getLinearConstraints() method...
IndexType numSlackVariables_
Storage for the return value of the LPFunctionTransfer::numSlackVariables() method.
LP_INFERENCE_BASE_TYPE * lpInference_
Pointer pointing to the instance of opengm::LPInferenceBase to get access to the LP/MIP model...
void addLocalPolytopeVariableConstraint(const IndexType variableID, const bool addToModel)
Add a new variable constraint to the lp model.
SolverIndexType numLinearConstraintsLPVariables_
The number of lp variables for the linear constraint factors of the graphical model.
size_t maxNumConstraintsPerIter_
Maximum number of violated constraints which are added per tightening iteration (all if set to 0)...
LPInferenceBaseType * lpInference_
Pointer pointing to the instance of opengm::LPInferenceBase to get access to the LP/MIP model...
LinearConstraintOperatorValueType getConstraintOperator() const
Get the constraint operator of the linear constraint.
Parameter()
Parameter constructor setting default value for all options.
SolverValueType bound_
The value for the right hand side of the constraint.
void sortFactors()
Sorts the factors of the graphical model into the lists unaryFactors_, higherOrderFactors_, linearConstraintFactors_ and transferableFactors_.
LPInferenceBaseType * lpInference_
Pointer pointing to the instance of opengm::LPInferenceBase to get access to the LP/MIP model...
size_t numConstraintsAdded_
Indicator used to tell how many constraints were added to the LP/MIP model.
SlackVariablesObjectiveCoefficientsContainerType * coefficients_
Pointer to the storage for the return value of the LPFunctionTransfer::getSlackVariablesObjectiveCoef...
Provides transformations for some function types when they are used in inference algorithms which use...
ValueType tolerance_
The tolerance used for the method challenge() of the underlying linear constraint function of a graph...
SolverIndexType numLPVariables_
The total number of lp variables except slack variables.
virtual ValueType value() const
Get the current value.
SubsequenceIterator< typename std::vector< LabelType >::const_iterator, typename std::vector< size_t >::const_iterator > IntegerSolutionSubsequenceIterator
Typedef of the iterator type used to iterate over a subset of the computed solution. This iterator type is used to challenge the linear constraint functions present in the model. Only used when the problem is solved as a MIP.
Relaxation relaxation_
Selected relaxation method.
View< T, isConst, A > boundView(const size_t, const size_t=0) const
Get a View where one coordinate is bound to a value.
Definition: marray.hxx:2374
Functor to call LPFunctionTransfer::getSlackVariablesOrder() for a factor of the graphical model...
double elapsedTime() const
Definition: timer.hxx:130
void addTightPolytopeConstraints()
Add all constraints to the lp model which are required by the tight polytope relaxation.
std::vector< IndicatorVariableType > IndicatorVariablesContainerType
Defines the indicator variables container type which is used to store multiple indicator variables...
meta::GetLinearConstraintFunctionTypeList< typename GraphicalModelType::FunctionTypeList >::type LinearConstraintFunctionTypeList
Typelist of all linear constraint function types which are present in the graphical model type...
void tic()
Definition: timer.hxx:96
bool violatedConstraintAdded_
Indicator used to tell if at least one constraint was added to the LP/MIP model.
LPFunctionTransfer< ValueType, IndexType, LabelType > LPFunctionTransferType
Typedef of the opengm::LPFunctionTransfer class with appropriate template parameter.
InferenceTermination infer_impl_selectViolatedConstraints(VISITOR_TYPE &visitor)
Helper function for LPInferenceBase::infer_impl to select the add all violated constraints template p...
IndicatorVariablesContainerType * variables_
Pointer to the storage for the return value of the LPFunctionTransfer::getIndicatorVariables() method...
bool integerConstraintNodeVar_
Use integer constraints for node variables.
LPInferenceTraitsType::SolverSolutionIteratorType SolverSolutionIteratorType
Typedef of the iterator type used to iterate over the computed solution from the LP/MIP solver...
const size_t size() const
Get the number of data items.
Definition: marray.hxx:1698
bool getLPVariableIndexFromIndicatorVariable(const HIGHER_ORDER_FACTORS_MAP_TYPE &higherOrderFactorVariablesLookupTable, const INDICATOR_VARIABLES_MAP_TYPE &indicatorVariablesLookupTable, const IndicatorVariableType &indicatorVariable, const IndexType linearConstraintFactorIndex, SolverIndexType &lpVariableIndex) const
Get the index of the lp variable associated with an indicator variable.
LPInferenceTraits< LPInferenceType > LPInferenceTraitsType
Typedef of the opengm::LPInferenceTraits class with appropriate template parameter.
ValueType tolerance_
The tolerance used for the method challengeRelaxed() of the underlying linear constraint function of ...
ValueType constValue_
Constant value offset.
IndicatorVariablesIteratorType indicatorVariablesEnd() const
Get the end iterator to the set of indicator variables.
Combine a group of variables to a new variable.
Inference algorithm interface.
Definition: inference.hxx:34
std::vector< IndexType > unaryFactors_
List of all unary factors.
void addLocalPolytopeFactorConstraint(const IndexType factor, const IndexType variable, const LabelType label, const bool addToModel)
Add a new factor constraint to the lp model.
LinearConstraintsIteratorType linearConstraintsEnd_
Storage for the iterator returned by the method linearConstraintsEnd().
Weighted will add constraints sorted by their weights. This is only meaningful if the maximum number ...
CoefficientsIteratorType coefficientsBegin() const
Get the begin iterator to the set of coefficients for the indicator variables.
CoefficientsIteratorType coefficientsEnd() const
Get the end iterator to the set of coefficients for the indicator variables.
bool integerConstraintFactorVar_
Use integer constraints for factor variables.
marray::Marray< SolverIndexType > addLocalPolytopeFactorConstraintCacheFactorLPVariableIDs_
Lookup table for the factor lp variable ids required by the LPInferenceBase::addLocalPolytopeFactorCo...
Provides implementation for class LinearConstraint.
LPInferenceTraitsType::AccumulationType AccumulationType
Typedef of the Accumulation type.
SolverIndexType numFactorsLPVariables_
The number of lp variables for the factors of the graphical model.
std::vector< std::map< const IndicatorVariableType, SolverIndexType > > transferedFactorsLPVariablesIndicesLookupTable_
Lookup table for the lp variable indices of each transferable factor.
std::multimap< double, InactiveConstraintFactorConstraintPairType > SortedViolatedConstraintsListType
Typedef of the map type used to store a set of violated constraints sorted by their weights...
Functor used to access the method indicatorVariablesOrderEnd() of the underlying linear constraint fu...
Functor used to access the method challengeRelaxed() of the underlying linear constraint function of ...
bool isTransferable_
Storage for the return value of the LPFunctionTransfer::isTransferable() method.
bool nameConstraints_
Create unique names for the linear constraints added to the model (might be helpful for debugging mod...
InferenceTermination infer_impl(VISITOR_TYPE &visitor)
The implementation of the inference method.
LP_INFERENCE_BASE_TYPE::SortedViolatedConstraintsListType * sortedViolatedConstraintsList_
Storage for the violated linear constraints sorted by their weights. Only used when LPInferenceBase::...
std::vector< SolverIndexType > nodesLPVariablesOffset_
The offsets for the indices of the lp variables for each node of the graphical model.
Functor used to access the method challenge() of the underlying linear constraint function of a graph...
Functor to call LPFunctionTransfer::getSlackVariablesObjectiveCoefficients() for a factor of the grap...
LP_INFERENCE_BASE_TYPE::IntegerSolutionSubsequenceIterator labelingBegin_
Iterator used to iterate over the current solution.
virtual InferenceTermination arg(std::vector< LabelType > &x, const size_t N=1) const
Get the current argument.
LinearConstraint< ValueType, IndexType, LabelType > LinearConstraintType
Typedef of the opengm::LinearConstraint class with appropriate template parameter. Used to represent linear constraints.
Functor to call LPFunctionTransfer::isTransferable() for a factor of the graphical model...
InferenceTermination infer_impl_selectIterations(VISITOR_TYPE &visitor)
Helper function for LPInferenceBase::infer_impl to select the use infinite iterations template parame...
IndexType addLocalPolytopeFactorConstraintCachePreviousFactorID_
Cache for the function LPInferenceBase::addLocalPolytopeFactorConstraint. It is used to store the fac...
void operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE &linearConstraintFunction)
Operator used to access the method challengeRelaxed() of the underlying linear constraint function of...
bool useSoftConstraints_
If constraint factors are present in the model add them as soft constraints e.g. treat them as normal...
Functor used to access the method indicatorVariablesOrderBegin() of the underlying linear constraint ...
ChallengeHeuristic
This enum defines the heuristic by which the violated constraints are added to the LP/MIP model...
const Parameter parameter_
Parameter which stores the settings for the inference.
void checkInactiveConstraint(const ConstraintStorage &constraint, double &weight) const
Check if a given linear constraint from the local polytope constraints is violated.
RelaxedSolutionSubsequenceIterator labelingBegin_
Iterator used to iterate over the current solution.
LinearConstraintType::LinearConstraintOperatorValueType operator_
The operator type used to compare the left hand side of the constraint against the right hand side (<...
void addIndicatorVariableConstraints(const IndexType factor, const IndicatorVariableType &indicatorVariable, const SolverIndexType indicatorVariableLPVariable, const bool addToModel)
Add constraints for an indicator variable to the lp model.
Provides implementation for class SubsequenceIterator.
Functor used to access the method challenge() of the underlying linear constraint function of a graph...
void fillLinearConstraintLPVariablesSubsequenceIndices()
Fill the variable LPInferenceBase::linearConstraintLPVariablesSubsequenceIndices_ with the appropriat...
SubsequenceIterator< SolverSolutionIteratorType, typename std::vector< size_t >::const_iterator > RelaxedSolutionSubsequenceIterator
Typedef of the iterator type used to iterate over a subset of the computed solution. This iterator type is used to challenge the linear constraint functions present in the model. Only used when the problem is solved as a LP.
Random will add violated constraints in a random order.
ValueType
This enum defines the operator type for the linear constraint.
void operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE &linearConstraintFunction)
Operator used to access the method challengeRelaxed() of the underlying linear constraint function of...
std::vector< LinearConstraintType > LinearConstraintsContainerType
Defines the linear constraints container type which is used to store multiple linear constraints...
Parameter class for opengm::LPInferenceBase.
SolverIndexType numNodesLPVariables_
The number of lp variables for the nodes of the graphical model.
void addLocalPolytopeConstraints()
Add all constraints to the lp model which are required by the local polytope relaxation.
void operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE &linearConstraintFunction)
Operator used to access the method challenge() of the underlying linear constraint function of a grap...
void operator()(const LINEAR_CONSTRAINT_FUNCTION_TYPE &linearConstraintFunction)
Operator used to access the method challenge() of the underlying linear constraint function of a grap...
LP_INFERENCE_BASE_TYPE::IndexType linearConstraintID_
Index of the linear constraint factor.
virtual const GraphicalModelType & graphicalModel() const
Get graphical model.
Traits class for lp inference classes.
IndexType linearConstraintID_
Index of the linear constraint factor.
Helper struct to distinguish between linear constraint functions and other function types...
LP_INFERENCE_BASE_TYPE::SortedViolatedConstraintsListType * sortedViolatedConstraintsList_
Storage for the violated linear constraints sorted by their weights. Only used when LPInferenceBase::...
InferenceTermination infer_impl_selectRelaxation(VISITOR_TYPE &visitor)
Helper function for LPInferenceBase::infer_impl to select the relaxation template parameter...
LP_INFERENCE_BASE_TYPE::ValueType tolerance_
The tolerance used for the method challengeRelaxed() of the underlying linear constraint function of ...
std::pair< IndexType, const LinearConstraintType * > FactorIndexConstraintPointerPairType
Typedef of the pair type used to store a pointer to a linear constraint in combination with the linea...
std::vector< IndexType > transferableFactors_
List of all transferable factors.
Functor to call LPFunctionTransfer::getIndicatorVariables() for a factor of the graphical model...
static void addAllViolatedLinearConstraintsRelaxedFunctor_impl(AddAllViolatedLinearConstraintsRelaxedFunctor &myself, const FUNCTION_TYPE &function)
Actual access to the method challengeRelaxed() of the underlying linear constraint function of a grap...
LogicalOperatorType getLogicalOperatorType() const
Get the logical operator type of the indicator variable.
bool violatedConstraintAdded_
Indicator used to tell if at least one constraint was added to the LP/MIP model.
std::vector< std::map< const IndicatorVariableType, SolverIndexType > > linearConstraintsLPVariablesIndicesLookupTable_
Lookup table for the lp variable indices of each linear constraint.
Define a linear constraint for a set of indicatorVariables.
std::vector< SolverValueType > coefficients_
The coefficients for the variables of the LP/MIP model which are used in the constraint.
bool inferenceStarted_
Tell if inference was already started.
std::vector< SolverIndexType > factorsLPVariablesOffset_
The offsets for the indices of the lp variables for each factor of the graphical model.
LinearConstraintType::VariableLabelPairsIteratorType VariableLabelPairsIteratorType
Typedef of the iterator type used to iterate over a set of varible label pairs used within an indicat...
OpenGM runtime error.
Definition: opengm.hxx:100
void resize(ShapeIterator, ShapeIterator, const T &=T())
Resize (existing entries are preserved, new entries are initialized).
Definition: marray.hxx:3886
LinearConstraintsIteratorType linearConstraintsBegin_
Storage for the iterator returned by the method linearConstraintsBegin().
IntegerSolutionSubsequenceIterator labelingBegin_
Iterator used to iterate over the current solution.
Helper struct to distinguish between linear constraint functions and other function types...
T abs(const T &x)
Definition: opengm.hxx:111
std::pair< InactiveConstraintsListIteratorType, FactorIndexConstraintPointerPairType > InactiveConstraintFactorConstraintPairType
Typedef of the pair type used to store a pointer to an inactive constraint of the local polytope cons...
InferenceTermination
Definition: inference.hxx:24
std::vector< std::vector< size_t > > linearConstraintLPVariablesSubsequenceIndices_
The indices of the subset of the solution variables which are relevant for each linear constraint...