trws_decomposition.hxx

Go to the documentation of this file.
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    {  // Reserve memory
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;//first=factorId, second=neighborNodeId
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  * So far oriented to 2-nd order factors only!
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 //-------------------------IMPLEMENTATION------------------------------------------------
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    //estimate xsize and ysize
00185    _computeGridSizes();
00186    parent::_numberOfModels=_xsize+_ysize;
00187    //bild variable and factor lists
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    //check vertical structure
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 //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
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 }//DD
00464 
00465 #endif /* DECOMPOSITIONTRWS_H_ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Mon Jun 17 16:31:06 2013 for OpenGM by  doxygen 1.6.3