lazyflipper.hxx

Go to the documentation of this file.
00001 #pragma once
00002 #ifndef OPENGM_LAZYFLIPPER_HXX
00003 #define OPENGM_LAZYFLIPPER_HXX
00004 
00005 #include <vector>
00006 #include <set>
00007 #include <string>
00008 #include <iostream>
00009 #include <stdexcept>
00010 #include <list>
00011 
00012 #include "opengm/opengm.hxx"
00013 #include "opengm/inference/inference.hxx"
00014 #include "opengm/inference/movemaker.hxx"
00015 #include "opengm/inference/visitors/visitor.hxx"
00016 #include "opengm/operations/minimizer.hxx"
00017 #include "opengm/utilities/tribool.hxx"
00018 
00019 namespace opengm {
00020 
00022 
00023 template<class T>
00024 class Tagging {
00025 public:
00026    typedef T ValueType;
00027    typedef std::vector<ValueType> tag_container_type;
00028    typedef std::vector<size_t> index_container_type;
00029    typedef index_container_type::const_iterator const_iterator;
00030 
00031    Tagging(const size_t = 0);
00032    void append(const size_t);
00033    ValueType tag(const size_t) const;
00034    void tag(const size_t, const typename Tagging<T>::ValueType);
00035    void untag(); // untag all
00036    const_iterator begin();
00037    const_iterator begin() const;
00038    const_iterator end();
00039    const_iterator end() const;
00040 
00041 private:
00042    tag_container_type tags_;
00043    index_container_type indices_;
00044 };
00045 
00046 // A simple undirected graph
00047 class Adjacency {
00048 public:
00049    typedef std::set<size_t>::const_iterator const_iterator;
00050 
00051    Adjacency(const size_t = 0);
00052    void resize(const size_t);
00053    void connect(const size_t, const size_t);
00054    bool connected(const size_t, const size_t) const;
00055    const_iterator neighborsBegin(const size_t);
00056    const_iterator neighborsBegin(const size_t) const;
00057    const_iterator neighborsEnd(const size_t);
00058    const_iterator neighborsEnd(const size_t) const;
00059 
00060 private:
00061    std::vector<std::set<size_t> > neighbors_;
00062 };
00063 
00064 // Forest with Level Order Traversal.
00065 //
00066 // - no manipulation after construction.
00067 // - level Successors must be set manually
00068 // - implementation nor const correct
00069 //
00070 template<class T>
00071 class Forest {
00072 public:
00073    typedef T Value;
00074    typedef size_t NodeIndex;
00075    typedef size_t Level;
00076 
00077    static const NodeIndex NONODE = -1;
00078 
00079    Forest();
00080    size_t size();
00081    size_t levels();
00082    NodeIndex levelAnchor(const Level&);
00083    NodeIndex push_back(const Value&, NodeIndex);
00084    size_t testInvariant();
00085    std::string asString();
00086    Value& value(NodeIndex);
00087    Level level(NodeIndex);
00088    NodeIndex parent(NodeIndex);
00089    NodeIndex levelOrderSuccessor(NodeIndex);
00090    size_t numberOfChildren(NodeIndex);
00091    NodeIndex child(NodeIndex, const size_t);
00092    void setLevelOrderSuccessor(NodeIndex, NodeIndex);
00093 
00094 private:
00095    struct Node {
00096       Node(const Value& value)
00097          : value_(value), parent_(NONODE),
00098          children_(std::vector<NodeIndex>()),
00099          level_(0), levelOrderSuccessor_(NONODE)
00100       {}
00101       Value value_;
00102       NodeIndex parent_;
00103       std::vector<NodeIndex> children_;
00104       Level level_;
00105       NodeIndex levelOrderSuccessor_;
00106    };
00107    std::vector<Node> nodes_;
00108    std::vector<NodeIndex> levelAnchors_;
00109 };
00110 
00112 
00117 template<class GM, class ACC = Minimizer>
00118 class LazyFlipper : public Inference<GM, ACC> {
00119 public:
00120    typedef ACC AccumulationType;
00121    typedef GM GraphicalModelType;
00122    OPENGM_GM_TYPE_TYPEDEFS;
00123    typedef Forest<IndexType> SubgraphForest;
00124    typedef size_t SubgraphForestNode;
00125    static const SubgraphForestNode NONODE = SubgraphForest::NONODE;
00126    typedef VerboseVisitor<LazyFlipper<GM, ACC> > VerboseVisitorType;
00127    typedef EmptyVisitor<LazyFlipper<GM, ACC> > EmptyVisitorType;
00128    typedef TimingVisitor<LazyFlipper<GM, ACC> > TimingVisitorType;
00129 
00130    struct Parameter
00131    {
00132       template<class StateIterator>
00133       Parameter(
00134          const size_t maxSubgraphSize,
00135          StateIterator stateBegin,
00136          StateIterator stateEnd,
00137          const Tribool inferMultilabel = Tribool::Maybe
00138       )
00139       :  maxSubgraphSize_(maxSubgraphSize),
00140          startingPoint_(stateBegin, stateEnd),
00141          inferMultilabel_(inferMultilabel)
00142       {}
00143 
00144       Parameter(
00145          const size_t maxSubgraphSize = 2,
00146          const Tribool inferMultilabel = Tribool::Maybe
00147       )
00148       :  maxSubgraphSize_(maxSubgraphSize),
00149          startingPoint_(),
00150          inferMultilabel_(inferMultilabel)
00151       {}
00152 
00153       size_t maxSubgraphSize_;
00154       std::vector<LabelType> startingPoint_;
00155       Tribool inferMultilabel_;
00156    };
00157 
00158    LazyFlipper(const GraphicalModelType&, const size_t = 2, const Tribool useMultilabelInference = Tribool::Maybe);
00159    LazyFlipper(const GraphicalModelType& gm, typename LazyFlipper::Parameter param);
00160    template<class StateIterator>
00161       LazyFlipper(const GraphicalModelType&, const size_t, StateIterator, const Tribool useMultilabelInference = Tribool::Maybe);
00162    std::string name() const;
00163    const GraphicalModelType& graphicalModel() const;
00164    const size_t maxSubgraphSize() const;
00165    ValueType value() const;
00166    void setMaxSubgraphSize(const size_t);
00167    void reset();
00168    InferenceTermination infer();
00169    template<class VisitorType>
00170       InferenceTermination infer(VisitorType&);
00171    void setStartingPoint(typename std::vector<LabelType>::const_iterator);
00172    InferenceTermination arg(std::vector<LabelType>&, const size_t = 1)const;
00173 
00174 private:
00175    InferenceTermination inferBinaryLabel();
00176    template<class VisitorType>
00177       InferenceTermination inferBinaryLabel(VisitorType&);
00178    template<class VisitorType>
00179       InferenceTermination inferMultiLabel(VisitorType&); 
00180    InferenceTermination inferMultiLabel(); 
00181 
00182    SubgraphForestNode appendVariableToPath(SubgraphForestNode);
00183    SubgraphForestNode generateFirstPathOfLength(const size_t);
00184    SubgraphForestNode generateNextPathOfSameLength(SubgraphForestNode);
00185    void activateInfluencedVariables(SubgraphForestNode, const size_t);
00186    void deactivateAllVariables(const size_t);
00187    SubgraphForestNode firstActivePath(const size_t);
00188    SubgraphForestNode nextActivePath(SubgraphForestNode, const size_t);
00189    ValueType energyAfterFlip(SubgraphForestNode);
00190    void flip(SubgraphForestNode);
00191    const bool flipMultiLabel(SubgraphForestNode); // ???
00192 
00193    const GraphicalModelType& gm_;
00194    Adjacency variableAdjacency_;
00195    Movemaker<GraphicalModelType> movemaker_;
00196    Tagging<bool> activation_[2];
00197    SubgraphForest subgraphForest_;
00198    size_t maxSubgraphSize_;
00199    Tribool useMultilabelInference_;
00200 };
00201 
00202 // implementation of Tagging
00203 
00204 template<class T>
00205 inline Tagging<T>::Tagging(
00206    const size_t size
00207 )
00208 :  tags_(tag_container_type(size)),
00209    indices_(index_container_type())
00210 {}
00211 
00212 template<class T>
00213 inline void Tagging<T>::append(
00214    const size_t number
00215 )
00216 {
00217    tags_.resize(tags_.size() + number);
00218 }
00219 
00220 // runtime complexity: constant
00221 template<class T>
00222 inline typename Tagging<T>::ValueType
00223 Tagging<T>::tag(
00224    const size_t index
00225 ) const
00226 {
00227    OPENGM_ASSERT(index < tags_.size());
00228    return tags_[index];
00229 }
00230 
00231 // runtime complexity: constant
00232 template<class T>
00233 inline void
00234 Tagging<T>::tag(
00235    const size_t index,
00236    const typename Tagging<T>::ValueType tag
00237 )
00238 {
00239    OPENGM_ASSERT(index < tags_.size());
00240    OPENGM_ASSERT(tag != T()); // no implicit un-tagging
00241    if(tags_[index] == T()) { // so far un-tagged
00242       indices_.push_back(index);
00243    }
00244    tags_[index] = tag;
00245 }
00246 
00247 // untag all
00248 // runtime complexity: linear in indices_.size()
00249 // note the performance gain over linearity in tags_.size()
00250 template<class T>
00251 inline void
00252 Tagging<T>::untag()
00253 {
00254    for(const_iterator it = indices_.begin(); it != indices_.end(); ++it) {
00255       tags_[*it] = T();
00256    }
00257    indices_.clear();
00258 }
00259 
00260 template<class T>
00261 inline typename Tagging<T>::const_iterator
00262 Tagging<T>::begin() const
00263 {
00264    return indices_.begin();
00265 }
00266 
00267 template<class T>
00268 inline typename Tagging<T>::const_iterator
00269 Tagging<T>::end() const
00270 {
00271    return indices_.end();
00272 }
00273 
00274 template<class T>
00275 inline typename Tagging<T>::const_iterator
00276 Tagging<T>::begin()
00277 {
00278    return indices_.begin();
00279 }
00280 
00281 template<class T>
00282 inline typename Tagging<T>::const_iterator
00283 Tagging<T>::end()
00284 {
00285    return indices_.end();
00286 }
00287 
00288 // implementation of Adjacency
00289 inline
00290 Adjacency::Adjacency(
00291    const size_t size
00292 )
00293 :  neighbors_(std::vector<std::set<size_t> >(size))
00294 {}
00295 
00296 inline void
00297 Adjacency::resize(
00298    const size_t size
00299 )
00300 {
00301    neighbors_.resize(size);
00302 }
00303 
00304 inline void
00305 Adjacency::connect
00306 (
00307    const size_t j,
00308    const size_t k
00309 )
00310 {
00311    neighbors_[j].insert(k);
00312    neighbors_[k].insert(j);
00313 }
00314 
00315 inline bool
00316 Adjacency::connected(
00317    const size_t j,
00318    const size_t k
00319 ) const
00320 {
00321    if(neighbors_[j].size() < neighbors_[k].size()) {
00322       if(neighbors_[j].find(k) == neighbors_[j].end()) {
00323          return false;
00324       }
00325       else {
00326          return true;
00327       }
00328    }
00329    else {
00330       if(neighbors_[k].find(j) == neighbors_[k].end()) {
00331          return false;
00332       }
00333       else {
00334          return true;
00335       }
00336    }
00337 }
00338 
00339 inline Adjacency::const_iterator
00340 Adjacency::neighborsBegin(
00341    const size_t index
00342 )
00343 {
00344    return neighbors_[index].begin();
00345 }
00346 
00347 inline Adjacency::const_iterator
00348 Adjacency::neighborsBegin(
00349    const size_t index
00350 ) const
00351 {
00352    return neighbors_[index].begin();
00353 }
00354 
00355 inline Adjacency::const_iterator
00356 Adjacency::neighborsEnd(
00357    const size_t index
00358 )
00359 {
00360    return neighbors_[index].end();
00361 }
00362 
00363 inline Adjacency::const_iterator
00364 Adjacency::neighborsEnd(
00365    const size_t index
00366 ) const
00367 {
00368    return neighbors_[index].end();
00369 }
00370 
00371 // implementation
00372 
00373 template<class T>
00374 inline Forest<T>::Forest()
00375 :  nodes_(std::vector<typename Forest<T>::Node>()),
00376    levelAnchors_(std::vector<typename Forest<T>::NodeIndex>())
00377 {}
00378 
00379 template<class T>
00380 inline size_t
00381 Forest<T>::levels()
00382 {
00383    return levelAnchors_.size();
00384 }
00385 
00386 template<class T>
00387 inline size_t
00388 Forest<T>::size()
00389 {
00390    return nodes_.size();
00391 }
00392 
00393 template<class T>
00394 inline typename Forest<T>::NodeIndex
00395 Forest<T>::levelAnchor(
00396    const typename Forest<T>::Level& level
00397 )
00398 {
00399    OPENGM_ASSERT(level < levels());
00400    return levelAnchors_[level];
00401 }
00402 
00403 template<class T>
00404 inline typename Forest<T>::Value&
00405 Forest<T>::value(
00406    typename Forest<T>::NodeIndex n
00407 )
00408 {
00409    OPENGM_ASSERT(n < nodes_.size());
00410    return nodes_[n].value_;
00411 }
00412 
00413 template<class T>
00414 inline typename Forest<T>::Level
00415 Forest<T>::level(
00416    typename Forest<T>::NodeIndex n
00417 )
00418 {
00419    OPENGM_ASSERT(n < nodes_.size());
00420    return nodes_[n].level_;
00421 }
00422 
00423 template<class T>
00424 inline typename Forest<T>::NodeIndex
00425 Forest<T>::parent(
00426    typename Forest<T>::NodeIndex n
00427 )
00428 {
00429    OPENGM_ASSERT(n < nodes_.size());
00430    return nodes_[n].parent_;
00431 }
00432 
00433 template<class T>
00434 inline typename Forest<T>::NodeIndex
00435 Forest<T>::levelOrderSuccessor(
00436    typename Forest<T>::NodeIndex n
00437 )
00438 {
00439    OPENGM_ASSERT(n < nodes_.size());
00440    return nodes_[n].levelOrderSuccessor_;
00441 }
00442 
00443 template<class T>
00444 inline size_t
00445 Forest<T>::numberOfChildren(
00446    typename Forest<T>::NodeIndex n
00447 )
00448 {
00449    OPENGM_ASSERT(n < nodes_.size());
00450    return nodes_[n].children_.size();
00451 }
00452 
00453 template<class T>
00454 inline typename Forest<T>::NodeIndex
00455 Forest<T>::child(
00456    typename Forest<T>::NodeIndex n,
00457    const size_t j
00458 )
00459 {
00460    OPENGM_ASSERT((n<nodes_.size() && j<nodes_[n].children_.size()));
00461    return nodes_[n].children_[j];
00462 }
00463 
00464 template<class T>
00465 typename Forest<T>::NodeIndex
00466 Forest<T>::push_back(
00467    const Value& value,
00468    typename Forest<T>::NodeIndex parentNodeIndex
00469 )
00470 {
00471    OPENGM_ASSERT((parentNodeIndex == NONODE || parentNodeIndex < nodes_.size()));
00472    // lock here in parallel code
00473    NodeIndex nodeIndex = nodes_.size();
00474    {
00475       Node node(value);
00476       nodes_.push_back(node);
00477       // unlock here in parallel code
00478       OPENGM_ASSERT(nodes_.size() == nodeIndex + 1);  // could fail in parallel code
00479    }
00480    if(parentNodeIndex != NONODE) {
00481       nodes_[nodeIndex].parent_ = parentNodeIndex;
00482       nodes_[parentNodeIndex].children_.push_back(nodeIndex);
00483       nodes_[nodeIndex].level_ = nodes_[parentNodeIndex].level_ + 1;
00484    }
00485    if(nodes_[nodeIndex].level_ >= levelAnchors_.size()) {
00486       OPENGM_ASSERT(levelAnchors_.size() == nodes_[nodeIndex].level_);
00487       levelAnchors_.push_back(nodeIndex);
00488    }
00489    return nodeIndex;
00490 }
00491 
00492 // returns the number of root nodes
00493 template<class T>
00494 size_t
00495 Forest<T>::testInvariant()
00496 {
00497    if(nodes_.size() == 0) {
00498       // tree is empty
00499       OPENGM_ASSERT(levelAnchors_.size() == 0);
00500       return 0;
00501    }
00502    else {
00503       // tree is not empty
00504       OPENGM_ASSERT( levelAnchors_.size() != 0);
00505       size_t numberOfRoots = 0;
00506       size_t nodesVisited = 0;
00507       Level level = 0;
00508       NodeIndex p = levelAnchors_[0];
00509       while(p != NONODE) {
00510          ++nodesVisited;
00511          OPENGM_ASSERT(this->level(p) == level);
00512          if(level == 0) {
00513             // p is a root node index
00514             OPENGM_ASSERT(parent(p) == NONODE);
00515             ++numberOfRoots;
00516          }
00517          else {
00518             // p is not a root node index
00519             OPENGM_ASSERT(parent(p) != NONODE);
00520             // test if p is among the children of its parent:
00521             bool foundP = false;
00522             for(size_t j=0; j<nodes_[parent(p)].children_.size(); ++j) {
00523                if(nodes_[parent(p)].children_[j] == p) {
00524                   foundP = true;
00525                   break;
00526                }
00527             }
00528             OPENGM_ASSERT(foundP)
00529          }
00530          // continue traversal in level-order
00531          if(levelOrderSuccessor(p) != NONODE) {
00532             p = levelOrderSuccessor(p);
00533          }
00534          else {
00535             if(level+1 < levelAnchors_.size()) {
00536                // tree has more levels
00537                ++level;
00538                p = levelAnchors_[level];
00539             }
00540             else {
00541                // tree has no more levels
00542                break;
00543             }
00544          }
00545       }
00546       OPENGM_ASSERT(nodesVisited == nodes_.size());
00547       OPENGM_ASSERT(levels() == level + 1);
00548       return numberOfRoots;
00549    }
00550 }
00551 
00552 template<class T>
00553 std::string
00554 Forest<T>::asString()
00555 {
00556    std::ostringstream out(std::ostringstream::out);
00557    for(size_t level=0; level<levels(); ++level) {
00558       NodeIndex p = levelAnchor(level);
00559       while(p != NONODE) {
00560          // print all variable indices on the path to the root
00561          NodeIndex q = p;
00562          while(q != NONODE) {
00563             // out << value(q) << ' ';
00564             out << value(q)+1 << ' '; // ??? replace by previous line!!!
00565             q = parent(q);
00566          }
00567          out << std::endl;
00568          // proceed
00569          p = levelOrderSuccessor(p);
00570       }
00571    }
00572    return out.str();
00573 }
00574 
00575 template<class T>
00576 inline void
00577 Forest<T>::setLevelOrderSuccessor(
00578    typename Forest<T>::NodeIndex nodeIndex,
00579    typename Forest<T>::NodeIndex successorNodeIndex
00580 )
00581 {
00582    OPENGM_ASSERT((nodeIndex < nodes_.size() && successorNodeIndex < nodes_.size()));
00583    nodes_[nodeIndex].levelOrderSuccessor_ = successorNodeIndex;
00584 }
00585 
00586 // implementation of LazyFlipper
00587 
00588 template<class GM, class ACC>
00589 inline
00590 LazyFlipper<GM, ACC>::LazyFlipper(
00591    const GraphicalModelType& gm,
00592    const size_t maxSubgraphSize,
00593    const Tribool useMultilabelInference
00594 )
00595 :  gm_(gm),
00596    variableAdjacency_(Adjacency(gm.numberOfVariables())),
00597    movemaker_(Movemaker<GM>(gm)),
00598    subgraphForest_(SubgraphForest()),
00599    maxSubgraphSize_(maxSubgraphSize),
00600    useMultilabelInference_(useMultilabelInference)
00601 {
00602    if(gm_.numberOfVariables() == 0) {
00603       throw RuntimeError("The graphical model has no variables.");
00604    }
00605    setMaxSubgraphSize(maxSubgraphSize);
00606    // initialize activation_
00607    activation_[0].append(gm_.numberOfVariables());
00608    activation_[1].append(gm_.numberOfVariables());
00609    // initialize variableAdjacency_
00610    for(size_t j=0; j<gm_.numberOfFactors(); ++j) {
00611       const FactorType& factor = gm_[j];
00612       for(size_t m=0; m<factor.numberOfVariables(); ++m) {
00613          for(size_t n=m+1; n<factor.numberOfVariables(); ++n) {
00614             variableAdjacency_.connect(factor.variableIndex(m), factor.variableIndex(n));
00615          }
00616       }
00617    }
00618 }
00619 
00620 template<class GM, class ACC>
00621 inline
00622 LazyFlipper<GM, ACC>::LazyFlipper(
00623    const GraphicalModelType& gm,
00624    typename LazyFlipper::Parameter param
00625 )
00626 :  gm_(gm),
00627    variableAdjacency_(Adjacency(gm.numberOfVariables())),
00628    movemaker_(Movemaker<GM>(gm)),
00629    subgraphForest_(SubgraphForest()),
00630    maxSubgraphSize_(param.maxSubgraphSize_),
00631    useMultilabelInference_(param.inferMultilabel_)
00632 {
00633    if(gm_.numberOfVariables() == 0) {
00634       throw RuntimeError("The graphical model has no variables.");
00635    }
00636    setMaxSubgraphSize(param.maxSubgraphSize_);
00637    // initialize activation_
00638    activation_[0].append(gm_.numberOfVariables());
00639    activation_[1].append(gm_.numberOfVariables());
00640    // initialize variableAdjacency_
00641    for(size_t j=0; j<gm_.numberOfFactors(); ++j) {
00642       const FactorType& factor = gm_[j];
00643       for(size_t m=0; m<factor.numberOfVariables(); ++m) {
00644          for(size_t n=m+1; n<factor.numberOfVariables(); ++n) {
00645             variableAdjacency_.connect(factor.variableIndex(m), factor.variableIndex(n));
00646          }
00647       }
00648    }
00649    if(param.startingPoint_.size() == gm_.numberOfVariables()) {
00650       movemaker_.initialize(param.startingPoint_.begin());
00651    }
00652 }
00653 
00654 template<class GM, class ACC>
00655 inline void
00656 LazyFlipper<GM, ACC>::reset()
00657 {}
00658 
00660 template<class GM, class ACC>
00661 template<class StateIterator>
00662 inline
00663 LazyFlipper<GM, ACC>::LazyFlipper(
00664    const GraphicalModelType& gm,
00665    const size_t maxSubgraphSize,
00666    StateIterator it,
00667    const Tribool useMultilabelInference
00668 )
00669 :  gm_(gm),
00670    variableAdjacency_(Adjacency(gm_.numberOfVariables())),
00671    movemaker_(Movemaker<GM>(gm, it)),
00672    subgraphForest_(SubgraphForest()),
00673    maxSubgraphSize_(2),
00674    useMultilabelInference_(useMultilabelInference)
00675 {
00676    if(gm_.numberOfVariables() == 0) {
00677       throw RuntimeError("The graphical model has no variables.");
00678    }
00679    setMaxSubgraphSize(maxSubgraphSize);
00680    // initialize activation_
00681    activation_[0].append(gm_.numberOfVariables());
00682    activation_[1].append(gm_.numberOfVariables());
00683    // initialize variableAdjacency_
00684    for(size_t j=0; j<gm_.numberOfFactors(); ++j) {
00685       const FactorType& factor = gm_[j];
00686       for(size_t m=0; m<factor.numberOfVariables(); ++m) {
00687          for(size_t n=m+1; n<factor.numberOfVariables(); ++n) {
00688             variableAdjacency_.connect(factor.variableIndex(m), factor.variableIndex(n));
00689          }
00690       }
00691    }
00692 }
00693 
00694 template<class GM, class ACC>
00695 inline void
00696 LazyFlipper<GM, ACC>::setStartingPoint(
00697    typename std::vector<typename LazyFlipper<GM, ACC>::LabelType>::const_iterator begin
00698 ) {
00699    movemaker_.initialize(begin);
00700 }
00701 
00702 template<class GM, class ACC>
00703 inline std::string
00704 LazyFlipper<GM, ACC>::name() const
00705 {
00706    return "LazyFlipper";
00707 }
00708 
00709 template<class GM, class ACC>
00710 inline const typename LazyFlipper<GM, ACC>::GraphicalModelType&
00711 LazyFlipper<GM, ACC>::graphicalModel() const
00712 {
00713    return gm_;
00714 }
00715 
00716 template<class GM, class ACC>
00717 inline const size_t
00718 LazyFlipper<GM, ACC>::maxSubgraphSize() const
00719 {
00720    return maxSubgraphSize_;
00721 }
00722 
00723 template<class GM, class ACC>
00724 inline void
00725 LazyFlipper<GM, ACC>::setMaxSubgraphSize(
00726    const size_t maxSubgraphSize
00727 )
00728 {
00729    if(maxSubgraphSize < 1) {
00730       throw RuntimeError("Maximum subgraph size < 1.");
00731    }
00732    else {
00733       maxSubgraphSize_ = maxSubgraphSize;
00734    }
00735 }
00736 
00738 template<class GM, class ACC>
00739 template<class VisitorType>
00740 inline InferenceTermination
00741 LazyFlipper<GM, ACC>::infer(
00742    VisitorType& visitor
00743 )
00744 {
00745    bool multiLabel;
00746    if(this->useMultilabelInference_ == true) {
00747       multiLabel = true;
00748    }
00749    else if(this->useMultilabelInference_ == false) {
00750       multiLabel = false;
00751    }
00752    else {
00753       multiLabel = false;
00754       for(size_t i=0; i<gm_.numberOfVariables(); ++i) {
00755          if(gm_.numberOfLabels(i) != 2) {
00756             multiLabel = true;
00757             break;
00758          }
00759       }
00760    }
00761 
00762    if(multiLabel) {
00763       return this->inferMultiLabel(visitor);
00764    }
00765    else {
00766       return this->inferBinaryLabel(visitor);
00767    }
00768 }
00769 
00771 template<class GM, class ACC>
00772 inline InferenceTermination
00773 LazyFlipper<GM, ACC>::infer()
00774 {
00775    EmptyVisitorType visitor;
00776    return this->infer(visitor);
00777 }
00778 
00779 template<class GM, class ACC>
00780 template<class VisitorType>
00781 InferenceTermination
00782 LazyFlipper<GM, ACC>::inferBinaryLabel(
00783    VisitorType& visitor
00784 ) 
00785 {
00786    size_t length = 1;
00787    ValueType bound;
00788    ACC::neutral(bound);
00789    visitor.begin(*this, movemaker_.value(), bound, length, subgraphForest_.size());
00790    for(;;) {
00791       visitor(*this, movemaker_.value(), bound, length, subgraphForest_.size());
00792       SubgraphForestNode p = generateFirstPathOfLength(length);
00793       if(p == NONODE) {
00794          break;
00795       }
00796       else {
00797          while(p != NONODE) {
00798             if(AccumulationType::bop(energyAfterFlip(p), movemaker_.value())) {
00799                flip(p);
00800                activateInfluencedVariables(p, 0);
00801                visitor(*this, movemaker_.value(), bound, length, subgraphForest_.size());
00802             }
00803             p = generateNextPathOfSameLength(p);
00804          }
00805          size_t currentActivationList = 0;
00806          size_t nextActivationList = 1;
00807          for(;;) {
00808             SubgraphForestNode p2 = firstActivePath(currentActivationList);
00809             if(p2 == NONODE) {
00810                break;
00811             }
00812             else {
00813                while(p2 != NONODE) {
00814                   if(AccumulationType::bop(energyAfterFlip(p2), movemaker_.value())) {
00815                      flip(p2);
00816                      activateInfluencedVariables(p2, nextActivationList);
00817                      visitor(*this, movemaker_.value(), bound, length, subgraphForest_.size());
00818                   }
00819                   p2 = nextActivePath(p2, currentActivationList);
00820                }
00821                deactivateAllVariables(currentActivationList);
00822                nextActivationList = 1 - nextActivationList;
00823                currentActivationList = 1 - currentActivationList;
00824             }
00825          }
00826       }
00827       if(length == maxSubgraphSize_) {
00828          break;
00829       }
00830       else {
00831          ++length;
00832       }
00833    }
00834    // assertion testing
00835    if(!NO_DEBUG) {
00836       subgraphForest_.testInvariant();
00837    }
00838    visitor.end(*this, movemaker_.value(), bound, length, subgraphForest_.size());
00839    // diagnose
00840    // std::cout << subgraphForest_.asString();
00841    return NORMAL;
00842 }
00843 
00844 template<class GM, class ACC>
00845 inline InferenceTermination
00846 LazyFlipper<GM, ACC>::inferBinaryLabel()
00847 {
00848    EmptyVisitorType v;
00849    return infer(v);
00850 }
00851 
00852 template<class GM, class ACC>
00853 template<class VisitorType>
00854 InferenceTermination
00855 LazyFlipper<GM, ACC>::inferMultiLabel(
00856    VisitorType& visitor
00857 )
00858 {
00859    size_t length = 1;
00860    visitor.begin(*this, movemaker_.value(), movemaker_.value(), length, subgraphForest_.size());
00861    for(;;) {
00862       visitor(*this, movemaker_.value(), movemaker_.value(), length, subgraphForest_.size());
00863       SubgraphForestNode p = generateFirstPathOfLength(length);
00864       if(p == NONODE) {
00865          break;
00866       }
00867       else {
00868          while(p != NONODE) {
00869             bool flipped = flipMultiLabel(p);
00870             if(flipped) {
00871                activateInfluencedVariables(p, 0);
00872                visitor(*this, movemaker_.value(), movemaker_.value(), length, subgraphForest_.size());
00873             }
00874             p = generateNextPathOfSameLength(p);
00875          }
00876          size_t currentActivationList = 0;
00877          size_t nextActivationList = 1;
00878          for(;;) {
00879             SubgraphForestNode p2 = firstActivePath(currentActivationList);
00880             if(p2 == NONODE) {
00881                break;
00882             }
00883             else {
00884                while(p2 != NONODE) {
00885                   bool flipped = flipMultiLabel(p2);
00886                   if(flipped) {
00887                      activateInfluencedVariables(p2, nextActivationList);
00888                      visitor(*this, movemaker_.value(), movemaker_.value(), length, subgraphForest_.size());
00889                   }
00890                   p2 = nextActivePath(p2, currentActivationList);
00891                }
00892                deactivateAllVariables(currentActivationList);
00893                nextActivationList = 1 - nextActivationList;
00894                currentActivationList = 1 - currentActivationList;
00895             }
00896          }
00897       }
00898       if(length == maxSubgraphSize_) {
00899          break;
00900       }
00901       else {
00902          ++length;
00903       }
00904    }
00905    // assertion testing
00906    if(!NO_DEBUG) {
00907       subgraphForest_.testInvariant();
00908    }
00909    // diagnose
00910    // std::cout << subgraphForest_.asString();
00911    visitor.end(*this, movemaker_.value(), movemaker_.value(), length, subgraphForest_.size());
00912    return NORMAL;
00913 }
00914 
00915 template<class GM, class ACC>
00916 inline InferenceTermination
00917 LazyFlipper<GM, ACC>::inferMultiLabel()
00918 {
00919    EmptyVisitorType visitor;
00920    return this->inferMultiLabel(visitor);
00921 }
00922 
00923 template<class GM, class ACC>
00924 inline InferenceTermination
00925 LazyFlipper<GM, ACC>::arg(
00926    std::vector<LabelType>& arg,
00927    const size_t n
00928 ) const
00929 {
00930    if(n > 1) {
00931       return UNKNOWN;
00932    }
00933    else {
00934       arg.resize(gm_.numberOfVariables());
00935       for(size_t j=0; j<gm_.numberOfVariables(); ++j) {
00936          arg[j] = movemaker_.state(j);
00937       }
00938       return NORMAL;
00939    }
00940 }
00941 
00942 template<class GM, class ACC>
00943 inline typename LazyFlipper<GM, ACC>::ValueType
00944 LazyFlipper<GM, ACC>::value() const
00945 {
00946    return movemaker_.value();
00947 }
00948 
00949 // Append the next possible variable to a node in the subgraph tree.
00950 // The null pointer is returned if no variable can be appended.
00951 template<class GM, class ACC>
00952 typename LazyFlipper<GM, ACC>::SubgraphForestNode
00953 LazyFlipper<GM, ACC>::appendVariableToPath(
00954    typename LazyFlipper<GM, ACC>::SubgraphForestNode p // input
00955 )
00956 {
00957    // collect variable indices on path
00958    std::vector<size_t> variableIndicesOnPath(subgraphForest_.level(p) + 1);
00959    {
00960       SubgraphForestNode p2 = p;
00961       for(size_t j=0; j<=subgraphForest_.level(p); ++j) {
00962          OPENGM_ASSERT(p2 != NONODE);
00963          variableIndicesOnPath[subgraphForest_.level(p) - j] = subgraphForest_.value(p2);
00964          p2 = subgraphForest_.parent(p2);
00965       }
00966       OPENGM_ASSERT(p2 == NONODE);
00967    }
00968    // find the mininum and maximum variable index on the path
00969    size_t minVI = variableIndicesOnPath[0];
00970    size_t maxVI = variableIndicesOnPath[0];
00971    for(size_t j=1; j<variableIndicesOnPath.size(); ++j) {
00972       if(variableIndicesOnPath[j] > maxVI) {
00973          maxVI = variableIndicesOnPath[j];
00974       }
00975    }
00976    // find the maximum variable index among the children of p.
00977    // the to be appended variable must have a greater index.
00978    if(subgraphForest_.numberOfChildren(p) > 0) {
00979       size_t maxChildIndex = subgraphForest_.numberOfChildren(p) - 1;
00980       minVI = subgraphForest_.value(subgraphForest_.child(p, maxChildIndex));
00981    }
00982    // build set of candidate variable indices for appending
00983    std::set<size_t> candidateVariableIndices;
00984    {
00985       SubgraphForestNode q = p;
00986       while(q != NONODE) {
00987          for(Adjacency::const_iterator it = variableAdjacency_.neighborsBegin(subgraphForest_.value(q));
00988             it != variableAdjacency_.neighborsEnd(subgraphForest_.value(q)); ++it) {
00989                candidateVariableIndices.insert(*it);
00990          }
00991          q = subgraphForest_.parent(q);
00992       }
00993    }
00994    // append candidate if possible
00995    for(std::set<size_t>::const_iterator it = candidateVariableIndices.begin();
00996       it != candidateVariableIndices.end(); ++it) {
00997          // for all variables adjacenct to the one at node p
00998          if(*it > minVI && std::find(variableIndicesOnPath.begin(), variableIndicesOnPath.end(), *it) == variableIndicesOnPath.end()) {
00999             // the variable index *it is not smaller than the lower bound AND
01000             // greater than the minimum variable index on the path AND
01001             // is not itself on the path (??? consider tagging instead of
01002             // searching in the previous if-condition)
01003             if(*it > maxVI) {
01004                // *it is greater than the largest variable index on the path
01005                return subgraphForest_.push_back(*it, p); // append to path
01006             }
01007             else {
01008                // *it is not the greatest variable index on the path.
01009                for(size_t j=1; j<variableIndicesOnPath.size(); ++j) {
01010                   if(variableAdjacency_.connected(variableIndicesOnPath[j-1], *it)) {
01011                      // *it could have been added as a child of
01012                      // variableIndicesOnPath[j-1]
01013                      for(size_t k=j; k<variableIndicesOnPath.size(); ++k) {
01014                         if(*it < variableIndicesOnPath[k]) {
01015                            // adding *it as a child of variableIndicesOnPath[j-1]
01016                            // would have made the path cheaper
01017                            goto doNotAppend; // escape loop over j
01018                         }
01019                      }
01020                   }
01021                }
01022                // *it could not have been introduced cheaper
01023                // append to path:
01024                return subgraphForest_.push_back(*it, p);
01025 doNotAppend:;
01026             }
01027          }
01028    }
01029    // no neighbor of p could be appended
01030    return NONODE;
01031 }
01032 
01033 template<class GM, class ACC>
01034 typename LazyFlipper<GM, ACC>::SubgraphForestNode
01035 LazyFlipper<GM, ACC>::generateFirstPathOfLength(
01036    const size_t length
01037 )
01038 {
01039    OPENGM_ASSERT(length > 0);
01040    if(length > gm_.numberOfVariables()) {
01041       return NONODE;
01042    }
01043    else {
01044       if(length == 1) {
01045          SubgraphForestNode p = subgraphForest_.push_back(0, NONODE);
01046          // variable index = 0, parent = NONODE
01047          return p;
01048       }
01049       else {
01050          SubgraphForestNode p = subgraphForest_.levelAnchor(length-2);
01051          while(p != NONODE) {
01052             SubgraphForestNode p2 = appendVariableToPath(p);
01053             if(p2 != NONODE) { // append succeeded
01054                return p2;
01055             }
01056             else { // append failed
01057                p = subgraphForest_.levelOrderSuccessor(p);
01058             }
01059          }
01060          return NONODE;
01061       }
01062    }
01063 }
01064 
01065 template<class GM, class ACC>
01066 typename LazyFlipper<GM, ACC>::SubgraphForestNode
01067 LazyFlipper<GM, ACC>::generateNextPathOfSameLength(
01068    SubgraphForestNode predecessor
01069 )
01070 {
01071    if(subgraphForest_.level(predecessor) == 0) {
01072       if(subgraphForest_.value(predecessor) + 1 < gm_.numberOfVariables()) {
01073          SubgraphForestNode newNode =
01074             subgraphForest_.push_back(subgraphForest_.value(predecessor) + 1, NONODE);
01075          subgraphForest_.setLevelOrderSuccessor(predecessor, newNode);
01076          return newNode;
01077       }
01078       else {
01079          // no more variables
01080          return NONODE;
01081       }
01082    }
01083    else {
01084       for(SubgraphForestNode parent = subgraphForest_.parent(predecessor);
01085          parent != NONODE; parent = subgraphForest_.levelOrderSuccessor(parent) ) {
01086             SubgraphForestNode newNode = appendVariableToPath(parent);
01087             if(newNode != NONODE) {
01088                // a variable has been appended
01089                subgraphForest_.setLevelOrderSuccessor(predecessor, newNode);
01090                return newNode;
01091             }
01092       }
01093       return NONODE;
01094    }
01095 }
01096 
01097 template<class GM, class ACC>
01098 void
01099 LazyFlipper<GM, ACC>::activateInfluencedVariables(
01100    SubgraphForestNode p,
01101    const size_t activationListIndex
01102 )
01103 {
01104    OPENGM_ASSERT(activationListIndex < 2);
01105    while(p != NONODE) {
01106       activation_[activationListIndex].tag(subgraphForest_.value(p), true);
01107       for(Adjacency::const_iterator it = variableAdjacency_.neighborsBegin(subgraphForest_.value(p));
01108          it != variableAdjacency_.neighborsEnd(subgraphForest_.value(p)); ++it) {
01109             activation_[activationListIndex].tag(*it, true);
01110       }
01111       p = subgraphForest_.parent(p);
01112    }
01113 }
01114 
01115 template<class GM, class ACC>
01116 inline void
01117 LazyFlipper<GM, ACC>::deactivateAllVariables(
01118    const size_t activationListIndex
01119 )
01120 {
01121    OPENGM_ASSERT(activationListIndex < 2);
01122    activation_[activationListIndex].untag();
01123 }
01124 
01125 template<class GM, class ACC>
01126 typename LazyFlipper<GM, ACC>::SubgraphForestNode
01127 LazyFlipper<GM, ACC>::firstActivePath(
01128    const size_t activationListIndex
01129 )
01130 {
01131    if(subgraphForest_.levels() == 0) {
01132       return NONODE;
01133    }
01134    else {
01135       // ??? improve code: no search, store reference
01136       SubgraphForestNode p = subgraphForest_.levelAnchor(0);
01137       while(p != NONODE) {
01138          if(activation_[activationListIndex].tag(subgraphForest_.value(p))) {
01139             return p;
01140          }
01141          p = subgraphForest_.levelOrderSuccessor(p);
01142       }
01143       return NONODE;
01144    }
01145 }
01146 
01147 // \todo next version: improve code: searching over all paths and all 
01148 // variables of each path for active variables is certainly not the ideal 
01149 // way
01150 template<class GM, class ACC>
01151 typename LazyFlipper<GM, ACC>::SubgraphForestNode
01152 LazyFlipper<GM, ACC>::nextActivePath(
01153    SubgraphForestNode predecessor,
01154    const size_t activationListIndex
01155 )
01156 {
01157    for(;;) {
01158       if(subgraphForest_.levelOrderSuccessor(predecessor) == NONODE) {
01159          if(subgraphForest_.level(predecessor) + 1 < subgraphForest_.levels()) {
01160             // there are more levels in the tree
01161             predecessor = subgraphForest_.levelAnchor(subgraphForest_.level(predecessor) + 1);
01162          }
01163          else {
01164             // there are no more levels in the tree
01165             return NONODE;
01166          }
01167       }
01168       else {
01169          // predecessor is not the last node on its level
01170          predecessor = subgraphForest_.levelOrderSuccessor(predecessor);
01171       }
01172       SubgraphForestNode p = predecessor;
01173       while(p != NONODE) {
01174          // search along path for active variables:
01175          if(activation_[activationListIndex].tag(subgraphForest_.value(p))) {
01176             return predecessor;
01177          }
01178          p = subgraphForest_.parent(p);
01179       }
01180    }
01181 }
01182 
01183 template<class GM, class ACC>
01184 inline typename LazyFlipper<GM, ACC>::ValueType
01185 LazyFlipper<GM, ACC>::energyAfterFlip(
01186    SubgraphForestNode node
01187 )
01188 {
01189    size_t numberOfFlippedVariables = subgraphForest_.level(node) + 1;
01190    std::vector<size_t> flippedVariableIndices(numberOfFlippedVariables);
01191    std::vector<LabelType> flippedVariableStates(numberOfFlippedVariables);
01192    for(size_t j=0; j<numberOfFlippedVariables; ++j) {
01193       OPENGM_ASSERT(node != NONODE);
01194       flippedVariableIndices[j] = subgraphForest_.value(node);
01195       // binary flip:
01196       flippedVariableStates[j] = 1 - movemaker_.state(subgraphForest_.value(node));
01197       node = subgraphForest_.parent(node);
01198    }
01199    OPENGM_ASSERT(node == NONODE);
01200    return movemaker_.valueAfterMove(flippedVariableIndices.begin(),
01201       flippedVariableIndices.end(), flippedVariableStates.begin());
01202 
01203 }
01204 
01205 template<class GM, class ACC>
01206 inline void
01207 LazyFlipper<GM, ACC>::flip(
01208    SubgraphForestNode node
01209 )
01210 {
01211    size_t numberOfFlippedVariables = subgraphForest_.level(node) + 1;
01212    std::vector<size_t> flippedVariableIndices(numberOfFlippedVariables);
01213    std::vector<LabelType> flippedVariableStates(numberOfFlippedVariables);
01214    for(size_t j=0; j<numberOfFlippedVariables; ++j) {
01215       OPENGM_ASSERT(node != NONODE)
01216          flippedVariableIndices[j] = subgraphForest_.value(node);
01217       // binary flip:
01218       flippedVariableStates[j] = 1 - movemaker_.state(subgraphForest_.value(node));
01219       node = subgraphForest_.parent(node);
01220    }
01221    OPENGM_ASSERT(node == NONODE);
01222    movemaker_.move(flippedVariableIndices.begin(),
01223       flippedVariableIndices.end(), flippedVariableStates.begin());
01224 }
01225 
01226 template<class GM, class ACC>
01227 inline const bool
01228 LazyFlipper<GM, ACC>::flipMultiLabel(
01229    SubgraphForestNode node
01230 )
01231 {
01232    size_t numberOfVariables = subgraphForest_.level(node) + 1;
01233    std::vector<size_t> variableIndices(numberOfVariables);
01234    for(size_t j=0; j<numberOfVariables; ++j) {
01235       OPENGM_ASSERT(node != NONODE);
01236       variableIndices[j] = subgraphForest_.value(node);
01237       node = subgraphForest_.parent(node);
01238    }
01239    OPENGM_ASSERT(node == NONODE);
01240    ValueType energy = movemaker_.value();
01241    movemaker_.template moveOptimallyWithAllLabelsChanging<AccumulationType>(variableIndices.begin(), variableIndices.end());
01242    if(AccumulationType::bop(movemaker_.value(), energy)) {
01243       return true;
01244    }
01245    else {
01246       return false;
01247    }
01248 }
01249 
01250 } // namespace opengm
01251 
01252 #endif // #ifndef OPENGM_LAZYFLIPPER_HXX
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Mon Jun 17 16:31:03 2013 for OpenGM by  doxygen 1.6.3