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();
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
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
00065
00066
00067
00068
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
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
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
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());
00241 if(tags_[index] == T()) {
00242 indices_.push_back(index);
00243 }
00244 tags_[index] = tag;
00245 }
00246
00247
00248
00249
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
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
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
00473 NodeIndex nodeIndex = nodes_.size();
00474 {
00475 Node node(value);
00476 nodes_.push_back(node);
00477
00478 OPENGM_ASSERT(nodes_.size() == nodeIndex + 1);
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
00493 template<class T>
00494 size_t
00495 Forest<T>::testInvariant()
00496 {
00497 if(nodes_.size() == 0) {
00498
00499 OPENGM_ASSERT(levelAnchors_.size() == 0);
00500 return 0;
00501 }
00502 else {
00503
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
00514 OPENGM_ASSERT(parent(p) == NONODE);
00515 ++numberOfRoots;
00516 }
00517 else {
00518
00519 OPENGM_ASSERT(parent(p) != NONODE);
00520
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
00531 if(levelOrderSuccessor(p) != NONODE) {
00532 p = levelOrderSuccessor(p);
00533 }
00534 else {
00535 if(level+1 < levelAnchors_.size()) {
00536
00537 ++level;
00538 p = levelAnchors_[level];
00539 }
00540 else {
00541
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
00561 NodeIndex q = p;
00562 while(q != NONODE) {
00563
00564 out << value(q)+1 << ' ';
00565 q = parent(q);
00566 }
00567 out << std::endl;
00568
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
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
00607 activation_[0].append(gm_.numberOfVariables());
00608 activation_[1].append(gm_.numberOfVariables());
00609
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
00638 activation_[0].append(gm_.numberOfVariables());
00639 activation_[1].append(gm_.numberOfVariables());
00640
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
00681 activation_[0].append(gm_.numberOfVariables());
00682 activation_[1].append(gm_.numberOfVariables());
00683
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
00835 if(!NO_DEBUG) {
00836 subgraphForest_.testInvariant();
00837 }
00838 visitor.end(*this, movemaker_.value(), bound, length, subgraphForest_.size());
00839
00840
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
00906 if(!NO_DEBUG) {
00907 subgraphForest_.testInvariant();
00908 }
00909
00910
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
00950
00951 template<class GM, class ACC>
00952 typename LazyFlipper<GM, ACC>::SubgraphForestNode
00953 LazyFlipper<GM, ACC>::appendVariableToPath(
00954 typename LazyFlipper<GM, ACC>::SubgraphForestNode p
00955 )
00956 {
00957
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
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
00977
00978 if(subgraphForest_.numberOfChildren(p) > 0) {
00979 size_t maxChildIndex = subgraphForest_.numberOfChildren(p) - 1;
00980 minVI = subgraphForest_.value(subgraphForest_.child(p, maxChildIndex));
00981 }
00982
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
00995 for(std::set<size_t>::const_iterator it = candidateVariableIndices.begin();
00996 it != candidateVariableIndices.end(); ++it) {
00997
00998 if(*it > minVI && std::find(variableIndicesOnPath.begin(), variableIndicesOnPath.end(), *it) == variableIndicesOnPath.end()) {
00999
01000
01001
01002
01003 if(*it > maxVI) {
01004
01005 return subgraphForest_.push_back(*it, p);
01006 }
01007 else {
01008
01009 for(size_t j=1; j<variableIndicesOnPath.size(); ++j) {
01010 if(variableAdjacency_.connected(variableIndicesOnPath[j-1], *it)) {
01011
01012
01013 for(size_t k=j; k<variableIndicesOnPath.size(); ++k) {
01014 if(*it < variableIndicesOnPath[k]) {
01015
01016
01017 goto doNotAppend;
01018 }
01019 }
01020 }
01021 }
01022
01023
01024 return subgraphForest_.push_back(*it, p);
01025 doNotAppend:;
01026 }
01027 }
01028 }
01029
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
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) {
01054 return p2;
01055 }
01056 else {
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
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
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
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
01148
01149
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
01161 predecessor = subgraphForest_.levelAnchor(subgraphForest_.level(predecessor) + 1);
01162 }
01163 else {
01164
01165 return NONODE;
01166 }
01167 }
01168 else {
01169
01170 predecessor = subgraphForest_.levelOrderSuccessor(predecessor);
01171 }
01172 SubgraphForestNode p = predecessor;
01173 while(p != NONODE) {
01174
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
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
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 }
01251
01252 #endif // #ifndef OPENGM_LAZYFLIPPER_HXX