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
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_;
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
00094
00095
00096 std::vector<std::vector<LabelType> > permutation_;
00097 std::vector<std::vector<LabelType> > inversePermutation_;
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
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
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
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);
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_);
00169 qpbo_->AddNode(numNodes_);
00170 }
00171 else{
00172 std::cout << "Small" <<std::endl;
00173 qpbo_ = new kolmogorov::qpbo::QPBO<GraphValueType > (gm_.numberOfVariables(), numSOF);
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
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 ;
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
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
00419 for(LabelType i=0; i<numStates;++i){
00420 permutation_[var][i]=i;
00421 }
00422
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
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
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
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
00496 ValueType constValue = 0;
00497 qpbo_->Reset();
00498 qpbo_->AddNode(numBVar);
00499
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
00512
00513
00514
00515
00516
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
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
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
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
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
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
00601
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
00617
00618 qpbo_->Solve();
00619 if(!param_.strongPersistency_)
00620 qpbo_->ComputeWeakPersistencies();
00621
00622
00623
00624
00625 bound_ = constValue + 0.5 * qpbo_->ComputeTwiceLowerBound();
00626
00627
00628 if(param_.probing_) {
00629 std::cout << "Start Probing ..."<<std::endl;
00630
00631 int *mapping = new int[numBVar];
00632
00633 for(int i = 0; i < static_cast<int>(numBVar); ++i) {
00634
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
00652 {
00653 int l = qpbo_->GetLabel(mapping[varROffset[varR]]/2);
00654 if(l>=0) l = (l + mapping[varROffset[varR]]) % 2;
00655
00656
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
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
00666
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
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
00680
00681
00682
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
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
00698 {
00699 int l = qpbo_->GetLabel(varROffset[varR]);
00700
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
00710 }
00711
00712 {
00713 int l = qpbo_->GetLabel(varROffset[varR]+gm_.numberOfLabels(var)-2);
00714
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
00724 }
00725
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
00732
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
00747
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
00830 }
00831 }
00832 else{
00833 std::cout << "Use Kovtuns method for non-potts is not supported yet"<<std::endl;
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
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
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 }
00970
00971 #endif // #ifndef OPENGM_MQPBO_HXX