OpenGM  2.3.x
Discrete Graphical Model Library
primal_lpbound.hxx
Go to the documentation of this file.
1 /*
2  * primal_lpbound.hxx
3  *
4  * Created on: Jan 31, 2013
5  * Author: bsavchyn
6  */
7 
8 #ifndef PRIMAL_LPBOUND_HXX_
9 #define PRIMAL_LPBOUND_HXX_
10 #include <limits>
11 #include <algorithm>
15 
16 namespace opengm
17 {
18 
19 using trws_base::FactorWrapper;
20 using trws_base::VariableToFactorMapping;
21 
22 /*
23  * Restriction of the code: unary and pairwise factors only. Extension to higher order possible (in future)
24  *
25  * Usage:
26  * PrimalLPBound<GM, Minimizer> bound(gm);
27  * std::vector<double> var(10, 0.1);
28  * bound.setVariable(varIndex,var.begin());
29  * bound.setVariable(.... )
30  * ...
31  * double optimalValue=bound.getTotalValue();
32  */
33 
34 template<class ValueType>
36 {
37  PrimalLPBound_Parameter(ValueType relativePrecision,
38  size_t maxIterationNumber)
39  :relativePrecision_(relativePrecision),
40  maxIterationNumber_(maxIterationNumber){};
41 
42  ValueType relativePrecision_;
44 };
45 
60 
61 template <class GM,class ACC>
63 {
64 public:
66  typedef typename Solver::floatType ValueType;
67  typedef std::vector<ValueType> UnaryFactor;
68  typedef typename GM::IndexType IndexType;
69  typedef typename GM::LabelType LabelType;
70 
71  static const IndexType InvalidIndex;
72  static const ValueType ValueTypeNan;
73 
75 
77 
78  template<class ValueIterator>
79  void setVariable(IndexType var, ValueIterator inputBegin);
80  template<class ValueIterator>
81  void getVariable(IndexType var, ValueIterator outputBegin);//memory has to be allocated in advance
82 
83  ValueType getTotalValue(); // calls getFactorValue() and getVariableValue() and add them. Buffered
84  ValueType getFactorValue(IndexType factorId);//pairwise factor factorId. Buffering of the current value is performed
85  ValueType getVariableValue(IndexType varId); //inner product. Buffered
86  template<class Matrix>
87  ValueType getFactorVariable(IndexType factorId, Matrix& matrix); //pairwise factor factorId, buffering of the solution is performed
88 
89  void ResetBuffer(){_bufferedValues(_gm.numberOfFactors(),ValueTypeNan); _totalValue=ValueTypeNan;}//reset buffer, if you changed potentials of gm and want to take this fact into account
90  bool IsValueBuffered(IndexType factorId)const{OPENGM_ASSERT(factorId<_bufferedValues.size()); return (_bufferedValues[factorId] != ValueTypeNan);}
91  bool IsFactorVariableBuffered(IndexType factorId)const{return _lastActiveSolver==factorId;}
92  static void CheckDuplicateUnaryFactors(const GM& gm);
93 private:
94  void _checkPWFactorID(IndexType factorId,const std::string& message_prefix=std::string());
95  const GM& _gm;
96  Solver _solver;
97  std::vector<UnaryFactor> _unaryFactors;
98  VariableToFactorMapping<GM> _mapping;
99 
100  std::vector<ValueType> _bufferedValues;
101  IndexType _lastActiveSolver;
102  ValueType _totalValue;
103 };
104 
105 template <class GM,class ACC>
107 {
108  std::vector<IndexType> numOfunaryFactors(gm.numberOfVariables(),0);
109  for (IndexType factorId=0;factorId<gm.numberOfFactors();++factorId)
110  {
111  if (gm[factorId].numberOfVariables()!=1)
112  continue;
113 
114  numOfunaryFactors[gm[factorId].variableIndex(0)]++;
115  }
116 
117  IndexType moreCount=std::count_if(numOfunaryFactors.begin(),numOfunaryFactors.end(),std::bind2nd(std::greater<IndexType>(),1));
118  if (moreCount!=0)
119  throw std::runtime_error("PrimalLPBound::CheckDuplicateUnaryFactors: all variables must have not more then a single associated unary factor!");
120 }
121 
122 template <class GM,class ACC>
123 const typename PrimalLPBound<GM,ACC>::IndexType PrimalLPBound<GM,ACC>::InvalidIndex=std::numeric_limits<IndexType>::max();
124 
125 template <class GM,class ACC>
126 const typename PrimalLPBound<GM,ACC>::ValueType PrimalLPBound<GM,ACC>::ValueTypeNan=std::numeric_limits<ValueType>::max();
127 
128 template <class GM,class ACC>
129 PrimalLPBound<GM,ACC>::PrimalLPBound(const GM& gm,const Parameter& param):
130 _gm(gm),
131 _solver(
132 #ifdef TRWS_DEBUG_OUTPUT
133  std::cerr,
134 #endif
135  param.relativePrecision_,param.maxIterationNumber_),
136 _unaryFactors(gm.numberOfVariables()),
137 _mapping(gm),
138 _bufferedValues(gm.numberOfFactors(),ValueTypeNan),
139 _lastActiveSolver(InvalidIndex),
140 _totalValue(ValueTypeNan)
141 {
143  //allocating memory for the unary factors
144  for (size_t i=0;i<_unaryFactors.size();++i)
145  _unaryFactors[i].assign(_gm.numberOfLabels(i),0);
146 }
147 
148 template <class GM,class ACC>
149 template<class Iterator>
150 void PrimalLPBound<GM,ACC>::setVariable(IndexType var, Iterator inputBegin)
151 {
152  OPENGM_ASSERT(var < _gm.numberOfVariables());
153  _totalValue=ValueTypeNan;
154  std::copy(inputBegin,inputBegin+_unaryFactors[var].size(),_unaryFactors[var].begin());
155 
156  //making invalid factors connected to the variable var
157  IndexType numOfFactors=_gm.numberOfFactors(var);
158  for (IndexType i=0;i<numOfFactors;++i)
159  {
160  IndexType factorId=_gm.factorOfVariable(var,i);
161  OPENGM_ASSERT(factorId < _gm.numberOfFactors() );
162  _bufferedValues[factorId] = ValueTypeNan;
163  }
164 }
165 
166 template <class GM,class ACC>
167 template<class Iterator>
168 void PrimalLPBound<GM,ACC>::getVariable(IndexType var, Iterator outputBegin)
169 {
170  OPENGM_ASSERT(var < _gm.numberOfVariables());
171  std::copy(_unaryFactors[var].begin(),_unaryFactors[var].end(),outputBegin);
172 }
173 
174 template <class GM,class ACC>
175 void PrimalLPBound<GM,ACC>::_checkPWFactorID(IndexType factorId, const std::string& message_prefix)
176 {
177  OPENGM_ASSERT(factorId < _gm.numberOfFactors());
178  if (_gm[factorId].numberOfVariables() !=2 )
179  std::runtime_error(message_prefix + "Function can be applied to second order factors only!");
180 }
181 
182 template <class GM,class ACC>
184 {
185  _checkPWFactorID(factorId,"PrimalLPBound::getFactorValue(): ");
186 
187  if (_bufferedValues[factorId] == ValueTypeNan)
188  {
189  const typename GM::FactorType& factor=_gm[factorId];
190  IndexType var0=factor.variableIndex(0),
191  var1=factor.variableIndex(1);
192  _solver.Init(_unaryFactors[var0].size(),_unaryFactors[var1].size(),FactorWrapper<typename GM::FactorType>(factor));
193  _bufferedValues[factorId]=_solver.Solve(_unaryFactors[var0].begin(),_unaryFactors[var1].begin());
194  _lastActiveSolver=factorId;
195  }
196 
197  return _bufferedValues[factorId];
198 }
199 
200 template <class GM,class ACC>
201 template<class Matrix>
203 {
204  _checkPWFactorID(factorId,"PrimalLPBound::getFactorVariable(): ");
205 
206  if (_lastActiveSolver!=factorId)
207  getFactorValue(factorId);
208 
209  return _solver.GetSolution(&matrix);
210 }
211 
212 template <class GM,class ACC>
214 {
215  OPENGM_ASSERT(varId < _gm.numberOfVariables());
216  OPENGM_ASSERT(varId < _unaryFactors.size());
217  IndexType factorId=_mapping(varId);
218  OPENGM_ASSERT(_mapping(varId) < _gm.numberOfFactors());
219  if (factorId==VariableToFactorMapping<GM>::InvalidIndex)
220  return (ValueType)0;
221 
222  if (_bufferedValues[factorId] != ValueTypeNan)
223  return _bufferedValues[factorId];
224 
225  ValueType sum=0;
226  const UnaryFactor& uf=_unaryFactors[varId];
227  OPENGM_ASSERT(_gm.numberOfLabels(varId)==uf.size());
228  OPENGM_ASSERT(_gm.numberOfLabels(varId)>0);
229  const typename GM::FactorType& f=_gm[factorId];
230  for (LabelType i=0;i<uf.size();++i)
231  sum+=uf[i]*f(&i);
232 
233  _bufferedValues[factorId]=sum;
234  return sum;
235 }
236 
237 template <class GM,class ACC>
239 {
240  if (_totalValue==ValueTypeNan)
241  {
242  _totalValue=0;
243  for (IndexType factorId=0;factorId<_gm.numberOfFactors();++factorId)
244  {
245  const typename GM::FactorType& f=_gm[factorId];
246  switch (f.numberOfVariables())
247  {
248  case 1: _totalValue+=getVariableValue(f.variableIndex(0)); break;
249  case 2: _totalValue+=getFactorValue(factorId);break;
250  default: throw std::runtime_error("PrimalLPBound::getTotalValue(): Only factors of order <= 2 are supported!");
251  }
252  }
253  }
254  return _totalValue;
255 }
256 
257 }
258 #endif /* PRIMAL_LPBOUND_HXX_ */
void setVariable(IndexType var, ValueIterator inputBegin)
The OpenGM namespace.
Definition: config.hxx:43
void getVariable(IndexType var, ValueIterator outputBegin)
STL namespace.
TransportSolver::TransportationSolver< ACC, FactorWrapper< typename GM::FactorType > > Solver
#define OPENGM_ASSERT(expression)
Definition: opengm.hxx:77
Solver::floatType ValueType
static void CheckDuplicateUnaryFactors(const GM &gm)
PrimalLPBound_Parameter< ValueType > Parameter
ValueType getVariableValue(IndexType varId)
ValueType getFactorVariable(IndexType factorId, Matrix &matrix)
std::vector< ValueType > UnaryFactor
static const ValueType ValueTypeNan
static const IndexType InvalidIndex
PrimalLPBound_Parameter(ValueType relativePrecision, size_t maxIterationNumber)
bool IsFactorVariableBuffered(IndexType factorId) const
PrimalLPBound(const GM &gm, const Parameter &param=Parameter(Solver::floatTypeEps, Solver::defaultMaxIterationNumber))
[class primallpbound] PrimalLPBound - estimating primal local polytope bound and feasible primal solu...
bool IsValueBuffered(IndexType factorId) const
ValueType getFactorValue(IndexType factorId)