alphaexpansionfusion.hxx

Go to the documentation of this file.
00001 #pragma once
00002 #ifndef OPENGM_ALPHAEXPANSIONFUSION_HXX
00003 #define OPENGM_ALPHAEXPANSIONSUSION_HXX
00004 
00005 #include "opengm/inference/inference.hxx"
00006 #include "opengm/inference/visitors/visitor.hxx"
00007 #include "opengm/inference/fix-fusion/fusion-move.hpp"
00008 #include "QPBO.h"
00009 
00010 namespace opengm {
00011 
00019 template<class GM, class ACC>
00020 class AlphaExpansionFusion : public Inference<GM, ACC>
00021 {
00022 public:
00023    typedef GM GraphicalModelType; 
00024    typedef ACC AccumulationType;
00025    OPENGM_GM_TYPE_TYPEDEFS;
00026    typedef VerboseVisitor<AlphaExpansionFusion<GM,ACC> > VerboseVisitorType;
00027    typedef TimingVisitor<AlphaExpansionFusion<GM,ACC> > TimingVisitorType;
00028    typedef EmptyVisitor<AlphaExpansionFusion<GM,ACC> > EmptyVisitorType;
00029 
00030    struct Parameter {
00031       enum LabelingIntitialType {DEFAULT_LABEL, RANDOM_LABEL, LOCALOPT_LABEL, EXPLICIT_LABEL};
00032       enum OrderType {DEFAULT_ORDER, RANDOM_ORDER, EXPLICIT_ORDER};
00033 
00034       Parameter
00035       (
00036          const size_t maxNumberOfSteps  = 1000
00037       )
00038       :  maxNumberOfSteps_(maxNumberOfSteps),
00039          labelInitialType_(DEFAULT_LABEL),
00040          orderType_(DEFAULT_ORDER),
00041          randSeedOrder_(0),
00042          randSeedLabel_(0),
00043          labelOrder_(),
00044          label_()
00045       {}
00046 
00047       size_t maxNumberOfSteps_;
00048       LabelingIntitialType labelInitialType_;
00049       OrderType orderType_;
00050       unsigned int randSeedOrder_;
00051       unsigned int randSeedLabel_;
00052       std::vector<LabelType> labelOrder_;
00053       std::vector<LabelType> label_;
00054    };
00055 
00056    AlphaExpansionFusion(const GraphicalModelType&, Parameter para = Parameter());
00057 
00058    std::string name() const;
00059    const GraphicalModelType& graphicalModel() const;
00060    template<class StateIterator>
00061       void setState(StateIterator, StateIterator);
00062    InferenceTermination infer();
00063    void reset();
00064    template<class Visitor>
00065       InferenceTermination infer(Visitor& visitor);
00066    void setStartingPoint(typename std::vector<LabelType>::const_iterator);
00067    InferenceTermination arg(std::vector<LabelType>&, const size_t = 1) const;
00068 
00069 private:
00070    const GraphicalModelType& gm_;
00071    Parameter parameter_; 
00072    static const size_t maxOrder_ =10;
00073    std::vector<LabelType> label_;
00074    std::vector<LabelType> labelList_;
00075    size_t maxState_;
00076    size_t alpha_;
00077    size_t counter_;
00078    void incrementAlpha();
00079    void setLabelOrder(std::vector<LabelType>& l);
00080    void setLabelOrderRandom(unsigned int);
00081    void setInitialLabel(std::vector<LabelType>& l);
00082    void setInitialLabelLocalOptimal();
00083    void setInitialLabelRandom(unsigned int);
00084    template<class INF>
00085    void addUnary(INF&, const size_t var, const ValueType v0, const ValueType v1);
00086    template<class INF>
00087    void addPairwise(INF&, const size_t var1, const size_t var2, const ValueType v0, const ValueType v1, const ValueType v2, const ValueType v3);
00088 };
00089 
00090 template<class GM, class ACC>
00091 inline std::string
00092 AlphaExpansionFusion<GM, ACC>::name() const
00093 {
00094    return "Alpha-Expansion-Fusion";
00095 }
00096 
00097 template<class GM, class ACC>
00098 inline const typename AlphaExpansionFusion<GM, ACC>::GraphicalModelType&
00099 AlphaExpansionFusion<GM, ACC>::graphicalModel() const
00100 {
00101    return gm_;
00102 }
00103 
00104 template<class GM, class ACC>
00105 template<class StateIterator>
00106 inline void
00107 AlphaExpansionFusion<GM, ACC>::setState
00108 (
00109    StateIterator begin,
00110    StateIterator end
00111 )
00112 {
00113    label_.assign(begin, end);
00114 }
00115 
00116 template<class GM, class ACC>
00117 inline void
00118 AlphaExpansionFusion<GM,ACC>::setStartingPoint
00119 (
00120    typename std::vector<typename AlphaExpansionFusion<GM,ACC>::LabelType>::const_iterator begin
00121 ) {
00122    try{
00123       label_.assign(begin, begin+gm_.numberOfVariables());
00124    }
00125    catch(...) {
00126       throw RuntimeError("unsuitable starting point");
00127    }
00128 }
00129 
00130 template<class GM, class ACC>
00131 inline
00132 AlphaExpansionFusion<GM, ACC>::AlphaExpansionFusion
00133 (
00134    const GraphicalModelType& gm,
00135    Parameter para
00136 )
00137 :  gm_(gm),
00138    parameter_(para),
00139    maxState_(0)
00140 {
00141    for(size_t j=0; j<gm_.numberOfFactors(); ++j) {
00142       if(gm_[j].numberOfVariables() > maxOrder_) {
00143          throw RuntimeError("This implementation of Alpha-Expansion-Fusion supports only factors of this order! Increase the constant maxOrder_!");
00144       }
00145    }
00146    for(size_t i=0; i<gm_.numberOfVariables(); ++i) {
00147       size_t numSt = gm_.numberOfLabels(i);
00148       if(numSt > maxState_) {
00149          maxState_ = numSt;
00150       }
00151    }
00152 
00153    if(parameter_.labelInitialType_ == Parameter::RANDOM_LABEL) {
00154       setInitialLabelRandom(parameter_.randSeedLabel_);
00155    }
00156    else if(parameter_.labelInitialType_ == Parameter::LOCALOPT_LABEL) {
00157       setInitialLabelLocalOptimal();
00158    }
00159    else if(parameter_.labelInitialType_ == Parameter::EXPLICIT_LABEL) {
00160       setInitialLabel(parameter_.label_);
00161    }
00162    else{
00163       label_.resize(gm_.numberOfVariables(), 0);
00164    }
00165 
00166 
00167    if(parameter_.orderType_ == Parameter::RANDOM_ORDER) {
00168       setLabelOrderRandom(parameter_.randSeedOrder_);
00169    }
00170    else if(parameter_.orderType_ == Parameter::EXPLICIT_ORDER) {
00171       setLabelOrder(parameter_.labelOrder_);
00172    }
00173    else{
00174       labelList_.resize(maxState_);
00175       for(size_t i=0; i<maxState_; ++i)
00176          labelList_[i] = i;
00177    }
00178 
00179    counter_ = 0;
00180    alpha_   = labelList_[counter_];
00181 }
00182 
00183 // reset assumes that the structure of
00184 // the graphical model has not changed
00185 template<class GM, class ACC>
00186 inline void
00187 AlphaExpansionFusion<GM, ACC>::reset() {
00188    if(parameter_.labelInitialType_ == Parameter::RANDOM_LABEL) {
00189       setInitialLabelRandom(parameter_.randSeedLabel_);
00190    }
00191    else if(parameter_.labelInitialType_ == Parameter::LOCALOPT_LABEL) {
00192       setInitialLabelLocalOptimal();
00193    }
00194    else if(parameter_.labelInitialType_ == Parameter::EXPLICIT_LABEL) {
00195       setInitialLabel(parameter_.label_);
00196    }
00197    else{
00198       std::fill(label_.begin(),label_.end(),0);
00199    }
00200 
00201 
00202    if(parameter_.orderType_ == Parameter::RANDOM_ORDER) {
00203       setLabelOrderRandom(parameter_.randSeedOrder_);
00204    }
00205    else if(parameter_.orderType_ == Parameter::EXPLICIT_ORDER) {
00206       setLabelOrder(parameter_.labelOrder_);
00207    }
00208    else{
00209       for(size_t i=0; i<maxState_; ++i)
00210          labelList_[i] = i;
00211    }
00212    counter_ = 0;
00213    alpha_   = labelList_[counter_];
00214 }
00215 
00216 template<class GM, class ACC>
00217 template<class INF>
00218 inline void
00219 AlphaExpansionFusion<GM, ACC>::addUnary
00220 (
00221    INF& inf,
00222    const size_t var1,
00223    const ValueType v0,
00224    const ValueType v1
00225 ) {
00226    inf.AddUnaryTerm((int) (var1), v0, v1);
00227 }
00228 
00229 template<class GM, class ACC>
00230 template<class INF>
00231 inline void
00232 AlphaExpansionFusion<GM, ACC>::addPairwise
00233 (
00234    INF& inf,
00235    const size_t var1,
00236    const size_t var2,
00237    const ValueType v0,
00238    const ValueType v1,
00239    const ValueType v2,
00240    const ValueType v3
00241 ) {
00242    inf.AddPairwiseTerm((int) (var1), (int)(var2),v0,v1,v2,v3);
00243 }
00244 
00245 template<class GM, class ACC>
00246 inline InferenceTermination
00247 AlphaExpansionFusion<GM, ACC>::infer()
00248 {
00249    EmptyVisitorType visitor;
00250    return infer(visitor);
00251 }
00252 
00253 template<class GM, class ACC>
00254 template<class Visitor>
00255 InferenceTermination
00256 AlphaExpansionFusion<GM, ACC>::infer
00257 (
00258    Visitor& visitor
00259 )
00260 {
00261    size_t it = 0;
00262    size_t countUnchanged = 0;
00263 //   size_t numberOfVariables = gm_.numberOfVariables();
00264 //   std::vector<size_t> variable2Node(numberOfVariables);
00265    ValueType energy = gm_.evaluate(label_);
00266    visitor.begin(*this,energy,this->bound(),0);
00267 /*
00268    LabelType vecA[1];
00269    LabelType vecX[1];
00270    LabelType vecAA[2];
00271    LabelType vecAX[2];
00272    LabelType vecXA[2];
00273    LabelType vecXX[2];
00274 */
00275    while(it++ < parameter_.maxNumberOfSteps_ && countUnchanged < maxState_) {
00276       // DO MOVE
00277       HigherOrderEnergy<ValueType, maxOrder_> hoe;
00278       hoe.AddVars(gm_.numberOfVariables());
00279       for(IndexType f=0; f<gm_.numberOfFactors(); ++f){
00280          IndexType size = gm_[f].numberOfVariables();
00281          if (size == 0) {
00282             continue;
00283          } else if (size == 1) {
00284             IndexType var = gm_[f].variableIndex(0);
00285             ValueType e0 = gm_[f](&label_[var]);
00286             ValueType e1 = gm_[f](&alpha_);
00287             hoe.AddUnaryTerm(var, e1 - e0);
00288          } else {
00289             unsigned int numAssignments = 1 << size;
00290             ValueType coeffs[numAssignments];
00291             for (unsigned int subset = 1; subset < numAssignments; ++subset) {
00292                coeffs[subset] = 0;
00293             }
00294             // For each boolean assignment, get the clique energy at the 
00295             // corresponding labeling
00296             LabelType cliqueLabels[size];
00297             for(unsigned int assignment = 0;  assignment < numAssignments; ++assignment){
00298                for (unsigned int i = 0; i < size; ++i) {
00299                   if (assignment & (1 << i)) { 
00300                      cliqueLabels[i] = alpha_;
00301                   } else {
00302                      cliqueLabels[i] = label_[gm_[f].variableIndex(i)];
00303                   }
00304                }
00305                ValueType energy = gm_[f](cliqueLabels);
00306                for (unsigned int subset = 1; subset < numAssignments; ++subset){
00307                   if (assignment & ~subset) {
00308                      continue;
00309                   } else {
00310                      int parity = 0;
00311                      for (unsigned int b = 0; b < size; ++b) {
00312                         parity ^=  (((assignment ^ subset) & (1 << b)) != 0);
00313                      }
00314                      coeffs[subset] += parity ? -energy : energy;
00315                   }
00316                }
00317             }
00318             typename HigherOrderEnergy<ValueType, maxOrder_> ::VarId vars[maxOrder_];
00319             for (unsigned int subset = 1; subset < numAssignments; ++subset) {
00320                int degree = 0;
00321                for (unsigned int b = 0; b < size; ++b) {
00322                   if (subset & (1 << b)) {
00323                      vars[degree++] = gm_[f].variableIndex(b);
00324                   }
00325                }
00326                std::sort(vars, vars+degree);
00327                hoe.AddTerm(coeffs[subset], degree, vars);
00328             }
00329          }
00330       }  
00331       kolmogorov::qpbo::QPBO<ValueType>  qr(gm_.numberOfVariables(), 0); 
00332       hoe.ToQuadratic(qr);
00333       qr.Solve();
00334       IndexType numberOfChangedVariables = 0;
00335       for (IndexType i = 0; i < gm_.numberOfVariables(); ++i) {
00336          int label = qr.GetLabel(i);
00337          if (label == 1) {
00338             label_[i] = alpha_;
00339             ++numberOfChangedVariables;
00340          } 
00341       }
00342       
00343       OPENGM_ASSERT(gm_.numberOfVariables() == label_.size());
00344       ValueType energy2 = gm_.evaluate(label_);
00345       if(numberOfChangedVariables>0){
00346          energy=energy2;
00347          countUnchanged = 0;
00348       }else{
00349          ++countUnchanged;
00350       }
00351       visitor(*this,energy2,this->bound(),"alpha",alpha_);
00352       // OPENGM_ASSERT(!AccumulationType::ibop(energy2, energy));
00353       incrementAlpha();
00354       OPENGM_ASSERT(alpha_ < maxState_);
00355    } 
00356    visitor.end(*this,energy,this->bound(),0);
00357    return NORMAL; 
00358    /*
00359       while(it++ < parameter_.maxNumberOfSteps_ && countUnchanged < maxState_) {
00360          size_t numberOfAuxiliaryNodes = 0;
00361          for(size_t k=0 ; k<gm_.numberOfFactors(); ++k) {
00362             const FactorType& factor = gm_[k];
00363             if(factor.numberOfVariables() == 2) {
00364                size_t var1 = factor.variableIndex(0);
00365                size_t var2 = factor.variableIndex(1);
00366                if(label_[var1] != label_[var2] && label_[var1] != alpha_ && label_[var2] != alpha_ ) {
00367                   ++numberOfAuxiliaryNodes;
00368                }
00369             }
00370          }
00371          std::vector<size_t> numFacDim(4, 0);
00372 
00373          kolmogorov::qpbo::QPBO<ValueType >  inf(numberOfVariables + numberOfAuxiliaryNodes, gm_.numberOfFactors()); 
00374          inf.AddNode(numberOfVariables + numberOfAuxiliaryNodes);
00375          size_t varX = numberOfVariables;
00376          size_t countAlphas = 0;
00377          for (size_t k=0 ; k<gm_.numberOfVariables(); ++k) {
00378             if (label_[k] == alpha_ ) {
00379                addUnary(inf, k, 0, std::numeric_limits<ValueType>::infinity());
00380                ++countAlphas;
00381             }
00382          }
00383          if(countAlphas < gm_.numberOfVariables()) {
00384             for (size_t k=0 ; k<gm_.numberOfFactors(); ++k) {
00385                const  FactorType& factor = gm_[k];
00386                if(factor.numberOfVariables() == 1) {
00387                   size_t var = factor.variableIndex(0);
00388                   vecA[0] = alpha_;
00389                   vecX[0] = label_[var];
00390                   if (label_[var] != alpha_ ) {
00391                      addUnary(inf, var, factor(vecX), factor(vecA));
00392                   }
00393                }
00394                else if (factor.numberOfVariables() == 2) {
00395                   size_t var1 = factor.variableIndex(0);
00396                   size_t var2 = factor.variableIndex(1);
00397                   std::vector<IndexType> vars(2); vars[0]=var1;vars[1]=var2;
00398                   vecAA[0] = vecAA[1] = alpha_;
00399                   vecAX[0] = alpha_;       vecAX[1] = label_[var2];
00400                   vecXA[0] = label_[var1]; vecXA[1] = alpha_;
00401                   vecXX[0] = label_[var1]; vecXX[1] = label_[var2];
00402                   if(label_[var1]==alpha_ && label_[var2]==alpha_) {
00403                      continue;
00404                   }
00405                   else if(label_[var1]==alpha_) {
00406                      addUnary(inf, var2, factor(vecAX), factor(vecAA));
00407                   }
00408                   else if(label_[var2]==alpha_) {
00409                      addUnary(inf, var1, factor(vecXA), factor(vecAA));
00410                   }
00411                   else if(label_[var1]==label_[var2]) {
00412                      addPairwise(inf, var1, var2, factor(vecXX), factor(vecXA), factor(vecAX), factor(vecAA));
00413                   }
00414                   else{
00415                      OPENGM_ASSERT(varX < numberOfVariables + numberOfAuxiliaryNodes);
00416                      addPairwise(inf, var1, varX, 0, factor(vecXA), 0, 0);
00417                      addPairwise(inf, var2, varX, 0, factor(vecAX), 0, 0);
00418                      addUnary(inf, varX, factor(vecXX), factor(vecAA));
00419                      ++varX;
00420                   }
00421                }
00422             }
00423             inf.MergeParallelEdges();
00424             inf.Solve();
00425        
00426             for(size_t var=0; var<numberOfVariables ; ++var) {
00427                int b = inf.GetLabel(var);
00428                if (label_[var] != alpha_ && b==1) {
00429                   label_[var] = alpha_;
00430                }
00431                OPENGM_ASSERT(label_[var] < gm_.numberOfLabels(var));
00432             }
00433          }
00434          OPENGM_ASSERT(gm_.numberOfVariables() == label_.size());
00435          ValueType energy2 = gm_.evaluate(label_);
00436          visitor(*this,energy,this->bound(),alpha_);
00437          // OPENGM_ASSERT(!AccumulationType::ibop(energy2, energy));
00438          if(AccumulationType::bop(energy2, energy)) {
00439             energy=energy2;
00440             countUnchanged = 0;
00441          }
00442          else{
00443             ++countUnchanged;
00444          }
00445          incrementAlpha();
00446          OPENGM_ASSERT(alpha_ < maxState_);
00447       }
00448    }
00449    visitor.end(*this,energy,this->bound(),0);
00450    return NORMAL; 
00451 */
00452 }
00453 
00454 template<class GM, class ACC>
00455 inline InferenceTermination
00456 AlphaExpansionFusion<GM, ACC>::arg
00457 (
00458    std::vector<LabelType>& arg,
00459    const size_t n
00460 ) const
00461 {
00462    if(n > 1) {
00463       return UNKNOWN;
00464    }
00465    else {
00466       OPENGM_ASSERT(label_.size() == gm_.numberOfVariables());
00467       arg.resize(label_.size());
00468       for(size_t i=0; i<label_.size(); ++i) {
00469          arg[i] = label_[i];
00470       }
00471       return NORMAL;
00472    }
00473 }
00474 
00475 template<class GM, class ACC>
00476 inline void
00477 AlphaExpansionFusion<GM, ACC>::setLabelOrder
00478 (
00479    std::vector<LabelType>& l
00480 ) {
00481    if(l.size() == maxState_) {
00482       labelList_=l;
00483    }
00484 }
00485 
00486 template<class GM, class ACC>
00487 inline void
00488 AlphaExpansionFusion<GM, ACC>::setLabelOrderRandom
00489 (
00490    unsigned int seed
00491 ) {
00492    srand(seed);
00493    labelList_.resize(maxState_);
00494    for (size_t i=0; i<maxState_;++i) {
00495       labelList_[i]=i;
00496    }
00497    random_shuffle(labelList_.begin(), labelList_.end());
00498 }
00499 
00500 template<class GM, class ACC>
00501 inline void
00502 AlphaExpansionFusion<GM, ACC>::setInitialLabel
00503 (
00504    std::vector<LabelType>& l
00505 ) {
00506    label_.resize(gm_.numberOfVariables());
00507    if(l.size() == label_.size()) {
00508       for(size_t i=0; i<l.size();++i) {
00509          if(l[i]>=gm_.numberOfLabels(i)) return;
00510       }
00511       for(size_t i=0; i<l.size();++i) {
00512          label_[i] = l[i];
00513       }
00514    }
00515 }
00516 
00517 template<class GM, class ACC>
00518 inline void
00519 AlphaExpansionFusion<GM, ACC>::setInitialLabelLocalOptimal() {
00520    label_.resize(gm_.numberOfVariables(), 0);
00521    std::vector<size_t> accVec;
00522    for(size_t i=0; i<gm_.numberOfFactors();++i) {
00523       if(gm_[i].numberOfVariables()==1) {
00524          std::vector<size_t> state(1, 0);
00525          ValueType value = gm_[i](state.begin());
00526          for(state[0]=1; state[0]<gm_.numberOfLabels(i); ++state[0]) {
00527             if(AccumulationType::bop(gm_[i](state.begin()), value)) {
00528                value = gm_[i](state.begin());
00529                label_[i] = state[0];
00530             }
00531          }
00532       }
00533    }
00534 }
00535 
00536 template<class GM, class ACC>
00537 inline void
00538 AlphaExpansionFusion<GM, ACC>::setInitialLabelRandom
00539 (
00540    unsigned int seed
00541 ) {
00542    srand(seed);
00543    label_.resize(gm_.numberOfVariables());
00544    for(size_t i=0; i<gm_.numberOfVariables();++i) {
00545       label_[i] = rand() % gm_.numberOfLabels(i);
00546    }
00547 }
00548 
00549 template<class GM, class ACC>
00550 inline void
00551 AlphaExpansionFusion<GM, ACC>::incrementAlpha() {
00552    counter_ = (counter_+1) % maxState_;
00553    alpha_ = labelList_[counter_];
00554 }
00555 
00556 } // namespace opengm
00557 
00558 #endif // #ifndef OPENGM_ALPHAEXPANSIONFUSION_HXX
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Mon Jun 17 16:31:01 2013 for OpenGM by  doxygen 1.6.3