00001 #ifndef TRWS_DECOMPOSITION_HXX_
00002 #define TRWS_DECOMPOSITION_HXX_
00003 #include <iostream>
00004 #include <list>
00005 #include <vector>
00006 #include <utility>
00007 #include <stdexcept>
00008 #include <algorithm>
00009 #include <opengm/graphicalmodel/decomposition/graphicalmodeldecomposition.hxx>
00010 #include <opengm/inference/trws/utilities2.hxx>
00011
00012 #ifdef TRWS_DEBUG_OUTPUT
00013 #include <opengm/inference/trws/output_debug_utils.hxx>
00014 #endif
00015
00016 namespace trws_base{
00017
00018 #ifdef TRWS_DEBUG_OUTPUT
00019 using OUT::operator <<;
00020 #endif
00021
00022 template<class GM>
00023 class Decomposition
00024 {
00025 public:
00026 typedef typename GM::IndexType IndexType;
00027 typedef typename GM::LabelType LabelType;
00028 typedef std::vector<IndexType> IndexList;
00029 typedef opengm::GraphicalModelDecomposition::SubVariable SubVariable;
00030 typedef opengm::GraphicalModelDecomposition::SubVariableListType SubVariableListType;
00031 Decomposition(const GM& gm,IndexType numSubModels=0)
00032 :_numberOfModels(0),_gm(gm)
00033 {
00034 _variableLists.reserve(numSubModels);
00035 _pwFactorLists.reserve(numSubModels);
00036 };
00037 virtual ~Decomposition()=0;
00038
00039 virtual IndexType getNumberOfSubModels()const{return _numberOfModels;}
00040 virtual const IndexList& getVariableList(IndexType subModelId)const {return _variableLists[subModelId];}
00041 virtual const IndexList& getFactorList(IndexType subModelId)const {return _pwFactorLists[subModelId];}
00042
00043 #ifdef TRWS_DEBUG_OUTPUT
00044 virtual void PrintTestData(std::ostream& fout);
00045 #endif
00046
00047 virtual void ComputeVariableDecomposition(std::vector<SubVariableListType>* plist)const;
00048
00049 static void CheckUnaryFactors(const GM& gm);
00050 static void CheckDuplicateUnaryFactors(const GM& gm);
00051 static void CheckForIsolatedNodes(const GM& gm);
00052 protected:
00053 typedef std::pair<IndexType,IndexType> Edge;
00054 typedef std::list<Edge> EdgeList;
00055 typedef std::vector<EdgeList> NodeList;
00056
00057 IndexType _numberOfModels;
00058 std::vector<IndexList> _variableLists;
00059 std::vector<IndexList> _pwFactorLists;
00060 const GM& _gm;
00061
00062 IndexType _addSubModel();
00063 void _addSubFactor(const IndexType& factorId);
00064 void _addSubVariable(const IndexType& variableId);
00065 static void _CreateNodeList(const GM& gm,NodeList* pnodeList);
00066 };
00067
00068
00069
00070
00071 template<class GM>
00072 class MonotoneChainsDecomposition : public Decomposition<GM>
00073 {
00074 public:
00075 typedef Decomposition<GM> parent;
00076 typedef typename parent::IndexType IndexType;
00077 typedef typename parent::LabelType LabelType;
00078 typedef typename parent::IndexList IndexList;
00079 typedef typename parent::SubVariable SubVariable;
00080 typedef typename parent::SubVariableListType SubVariableListType;
00081
00082 MonotoneChainsDecomposition(const GM& gm,IndexType numSubModels=0);
00083 protected:
00084 void _GetMaximalMonotoneSequence(typename parent::NodeList* pnodesList,IndexType start);
00085 };
00086
00087 template<class GM>
00088 class GridDecomposition : public Decomposition<GM>
00089 {
00090 public:
00091 typedef Decomposition<GM> parent;
00092 typedef typename parent::IndexType IndexType;
00093 typedef typename parent::LabelType LabelType;
00094 typedef typename parent::IndexList IndexList;
00095 typedef typename parent::SubVariable SubVariable;
00096 typedef typename parent::SubVariableListType SubVariableListType;
00097
00098 GridDecomposition(const GM& gm,IndexType numSubModels=0);
00099 IndexType xsize()const{return _xsize;}
00100 IndexType ysize()const{return _ysize;}
00101 private:
00102 IndexType _xsize, _ysize;
00103 protected:
00104 void _computeGridSizes();
00105 void _CheckGridModel();
00106 void _initDecompositionLists();
00107
00108 IndexType _xysize()const{return _xsize*_ysize;}
00109 IndexType _pwrowsize()const{return 2*_xsize-1;}
00110 IndexType _pwIndexRow(IndexType x,IndexType y)const;
00111 IndexType _pwIndexCol(IndexType x,IndexType y)const;
00112 IndexType _varIndex(IndexType x,IndexType y)const{return x+_xsize*y;}
00113 void _getRow(IndexType y,IndexList* plist)const;
00114 void _getCol(IndexType x,IndexList* plist)const;
00115 void _getPWRow(IndexType y, IndexList* plist)const;
00116 void _getPWCol(IndexType x,IndexList* plist)const;
00117 };
00118
00119 #ifdef TRWS_DEBUG_OUTPUT
00120 template <class SubFactor>
00121 struct printSubFactor
00122 {
00123 printSubFactor(std::ostream& out):_out(out){};
00124 void operator()(const SubFactor& a)
00125 {
00126 _out << "("<<a.subModelId_ <<","<< a.subFactorId_ <<")"<<", ";
00127 }
00128
00129 private:
00130 std::ostream& _out;
00131 };
00132 #endif
00133
00134 #ifdef TRWS_DEBUG_OUTPUT
00135 template <class SubVariable>
00136 struct printSubVariable
00137 {
00138 printSubVariable(std::ostream& out):_out(out){};
00139 void operator()(const SubVariable& a)
00140 {
00141 _out << "("<<a.subModelId_ <<","<< a.subVariableId_ <<")"<<", ";
00142 }
00143
00144 private:
00145 std::ostream& _out;
00146 };
00147 #endif
00148
00149
00150 template<class GM>
00151 Decomposition<GM>::~Decomposition<GM>()
00152 {}
00153
00154 #ifdef TRWS_DEBUG_OUTPUT
00155 template<class GM>
00156 void Decomposition<GM>::PrintTestData(std::ostream& fout)
00157 {
00158 fout <<"_numberOfModels;" << _numberOfModels<<std::endl;
00159 fout <<"_variableLists:"<<_variableLists<<std::endl;
00160 fout <<"_pwFactorLists:"<<_pwFactorLists<<std::endl;
00161 }
00162 #endif
00163
00164 template<class GM>
00165 MonotoneChainsDecomposition<GM>::MonotoneChainsDecomposition(const GM& gm,IndexType numSubModels)
00166 :parent(gm,numSubModels)
00167 { parent::CheckDuplicateUnaryFactors(gm);
00168 parent::CheckForIsolatedNodes(gm);
00169
00170 typename parent::NodeList nodeList(gm.numberOfVariables());
00171 parent::_CreateNodeList(gm,&nodeList);
00172
00173 for (IndexType start=0;start<nodeList.size();++start)
00174 while (!nodeList[start].empty())
00175 { parent::_addSubModel();
00176 _GetMaximalMonotoneSequence(&nodeList,(IndexType)start);
00177 }
00178 }
00179
00180 template<class GM>
00181 GridDecomposition<GM>::GridDecomposition(const GM& gm,IndexType numSubModels)
00182 :parent(gm,numSubModels)
00183 {
00184
00185 _computeGridSizes();
00186 parent::_numberOfModels=_xsize+_ysize;
00187
00188 _initDecompositionLists();
00189 }
00190
00191 template<class Factor>
00192 bool dependsOnVariable(const Factor& f,typename Factor::IndexType varId)
00193 {
00194 return (std::find(f.variableIndicesBegin(),f.variableIndicesEnd(),varId) != f.variableIndicesEnd());
00195 }
00196
00197 template<class GM>
00198 void GridDecomposition<GM>::_computeGridSizes()
00199 {
00200 IndexType numberOfVars=parent::_gm.numberOfVariables();
00201 IndexType numTotal=parent::_gm.numberOfFactors();
00202 std::vector<IndexType> ind;
00203 for (IndexType f=numberOfVars;f<numTotal;++f)
00204 {
00205 std::vector<IndexType> ind(parent::_gm[f].numberOfVariables());
00206 if (ind.size()!=2)
00207 throw std::runtime_error("GridDecomposition<GM>::_computeGridSizes():Incorrect grid structure! : only pairwise factors are supported !=0");
00208 parent::_gm[f].variableIndices(ind.begin());
00209 if (ind[1]<=ind[0])
00210 throw std::runtime_error("GridDecomposition<GM>::_computeGridSizes():Incorrect grid structure! : pairwise factors should be oriented from smaller to larger variable indices !=0");
00211
00212 if (ind[1]-ind[0]!=1)
00213 {
00214 _xsize=ind[1]-ind[0];
00215 _ysize=numberOfVars/_xsize;
00216 if (numberOfVars%_xsize !=0)
00217 throw std::runtime_error("GridDecomposition<GM>::_computeGridSizes():Incorrect grid structure! : numberOfVars%xsize !=0");
00218 break;
00219 }else if (f==numTotal-1)
00220 {
00221 _xsize=numberOfVars;
00222 _ysize=1;
00223 break;
00224 };
00225
00226 };
00227 _CheckGridModel();
00228 };
00229
00230 template<class GM>
00231 void GridDecomposition<GM>::_CheckGridModel()
00232 {
00233 bool incorrect=false;
00234
00235 for (IndexType y=0;y<_ysize;++y)
00236 for (IndexType x=0;x<_xsize;++x)
00237 {
00238 if (y<_ysize-1)
00239 {
00240 IndexType ind=_pwIndexCol(x,y);
00241 if (!dependsOnVariable(parent::_gm[ind],_varIndex(x,y)) || !dependsOnVariable(parent::_gm[ind],_varIndex(x,y+1)) )
00242 incorrect=true;
00243 };
00244
00245 if ((x<_xsize-1))
00246 {
00247 IndexType ind=_pwIndexRow(x,y);
00248 if (!dependsOnVariable(parent::_gm[ind],_varIndex(x,y)) || !dependsOnVariable(parent::_gm[ind],_varIndex(x+1,y)))
00249 incorrect=true;
00250 }
00251
00252 if (incorrect)
00253 throw std::runtime_error("ADSal::_CheckGridModel():Incorrect grid structure!");
00254 };
00255 };
00256
00257
00258 template<class GM>
00259 void GridDecomposition<GM>::_initDecompositionLists()
00260 {
00261 parent::_variableLists.resize(parent::_numberOfModels);
00262 parent::_pwFactorLists.resize(parent::_numberOfModels);
00263 for (IndexType x=0;x<_xsize;++x)
00264 {
00265 _getCol(x,&parent::_variableLists[x]);
00266 _getPWCol(x,&parent::_pwFactorLists[x]);
00267 }
00268
00269 for (IndexType y=0;y<_ysize;++y)
00270 {
00271 _getRow(y,&parent::_variableLists[_xsize+y]);
00272 _getPWRow(y,&parent::_pwFactorLists[_xsize+y]);
00273 };
00274 }
00275
00276
00277 template<class GM>
00278 void Decomposition<GM>::_CreateNodeList(const GM & gm,NodeList* pnodeList)
00279 {
00280 NodeList& varList=*pnodeList;
00281 varList.resize(gm.numberOfVariables());
00282 for (IndexType factorId=0;factorId<gm.numberOfFactors();++factorId)
00283 {
00284 if (gm[factorId].numberOfVariables()>2)
00285 throw std::runtime_error("CreateEdgeList(): Only factors up to order 2 are supported!");
00286
00287 if (gm[factorId].numberOfVariables()==1) continue;
00288 std::vector<IndexType> varIndices(gm[factorId].variableIndicesBegin(),gm[factorId].variableIndicesEnd());
00289 if (varIndices[0] < varIndices[1])
00290 varList[varIndices[0]].push_back(std::make_pair(factorId,varIndices[1]));
00291 else
00292 varList[varIndices[1]].push_back(std::make_pair(factorId,varIndices[0]));
00293 }
00294 }
00295
00296 template<class GM>
00297 typename Decomposition<GM>::IndexType Decomposition<GM>::_addSubModel()
00298 {
00299 _variableLists.push_back(IndexList());
00300 _pwFactorLists.push_back(IndexList());
00301 _numberOfModels++;
00302 return IndexType(_numberOfModels-1);
00303 };
00304
00305 template<class GM>
00306 void Decomposition<GM>::_addSubFactor(const IndexType& factorId)
00307 {
00308 _pwFactorLists[_numberOfModels-1].push_back(factorId);
00309 }
00310
00311 template<class GM>
00312 void Decomposition<GM>::_addSubVariable(const IndexType& variableId)
00313 {
00314 _variableLists[_numberOfModels-1].push_back(variableId);
00315 }
00316
00317 template<class GM>
00318 void MonotoneChainsDecomposition<GM>::_GetMaximalMonotoneSequence(typename parent::NodeList* pnodeList,IndexType start)
00319 {
00320 assert(start < pnodeList->size());
00321 typename parent::NodeList& nodeList=*pnodeList;
00322 if (!nodeList[start].empty())
00323 parent::_addSubVariable(start);
00324 else return;
00325
00326 while ( !nodeList[start].empty() )
00327 {
00328 typename parent::EdgeList::iterator it= nodeList[start].begin();
00329 parent::_addSubVariable(it->second);
00330 parent::_addSubFactor(it->first);
00331 IndexType tmp=it->second;
00332 nodeList[start].erase(it);
00333 start=tmp;
00334 }
00335
00336 }
00337
00338 template<class GM>
00339 void Decomposition<GM>::CheckUnaryFactors(const GM& gm)
00340 {
00341 bool error=false;
00342 for (IndexType factorId=0;factorId<gm.numberOfFactors();++factorId)
00343 {
00344 std::vector<IndexType> varIndices(gm[factorId].variableIndicesBegin(),gm[factorId].variableIndicesEnd());
00345 if (gm[factorId].numberOfVariables()==1)
00346 {
00347 if ( (factorId < gm.numberOfVariables()) && (varIndices[0]==factorId))
00348 continue;
00349 else error=true;
00350 }else if (factorId < gm.numberOfVariables())
00351 error=true;
00352
00353 if (error)
00354 throw std::runtime_error("Decomposition<GM>::CheckUnaryFactors(): Each variable has to have a unique unary factor, which moreover has the same index!");
00355 }
00356 }
00357
00358 template<class GM>
00359 void Decomposition<GM>::CheckDuplicateUnaryFactors(const GM& gm)
00360 {
00361 std::vector<IndexType> numOfunaryFactors(gm.numberOfVariables(),(IndexType)0);
00362 for (IndexType factorId=0;factorId<gm.numberOfFactors();++factorId)
00363 {
00364 if (gm[factorId].numberOfVariables()!=1)
00365 continue;
00366
00367 numOfunaryFactors[gm[factorId].variableIndex(0)]++;
00368 }
00369
00370 IndexType oneCount=std::count(numOfunaryFactors.begin(),numOfunaryFactors.end(),(IndexType)1);
00371 exception_check(oneCount==numOfunaryFactors.size(),"Decomposition::CheckDuplicateUnaryFactors: all variables must have a unique associated unary factor!");
00372 }
00373
00374 template<class GM>
00375 void Decomposition<GM>::CheckForIsolatedNodes(const GM& gm)
00376 {
00377 for (IndexType varId=0;varId<gm.numberOfVariables();++varId)
00378 {
00379 bool isolatedNode=true;
00380 for (IndexType localId=0;localId<gm.numberOfFactors(varId);++localId)
00381 {
00382 if (gm[gm.factorOfVariable(varId,localId)].numberOfVariables()>1)
00383 isolatedNode=false;
00384 }
00385 if (isolatedNode==true) throw std::runtime_error("Decomposition<GM>::CheckForIsolatedNodes(): Procesing of isolated nodes is not supported!");
00386 }
00387 }
00388
00389 template<class GM>
00390 void Decomposition<GM>::ComputeVariableDecomposition(std::vector<SubVariableListType>* plist)const
00391 {
00392 plist->resize(_gm.numberOfVariables());
00393 for (IndexType modelId=0;modelId<_numberOfModels;++modelId)
00394 for (IndexType varId=0;varId<_variableLists[modelId].size();++varId)
00395 (*plist)[_variableLists[modelId][varId]].push_back(SubVariable(modelId,varId));
00396 }
00397
00398 template<class GM>
00399 typename GridDecomposition<GM>::IndexType
00400 GridDecomposition<GM>::_pwIndexRow(IndexType x,IndexType y)const
00401 {
00402 assert(x<_xsize-1);
00403 assert(y<_ysize);
00404 if ((y==_ysize-1) && (x!=0)) return _pwIndexRow(0,y) + x;
00405 return _xysize()+y*_pwrowsize()+2*x;
00406 };
00407 template<class GM>
00408 typename GridDecomposition<GM>::IndexType
00409 GridDecomposition<GM>::_pwIndexCol(IndexType x,IndexType y)const
00410 {
00411 if (x==_xsize-1) return _pwIndexCol(x-1,y)+1;
00412 return _pwIndexRow(x,y)+1;
00413 };
00414
00415 template<class GM>
00416 void GridDecomposition<GM>::
00417 _getRow(IndexType y,IndexList* plist)const
00418 {
00419 plist->resize(_xsize);
00420 (*plist)[0]=_varIndex(0,y);
00421 for (IndexType i=1;i<_xsize;++i)
00422 (*plist)[i]=(*plist)[i-1]+1;
00423 };
00424
00425 template<class GM>
00426 void GridDecomposition<GM>::
00427 _getCol(IndexType x,IndexList* plist)const
00428 {
00429 plist->resize(_ysize);
00430 (*plist)[0]=_varIndex(x,0);
00431 for (IndexType i=1;i<_ysize;++i)
00432 (*plist)[i]=(*plist)[i-1]+_xsize;
00433 };
00434
00435 template<class GM>
00436 void GridDecomposition<GM>::
00437 _getPWRow(IndexType y, IndexList* plist)const
00438 {
00439 plist->resize(_xsize-1);
00440 if (_xsize<=1)
00441 return;
00442 (*plist)[0]=_pwIndexRow(0,y);
00443 IndexType step=2;
00444 if (y==_ysize-1) step=1;
00445 for (IndexType i=1;i<_xsize-1;++i)
00446 (*plist)[i]=(*plist)[i-1]+step;
00447 };
00448
00449 template<class GM>
00450 void GridDecomposition<GM>::
00451 _getPWCol(IndexType x,IndexList* plist)const
00452 {
00453 plist->resize(_ysize-1);
00454 if (_ysize<=1)
00455 return;
00456
00457 (*plist)[0]=_pwIndexCol(x,0);
00458 for (IndexType i=1;i<_ysize-1;++i)
00459 (*plist)[i]=(*plist)[i-1]+_pwrowsize();
00460 };
00461
00462
00463 }
00464
00465 #endif