OpenGM  2.3.x
Discrete Graphical Model Library
trws_decomposition.hxx
Go to the documentation of this file.
1 #ifndef TRWS_DECOMPOSITION_HXX_
2 #define TRWS_DECOMPOSITION_HXX_
3 #include <iostream>
4 #include <list>
5 #include <vector>
6 #include <utility>
7 #include <stdexcept>
8 #include <algorithm>
11 
12 #ifdef TRWS_DEBUG_OUTPUT
14 #endif
15 
16 namespace opengm {
17 namespace trws_base{
18 
19 #ifdef TRWS_DEBUG_OUTPUT
20 using OUT::operator <<;
21 #endif
22 
23 template<class GM>
25 {
26 public:
27  typedef typename GM::IndexType IndexType;
28  typedef typename GM::LabelType LabelType;
29  typedef std::vector<IndexType> IndexList;
30  typedef opengm::GraphicalModelDecomposition::SubVariable SubVariable;
31  typedef opengm::GraphicalModelDecomposition::SubVariableListType SubVariableListType;
32  Decomposition(const GM& gm,IndexType numSubModels=0)
33  :_numberOfModels(0),_gm(gm)
34  { // Reserve memory
35  _variableLists.reserve(numSubModels);
36  _pwFactorLists.reserve(numSubModels);
37  };
38  virtual ~Decomposition()=0;
39 
40  virtual IndexType getNumberOfSubModels()const{return _numberOfModels;}
41  virtual const IndexList& getVariableList(IndexType subModelId)const {return _variableLists[subModelId];}
42  virtual const IndexList& getFactorList(IndexType subModelId)const {return _pwFactorLists[subModelId];}
43 
44 #ifdef TRWS_DEBUG_OUTPUT
45  virtual void PrintTestData(std::ostream& fout);
46 #endif
47 
48  virtual void ComputeVariableDecomposition(std::vector<SubVariableListType>* plist)const;
49 
50  static void CheckUnaryFactors(const GM& gm);
51  static void CheckDuplicateUnaryFactors(const GM& gm);
52  /*static*/ void CheckForIsolatedNodes(const GM& gm);
53 protected:
54  typedef std::pair<IndexType,IndexType> Edge;//first=factorId, second=neighborNodeId
55  typedef std::list<Edge> EdgeList;
56  typedef std::vector<EdgeList> NodeList;
57 
58  IndexType _numberOfModels;
59  std::vector<IndexList> _variableLists;
60  std::vector<IndexList> _pwFactorLists;
61  const GM& _gm;
62 
63  IndexType _addSubModel();
64  void _addSubFactor(const IndexType& factorId);
65  void _addSubVariable(const IndexType& variableId);
66  static void _CreateNodeList(const GM& gm,NodeList* pnodeList);
67 };
68 
69 /*
70  * So far oriented to 2-nd order factors only!
71  */
72 template<class GM>
74 {
75 public:
77  typedef typename parent::IndexType IndexType;
78  typedef typename parent::LabelType LabelType;
79  typedef typename parent::IndexList IndexList;
80  typedef typename parent::SubVariable SubVariable;
82 
83  MonotoneChainsDecomposition(const GM& gm,IndexType numSubModels=0);
84 protected:
85  void _GetMaximalMonotoneSequence(typename parent::NodeList* pnodesList,IndexType start);
86 };
87 
88 template<class GM>
89 class GridDecomposition : public Decomposition<GM>
90 {
91 public:
93  typedef typename parent::IndexType IndexType;
94  typedef typename parent::LabelType LabelType;
95  typedef typename parent::IndexList IndexList;
96  typedef typename parent::SubVariable SubVariable;
98 
99  GridDecomposition(const GM& gm,IndexType numSubModels=0);
100  IndexType xsize()const{return _xsize;}
101  IndexType ysize()const{return _ysize;}
102 private:
103  IndexType _xsize, _ysize;
104 protected:
105  void _computeGridSizes();
106  void _CheckGridModel();
108 
109  IndexType _xysize()const{return _xsize*_ysize;}
110  IndexType _pwrowsize()const{return 2*_xsize-1;}
111  IndexType _pwIndexRow(IndexType x,IndexType y)const;
112  IndexType _pwIndexCol(IndexType x,IndexType y)const;
113  IndexType _varIndex(IndexType x,IndexType y)const{return x+_xsize*y;}
114  void _getRow(IndexType y,IndexList* plist)const;
115  void _getCol(IndexType x,IndexList* plist)const;
116  void _getPWRow(IndexType y, IndexList* plist)const;
117  void _getPWCol(IndexType x,IndexList* plist)const;
118 };
119 
120 template<class GM>
122 {
123 public:
125  typedef typename parent::IndexType IndexType;
126  typedef typename parent::LabelType LabelType;
127  typedef typename parent::IndexList IndexList;
130 
131  EdgeDecomposition(const GM& gm):parent(gm)
132  {
133  //parent::CheckUnaryFactors(gm);
135  parent::_numberOfModels=gm.numberOfFactors()-gm.numberOfVariables();
136  //bild variable and factor lists
139 
140  IndexType pwFid=0;
141  for (IndexType fId=0;fId<gm.numberOfFactors();++fId)
142  {
143  if (gm[fId].numberOfVariables()==1) continue;
144  if ((gm[fId].numberOfVariables()>2) || (gm[fId].numberOfVariables()==0))
145  std::runtime_error("EdgeDecomposition<GM>::EdgeDecomposition(): Only factors of order 1 or 2 are supported!");
146 
147  //factor of order 2:
148  parent::_variableLists[pwFid][0]=gm[fId].variableIndex(0);
149  parent::_variableLists[pwFid][1]=gm[fId].variableIndex(1);
150  parent::_pwFactorLists[pwFid][0]=fId;
151  ++pwFid;
152  }
153  }
154 };
155 
156 
157 #ifdef TRWS_DEBUG_OUTPUT
158 template <class SubFactor>
159 struct printSubFactor
160 {
161  printSubFactor(std::ostream& out):_out(out){};
162  void operator()(const SubFactor& a)
163  {
164  _out << "("<<a.subModelId_ <<","<< a.subFactorId_ <<")"<<", ";
165  }
166 
167 private:
168  std::ostream& _out;
169 };
170 #endif
171 
172 #ifdef TRWS_DEBUG_OUTPUT
173 template <class SubVariable>
174 struct printSubVariable
175 {
176  printSubVariable(std::ostream& out):_out(out){};
177  void operator()(const SubVariable& a)
178  {
179  _out << "("<<a.subModelId_ <<","<< a.subVariableId_ <<")"<<", ";
180  }
181 
182 private:
183  std::ostream& _out;
184 };
185 #endif
186 //-------------------------IMPLEMENTATION------------------------------------------------
187 
188 template<class GM>
189 Decomposition<GM>::~Decomposition<GM>()
190 {}
191 
192 #ifdef TRWS_DEBUG_OUTPUT
193 template<class GM>
194 void Decomposition<GM>::PrintTestData(std::ostream& fout)
195 {
196  fout <<"_numberOfModels;" << _numberOfModels<<std::endl;
197  fout <<"_variableLists:"<<_variableLists<<std::endl;
198  fout <<"_pwFactorLists:"<<_pwFactorLists<<std::endl;
199 }
200 #endif
201 
202 template<class GM>
204 :parent(gm,numSubModels)
207 
208  typename parent::NodeList nodeList(gm.numberOfVariables());
209  parent::_CreateNodeList(gm,&nodeList);
210 
211  for (IndexType start=0;start<nodeList.size();++start)
212  while (!nodeList[start].empty())
214  _GetMaximalMonotoneSequence(&nodeList,(IndexType)start);
215  }
216 }
217 
218 template<class GM>
220 :parent(gm,numSubModels)
221  {
222  //estimate xsize and ysize
224  parent::_numberOfModels=_xsize+_ysize;
225  //bild variable and factor lists
227  }
228 
229 template<class Factor>
230 bool dependsOnVariable(const Factor& f,typename Factor::IndexType varId)
231 {
232  return (std::find(f.variableIndicesBegin(),f.variableIndicesEnd(),varId) != f.variableIndicesEnd());
233 }
234 
235 template<class GM>
237 {
238  IndexType numberOfVars=parent::_gm.numberOfVariables();
239  IndexType numTotal=parent::_gm.numberOfFactors();
240  std::vector<IndexType> ind;
241  for (IndexType f=numberOfVars;f<numTotal;++f)
242  {
243  std::vector<IndexType> ind(parent::_gm[f].numberOfVariables());
244  if (ind.size()!=2)
245  throw std::runtime_error("GridDecomposition<GM>::_computeGridSizes():Incorrect grid structure! : only pairwise factors are supported !=0");
246  parent::_gm[f].variableIndices(ind.begin());
247  if (ind[1]<=ind[0])
248  throw std::runtime_error("GridDecomposition<GM>::_computeGridSizes():Incorrect grid structure! : pairwise factors should be oriented from smaller to larger variable indices !=0");
249 
250  if (ind[1]-ind[0]!=1)
251  {
252  _xsize=ind[1]-ind[0];
253  _ysize=numberOfVars/_xsize;
254  if (numberOfVars%_xsize !=0)
255  throw std::runtime_error("GridDecomposition<GM>::_computeGridSizes():Incorrect grid structure! : numberOfVars%xsize !=0");
256  break;
257  }else if (f==numTotal-1)
258  {
259  _xsize=numberOfVars;
260  _ysize=1;
261  break;
262  };
263 
264  };
265  _CheckGridModel();
266 };
267 
268 template<class GM>
270 {
271  bool incorrect=false;
272  //check vertical structure
273  for (IndexType y=0;y<_ysize;++y)
274  for (IndexType x=0;x<_xsize;++x)
275  {
276  if (y<_ysize-1)
277  {
278  IndexType ind=_pwIndexCol(x,y);
279  if (!dependsOnVariable(parent::_gm[ind],_varIndex(x,y)) || !dependsOnVariable(parent::_gm[ind],_varIndex(x,y+1)) )
280  incorrect=true;
281  };
282 
283  if ((x<_xsize-1))
284  {
285  IndexType ind=_pwIndexRow(x,y);
286  if (!dependsOnVariable(parent::_gm[ind],_varIndex(x,y)) || !dependsOnVariable(parent::_gm[ind],_varIndex(x+1,y)))
287  incorrect=true;
288  }
289 
290  if (incorrect)
291  throw std::runtime_error("GridDecomposition::_CheckGridModel():Incorrect grid structure!");
292  };
293 };
294 
295 
296 template<class GM>
298 {
299  parent::_variableLists.resize(parent::_numberOfModels);
300  parent::_pwFactorLists.resize(parent::_numberOfModels);
301  for (IndexType x=0;x<_xsize;++x)
302  {
303  _getCol(x,&parent::_variableLists[x]);
304  _getPWCol(x,&parent::_pwFactorLists[x]);
305  }
306 
307  for (IndexType y=0;y<_ysize;++y)
308  {
309  _getRow(y,&parent::_variableLists[_xsize+y]);
310  _getPWRow(y,&parent::_pwFactorLists[_xsize+y]);
311  };
312 }
313 
314 //make the vector of nodes with lists of edges. Each edge is present only once - in the list of the node with the smaller index
315 template<class GM>
316 void Decomposition<GM>::_CreateNodeList(const GM & gm,NodeList* pnodeList)
317 {
318  NodeList& varList=*pnodeList;
319  varList.resize(gm.numberOfVariables());
320  for (IndexType factorId=0;factorId<gm.numberOfFactors();++factorId)
321  {
322  if (gm[factorId].numberOfVariables()>2)
323  throw std::runtime_error("CreateEdgeList(): Only factors up to order 2 are supported!");
324 
325  if (gm[factorId].numberOfVariables()==1) continue;
326  std::vector<IndexType> varIndices(gm[factorId].variableIndicesBegin(),gm[factorId].variableIndicesEnd());
327  if (varIndices[0] < varIndices[1])
328  varList[varIndices[0]].push_back(std::make_pair(factorId,varIndices[1]));
329  else
330  varList[varIndices[1]].push_back(std::make_pair(factorId,varIndices[0]));
331  }
332 }
333 
334 template<class GM>
336 {
337  _variableLists.push_back(IndexList());
338  _pwFactorLists.push_back(IndexList());
339  _numberOfModels++;
340  return IndexType(_numberOfModels-1);
341 };
342 
343 template<class GM>
345  {
346  _pwFactorLists[_numberOfModels-1].push_back(factorId);
347  }
348 
349 template<class GM>
351 {
352  _variableLists[_numberOfModels-1].push_back(variableId);
353 }
354 
355 template<class GM>
357 {
358  assert(start < pnodeList->size());
359  typename parent::NodeList& nodeList=*pnodeList;
360  if (!nodeList[start].empty())
361  parent::_addSubVariable(start);
362  else return;
363 
364  while ( !nodeList[start].empty() )
365  {
366  typename parent::EdgeList::iterator it= nodeList[start].begin();
367  parent::_addSubVariable(it->second);
368  parent::_addSubFactor(it->first);
369  IndexType tmp=it->second;
370  nodeList[start].erase(it);
371  start=tmp;
372  }
373 
374 }
375 
376 template<class GM>
378 {
379  bool error=false;
380  for (IndexType factorId=0;factorId<gm.numberOfFactors();++factorId)
381  {
382  std::vector<IndexType> varIndices(gm[factorId].variableIndicesBegin(),gm[factorId].variableIndicesEnd());
383  if (gm[factorId].numberOfVariables()==1)
384  {
385  if ( (factorId < gm.numberOfVariables()) && (varIndices[0]==factorId))
386  continue;
387  else error=true;
388  }else if (factorId < gm.numberOfVariables())
389  error=true;
390 
391  if (error)
392  throw std::runtime_error("Decomposition<GM>::CheckUnaryFactors(): Each variable has to have a unique unary factor, which moreover has the same index!");
393  }
394 }
395 
396 template<class GM>
398 {
399  std::vector<IndexType> numOfunaryFactors(gm.numberOfVariables(),(IndexType)0);
400  for (IndexType factorId=0;factorId<gm.numberOfFactors();++factorId)
401  {
402  if (gm[factorId].numberOfVariables()!=1)
403  continue;
404 
405  numOfunaryFactors[gm[factorId].variableIndex(0)]++;
406  }
407 
408  IndexType oneCount=std::count(numOfunaryFactors.begin(),numOfunaryFactors.end(),(IndexType)1);
409  exception_check(oneCount==numOfunaryFactors.size(),"Decomposition::CheckDuplicateUnaryFactors: all variables must have a unique associated unary factor!");
410 }
411 
412 template<class GM>
414 {
415  for (IndexType varId=0;varId<gm.numberOfVariables();++varId)
416  {
417  bool isolatedNode=true;
418  for (IndexType localId=0;localId<gm.numberOfFactors(varId);++localId)
419  {
420  if (gm[gm.factorOfVariable(varId,localId)].numberOfVariables()>1)
421  isolatedNode=false;
422  }
423  if (isolatedNode==true)
424  {
425  _addSubModel();
426  _addSubVariable(varId);
427 //TODO:TEST throw std::runtime_error("Decomposition<GM>::CheckForIsolatedNodes(): Procesing of isolated nodes is not supported!");
428  }
429  }
430 }
431 
432 template<class GM>
433 void Decomposition<GM>::ComputeVariableDecomposition(std::vector<SubVariableListType>* plist)const
434 {
435  plist->resize(_gm.numberOfVariables());
436  for (IndexType modelId=0;modelId<_numberOfModels;++modelId)
437  for (IndexType varId=0;varId<_variableLists[modelId].size();++varId)
438  (*plist)[_variableLists[modelId][varId]].push_back(SubVariable(modelId,varId));
439 }
440 
441 template<class GM>
444 {
445  assert(x<_xsize-1);
446  assert(y<_ysize);
447  if ((y==_ysize-1) && (x!=0)) return _pwIndexRow(0,y) + x;
448  return _xysize()+y*_pwrowsize()+2*x;
449 };
450 template<class GM>
453 {
454  if (x==_xsize-1) return _pwIndexCol(x-1,y)+1;
455  return _pwIndexRow(x,y)+1;
456 };
457 
458 template<class GM>
461 {
462  plist->resize(_xsize);
463  (*plist)[0]=_varIndex(0,y);
464  for (IndexType i=1;i<_xsize;++i)
465  (*plist)[i]=(*plist)[i-1]+1;
466 };
467 
468 template<class GM>
471 {
472  plist->resize(_ysize);
473  (*plist)[0]=_varIndex(x,0);
474  for (IndexType i=1;i<_ysize;++i)
475  (*plist)[i]=(*plist)[i-1]+_xsize;
476 };
477 
478 template<class GM>
481 {
482  plist->resize(_xsize-1);
483  if (_xsize<=1)
484  return;
485  (*plist)[0]=_pwIndexRow(0,y);
486  IndexType step=2;
487  if (y==_ysize-1) step=1;
488  for (IndexType i=1;i<_xsize-1;++i)
489  (*plist)[i]=(*plist)[i-1]+step;
490 };
491 
492 template<class GM>
495 {
496  plist->resize(_ysize-1);
497  if (_ysize<=1)
498  return;
499 
500  (*plist)[0]=_pwIndexCol(x,0);
501  for (IndexType i=1;i<_ysize-1;++i)
502  (*plist)[i]=(*plist)[i-1]+_pwrowsize();
503 };
504 
505 
506 }//namespace trws_base
507 }//namespace opengm
508 
509 #endif /* DECOMPOSITIONTRWS_H_ */
The OpenGM namespace.
Definition: config.hxx:43
void exception_check(bool condition, const std::string &str)
Definition: utilities2.hxx:90
std::vector< IndexList > _pwFactorLists
parent::SubVariableListType SubVariableListType
IndexType _varIndex(IndexType x, IndexType y) const
returns an index of a column pairwise factor places to the down to var (x,y)
std::pair< IndexType, IndexType > Edge
bool dependsOnVariable(const Factor &f, typename Factor::IndexType varId)
std::vector< IndexList > _variableLists
void _addSubFactor(const IndexType &factorId)
virtual const IndexList & getVariableList(IndexType subModelId) const
static void CheckUnaryFactors(const GM &gm)
checks whether all variables have corresp. unary factor with the same index and vice versa ...
opengm::GraphicalModelDecomposition::SubVariableListType SubVariableListType
VariablesIteratorType variableIndicesBegin() const
std::vector< IndexType > IndexList
GridDecomposition(const GM &gm, IndexType numSubModels=0)
numSubModels - ESTIMATED number of submodels to optimize memory allocation
static void _CreateNodeList(const GM &gm, NodeList *pnodeList)
void _addSubVariable(const IndexType &variableId)
VariablesIteratorType variableIndicesEnd() const
Abstraction (wrapper class) of factors, independent of the function used to implement the factor...
GraphicalModelType::IndexType IndexType
virtual const IndexList & getFactorList(IndexType subModelId) const
IndexType _pwIndexRow(IndexType x, IndexType y) const
returns an index of a row pairwise factor places to the right to var (x,y)
static void CheckDuplicateUnaryFactors(const GM &gm)
virtual void ComputeVariableDecomposition(std::vector< SubVariableListType > *plist) const
void _GetMaximalMonotoneSequence(typename parent::NodeList *pnodesList, IndexType start)
opengm::GraphicalModelDecomposition::SubVariable SubVariable
IndexType _pwIndexCol(IndexType x, IndexType y) const
returns an index of a row pairwise factor places to the right to var (x,y)
virtual IndexType getNumberOfSubModels() const
void _getPWCol(IndexType x, IndexList *plist) const
return indexes of pairwise factors in the row
void _getRow(IndexType y, IndexList *plist) const
returns indexes of variables in the row
void _getCol(IndexType x, IndexList *plist) const
returns indexes of variables in the row
void _getPWRow(IndexType y, IndexList *plist) const
returns indexes of variables in the column
parent::SubVariableListType SubVariableListType
Decomposition(const GM &gm, IndexType numSubModels=0)
MonotoneChainsDecomposition(const GM &gm, IndexType numSubModels=0)
numSubModels - ESTIMATED number of submodels to optimize memory allocation