mqpbo.hxx

Go to the documentation of this file.
00001 #pragma once
00002 #ifndef OPENGM_MQPBO_HXX
00003 #define OPENGM_MQPBO_HXX
00004 
00005 #include <vector>
00006 #include <string>
00007 #include <iostream>
00008 
00009 #include "opengm/opengm.hxx"
00010 #include "opengm/inference/visitors/visitor.hxx"
00011 #include "opengm/inference/inference.hxx"
00012 #include <opengm/utilities/metaprogramming.hxx>
00013 #include "opengm/utilities/tribool.hxx"
00014 #include <opengm/inference/messagepassing/messagepassing.hxx>
00015 #include <opengm/functions/view_fix_variables_function.hxx>
00016 
00017 //#define MQPBOHotFixOutPutPartialOPtimalityMap
00018 #ifdef MQPBOHotFixOutPutPartialOPtimalityMap
00019 #include <opengm/datastructures/marray/marray_hdf5.hxx>
00020 #endif
00021 
00022 #include "opengm/inference/external/qpbo.hxx"
00023 
00024 namespace opengm {
00025    
00036    template<class GM, class ACC>
00037    class MQPBO : public Inference<GM, ACC>
00038    {
00039    public:
00040       typedef ACC AccumulationType;
00041       typedef GM GmType;
00042       typedef GM GraphicalModelType;
00043       OPENGM_GM_TYPE_TYPEDEFS;
00044       typedef VerboseVisitor<MQPBO<GM, ACC> > VerboseVisitorType;
00045       typedef EmptyVisitor<MQPBO<GM, ACC> >   EmptyVisitorType; 
00046       typedef TimingVisitor<MQPBO<GM, ACC> >  TimingVisitorType; 
00047       typedef ValueType                       GraphValueType;
00048       
00049       enum PermutationType {NONE, RANDOM, MINMARG};
00050       
00051       class Parameter{
00052       public:
00053          Parameter(): useKovtunsMethod_(true), probing_(false),  strongPersistency_(false), rounds_(0), permutationType_(NONE) {};
00054          std::vector<LabelType> label_;
00055          bool useKovtunsMethod_;
00056          const bool probing_; //do not use this!
00057          bool strongPersistency_;
00058          size_t rounds_;
00059          PermutationType permutationType_;
00060       };
00061 
00062       MQPBO(const GmType&, const Parameter& = Parameter());
00063       ~MQPBO();
00064       std::string name() const;
00065       const GmType& graphicalModel() const;
00066       InferenceTermination infer();
00067       void reset();
00068       typename GM::ValueType bound() const;
00069       typename GM::ValueType value() const;  
00070       template<class VisitorType>
00071          InferenceTermination infer(VisitorType&);
00072       InferenceTermination testQuess(std::vector<LabelType> &guess);
00073       InferenceTermination testPermutation(PermutationType permutationType);
00074       void setStartingPoint(typename std::vector<LabelType>::const_iterator);
00075       virtual InferenceTermination arg(std::vector<LabelType>&, const size_t = 1) const ;
00076 
00077       const std::vector<opengm::Tribool>& partialOptimality(IndexType var) const {return partialOptimality_[var];}
00078       bool partialOptimality(IndexType var, LabelType& l) const                  {l=label_[var]; return optimal_[var];}
00079     
00080       double optimalityV() const;
00081       double optimality() const;
00082    private: 
00083       InferenceTermination testQuess(LabelType guess);
00084       void AddUnaryTerm(int var, ValueType v0, ValueType v1);
00085       void AddPairwiseTerm(int var0, int var1,ValueType v00,ValueType v01,ValueType v10,ValueType v11);
00086 
00087       const GmType& gm_;
00088       Parameter param_;
00089 
00090       kolmogorov::qpbo::QPBO<GraphValueType>* qpbo_;
00091       ValueType constTerm_;
00092       ValueType bound_;
00093       //int* label_;
00094       //int* defaultLabel_;
00095    
00096       std::vector<std::vector<LabelType> >         permutation_;        // org -> new
00097       std::vector<std::vector<LabelType> >         inversePermutation_;  // new -> org
00098       std::vector<std::vector<opengm::Tribool> >   partialOptimality_;
00099       std::vector<bool>                            optimal_;
00100       std::vector<LabelType>                       label_;
00101       std::vector<size_t>                          variableOffset_; 
00102 
00103       size_t numNodes_;
00104       size_t numEdges_;
00105 
00106       GraphValueType scale;
00107 
00108    };
00110       
00111   
00112    template<class GM, class ACC>
00113    MQPBO<GM,ACC>::MQPBO
00114    (
00115        const GmType& gm,
00116        const Parameter& parameter
00117    )
00118    :  gm_(gm),    
00119       param_(parameter),
00120       scale(1)
00121    {
00122       for(size_t j = 0; j < gm_.numberOfFactors(); ++j) {
00123          if(gm_[j].numberOfVariables() > 2) {
00124             throw RuntimeError("This implementation of MQPBO supports only factors of order <= 2.");
00125          }
00126       }
00127       
00128       //Allocate Memory for Permutations
00129       permutation_.resize(gm_.numberOfVariables());
00130       inversePermutation_.resize(gm_.numberOfVariables());
00131       for(IndexType var=0; var<gm_.numberOfVariables(); ++var){
00132          permutation_[var].resize(gm_.numberOfLabels(var));
00133          inversePermutation_[var].resize(gm_.numberOfLabels(var));
00134       }
00135 
00136       //Set Default Optimality
00137       partialOptimality_.resize(gm_.numberOfVariables());
00138       optimal_.resize(gm_.numberOfVariables(),false);
00139       label_.resize(gm_.numberOfVariables());
00140       for(IndexType var=0; var<gm_.numberOfVariables(); ++var){
00141         partialOptimality_[var].resize(gm_.numberOfLabels(var),opengm::Tribool::Maybe); 
00142       }
00143 
00144       //Calculated number of nodes and edges
00145       numNodes_=0;
00146       numEdges_=0;
00147       size_t numSOF=0;
00148       variableOffset_.resize(gm_.numberOfVariables(),0);
00149       for(IndexType var=0; var<gm_.numberOfVariables(); ++var){
00150          variableOffset_[var] = numNodes_;
00151          numNodes_ += gm_.numberOfLabels(var)-1;
00152       }
00153       for(IndexType var=1; var<gm_.numberOfVariables(); ++var){
00154          OPENGM_ASSERT( variableOffset_[var-1]< variableOffset_[var]);
00155       }
00156 
00157       for(IndexType f=0; f<gm_.numberOfFactors(); ++f){
00158          if(gm_[f].numberOfVariables()==1)
00159             numEdges_ += gm_[f].numberOfLabels(0)-2;
00160          if(gm_[f].numberOfVariables()==2){
00161             numEdges_ += (gm_[f].numberOfLabels(0)-1);//*(gm_[f].numberOfLabels(1)-1);
00162             ++numSOF;
00163          }
00164       }
00165 
00166       if(param_.rounds_>0){
00167          std::cout << "Large" <<std::endl;
00168          qpbo_ = new kolmogorov::qpbo::QPBO<GraphValueType > (numNodes_, numEdges_); // max number of nodes & edges
00169          qpbo_->AddNode(numNodes_);
00170       }
00171       else{
00172          std::cout << "Small" <<std::endl;      
00173          qpbo_ = new kolmogorov::qpbo::QPBO<GraphValueType > (gm_.numberOfVariables(), numSOF); // max number of nodes & edges
00174          qpbo_->AddNode(gm_.numberOfVariables());
00175       }
00176    } 
00177 
00178    template<class GM, class ACC>
00179    MQPBO<GM,ACC>::~MQPBO
00180    (
00181       )
00182    {
00183       delete qpbo_;
00184    }
00185       
00188    template<class GM, class ACC>
00189    inline void
00190    MQPBO<GM,ACC>::reset()
00191    {
00193    }
00194    
00196    template<class GM, class ACC>
00197    inline void 
00198    MQPBO<GM,ACC>::setStartingPoint
00199    (
00200       typename std::vector<typename GM::LabelType>::const_iterator begin
00201    )
00202    { 
00204    }
00205    
00206    template<class GM, class ACC>
00207    inline std::string
00208    MQPBO<GM,ACC>::name() const
00209    {
00210       return "MQPBO";
00211    }
00212 
00213    template<class GM, class ACC>
00214    inline const typename MQPBO<GM,ACC>::GmType&
00215    MQPBO<GM,ACC>::graphicalModel() const
00216    {
00217       return gm_;
00218    } 
00219 
00220 
00221    template<class GM, class ACC>
00222    inline void
00223    MQPBO<GM,ACC>::AddUnaryTerm(int var, ValueType v0, ValueType v1){
00224       qpbo_->AddUnaryTerm(var, scale*v0, scale*v1);
00225    }
00226    
00227    template<class GM, class ACC>
00228    inline void
00229    MQPBO<GM,ACC>::AddPairwiseTerm(int var0, int var1,ValueType v00,ValueType v01,ValueType v10,ValueType v11){
00230       qpbo_->AddPairwiseTerm(var0, var1,scale*v00,scale*v01,scale*v10,scale*v11);
00231    } 
00232        
00233    template<class GM, class ACC>
00234    inline InferenceTermination
00235    MQPBO<GM,ACC>::testQuess(LabelType guess)
00236    {
00237       qpbo_->Reset();
00238       qpbo_->AddNode(gm_.numberOfVariables());
00239       for(size_t f = 0; f < gm_.numberOfFactors(); ++f) {
00240          if(gm_[f].numberOfVariables() == 0) {
00241             ;
00242          }
00243          else if(gm_[f].numberOfVariables() == 1) {
00244             const LabelType numLabels =  gm_[f].numberOfLabels(0);
00245             const IndexType var = gm_[f].variableIndex(0);
00246             
00247             ValueType v0 = gm_[f](&guess);
00248             ValueType v1; ACC::neutral(v1);
00249             for(LabelType i=0; i<guess; ++i)
00250                ACC::op(gm_[f](&i),v1);
00251             for(LabelType i=guess+1; i<numLabels; ++i)
00252                ACC::op(gm_[f](&i),v1);
00253             AddUnaryTerm(var, v0, v1);
00254          }
00255          else if(gm_[f].numberOfVariables() == 2) {
00256             const IndexType var0 = gm_[f].variableIndex(0);
00257             const IndexType var1 = gm_[f].variableIndex(1); 
00258             
00259             LabelType c[2] = {guess,guess};
00260             LabelType c2[2] = {0,1};
00261 
00262             ValueType v00 = gm_[f](c);
00263             ValueType v01 = gm_[f](c2);
00264             ValueType v10 = v01; 
00265             ValueType v11 = std::min(v00,v01);
00266             AddPairwiseTerm(var0, var1,v00,v01,v10,v11);
00267          }
00268       }
00269       qpbo_->MergeParallelEdges();
00270       qpbo_->Solve();
00271       for(IndexType var=0; var<gm_.numberOfVariables();++var){
00272          if(qpbo_->GetLabel(var)==0){
00273             for(LabelType l=0; l<gm_.numberOfLabels(var); ++l){
00274                partialOptimality_[var][l] =opengm::Tribool::False;   
00275             } 
00276             partialOptimality_[var][guess] =opengm::Tribool::True; 
00277             optimal_[var]=true;
00278             label_[var]=guess;
00279          }
00280       }
00281       return NORMAL;
00282    }
00283 
00284 
00285    template<class GM, class ACC>
00286    inline InferenceTermination
00287    MQPBO<GM,ACC>::testQuess(std::vector<LabelType> &guess)
00288    {
00289       qpbo_->Reset();
00290       qpbo_->AddNode(gm_.numberOfVariables());
00291       
00292       for(size_t var=0; var<gm_.numberOfVariables(); ++var){
00293          std::vector<ValueType> v(gm_.numberOfLabels(var),0);
00294          for(size_t i=0; i<gm_.numberOfFactors(var); ++i){
00295             size_t f =  gm_.factorOfVariable(var, i);
00296             if(gm_[f].numberOfVariables()==1){
00297                for(size_t j=0; j<v.size(); ++j){
00298                   v[j] += gm_[f](&j);
00299                }
00300                
00301             }
00302             else if(gm_[f].numberOfVariables() == 2) {
00303                LabelType c[] = {guess[gm_[f].variableIndex(0)],guess[gm_[f].variableIndex(1)]};
00304                if(gm_[f].variableIndex(0)==var){
00305                   for(c[0]=0; c[0]<guess[var]; ++c[0]){
00306                      v[c[0]] += gm_[f](c);
00307                   }
00308                   for(c[0]=guess[var]+1; c[0]<v.size(); ++c[0]){
00309                      v[c[0]] += gm_[f](c);
00310                   } 
00311                }
00312                else if(gm_[f].variableIndex(1)==var){
00313                   for(c[1]=0; c[1]<guess[var]; ++c[1]){
00314                      v[c[1]] += gm_[f](c);
00315                   }
00316                   for(c[1]=guess[var]+1; c[1]<v.size(); ++c[1]){
00317                      v[c[1]] += gm_[f](c);
00318                   } 
00319                }
00320                else{
00321                   OPENGM_ASSERT(false);
00322                }
00323             }
00324          } 
00325          ValueType v0 = v[guess[var]];
00326          ValueType v1; ACC::neutral(v1);
00327          for(size_t j=0; j<guess[var]; ++j){
00328             ACC::op(v[j],v1);
00329          }
00330          for(size_t j=guess[var]+1; j<v.size(); ++j){
00331             ACC::op(v[j],v1);
00332          } 
00333          AddUnaryTerm(var, v0, v1);
00334       }
00335 
00336 
00337       for(size_t f = 0; f < gm_.numberOfFactors(); ++f) {    
00338          if(gm_[f].numberOfVariables() < 2) {
00339             continue;
00340          }
00341          else if(gm_[f].numberOfVariables() == 2) {
00342             const IndexType var0 = gm_[f].variableIndex(0);
00343             const IndexType var1 = gm_[f].variableIndex(1); 
00344             
00345             LabelType c[2] = {guess[var0],guess[var1]};
00346             LabelType c0[2] = {guess[var0],guess[var1]};
00347             LabelType c1[2] = {guess[var0],guess[var1]};
00348             ValueType v00 = gm_[f](c);
00349             ValueType v01 = 0;
00350             ValueType v10 = 0;
00351             ValueType v11; ACC::neutral(v11);
00352 
00353             for(c[0]=0; c[0]<gm_[f].numberOfLabels(0); ++c[0]){
00354                for(c[1]=0; c[1]<gm_[f].numberOfLabels(1); ++c[1]){
00355                   if(c[0]==guess[var0] || c[1]==guess[var1]){
00356                      continue;
00357                   }
00358                   else{
00359                      c0[0]=c[0];
00360                      c1[1]=c[1];
00361                      ValueType v = gm_[f](c) - gm_[f](c0) - gm_[f](c1);
00362                      ACC::op(v,v11);
00363                   }
00364                }
00365             }
00366             AddPairwiseTerm(var0, var1,v00,v01,v10,v11);
00367          }
00368       }
00369       qpbo_->MergeParallelEdges();
00370       qpbo_->Solve();
00371       for(IndexType var=0; var<gm_.numberOfVariables();++var){
00372          if(qpbo_->GetLabel(var)==0){
00373             for(LabelType l=0; l<gm_.numberOfLabels(var); ++l){
00374                partialOptimality_[var][l] =opengm::Tribool::False;   
00375             } 
00376             partialOptimality_[var][guess[var]] =opengm::Tribool::True; 
00377             optimal_[var]=true;
00378             label_[var]=guess[var];
00379          }
00380       }
00381       return NORMAL;
00382    }
00383 
00384    template<class GM, class ACC>
00385    inline InferenceTermination
00386    MQPBO<GM,ACC>::testPermutation(PermutationType permutationType)
00387    {
00388       //Set up MQPBO for current partial optimality
00389       std::vector<IndexType> var2VarR(gm_.numberOfVariables());
00390       std::vector<IndexType> varR2Var;
00391       std::vector<size_t>    varROffset;
00392       size_t numBVar=0;
00393       for(size_t var = 0; var < gm_.numberOfVariables(); ++var) {
00394          if(optimal_[var]){
00395             ;//do nothing
00396          }
00397          else{
00398             varROffset.push_back(numBVar);
00399             numBVar = numBVar + gm_.numberOfLabels(var)-1;
00400             var2VarR[var]=varR2Var.size();
00401             varR2Var.push_back(var);
00402          }
00403       }
00404       std::cout <<  varR2Var.size() <<" / "<<gm_.numberOfVariables()<<std::endl;
00405 
00406       //Find Permutation
00407       if(permutationType==NONE){ 
00408          for(IndexType var=0; var<gm_.numberOfVariables(); ++var){
00409             for(LabelType l=0; l<gm_.numberOfLabels(var); ++l){
00410                permutation_[var][l]=l;
00411             }
00412          }
00413       }
00414       else if(permutationType==RANDOM){ 
00415          srand ( unsigned ( time (NULL) ) );
00416          for(IndexType var=0; var<gm_.numberOfVariables(); ++var){
00417             LabelType numStates = gm_.numberOfLabels(var);
00418             //IDENTYTY PERMUTATION
00419             for(LabelType i=0; i<numStates;++i){
00420                permutation_[var][i]=i;
00421             }
00422             //SHUFFEL PERMUTATION  
00423             std::random_shuffle(permutation_[var].begin(),permutation_[var].end());
00424          }
00425       }
00426       else if(permutationType==MINMARG){
00427          typedef typename opengm::GraphicalModel<ValueType, OperatorType, opengm::ViewFixVariablesFunction<GM>, typename GM::SpaceType> SUBGM;
00428 
00429          std::vector<LabelType> numberOfLabels(varR2Var.size());
00430          for(size_t i=0; i<varR2Var.size(); ++i)
00431             numberOfLabels[i] = gm_.numberOfLabels(varR2Var[i]);
00432          typename GM::SpaceType subspace(numberOfLabels.begin(),numberOfLabels.end());
00433          SUBGM gm(subspace);
00434          for(IndexType f=0; f<gm_.numberOfFactors();++f){
00435             std::vector<PositionAndLabel<IndexType, LabelType> > fixed;
00436             std::vector<IndexType> vars;
00437             for(IndexType i=0; i<gm_[f].numberOfVariables();++i){
00438                const IndexType var = gm_[f].variableIndex(i);
00439                if(optimal_[var]){
00440                   fixed.push_back(PositionAndLabel<IndexType, LabelType>(i,label_[var]));
00441                }
00442                else{
00443                   vars.push_back(var2VarR[var]);
00444                }
00445             }
00446             opengm::ViewFixVariablesFunction<GM> func(gm_[f], fixed);
00447             gm.addFactor(gm.addFunction(func),vars.begin(),vars.end());
00448          }
00449       
00450          typedef typename opengm::MessagePassing<SUBGM, ACC,opengm::BeliefPropagationUpdateRules<SUBGM,ACC>, opengm::MaxDistance> LBP;  
00451          typename LBP::Parameter para;
00452          para.maximumNumberOfSteps_ = 100;
00453          para.damping_ = 0.5;
00454          LBP bp(gm,para);
00455          bp.infer();
00456          
00457          //for(IndexType var=0; var<gm_.numberOfVariables(); ++var){
00458          for(IndexType varR=0; varR<gm.numberOfVariables(); ++varR){
00459             IndexType var = varR2Var[varR];
00460             LabelType numStates = gm_.numberOfLabels(var);
00461             typename GM::IndependentFactorType marg;
00462             bp.marginal(varR, marg);
00463          
00464             //SHUFFEL PERMUTATION 
00465             std::vector<LabelType> list(numStates);
00466             for(LabelType i=0; i<numStates;++i){
00467                list[i]=i;
00468             }
00469             LabelType t;
00470             for(LabelType i=0; i<numStates;++i){
00471                for(LabelType j=i+1; i<numStates;++i){
00472                   if(marg(&list[j])<marg(&list[i])){
00473                      t = list[i];
00474                      list[i]=list[j];
00475                      list[j]=t;
00476                   }
00477                }
00478             }
00479             for(LabelType i=0; i<numStates;++i){
00480                permutation_[var][i] = list[i];
00481             }
00482          }
00483       }
00484       else{
00485          throw RuntimeError("Error: Unknown Permutation!");
00486       }
00487       //CALCULATE INVERSE PERMUTATION
00488       for(IndexType var=0; var<gm_.numberOfVariables(); ++var){   
00489          for(LabelType l=0; l<gm_.numberOfLabels(var); ++l){
00490             inversePermutation_[var][permutation_[var][l]]=l;
00491          }
00492       }
00493       
00494       
00495       //Build Graph
00496       ValueType constValue = 0;
00497       qpbo_->Reset();
00498       qpbo_->AddNode(numBVar);
00499       //qpbo_->AddNode(numNodes_);
00500       
00501       for(IndexType varR = 0; varR < varR2Var.size(); ++varR) {
00502          IndexType var = varR2Var[varR];
00503          for(size_t l = 0; l+1<gm_.numberOfLabels(var); ++l){
00504             AddUnaryTerm((int) (varROffset[varR]+l), 0.0, 0.0);
00505          } 
00506          for(LabelType l=1; l+1<gm_.numberOfLabels(var); ++l){
00507             AddPairwiseTerm((int) (varROffset[varR]+l-1), (int) (varROffset[varR]+l), 0.0,  1000000.0, 0.0, 0.0);
00508          }
00509       }
00510       /*      
00511       for(size_t var = 0; var < gm_.numberOfVariables(); ++var) {
00512          for(size_t l = 0; l+1<gm_.numberOfLabels(var); ++l){
00513             AddUnaryTerm((int) (variableOffset_[var]+l), 0.0, 0.0);
00514          } 
00515          for(LabelType l=1; l+1<gm_.numberOfLabels(var); ++l){
00516             AddPairwiseTerm((int) (variableOffset_[var]+l-1), (int) (variableOffset_[var]+l), 0.0,  1000000.0, 0.0, 0.0);
00517          }
00518       }
00519        */
00520 
00521       for(size_t f = 0; f < gm_.numberOfFactors(); ++f) {
00522          if(gm_[f].numberOfVariables() == 0) {
00523             const LabelType l = 0;
00524             constValue += gm_[f](&l);
00525          }
00526          else if(gm_[f].numberOfVariables() == 1) {
00527             const LabelType numLabels =  gm_[f].numberOfLabels(0);
00528             const IndexType var = gm_[f].variableIndex(0);
00529             if(optimal_[var]){
00530                constValue += gm_[f](&(label_[var]));  
00531             }
00532             else{
00533                LabelType l0 = inversePermutation_[var][0];
00534                LabelType l1;
00535                constValue += gm_[f](&l0);
00536                const IndexType varR = var2VarR[var];
00537                for(LabelType i=1 ; i<numLabels; ++i){
00538                   l0 = inversePermutation_[var][i-1];
00539                   l1 = inversePermutation_[var][i];
00540                   AddUnaryTerm((int) (varROffset[varR]+i-1),  0.0, gm_[f](&l1)-gm_[f](&l0));       
00541                   //AddUnaryTerm((int) (variableOffset_[var]+i-1),  0.0, gm_[f](&l1)-gm_[f](&l0));
00542                }      
00543             }
00544          }
00545          else if(gm_[f].numberOfVariables() == 2) {
00546             const IndexType var0 = gm_[f].variableIndex(0);
00547             const IndexType var1 = gm_[f].variableIndex(1); 
00548             const IndexType varR0 = var2VarR[var0];
00549             const IndexType varR1 = var2VarR[var1]; 
00550             
00551             if(optimal_[var0]&&optimal_[var1]){
00552                LabelType l[2] = { label_[var0], label_[var1]};
00553                constValue += gm_[f](l);   
00554             }
00555             else if(optimal_[var0]){
00556                const LabelType numLabels =  gm_[f].numberOfLabels(1);
00557                LabelType l0[2] = { label_[var0], inversePermutation_[var1][0]};
00558                LabelType l1[2] = { label_[var0], 0};
00559                constValue += gm_[f](l0);
00560                for(LabelType i=1 ; i<numLabels; ++i){
00561                   l0[1] = inversePermutation_[var1][i-1];
00562                   l1[1] = inversePermutation_[var1][i];
00563                   //AddUnaryTerm((int) (variableOffset_[var1]+i-1),  0.0, gm_[f](l1)-gm_[f](l0)); 
00564                   AddUnaryTerm((int) (varROffset[varR1]+i-1),  0.0, gm_[f](l1)-gm_[f](l0));
00565                }
00566             }
00567             else if(optimal_[var1]){
00568                const LabelType numLabels =  gm_[f].numberOfLabels(0);  
00569                LabelType l0[2] = { inversePermutation_[var0][0], label_[var1]};
00570                LabelType l1[2] = { 0, label_[var1]};
00571                constValue += gm_[f](l0);
00572                for(LabelType i=1 ; i<numLabels; ++i){
00573                   l0[0] = inversePermutation_[var0][i-1];
00574                   l1[0] = inversePermutation_[var0][i];
00575                   AddUnaryTerm((int) (varROffset[varR0]+i-1),  0.0, gm_[f](l1)-gm_[f](l0));
00576                   //AddUnaryTerm((int) (variableOffset_[var0]+i-1),  0.0, gm_[f](l1)-gm_[f](l0));
00577                }
00578             }
00579             else{
00580                {
00581                   const LabelType l[2]={inversePermutation_[var0][0],inversePermutation_[var1][0]}; 
00582                   constValue += gm_[f](l);
00583                } 
00584                for(size_t i=1; i<gm_[f].numberOfLabels(0);++i){
00585                   const LabelType l1[2]={inversePermutation_[var0][i]  ,inversePermutation_[var1][0]};
00586                   const LabelType l2[2]={inversePermutation_[var0][i-1],inversePermutation_[var1][0]};
00587                   AddUnaryTerm((int) (varROffset[varR0]+i-1), 0.0, gm_[f](l1)-gm_[f](l2));
00588                   //AddUnaryTerm((int) (variableOffset_[var0]+i-1), 0.0, gm_[f](l1)-gm_[f](l2));
00589                } 
00590                for(size_t i=1; i<gm_[f].numberOfLabels(1);++i){
00591                   const LabelType l1[2]={inversePermutation_[var0][0],inversePermutation_[var1][i]};
00592                   const LabelType l2[2]={inversePermutation_[var0][0],inversePermutation_[var1][i-1]};
00593                   AddUnaryTerm((int) (varROffset[varR1]+i-1), 0.0, gm_[f](l1)-gm_[f](l2));
00594                   //AddUnaryTerm((int) (variableOffset_[var1]+i-1), 0.0, gm_[f](l1)-gm_[f](l2));
00595                }
00596                for(size_t i=1; i<gm_[f].numberOfLabels(0);++i){
00597                   for(size_t j=1; j<gm_[f].numberOfLabels(1);++j){
00598                      const int node0 = varROffset[varR0]+i-1;
00599                      const int node1 = varROffset[varR1]+j-1;
00600                      //const int node0 = variableOffset_[var0]+i-1;
00601                      //const int node1 = variableOffset_[var1]+j-1;
00602                      ValueType v = 0;
00603                      int l[2] = {(int)inversePermutation_[var0][i],(int)inversePermutation_[var1][j]};  v += gm_[f](l);
00604                      l[0]=inversePermutation_[var0][i-1];                                    v -= gm_[f](l);
00605                      l[1]=inversePermutation_[var1][j-1];                                    v += gm_[f](l);
00606                      l[0]=inversePermutation_[var0][i];                                      v -= gm_[f](l);
00607                      if(v!=0.0)
00608                         AddPairwiseTerm(node0, node1,0.0,0.0,0.0,v);
00609                   }
00610                }
00611             }
00612          }
00613       }
00614       qpbo_->MergeParallelEdges();
00615          
00616       //Optimize
00617       
00618       qpbo_->Solve();
00619       if(!param_.strongPersistency_)
00620          qpbo_->ComputeWeakPersistencies();
00621       //   if(!parameter_.strongPersistency_) {
00622       //      qpbo_->ComputeWeakPersistencies();
00623       //   } 
00624 
00625       bound_ = constValue + 0.5 * qpbo_->ComputeTwiceLowerBound();
00626       
00627       /*PROBEING*/
00628       if(param_.probing_) { 
00629          std::cout << "Start Probing ..."<<std::endl;
00630          // Initialize mapping for probe
00631          int *mapping = new int[numBVar];
00632          //int *mapping = new int[numNodes_];
00633          for(int i = 0; i < static_cast<int>(numBVar); ++i) {
00634             //for(int i = 0; i < static_cast<int>(numNodes_); ++i) {
00635             qpbo_->SetLabel(i, qpbo_->GetLabel(i));
00636             mapping[i] = i * 2;
00637          }
00638          typename kolmogorov::qpbo::QPBO<GraphValueType>::ProbeOptions options;
00639          options.C = 1000000000;
00640          if(!param_.strongPersistency_)
00641             options.weak_persistencies = 1;
00642          else
00643             options.weak_persistencies = 0;
00644          qpbo_->Probe(mapping, options);
00645          if(!param_.strongPersistency_)
00646             qpbo_->ComputeWeakPersistencies();      
00647          
00648          for(IndexType var=0; var<gm_.numberOfVariables();++var){
00649             if(optimal_[var]) continue;
00650             IndexType varR = var2VarR[var];
00651             //Lable==0
00652             {
00653                int l = qpbo_->GetLabel(mapping[varROffset[varR]]/2);
00654                if(l>=0) l = (l + mapping[varROffset[varR]]) % 2;
00655                //int l = qpbo_->GetLabel(mapping[variableOffset_[var]]/2);
00656                //if(l>=0) l = (l + mapping[variableOffset_[var]]) % 2;
00657                if(l==0)     {partialOptimality_[var][inversePermutation_[var][0]]&=opengm::Tribool::True;}
00658                else if(l==1){partialOptimality_[var][inversePermutation_[var][0]]&=opengm::Tribool::False;}
00659                else         {partialOptimality_[var][inversePermutation_[var][0]]&=opengm::Tribool::Maybe;}
00660             }
00661             //Label==max
00662             {
00663                int l = qpbo_->GetLabel(mapping[varROffset[varR]+gm_.numberOfLabels(var)-2]/2);
00664                if(l>=0) l = (l + mapping[varROffset[varR]+gm_.numberOfLabels(var)-2]) % 2;      
00665                //int l = qpbo_->GetLabel(mapping[variableOffset_[var]+gm_.numberOfLabels(var)-2]/2);
00666                //if(l>=0) l = (l + mapping[variableOffset_[var]+gm_.numberOfLabels(var)-2]) % 2;      
00667                if(l==0)     {partialOptimality_[var][inversePermutation_[var][gm_.numberOfLabels(var)-1]]&=opengm::Tribool::False;}
00668                else if(l==1){partialOptimality_[var][inversePermutation_[var][gm_.numberOfLabels(var)-1]]&=opengm::Tribool::True;}
00669                else         {partialOptimality_[var][inversePermutation_[var][gm_.numberOfLabels(var)-1]]&=opengm::Tribool::Maybe;}
00670             }
00671             //ELSE
00672             
00673             for(LabelType l=1; l+1<gm_.numberOfLabels(var);++l)
00674             {
00675                int l1 = qpbo_->GetLabel(mapping[varROffset[varR]+l-1]/2);
00676                int l2 = qpbo_->GetLabel(mapping[varROffset[varR]+l]/2);
00677                if(l1>=0) l1 = (l1 + mapping[varROffset[varR]+l-1]) % 2;
00678                if(l2>=0) l2 = (l2 + mapping[varROffset[varR]+l]) % 2;
00679                //int l1 = qpbo_->GetLabel(mapping[variableOffset_[var]+l-1]/2);
00680                //int l2 = qpbo_->GetLabel(mapping[variableOffset_[var]+l]/2);
00681                //if(l1>=0) l1 = (l1 + mapping[variableOffset_[var]+l-1]) % 2;
00682                //if(l2>=0) l2 = (l2 + mapping[variableOffset_[var]+l]) % 2;
00683                
00684                OPENGM_ASSERT(!(l1==0 && l2==1));
00685                if(l1==1 && l2==0) {partialOptimality_[var][inversePermutation_[var][l]]&=opengm::Tribool::True;}
00686                else if(l2==1)     {partialOptimality_[var][inversePermutation_[var][l]]&=opengm::Tribool::False;}
00687                else if(l1==0)     {partialOptimality_[var][inversePermutation_[var][l]]&=opengm::Tribool::False;}
00688                //else               {partialOptimality_[var][inversePermutation_[var][l]]&=opengm::Tribool::Maybe;}
00689             }  
00690          }
00691          delete mapping;
00692       }
00693       else{
00694          for(IndexType var=0; var<gm_.numberOfVariables();++var){
00695             if(optimal_[var]) continue;
00696             IndexType varR = var2VarR[var];
00697             //Lable==0
00698             {
00699                int l = qpbo_->GetLabel(varROffset[varR]);
00700                //int l = qpbo_->GetLabel(variableOffset_[var]);
00701                if(l==0){
00702                   OPENGM_ASSERT(!(partialOptimality_[var][inversePermutation_[var][0]]==opengm::Tribool::False));
00703                   partialOptimality_[var][inversePermutation_[var][0]]&=opengm::Tribool::True;
00704                }
00705                else if(l==1){
00706                   OPENGM_ASSERT(!(partialOptimality_[var][inversePermutation_[var][0]]==opengm::Tribool::True));
00707                   partialOptimality_[var][inversePermutation_[var][0]]&=opengm::Tribool::False;
00708                }
00709                //  else         {partialOptimality_[var][permutation_[var][0]]&=opengm::Tribool::Maybe;}
00710             }
00711             //Label==max
00712             {
00713                int l = qpbo_->GetLabel(varROffset[varR]+gm_.numberOfLabels(var)-2);
00714                //int l = qpbo_->GetLabel(variableOffset_[var]+gm_.numberOfLabels(var)-2);
00715                if(l==0){
00716                   OPENGM_ASSERT(!(partialOptimality_[var][inversePermutation_[var][gm_.numberOfLabels(var)-1]]==opengm::Tribool::True));
00717                   partialOptimality_[var][inversePermutation_[var][gm_.numberOfLabels(var)-1]]&=opengm::Tribool::False;
00718                }
00719                else if(l==1){
00720                   OPENGM_ASSERT(!(partialOptimality_[var][inversePermutation_[var][gm_.numberOfLabels(var)-1]]==opengm::Tribool::False));        
00721                   partialOptimality_[var][inversePermutation_[var][gm_.numberOfLabels(var)-1]]&=opengm::Tribool::True;
00722                }
00723                //else         {partialOptimality_[var][permutation_[var][gm_.numberOfLabels(var)-1]]&=opengm::Tribool::Maybe;}
00724             }
00725             //ELSE
00726             
00727             for(LabelType l=1; l+1<gm_.numberOfLabels(var);++l)
00728             {
00729                int l1 = qpbo_->GetLabel(varROffset[varR]+l-1);
00730                int l2 = qpbo_->GetLabel(varROffset[varR]+l);
00731                //int l1 = qpbo_->GetLabel(variableOffset_[var]+l-1);
00732                //int l2 = qpbo_->GetLabel(variableOffset_[var]+l);
00733                OPENGM_ASSERT(!(l1==0 && l2==1));
00734                if(l1==1 && l2==0) {
00735                   OPENGM_ASSERT(!(partialOptimality_[var][inversePermutation_[var][l]]==opengm::Tribool::False));
00736                   partialOptimality_[var][inversePermutation_[var][l]]&=opengm::Tribool::True;
00737                }
00738                else if(l2==1){
00739                   OPENGM_ASSERT(!(partialOptimality_[var][inversePermutation_[var][l]]==opengm::Tribool::True));
00740                   partialOptimality_[var][inversePermutation_[var][l]]&=opengm::Tribool::False;
00741                }
00742                else if(l1==0){
00743                   OPENGM_ASSERT(!(partialOptimality_[var][inversePermutation_[var][l]]==opengm::Tribool::True));
00744                   partialOptimality_[var][inversePermutation_[var][l]]&=opengm::Tribool::False;
00745                }
00746                //else{  
00747                //   partialOptimality_[var][permutation_[var][l]]&=opengm::Tribool::Maybe;
00748                //}
00749             }  
00750          }
00751       }
00752       for(IndexType var=0; var<gm_.numberOfVariables();++var){
00753          if(optimal_[var]) continue;
00754          LabelType countTRUE = 0;
00755          LabelType countFALSE = 0;
00756          for(LabelType l=1; l+1<gm_.numberOfLabels(var);++l){
00757             if(partialOptimality_[var][l]==opengm::Tribool::True) 
00758                ++countTRUE;
00759             if(partialOptimality_[var][l]==opengm::Tribool::False) 
00760                ++countFALSE;
00761          }
00762          if(countTRUE==1){
00763             optimal_[var]=true;
00764             for(LabelType l=1; l+1<gm_.numberOfLabels(var);++l){
00765                if(partialOptimality_[var][l]==opengm::Tribool::True)
00766                   label_[var]=l;
00767                else
00768                   partialOptimality_[var][l]=opengm::Tribool::False;
00769             }
00770          }
00771          if(countFALSE+1==gm_.numberOfLabels(var)){
00772             optimal_[var]=true;
00773             for(LabelType l=1; l+1<gm_.numberOfLabels(var);++l){
00774                if(partialOptimality_[var][l]==opengm::Tribool::Maybe){
00775                   label_[var]=l;
00776                   partialOptimality_[var][l]=opengm::Tribool::True;
00777                }
00778             }
00779          }
00780       }
00781       return NORMAL; 
00782    }
00783 
00784    template<class GM, class ACC>
00785    InferenceTermination MQPBO<GM,ACC>::infer
00786    ()
00787    {
00788       EmptyVisitorType visitor;
00789       return infer(visitor);
00790    }
00791      
00792    template<class GM, class ACC>
00793    template<class VisitorType>
00794    InferenceTermination MQPBO<GM,ACC>::infer
00795    (
00796       VisitorType& visitor
00797    )
00798    { 
00799 
00800       if(param_.rounds_>1 && param_.strongPersistency_==false)
00801          std::cout << "WARNING: Using weak persistency and several rounds may lead to wrong results if solution is not unique!"<<std::endl;
00802 
00803       LabelType maxNumberOfLabels = 0;
00804       for(IndexType var=0; var<gm_.numberOfVariables();++var){
00805          maxNumberOfLabels = std::max(maxNumberOfLabels, gm_.numberOfLabels(var));
00806       }
00807       bool isPotts = true;
00808 
00809       for(IndexType f=0; f< gm_.numberOfFactors(); ++f){
00810          if(gm_[f].numberOfVariables()<2) continue;
00811          isPotts &= gm_[f].isPotts();
00812          if(!isPotts) break;
00813       }
00814 
00815       visitor.begin(*this);
00816 
00817       if(param_.useKovtunsMethod_){
00818          if(isPotts){
00819             std::cout << "Use Kovtuns method for potts"<<std::endl;
00820             for(LabelType l=0; l<maxNumberOfLabels; ++l) {
00821                testQuess(l);
00822                double xoptimality = optimality(); 
00823                double xoptimalityV = optimalityV();
00824                #ifdef MQPBO_PYTHON_WRAPPER_HACK
00825                visitor(*this,value(),bound(),"partialOptimality",xoptimality,"partialOptimalityV",xoptimalityV);
00826                #else
00827                visitor.visit(value(),bound(),"partialOptimality",xoptimality,"partialOptimalityV",xoptimalityV);
00828                #endif
00829                //std::cout << "partialOptimality  : " << optimality() << std::endl; 
00830             }
00831          }
00832          else{
00833             std::cout << "Use Kovtuns method for non-potts is not supported yet"<<std::endl;
00834             /*
00835             for(LabelType l=0; l<maxNumberOfLabels; ++l){
00836                std::vector<LabelType> guess(gm_.numberOfVariables(),l);
00837                for(IndexType var=0; var<gm_.numberOfVariables();++var){
00838                   if(l>=gm_.numberOfLabels(var)){
00839                      guess[var]=l-1;
00840                   }
00841                }
00842                testQuess(guess);
00843                double xoptimality = optimality();
00844                visitor(*this,this->value(),bound(),"partialOptimality",xoptimality);
00845                //std::cout << "partialOptimality  : " << optimality() << std::endl;
00846             }
00847             */
00848          }
00849       }
00850 
00851       if(param_.rounds_>0){
00852          std::cout << "Start "<<param_.rounds_ << " of multilabel QPBO for different permutations" <<std::endl;
00853          for(size_t rr=0; rr<param_.rounds_;++rr){
00854             testPermutation(param_.permutationType_);
00855             double xoptimality = optimality();
00856             double xoptimalityV = optimalityV();
00857             #ifdef MQPBO_PYTHON_WRAPPER_HACK
00858             visitor(*this,value(),bound(),"partialOptimality",xoptimality,"partialOptimalityV",xoptimalityV);
00859             #else
00860             visitor.visit(value(),bound(),"partialOptimality",xoptimality,"partialOptimalityV",xoptimalityV);
00861             #endif
00862             //std::cout << "partialOptimality  : " << optimality() << std::endl;
00863          }
00864       }
00865 
00866 #ifdef MQPBOHotFixOutPutPartialOPtimalityMap
00867       hid_t fid = marray::hdf5::createFile("mqpbotmp.h5");
00868       std::vector<double> optimal;
00869       for(size_t i=0; i<optimal_.size();++i)
00870          optimal.push_back((double)(optimal_[i]));
00871       marray::hdf5::save(fid, "popt", optimal);
00872       marray::hdf5::closeFile(fid);
00873 #endif  
00874    
00875       visitor.end(*this);
00876       
00877       return NORMAL;
00878    }
00879    
00880    template<class GM, class ACC>
00881    double 
00882    MQPBO<GM,ACC>::optimality
00883    () const
00884    { 
00885       size_t labeled   = 0;
00886       size_t unlabeled = 0; 
00887       for(IndexType var=0; var<gm_.numberOfVariables();++var){
00888          for(LabelType l=0; l<gm_.numberOfLabels(var);++l){
00889             if(partialOptimality_[var][l]==opengm::Tribool::Maybe)
00890                ++unlabeled;
00891             else
00892                ++labeled;
00893          }
00894       }
00895       return labeled*1.0/(labeled+unlabeled);
00896    }  
00897 
00898    template<class GM, class ACC>
00899    double 
00900    MQPBO<GM,ACC>::optimalityV
00901    () const
00902    { 
00903       size_t labeled   = 0; 
00904       for(IndexType var=0; var<gm_.numberOfVariables();++var){
00905          for(LabelType l=0; l<gm_.numberOfLabels(var);++l){
00906             if(partialOptimality_[var][l]==opengm::Tribool::True){
00907                ++labeled;
00908                continue;
00909             }
00910          }
00911       }
00912       return labeled*1.0/gm_.numberOfVariables();
00913    } 
00914 
00915    template<class GM, class ACC>
00916    typename GM::ValueType 
00917    MQPBO<GM,ACC>::bound
00918    () const
00919    {
00920       return bound_;
00921    } 
00922    
00923    template<class GM, class ACC>
00924    typename GM::ValueType  MQPBO<GM,ACC>::value() const { 
00925       std::vector<LabelType> states;
00926       arg(states);
00927       return gm_.evaluate(states);
00928    }
00929 
00930    template<class GM, class ACC>
00931    inline InferenceTermination
00932    MQPBO<GM,ACC>::arg
00933    (
00934       std::vector<LabelType>& x,
00935       const size_t N
00936    ) const
00937    {
00938       if(N==1){
00939          x.resize(gm_.numberOfVariables(),0); 
00940 
00941          for(IndexType var=0; var<gm_.numberOfVariables(); ++var){
00942             size_t countTrue  = 0;
00943             size_t countFalse = 0;
00944             size_t countMaybe = 0;
00945             x[var]=0;
00946             for(LabelType l=0; l<gm_.numberOfLabels(var);++l){
00947                if(partialOptimality_[var][l]==opengm::Tribool::Maybe){ 
00948                   x[var] = l;
00949                   ++countMaybe;
00950                }
00951                if(partialOptimality_[var][l]==opengm::Tribool::True){ 
00952                   x[var] = l;
00953                   ++countTrue;
00954                } 
00955                if(partialOptimality_[var][l]==opengm::Tribool::False){ 
00956                   ++countFalse;
00957                }
00958             }
00959             OPENGM_ASSERT(countTrue+countFalse+countMaybe == gm_.numberOfLabels(var));
00960             OPENGM_ASSERT(countTrue<2); 
00961             OPENGM_ASSERT(countFalse<gm_.numberOfLabels(var));
00962          }
00963          return NORMAL;
00964       }
00965       else {
00966          return UNKNOWN;
00967       }
00968    }
00969 } // namespace opengm
00970 
00971 #endif // #ifndef OPENGM_MQPBO_HXX
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Mon Jun 17 16:31:05 2013 for OpenGM by  doxygen 1.6.3