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
00184
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
00264
00265 ValueType energy = gm_.evaluate(label_);
00266 visitor.begin(*this,energy,this->bound(),0);
00267
00268
00269
00270
00271
00272
00273
00274
00275 while(it++ < parameter_.maxNumberOfSteps_ && countUnchanged < maxState_) {
00276
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
00295
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
00353 incrementAlpha();
00354 OPENGM_ASSERT(alpha_ < maxState_);
00355 }
00356 visitor.end(*this,energy,this->bound(),0);
00357 return NORMAL;
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
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 }
00557
00558 #endif // #ifndef OPENGM_ALPHAEXPANSIONFUSION_HXX