factorgraph.hxx

Go to the documentation of this file.
00001 #pragma once
00002 #ifndef OPENGM_FACTORGRAPH_HXX
00003 #define OPENGM_FACTORGRAPH_HXX
00004 
00005 #include <algorithm>
00006 #include <limits>
00007 
00008 #include "opengm/utilities/accessor_iterator.hxx"
00009 #include "opengm/datastructures/randomaccessset.hxx"
00010 #include "opengm/datastructures/partition.hxx"
00011 
00012 #include <typeinfo>
00013 namespace opengm {
00014 
00017 template<class S,class I>
00018 class FactorGraph {
00019 private:
00020    class VariableAccessor;
00021    class FactorAccessor;
00022    typedef I IndexType;
00023 public:
00024    typedef S SpecialType;
00025    typedef AccessorIterator<VariableAccessor, true> ConstVariableIterator;
00026    typedef AccessorIterator<FactorAccessor, true> ConstFactorIterator;
00027 
00028    // required interface of S (the template parameter)
00029    size_t numberOfVariables() const;
00030    size_t numberOfVariables(const size_t) const;
00031    size_t numberOfFactors() const;
00032    size_t numberOfFactors(const size_t) const;
00033    size_t variableOfFactor(const size_t, const size_t) const;
00034    size_t factorOfVariable(const size_t, const size_t) const;
00035 
00036    // functions that need not be member functions of S (the template parameter)
00037    ConstVariableIterator variablesOfFactorBegin(const size_t) const;
00038    ConstVariableIterator variablesOfFactorEnd(const size_t) const;
00039    ConstFactorIterator factorsOfVariableBegin(const size_t) const;
00040    ConstFactorIterator factorsOfVariableEnd(const size_t) const;
00041    bool variableFactorConnection(const size_t, const size_t) const;
00042    bool factorVariableConnection(const size_t, const size_t) const;
00043    bool variableVariableConnection(const size_t, const size_t) const;
00044    bool factorFactorConnection(const size_t, const size_t) const;
00045    bool isAcyclic() const;
00046    bool isConnected(marray::Vector<size_t>& representatives) const;
00047    bool isChain(marray::Vector<size_t>&) const;
00048    bool isGrid(marray::Matrix<size_t>&) const;
00049 
00050    size_t maxFactorOrder() const;
00051    bool maxFactorOrder(const size_t maxOrder) const;
00052    size_t numberOfNthOrderFactorsOfVariable(const size_t, const size_t) const;
00053    size_t numberOfNthOrderFactorsOfVariable(const size_t, const size_t, marray::Vector<size_t>&) const;
00054    size_t secondVariableOfSecondOrderFactor(const size_t, const size_t) const;
00055 
00056    // export functions
00057    void variableAdjacencyMatrix(marray::Matrix<bool>&) const;
00058    void variableAdjacencyList(std::vector<std::set<IndexType> >&) const;
00059    void variableAdjacencyList(std::vector<RandomAccessSet<IndexType> >&) const;
00060    void factorAdjacencyList(std::vector<std::set<IndexType>  >&) const;
00061    void factorAdjacencyList(std::vector<RandomAccessSet<IndexType> >&) const;
00062 
00063 protected:
00064    // cast operators
00065    operator S&() 
00066       { return static_cast<S&>(*this); }
00067    operator S const&() const 
00068       { return static_cast<const S&>(*this); }
00069 
00070    template <class LIST>
00071    bool shortestPath(const size_t, const size_t, LIST&, const LIST& = LIST()) const;
00072    template <class LIST>
00073    bool twoHopConnected(const size_t, const size_t, LIST&) const;
00074 
00075 private:
00076    class VariableAccessor {
00077    public:
00078       typedef size_t value_type;
00079 
00080       VariableAccessor(const FactorGraph<S,I>* factorGraph = NULL, const size_t factor = 0)
00081          : factorGraph_(factorGraph), factor_(factor) 
00082          {}
00083       VariableAccessor(const FactorGraph<S,I>& factorGraph, const size_t factor = 0)
00084          : factorGraph_(&factorGraph), factor_(factor) 
00085          {}
00086       size_t size() const
00087          { OPENGM_ASSERT(factorGraph_ != NULL);
00088            return factorGraph_->numberOfVariables(factor_); }
00089       const size_t operator[](const size_t number) const
00090          { OPENGM_ASSERT(factorGraph_ != NULL);
00091            return factorGraph_->variableOfFactor(factor_, number); }
00092       bool operator==(const VariableAccessor& a) const
00093          { OPENGM_ASSERT(factorGraph_ != NULL);
00094            return factor_ == a.factor_ && factorGraph_ == a.factorGraph_; }
00095 
00096    private:
00097       const FactorGraph<S,I>* factorGraph_;
00098       size_t factor_;
00099    };
00100 
00101    class FactorAccessor {
00102    public:
00103       typedef I value_type;
00104 
00105       FactorAccessor(const FactorGraph<S,I>* factorGraph = NULL, const size_t variable = 0)
00106          : factorGraph_(factorGraph), variable_(variable) 
00107          {}
00108       FactorAccessor(const FactorGraph<S,I>& factorGraph, const size_t variable = 0)
00109          : factorGraph_(&factorGraph), variable_(variable) 
00110          {}
00111       size_t size() const
00112          { OPENGM_ASSERT(factorGraph_ != NULL);
00113            return factorGraph_->numberOfFactors(variable_); }
00114       const size_t operator[](const size_t number) const
00115          { OPENGM_ASSERT(factorGraph_ != NULL);
00116            return factorGraph_->factorOfVariable(variable_, number); }
00117       bool operator==(const FactorAccessor& a) const
00118          { OPENGM_ASSERT(factorGraph_ != NULL);
00119            return variable_ == a.variable_ && factorGraph_ == a.factorGraph_; }
00120 
00121    private:
00122       const FactorGraph<S,I>* factorGraph_;
00123       size_t variable_;
00124    };
00125 
00126    template<class LIST>
00127       void templatedVariableAdjacencyList(LIST&) const;
00128    template<class LIST>
00129       void templatedFactorAdjacencyList(LIST&) const;
00130 };
00131 
00134 template<class S,class I>
00135 inline size_t 
00136 FactorGraph<S,I>::numberOfVariables() const
00137 {
00138    return static_cast<const SpecialType&>(*this).numberOfVariables();
00139 }
00140 
00144 template<class S,class I>
00145 inline size_t 
00146 FactorGraph<S,I>::numberOfVariables
00147 (
00148    const size_t factor
00149 ) const
00150 {
00151    return static_cast<const SpecialType&>(*this).numberOfVariables(factor);
00152 }
00153 
00156 template<class S,class I>
00157 inline size_t 
00158 FactorGraph<S,I>::numberOfFactors() const
00159 {
00160    return static_cast<const SpecialType&>(*this).numberOfFactors();
00161 }
00162 
00166 template<class S,class I>
00167 inline size_t 
00168 FactorGraph<S,I>::numberOfFactors
00169 (
00170    const size_t variable
00171 ) const
00172 {
00173    return static_cast<const SpecialType&>(*this).numberOfFactors(variable);
00174 }
00175 
00180 template<class S,class I>
00181 inline size_t 
00182 FactorGraph<S,I>::variableOfFactor
00183 (
00184    const size_t factor, 
00185    const size_t j
00186 ) const
00187 {
00188    return static_cast<const SpecialType&>(*this).variableOfFactor(factor, j);
00189 }
00190 
00195 template<class S,class I>
00196 inline size_t 
00197 FactorGraph<S,I>::factorOfVariable
00198 (
00199    const size_t variable, 
00200    const size_t j
00201 ) const
00202 {
00203    return static_cast<const SpecialType&>(*this).factorOfVariable(variable, j);
00204 }
00205 
00209 template<class S,class I>
00210 inline typename FactorGraph<S,I>::ConstVariableIterator 
00211 FactorGraph<S,I>::variablesOfFactorBegin
00212 (
00213    const size_t factor
00214 ) const
00215 {
00216    VariableAccessor accessor(this, factor);
00217    return ConstVariableIterator(accessor);
00218 }
00219 
00223 template<class S,class I>
00224 inline typename FactorGraph<S,I>::ConstVariableIterator 
00225 FactorGraph<S,I>::variablesOfFactorEnd
00226 (
00227    const size_t factor
00228 ) const
00229 {
00230    VariableAccessor accessor(this, factor);
00231    return ConstVariableIterator(accessor, numberOfVariables(factor));
00232 }
00233 
00237 template<class S,class I>
00238 inline typename FactorGraph<S,I>::ConstFactorIterator 
00239 FactorGraph<S,I>::factorsOfVariableBegin
00240 (
00241    const size_t variable
00242 ) const
00243 {
00244    FactorAccessor accessor(this, variable);
00245    return ConstFactorIterator(accessor);
00246 }
00247 
00251 template<class S,class I>
00252 inline typename FactorGraph<S,I>::ConstFactorIterator 
00253 FactorGraph<S,I>::factorsOfVariableEnd
00254 (
00255    const size_t variable
00256 ) const
00257 {
00258    FactorAccessor accessor(this, variable);
00259    return ConstFactorIterator(accessor, numberOfFactors(variable));
00260 }
00261 
00266 template<class S,class I>
00267 inline bool 
00268 FactorGraph<S,I>::variableFactorConnection
00269 (
00270    const size_t variable,
00271    const size_t factor
00272 ) const
00273 {
00274    OPENGM_ASSERT(factor < numberOfFactors());
00275    OPENGM_ASSERT(variable < numberOfVariables());
00276    if(!NO_DEBUG) {
00277       for(size_t j=1; j<numberOfVariables(factor); ++j) {
00278          OPENGM_ASSERT(variableOfFactor(factor, j-1) < variableOfFactor(factor, j));
00279       }
00280    }
00281    return std::binary_search(variablesOfFactorBegin(factor), 
00282       variablesOfFactorEnd(factor), variable);
00283    return false;
00284 }
00285 
00290 template<class S,class I>
00291 inline bool 
00292 FactorGraph<S,I>::factorVariableConnection
00293 (
00294    const size_t factor, 
00295    const size_t variable
00296 ) const
00297 {
00298    OPENGM_ASSERT(factor < numberOfFactors());
00299    OPENGM_ASSERT(variable < numberOfVariables());
00300    return variableFactorConnection(variable, factor);
00301 }
00302 
00307 template<class S,class I>
00308 inline bool 
00309 FactorGraph<S,I>::variableVariableConnection
00310 (
00311    const size_t variable1, 
00312    const size_t variable2
00313 ) const
00314 {
00315    OPENGM_ASSERT(variable1 < numberOfVariables());
00316    OPENGM_ASSERT(variable2 < numberOfVariables());
00317    if(variable1 != variable2) {
00318       ConstFactorIterator it1 = factorsOfVariableBegin(variable1);
00319       ConstFactorIterator it2 = factorsOfVariableBegin(variable2);
00320       while(it1 != factorsOfVariableEnd(variable1) && it2 != factorsOfVariableEnd(variable2)) {
00321          if(*it1 < *it2) {
00322             ++it1;
00323          }
00324          else if(*it1 == *it2) {
00325             return true;
00326          }
00327          else {
00328             ++it2;
00329          }
00330       }
00331    }
00332    return false;
00333 }
00334 
00337 template<class S,class I>
00338 bool
00339 FactorGraph<S,I>::isAcyclic() const
00340 {
00341    const size_t NO_FACTOR = numberOfFactors();
00342    const size_t NO_VARIABLE = numberOfVariables();
00343    const size_t ROOT_FACTOR = numberOfVariables() + 1;
00344    std::vector<size_t> factorFathers(numberOfFactors(), NO_VARIABLE);
00345    std::vector<size_t> variableFathers(numberOfVariables(), NO_FACTOR);
00346    std::queue<size_t> factorQueue;
00347    std::queue<size_t> variableQueue;
00348    for(size_t F = 0; F < numberOfFactors(); ++F) {
00349       if(factorFathers[F] == NO_VARIABLE) {
00350          factorFathers[F] = ROOT_FACTOR;
00351          factorQueue.push(F);
00352          while(!factorQueue.empty()) {
00353             while(!factorQueue.empty()) {
00354                const size_t f = factorQueue.front();
00355                factorQueue.pop();
00356                for(size_t j = 0; j < numberOfVariables(f); ++j) {
00357                   const size_t v = variableOfFactor(f, j);
00358                   if(variableFathers[v] == NO_FACTOR) {
00359                      variableFathers[v] = f;
00360                      variableQueue.push(v);
00361                   }
00362                   else if(factorFathers[f] != v) {
00363                      return false;
00364                   }
00365                }
00366             }
00367             while(!variableQueue.empty()) {
00368                const size_t v = variableQueue.front();
00369                variableQueue.pop();
00370                for(size_t j = 0; j < numberOfFactors(v); ++j) {
00371                   const size_t f = factorOfVariable(v, j);
00372                   if(factorFathers[f] == NO_VARIABLE) {
00373                      factorFathers[f] = v;
00374                      factorQueue.push(f);
00375                   }
00376                   else if(variableFathers[v] != f) {
00377                      return false;
00378                   }
00379                }
00380             }
00381          }
00382       }
00383    }
00384    return true;
00385 }
00386 
00390 template<class S,class I>
00391 bool
00392 FactorGraph<S,I>::isConnected(marray::Vector<size_t>& representatives) const
00393 {
00394    // check if factor graph has zero variables
00395    if(numberOfVariables() == 0) {
00396       return false;
00397    }
00398 
00399    // create a partition of all connected components
00400    Partition<size_t> connectedComponents(numberOfVariables());
00401    // iterate over all factors
00402    for(size_t i = 0; i < numberOfFactors(); i++) {
00403       // iterate over all connected variables of factor and merge them to one partition
00404       const ConstVariableIterator variablesBegin = variablesOfFactorBegin(i);
00405       const ConstVariableIterator variablesEnd = variablesOfFactorEnd(i);
00406       OPENGM_ASSERT(variablesBegin != variablesEnd);
00407 
00408       for(ConstVariableIterator iter = variablesBegin + 1; iter != variablesEnd; iter++) {
00409          connectedComponents.merge(*(iter - 1), *iter);
00410       }
00411    }
00412 
00413    // check number of connected components
00414    OPENGM_ASSERT(connectedComponents.numberOfSets() > 0);
00415 
00416    representatives = marray::Vector<size_t>(connectedComponents.numberOfSets());
00417    connectedComponents.representatives(representatives.begin());
00418 
00419    if(connectedComponents.numberOfSets() == 1) {
00420       return true;
00421    } else {
00422       return false;
00423    }
00424 }
00425 
00429 template<class S,class I>
00430 inline bool
00431 FactorGraph<S,I>::isChain(marray::Vector<size_t>& chainIDs) const {
00432    const size_t numVariables = numberOfVariables();
00433 
00434    // check if factor graph has zero variables
00435    if(numVariables == 0) {
00436       return false;
00437    }
00438 
00439    // check Factor Order
00440    if(!maxFactorOrder(2)) {
00441       return false;
00442    }
00443 
00444    // special case: graph contains only one variable
00445    if(numVariables == 1) {
00446       chainIDs = marray::Vector<size_t>(numVariables);
00447       chainIDs[0] = 0;
00448       return true;
00449    }
00450 
00451    // find ends
00452    marray::Vector<size_t> ends(2);
00453    size_t detectedEnds = 0;
00454    for(size_t i = 0; i < numVariables; i++) {
00455       size_t countSecondOrderFactors = numberOfNthOrderFactorsOfVariable(i, 2);
00456       if(countSecondOrderFactors == 1) {
00457          if(detectedEnds > 1) {
00458             return false;
00459          }
00460          ends[detectedEnds] = i;
00461          detectedEnds++;
00462       }
00463    }
00464 
00465    // two ends found?
00466    if(detectedEnds != 2) {
00467       return false;
00468    }
00469 
00470    chainIDs = marray::Vector<size_t>(numVariables);
00471    // set ends
00472    chainIDs[0] = ends[0];
00473    chainIDs[numVariables - 1] = ends[1];
00474 
00475    // try to traverse from first end to second end
00476    // set predecessor and successor of ends[0]
00477    size_t predecessor = ends[0];
00478    OPENGM_ASSERT(numberOfVariables() < std::numeric_limits<size_t>::max());
00479    size_t successor = std::numeric_limits<size_t>::max();
00480    for(ConstFactorIterator iter = factorsOfVariableBegin(ends[0]); iter != factorsOfVariableEnd(ends[0]); iter++) {
00481       if(numberOfVariables(*iter) == 2) {
00482          successor = secondVariableOfSecondOrderFactor(ends[0], *iter);
00483       }
00484    }
00485 
00486    OPENGM_ASSERT(successor != std::numeric_limits<size_t>::max());
00487 
00488    // traverse chain while successor != ends[1]
00489    size_t countTraversedVariables = 1;
00490    while(successor != ends[1]) {
00491       marray::Vector<size_t> secondOrderFactorIds;
00492       size_t countSecondOrderFactors = numberOfNthOrderFactorsOfVariable(successor, 2, secondOrderFactorIds);
00493       if(countSecondOrderFactors > 2) {
00494          return false;
00495       }
00496       // add successor to chainIDs
00497       chainIDs[countTraversedVariables] = successor;
00498       countTraversedVariables++;
00499 
00500       // update predecessor and successor
00501       OPENGM_ASSERT(secondOrderFactorIds.size() == 2);
00502       for(size_t j = 0; j < 2; j++) {
00503          size_t possibleSuccesor = secondVariableOfSecondOrderFactor(successor, secondOrderFactorIds[j]);
00504          if(possibleSuccesor != predecessor) {
00505             predecessor = successor;
00506             successor = possibleSuccesor;
00507             break;
00508          }
00509       }
00510    }
00511 
00512    if(countTraversedVariables != numVariables - 1) {
00513       // end of chain reached too soon
00514       return false;
00515    }
00516    OPENGM_ASSERT(countTraversedVariables == numVariables - 1);
00517 
00518    // check if last variable is really the expected second end
00519    OPENGM_ASSERT(chainIDs[numVariables - 1] == ends[1]);
00520 
00521    return true;
00522 }
00523 
00527 template<class S,class I>
00528 inline bool
00529 FactorGraph<S,I>::isGrid(marray::Matrix<size_t>& gridIDs) const {
00530 
00531    // check if factor graph has zero variables
00532    if(numberOfVariables() == 0) {
00533       return false;
00534    }
00535 
00536    // check Factor Order
00537    if(!maxFactorOrder(2)) {
00538       return false;
00539    }
00540 
00541    // special case: graph contains only one variable
00542    if(numberOfVariables() == 1) {
00543       gridIDs = marray::Matrix<size_t>(1,1);
00544       gridIDs(0, 0) = 0;
00545       return true;
00546    }
00547 
00548    // check one dimensional case (e.g. graph is a chain)
00549    marray::Vector<size_t> chainIDs;
00550    bool graphIsChain = isChain(chainIDs);
00551    if(graphIsChain) {
00552       gridIDs = marray::Matrix<size_t>(1, chainIDs.size());
00553       for(size_t i = 0; i < chainIDs.size(); i++) {
00554          gridIDs(0, i) = chainIDs[i];
00555       }
00556       return true;
00557    }
00558 
00559    // find corner variables (variables connected to two second order factors)
00560    // and outer hull variables
00561    marray::Vector<size_t> cornerIDs(4);
00562    size_t numCornersFound = 0;
00563    std::list<size_t> outerHullVariableIDs;
00564 
00565    for(size_t i = 0; i < numberOfVariables(); i++) {
00566       size_t countSecondOrderFactors = numberOfNthOrderFactorsOfVariable(i, 2);
00567       if(countSecondOrderFactors == 2) {
00568          // corner found
00569          if(numCornersFound > 3) {
00570             return false;
00571          }
00572          cornerIDs(numCornersFound) = i;
00573          numCornersFound++;
00574          // corner is also an outer hull variable
00575          outerHullVariableIDs.push_back(i);
00576       } else if(countSecondOrderFactors == 3) {
00577          outerHullVariableIDs.push_back(i);
00578       } else if(countSecondOrderFactors > 4) {
00579          // variable is connected to too many other variables
00580          return false;
00581       }
00582    }
00583 
00584    if(numCornersFound < 4) {
00585       return false;
00586    }
00587 
00588    OPENGM_ASSERT(numCornersFound == 4);
00589 
00590    // find shortest path from one corner to all other corners
00591    std::vector<std::list<size_t> > shortestPaths(3);
00592    if(!shortestPath(cornerIDs(0), cornerIDs(1), shortestPaths[0], outerHullVariableIDs)) {
00593       return false;
00594    }
00595 
00596    if(!shortestPath(cornerIDs(0), cornerIDs(2), shortestPaths[1], outerHullVariableIDs)) {
00597       return false;
00598    }
00599 
00600    if(!shortestPath(cornerIDs(0), cornerIDs(3), shortestPaths[2], outerHullVariableIDs)) {
00601       return false;
00602    }
00603 
00604    // find diagonal corner
00605    size_t diagonalCorner = 1;
00606    for(size_t i = 1; i < 4; i++) {
00607       if(shortestPaths[i - 1].size() > shortestPaths[diagonalCorner].size()) {
00608          diagonalCorner = i;
00609       }
00610    }
00611 
00612    // compute shortest paths from adjacent corners to diagonal corner
00613    std::vector<std::list<size_t> > shortestAdjacentCornerPaths(2);
00614    size_t shortestAdjacentCornerPathsComputed = 0;
00615    for(size_t i = 1; i < 4; i++) {
00616       if(i != diagonalCorner) {
00617          if(!shortestPath(cornerIDs(i), cornerIDs(diagonalCorner), shortestAdjacentCornerPaths[shortestAdjacentCornerPathsComputed], outerHullVariableIDs)) {
00618             return false;
00619          }
00620          shortestAdjacentCornerPathsComputed++;
00621       }
00622    }
00623    OPENGM_ASSERT(shortestAdjacentCornerPathsComputed == 2);
00624 
00625    // compute grid dimension
00626    std::vector<size_t> dimension(2);
00627    size_t dimensionIndex = 0;
00628    for(size_t i = 1; i < 4; i++) {
00629       if(i != diagonalCorner) {
00630          dimension[dimensionIndex] = shortestPaths[i - 1].size();
00631          dimensionIndex++;
00632       }
00633    }
00634    OPENGM_ASSERT(dimensionIndex == 2);
00635 
00636    //check dimensions
00637    if(dimension[0] != shortestAdjacentCornerPaths[1].size()) {
00638       return false;
00639    }
00640    if(dimension[1] != shortestAdjacentCornerPaths[0].size()) {
00641       return false;
00642    }
00643 
00644    // create storage
00645    gridIDs = marray::Matrix<size_t>(dimension[0], dimension[1]);
00646 
00647    // fill outer values
00648    // from first corner to adjacent corners
00649    bool transpose = false;
00650    for(size_t i = 1; i < 4; i++) {
00651       if(i != diagonalCorner) {
00652          size_t indexHelper = 0;
00653          if(transpose == false) {
00654             for(typename std::list<size_t>::iterator iter = shortestPaths[i - 1].begin(); iter != shortestPaths[i - 1].end(); iter++) {
00655                gridIDs(indexHelper, 0) = *iter;
00656                indexHelper++;
00657             }
00658             transpose = true;
00659          } else {
00660             for(typename std::list<size_t>::iterator iter = shortestPaths[i - 1].begin(); iter != shortestPaths[i - 1].end(); iter++) {
00661                gridIDs(0, indexHelper) = *iter;
00662                indexHelper++;
00663             }
00664          }
00665 
00666       }
00667    }
00668 
00669    // from diagonal corner to adjacent corners
00670    transpose = false;
00671    for(size_t i = 0; i <= 1; i++) {
00672       size_t indexHelper = 0;
00673       if(transpose == false) {
00674          for(typename std::list<size_t>::iterator iter = shortestAdjacentCornerPaths[i].begin(); iter != shortestAdjacentCornerPaths[i].end(); iter++) {
00675             gridIDs(dimension[0] - 1, indexHelper) = *iter;
00676             indexHelper++;
00677          }
00678          transpose = true;
00679       } else {
00680          for(typename std::list<size_t>::iterator iter = shortestAdjacentCornerPaths[i].begin(); iter != shortestAdjacentCornerPaths[i].end(); iter++) {
00681             gridIDs(indexHelper, dimension[1] - 1) = *iter;
00682             indexHelper++;
00683          }
00684       }
00685    }
00686 
00687    // fill inner values
00688    for(size_t i = 1; i < dimension[0] - 1; i++) {
00689       for(size_t j = 1; j < dimension[1] - 1; j++) {
00690          std::vector<size_t> oneHopVariables;
00691          if(twoHopConnected(gridIDs(i - 1, j), gridIDs(i, j - 1), oneHopVariables)) {
00692             if(oneHopVariables.size() < 2) {
00693                return false;
00694             }
00695             OPENGM_ASSERT(oneHopVariables.size() == 2);
00696             if(oneHopVariables[0] != gridIDs(i - 1, j - 1)) {
00697                gridIDs(i, j) = oneHopVariables[0];
00698             } else {
00699                gridIDs(i, j) = oneHopVariables[1];
00700             }
00701          } else {
00702             return false;
00703          }
00704       }
00705    }
00706 
00707    return true;
00708 }
00709 
00712 template<class S,class I>
00713 inline size_t
00714 FactorGraph<S,I>::maxFactorOrder() const {
00715    size_t maxFactorOrder = 0;
00716    for(size_t i = 0; i < numberOfFactors(); i++) {
00717       if(numberOfVariables(i) > maxFactorOrder) {
00718          maxFactorOrder = numberOfVariables(i);
00719       }
00720    }
00721    return maxFactorOrder;
00722 }
00723 
00727 template<class S,class I>
00728 inline bool
00729 FactorGraph<S,I>::maxFactorOrder(const size_t maxOrder) const {
00730    for(size_t i = 0; i < numberOfFactors(); i++) {
00731       if(numberOfVariables(i) > maxOrder) {
00732          return false;
00733       }
00734    }
00735    return true;
00736 }
00737 
00742 template<class S,class I>
00743 inline size_t
00744 FactorGraph<S,I>::numberOfNthOrderFactorsOfVariable(const size_t variable, const size_t n) const {
00745    OPENGM_ASSERT(variable < numberOfVariables());
00746    size_t countNthOrderFactors = 0;
00747    for(ConstFactorIterator iter = factorsOfVariableBegin(variable); iter != factorsOfVariableEnd(variable); iter++) {
00748       if(numberOfVariables(*iter) == n) {
00749          countNthOrderFactors++;
00750       }
00751    }
00752    return countNthOrderFactors;
00753 }
00754 
00760 template<class S,class I>
00761 inline size_t
00762 FactorGraph<S,I>::numberOfNthOrderFactorsOfVariable(const size_t variable, const size_t n, marray::Vector<size_t>& factorIDs) const {
00763    OPENGM_ASSERT(variable < numberOfVariables());
00764    // FIXME this might be done more efficiently without numberOfNthOrderFactorsOfVariable(variable, n) if marray::Vector<size_t> would support something like push_back()
00765    size_t countNthOrderFactors = numberOfNthOrderFactorsOfVariable(variable, n);
00766    factorIDs = marray::Vector<size_t>(countNthOrderFactors);
00767    for(ConstFactorIterator iter = factorsOfVariableBegin(variable); iter != factorsOfVariableEnd(variable); iter++) {
00768       if(numberOfVariables(*iter) == n) {
00769          countNthOrderFactors--;
00770          factorIDs[countNthOrderFactors] = *iter;
00771       }
00772    }
00773    OPENGM_ASSERT(countNthOrderFactors == 0);
00774    return factorIDs.size();
00775 }
00776 
00781 template<class S,class I>
00782 inline size_t
00783 FactorGraph<S,I>::secondVariableOfSecondOrderFactor(const size_t variable, const size_t factor) const {
00784    OPENGM_ASSERT(variable < numberOfVariables());
00785    OPENGM_ASSERT(factor < numberOfFactors());
00786    OPENGM_ASSERT(numberOfVariables(factor) == 2);
00787    OPENGM_ASSERT(variableFactorConnection(variable, factor));
00788    for(ConstVariableIterator iter = variablesOfFactorBegin(factor); iter != variablesOfFactorEnd(factor); iter++) {
00789       if(*iter != variable) {
00790          return *iter;
00791       }
00792    }
00793    return variable;
00794 }
00795 
00800 template<class S,class I>
00801 inline bool 
00802 FactorGraph<S,I>::factorFactorConnection
00803 (
00804    const size_t factor1, 
00805    const size_t factor2
00806 ) const
00807 {
00808    OPENGM_ASSERT(factor1 < numberOfFactors());
00809    OPENGM_ASSERT(factor2 < numberOfFactors());
00810    if(factor1 != factor2) {
00811       ConstVariableIterator it1 = variablesOfFactorBegin(factor1);
00812       ConstVariableIterator it2 = variablesOfFactorBegin(factor2);
00813       while(it1 != variablesOfFactorEnd(factor1) && it2 != variablesOfFactorEnd(factor2)) {
00814          if(*it1 < *it2) {
00815             ++it1;
00816          }
00817          else if(*it1 == *it2) {
00818             return true;
00819          }
00820          else {
00821             ++it2;
00822          }
00823       }
00824    }
00825    return false;
00826 }
00827 
00830 template<class S,class I>
00831 inline void 
00832 FactorGraph<S,I>::variableAdjacencyMatrix
00833 (
00834    marray::Matrix<bool>& out
00835 ) const
00836 {
00837    out = marray::Matrix<bool>(numberOfVariables(), numberOfVariables(), false);
00838    for(size_t factor=0; factor<numberOfFactors(); ++factor) {
00839       for(size_t j=0; j<numberOfVariables(factor); ++j) {
00840          for(size_t k=j+1; k<numberOfVariables(factor); ++k) {
00841             const size_t variable1 = variableOfFactor(factor, j);
00842             const size_t variable2 = variableOfFactor(factor, k);
00843             out(variable1, variable2) = true;
00844             out(variable2, variable1) = true;
00845          }
00846       }
00847    }
00848 }
00849 
00852 template<class S,class I>
00853 inline void 
00854 FactorGraph<S,I>::variableAdjacencyList
00855 (
00856    std::vector<RandomAccessSet<IndexType> >& out
00857 ) const
00858 {
00859    templatedVariableAdjacencyList(out);
00860 }
00861 
00864 template<class S,class I>
00865 inline void 
00866 FactorGraph<S,I>::variableAdjacencyList
00867 (
00868    std::vector<std::set<IndexType> >& out
00869 ) const
00870 {
00871    templatedVariableAdjacencyList(out);
00872 }
00873 
00876 template<class S,class I>
00877 template<class LIST>
00878 inline void 
00879 FactorGraph<S,I>::templatedVariableAdjacencyList
00880 (
00881    LIST& out
00882 ) const
00883 {
00884    out.clear();
00885    out.resize(numberOfVariables());
00886    for(size_t factor=0; factor<numberOfFactors(); ++factor) {
00887       for(size_t j=0; j<numberOfVariables(factor); ++j) {
00888          for(size_t k=j+1; k<numberOfVariables(factor); ++k) {
00889             const size_t variable1 = variableOfFactor(factor, j);
00890             const size_t variable2 = variableOfFactor(factor, k);
00891             out[variable1].insert(variable2);
00892             out[variable2].insert(variable1);
00893          }
00894       }
00895    }
00896 }
00897 
00898 template<class S,class I>
00899 inline void 
00900 FactorGraph<S,I>::factorAdjacencyList
00901 (
00902    std::vector<std::set<IndexType> >& out
00903 ) const
00904 {
00905    templatedFactorAdjacencyList(out);
00906 }
00907 
00908 template<class S,class I>
00909 inline void 
00910 FactorGraph<S,I>::factorAdjacencyList
00911 (
00912    std::vector< RandomAccessSet<IndexType> >& out
00913 ) const
00914 {
00915    templatedFactorAdjacencyList(out);
00916 }
00917 
00918 template<class S,class I>
00919 template<class LIST>
00920 inline void 
00921 FactorGraph<S,I>::templatedFactorAdjacencyList
00922 (
00923    LIST& out
00924 ) const
00925 {
00926    out.clear();
00927    out.resize(numberOfFactors());
00928    for(size_t f=0; f<numberOfFactors(); ++f) {
00929       for(size_t v=0 ;v<numberOfVariables(f); ++v) {
00930          for(size_t ff=0;ff<numberOfFactors(v);++ff) {
00931             const size_t fOfVar=factorOfVariable(v,ff);
00932             if(f!=fOfVar) {
00933                out[f].insert(fOfVar);
00934             }
00935          }
00936       }
00937    }
00938 }
00939 
00945 template<class S,class I>
00946 template <class LIST>
00947 inline bool
00948 FactorGraph<S,I>::shortestPath(const size_t s, const size_t t, LIST& path, const LIST& allowedVariables) const {
00949    OPENGM_ASSERT(s < numberOfVariables());
00950    OPENGM_ASSERT(t < numberOfVariables());
00951    OPENGM_ASSERT(allowedVariables.size() <= numberOfVariables());
00952    OPENGM_ASSERT(numberOfVariables() != std::numeric_limits<size_t>::max());
00953    const size_t infinity = std::numeric_limits<size_t>::max();
00954 
00955    bool useAllVariables = (allowedVariables.size() == 0) || (allowedVariables.size() == numberOfVariables());
00956 
00957    if(useAllVariables) {
00958       std::vector<size_t> distances(numberOfVariables(), infinity);
00959       std::vector<size_t> previous(numberOfVariables(), infinity);
00960       distances[s] = 0;
00961       LIST Q;
00962       for(size_t i = 0; i < numberOfVariables(); i++) {
00963          Q.push_back(i);
00964       }
00965       while(Q.size() !=0) {
00966          typename LIST::iterator currentIter = Q.begin();
00967          for(typename LIST::iterator iter = Q.begin(); iter != Q.end(); iter++) {
00968             if(distances[*iter] < distances[*currentIter]) {
00969                currentIter = iter;
00970             }
00971          }
00972          if(distances[*currentIter] == infinity) {
00973             // all remaining variables are inaccessible from s
00974             return false;
00975          }
00976          if(*currentIter == t) {
00977             // target found
00978             break;
00979          }
00980          size_t currentID = *currentIter;
00981          Q.erase(currentIter);
00982          // iterate over all neighbor variables of *current which are still in Q
00983          for(ConstFactorIterator factorIter = factorsOfVariableBegin(currentID); factorIter != factorsOfVariableEnd(currentID); factorIter++) {
00984             for(ConstVariableIterator variableIter = variablesOfFactorBegin(*factorIter); variableIter != variablesOfFactorEnd(*factorIter); variableIter++) {
00985                if(std::find(Q.begin(), Q.end(), *variableIter) != Q.end()) {
00986                   size_t newDistance = distances[currentID] + 1;
00987                   if(newDistance < distances[*variableIter]) {
00988                      distances[*variableIter] = newDistance;
00989                      previous[*variableIter] = currentID;
00990                   }
00991                }
00992             }
00993          }
00994       }
00995       OPENGM_ASSERT(previous[t] != infinity);
00996       // create path
00997       size_t u = t;
00998       while(previous[u] != infinity) {
00999          path.push_front(u);
01000          u = previous[u];
01001       }
01002       path.push_front(s);
01003       return true;
01004    } else {
01005       OPENGM_ASSERT(std::find(allowedVariables.begin(), allowedVariables.end(), s) != allowedVariables.end());
01006       OPENGM_ASSERT(std::find(allowedVariables.begin(), allowedVariables.end(), t) != allowedVariables.end());
01007       std::vector<size_t> distances(allowedVariables.size(), infinity);
01008       std::vector<size_t> previous(allowedVariables.size(), infinity);
01009       std::map<size_t, size_t> local2actualIDs;
01010       std::map<size_t, size_t> actual2localIDs;
01011       LIST Q;
01012       size_t counter = 0;
01013       for(typename LIST::const_iterator iter = allowedVariables.begin(); iter != allowedVariables.end(); iter++) {
01014          Q.push_back(counter);
01015          local2actualIDs.insert(std::pair<size_t, size_t>(counter, *iter));
01016          actual2localIDs.insert(std::pair<size_t, size_t>(*iter, counter));
01017          counter++;
01018       }
01019       distances[actual2localIDs.find(s)->second] = 0;
01020       while(Q.size() !=0) {
01021          typename LIST::iterator currentIter = Q.begin();
01022          for(typename LIST::iterator iter = Q.begin(); iter != Q.end(); iter++) {
01023             if(distances[*iter] < distances[*currentIter]) {
01024                currentIter = iter;
01025             }
01026          }
01027          if(distances[*currentIter] == infinity) {
01028             // all remaining variables are inaccessible from s
01029             return false;
01030          }
01031          // get actual ID
01032          size_t actualID = local2actualIDs.find(*currentIter)->second;
01033          if(actualID == t) {
01034             // target found
01035             break;
01036          }
01037          size_t currentLocalID = *currentIter;
01038          Q.erase(currentIter);
01039          // iterate over all neighbor variables of *current which are in allowedVariables and are still in Q
01040          for(ConstFactorIterator factorIter = factorsOfVariableBegin(actualID); factorIter != factorsOfVariableEnd(actualID); factorIter++) {
01041             for(ConstVariableIterator variableIter = variablesOfFactorBegin(*factorIter); variableIter != variablesOfFactorEnd(*factorIter); variableIter++) {
01042                const std::map<size_t, size_t>::const_iterator actual2localIDsCurrentPosition = actual2localIDs.find(*variableIter);
01043                if(actual2localIDsCurrentPosition != actual2localIDs.end()) {
01044                   size_t localID = actual2localIDsCurrentPosition->second;
01045                   if(std::find(Q.begin(), Q.end(), localID) != Q.end()) {
01046                      size_t newDistance = distances[currentLocalID] + 1;
01047                      if(newDistance < distances[localID]) {
01048                         distances[localID] = newDistance;
01049                         previous[localID] = currentLocalID;
01050                      }
01051                   }
01052                }
01053             }
01054          }
01055       }
01056       OPENGM_ASSERT(actual2localIDs.find(t)->second != infinity);
01057       // create path
01058       size_t u = actual2localIDs.find(t)->second;
01059       while(previous[u] != infinity) {
01060 
01061          path.push_front(local2actualIDs.find(u)->second);
01062          u = previous[u];
01063       }
01064       path.push_front(s);
01065       return true;
01066    }
01067    return false;
01068 }
01069 
01074 template<class S,class I>
01075 template <class LIST>
01076 inline bool
01077 FactorGraph<S,I>::twoHopConnected(const size_t variable1, const size_t variable2, LIST& oneHopVariables) const {
01078    OPENGM_ASSERT(variable1 < numberOfVariables());
01079    OPENGM_ASSERT(variable2 < numberOfVariables());
01080    oneHopVariables.clear();
01081    if(variable1 != variable2) {
01082       for(ConstFactorIterator factorIter = factorsOfVariableBegin(variable1); factorIter != factorsOfVariableEnd(variable1); factorIter++) {
01083          for(ConstVariableIterator variableIter = variablesOfFactorBegin(*factorIter); variableIter != variablesOfFactorEnd(*factorIter); variableIter++) {
01084             if((*variableIter != variable1) || (*variableIter != variable2)) {
01085                if(variableVariableConnection(*variableIter, variable2)) {
01086                   oneHopVariables.push_back(*variableIter);
01087                }
01088             }
01089          }
01090       }
01091    }
01092    if(oneHopVariables.size() == 0) {
01093       return false;
01094    } else {
01095       return true;
01096    }
01097 }
01098 
01099 } // namespace opengm
01100 
01101 #endif // #ifndef OPENGM_FACTORGRAPH_HXX
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Mon Jun 17 16:31:02 2013 for OpenGM by  doxygen 1.6.3