00001 #pragma once
00002 #ifndef OPENGM_ALPHAEXPANSION_HXX
00003 #define OPENGM_ALPHAEXPANSION_HXX
00004
00005 #include "opengm/inference/inference.hxx"
00006 #include "opengm/inference/visitors/visitor.hxx"
00007
00008 namespace opengm {
00009
00012 template<class GM, class INF>
00013 class AlphaExpansion
00014 : public Inference<GM, typename INF::AccumulationType>
00015 {
00016 public:
00017 typedef GM GraphicalModelType;
00018 typedef INF InferenceType;
00019 typedef typename INF::AccumulationType AccumulationType;
00020 OPENGM_GM_TYPE_TYPEDEFS;
00021 typedef VerboseVisitor<AlphaExpansion<GM,INF> > VerboseVisitorType;
00022 typedef TimingVisitor<AlphaExpansion<GM,INF> > TimingVisitorType;
00023 typedef EmptyVisitor<AlphaExpansion<GM,INF> > EmptyVisitorType;
00024
00025 struct Parameter {
00026 typedef typename InferenceType::Parameter InferenceParameter;
00027 enum LabelingIntitialType {DEFAULT_LABEL, RANDOM_LABEL, LOCALOPT_LABEL, EXPLICIT_LABEL};
00028 enum OrderType {DEFAULT_ORDER, RANDOM_ORDER, EXPLICIT_ORDER};
00029
00030 Parameter
00031 (
00032 const size_t maxNumberOfSteps = 1000,
00033 const InferenceParameter& para = InferenceParameter()
00034 )
00035 : parameter_(para),
00036 maxNumberOfSteps_(maxNumberOfSteps),
00037 labelInitialType_(DEFAULT_LABEL),
00038 orderType_(DEFAULT_ORDER),
00039 randSeedOrder_(0),
00040 randSeedLabel_(0),
00041 labelOrder_(),
00042 label_()
00043 {}
00044
00045 InferenceParameter parameter_;
00046 size_t maxNumberOfSteps_;
00047 LabelingIntitialType labelInitialType_;
00048 OrderType orderType_;
00049 unsigned int randSeedOrder_;
00050 unsigned int randSeedLabel_;
00051 std::vector<LabelType> labelOrder_;
00052 std::vector<LabelType> label_;
00053 };
00054
00055 AlphaExpansion(const GraphicalModelType&, Parameter para = Parameter());
00056
00057 std::string name() const;
00058 const GraphicalModelType& graphicalModel() const;
00059 template<class StateIterator>
00060 void setState(StateIterator, StateIterator);
00061 InferenceTermination infer();
00062 void reset();
00063 template<class Visitor>
00064 InferenceTermination infer(Visitor& visitor);
00065 void setStartingPoint(typename std::vector<LabelType>::const_iterator);
00066 InferenceTermination arg(std::vector<LabelType>&, const size_t = 1) const;
00067
00068 private:
00069 const GraphicalModelType& gm_;
00070 Parameter parameter_;
00071 std::vector<LabelType> label_;
00072 std::vector<LabelType> labelList_;
00073 size_t maxState_;
00074 size_t alpha_;
00075 size_t counter_;
00076 void incrementAlpha();
00077 void setLabelOrder(std::vector<LabelType>& l);
00078 void setLabelOrderRandom(unsigned int);
00079 void setInitialLabel(std::vector<LabelType>& l);
00080 void setInitialLabelLocalOptimal();
00081 void setInitialLabelRandom(unsigned int);
00082 void addUnary(INF&, const size_t var, const ValueType v0, const ValueType v1);
00083 void addPairwise(INF&, const size_t var1, const size_t var2, const ValueType v0, const ValueType v1, const ValueType v2, const ValueType v3);
00084 };
00085
00086 template<class GM, class INF>
00087 inline std::string
00088 AlphaExpansion<GM, INF>::name() const
00089 {
00090 return "Alpha-Expansion";
00091 }
00092
00093 template<class GM, class INF>
00094 inline const typename AlphaExpansion<GM, INF>::GraphicalModelType&
00095 AlphaExpansion<GM, INF>::graphicalModel() const
00096 {
00097 return gm_;
00098 }
00099
00100 template<class GM, class INF>
00101 template<class StateIterator>
00102 inline void
00103 AlphaExpansion<GM, INF>::setState
00104 (
00105 StateIterator begin,
00106 StateIterator end
00107 )
00108 {
00109 label_.assign(begin, end);
00110 }
00111
00112 template<class GM, class INF>
00113 inline void
00114 AlphaExpansion<GM,INF>::setStartingPoint
00115 (
00116 typename std::vector<typename AlphaExpansion<GM,INF>::LabelType>::const_iterator begin
00117 ) {
00118 try{
00119 label_.assign(begin, begin+gm_.numberOfVariables());
00120 }
00121 catch(...) {
00122 throw RuntimeError("unsuitable starting point");
00123 }
00124 }
00125
00126 template<class GM, class INF>
00127 inline
00128 AlphaExpansion<GM, INF>::AlphaExpansion
00129 (
00130 const GraphicalModelType& gm,
00131 Parameter para
00132 )
00133 : gm_(gm),
00134 parameter_(para),
00135 maxState_(0)
00136 {
00137 for(size_t j=0; j<gm_.numberOfFactors(); ++j) {
00138 if(gm_[j].numberOfVariables() > 2) {
00139 throw RuntimeError("This implementation of Alpha-Expansion supports only factors of order <= 2.");
00140 }
00141 }
00142 for(size_t i=0; i<gm_.numberOfVariables(); ++i) {
00143 size_t numSt = gm_.numberOfLabels(i);
00144 if(numSt > maxState_) {
00145 maxState_ = numSt;
00146 }
00147 }
00148
00149 if(parameter_.labelInitialType_ == Parameter::RANDOM_LABEL) {
00150 setInitialLabelRandom(parameter_.randSeedLabel_);
00151 }
00152 else if(parameter_.labelInitialType_ == Parameter::LOCALOPT_LABEL) {
00153 setInitialLabelLocalOptimal();
00154 }
00155 else if(parameter_.labelInitialType_ == Parameter::EXPLICIT_LABEL) {
00156 setInitialLabel(parameter_.label_);
00157 }
00158 else{
00159 label_.resize(gm_.numberOfVariables(), 0);
00160 }
00161
00162
00163 if(parameter_.orderType_ == Parameter::RANDOM_ORDER) {
00164 setLabelOrderRandom(parameter_.randSeedOrder_);
00165 }
00166 else if(parameter_.orderType_ == Parameter::EXPLICIT_ORDER) {
00167 setLabelOrder(parameter_.labelOrder_);
00168 }
00169 else{
00170 labelList_.resize(maxState_);
00171 for(size_t i=0; i<maxState_; ++i)
00172 labelList_[i] = i;
00173 }
00174
00175 counter_ = 0;
00176 alpha_ = labelList_[counter_];
00177 }
00178
00179
00180
00181 template<class GM, class INF>
00182 inline void
00183 AlphaExpansion<GM, INF>::reset() {
00184 if(parameter_.labelInitialType_ == Parameter::RANDOM_LABEL) {
00185 setInitialLabelRandom(parameter_.randSeedLabel_);
00186 }
00187 else if(parameter_.labelInitialType_ == Parameter::LOCALOPT_LABEL) {
00188 setInitialLabelLocalOptimal();
00189 }
00190 else if(parameter_.labelInitialType_ == Parameter::EXPLICIT_LABEL) {
00191 setInitialLabel(parameter_.label_);
00192 }
00193 else{
00194 std::fill(label_.begin(),label_.end(),0);
00195 }
00196
00197
00198 if(parameter_.orderType_ == Parameter::RANDOM_ORDER) {
00199 setLabelOrderRandom(parameter_.randSeedOrder_);
00200 }
00201 else if(parameter_.orderType_ == Parameter::EXPLICIT_ORDER) {
00202 setLabelOrder(parameter_.labelOrder_);
00203 }
00204 else{
00205 for(size_t i=0; i<maxState_; ++i)
00206 labelList_[i] = i;
00207 }
00208 counter_ = 0;
00209 alpha_ = labelList_[counter_];
00210 }
00211
00212 template<class GM, class INF>
00213 inline void
00214 AlphaExpansion<GM, INF>::addUnary
00215 (
00216 INF& inf,
00217 const size_t var1,
00218 const ValueType v0,
00219 const ValueType v1
00220 ) {
00221 const size_t shape[] = {2};
00222 size_t vars[] = {var1};
00223 opengm::IndependentFactor<ValueType,IndexType,LabelType> fac(vars, vars+1, shape, shape+1);
00224 fac(0) = v0;
00225 fac(1) = v1;
00226 inf.addFactor(fac);
00227 }
00228
00229 template<class GM, class INF>
00230 inline void
00231 AlphaExpansion<GM, INF>::addPairwise
00232 (
00233 INF& inf,
00234 const size_t var1,
00235 const size_t var2,
00236 const ValueType v0,
00237 const ValueType v1,
00238 const ValueType v2,
00239 const ValueType v3
00240 ) {
00241 const LabelType shape[] = {2, 2};
00242 const IndexType vars[] = {var1, var2};
00243 opengm::IndependentFactor<ValueType,IndexType,LabelType> fac(vars, vars+2, shape, shape+2);
00244 fac(0, 0) = v0;
00245 fac(0, 1) = v1;
00246 fac(1, 0) = v2;
00247 fac(1, 1) = v3;
00248 inf.addFactor(fac);
00249 }
00250
00251 template<class GM, class INF>
00252 inline InferenceTermination
00253 AlphaExpansion<GM, INF>::infer()
00254 {
00255 EmptyVisitorType visitor;
00256 return infer(visitor);
00257 }
00258
00259 template<class GM, class INF>
00260 template<class Visitor>
00261 InferenceTermination
00262 AlphaExpansion<GM, INF>::infer
00263 (
00264 Visitor& visitor
00265 )
00266 {
00267 size_t it = 0;
00268 size_t countUnchanged = 0;
00269 size_t numberOfVariables = gm_.numberOfVariables();
00270 std::vector<size_t> variable2Node(numberOfVariables);
00271 ValueType energy = gm_.evaluate(label_);
00272 visitor.begin(*this,energy,energy);
00273 LabelType vecA[1];
00274 LabelType vecX[1];
00275 LabelType vecAA[2];
00276 LabelType vecAX[2];
00277 LabelType vecXA[2];
00278 LabelType vecXX[2];
00279 while(it++ < parameter_.maxNumberOfSteps_ && countUnchanged < maxState_) {
00280 size_t numberOfAuxiliaryNodes = 0;
00281 for(size_t k=0 ; k<gm_.numberOfFactors(); ++k) {
00282 const FactorType& factor = gm_[k];
00283 if(factor.numberOfVariables() == 2) {
00284 size_t var1 = factor.variableIndex(0);
00285 size_t var2 = factor.variableIndex(1);
00286 if(label_[var1] != label_[var2] && label_[var1] != alpha_ && label_[var2] != alpha_ ) {
00287 ++numberOfAuxiliaryNodes;
00288 }
00289 }
00290 }
00291 std::vector<size_t> numFacDim(4, 0);
00292 INF inf(numberOfVariables + numberOfAuxiliaryNodes, numFacDim, parameter_.parameter_);
00293 size_t varX = numberOfVariables;
00294 size_t countAlphas = 0;
00295 for (size_t k=0 ; k<gm_.numberOfVariables(); ++k) {
00296 if (label_[k] == alpha_ ) {
00297 addUnary(inf, k, 0, std::numeric_limits<ValueType>::infinity());
00298 ++countAlphas;
00299 }
00300 }
00301 if(countAlphas < gm_.numberOfVariables()) {
00302 for (size_t k=0 ; k<gm_.numberOfFactors(); ++k) {
00303 const FactorType& factor = gm_[k];
00304 if(factor.numberOfVariables() == 1) {
00305 size_t var = factor.variableIndex(0);
00306 vecA[0] = alpha_;
00307 vecX[0] = label_[var];
00308 if (label_[var] != alpha_ ) {
00309 addUnary(inf, var, factor(vecA), factor(vecX));
00310 }
00311 }
00312 else if (factor.numberOfVariables() == 2) {
00313 size_t var1 = factor.variableIndex(0);
00314 size_t var2 = factor.variableIndex(1);
00315 std::vector<IndexType> vars(2); vars[0]=var1;vars[1]=var2;
00316 vecAA[0] = vecAA[1] = alpha_;
00317 vecAX[0] = alpha_; vecAX[1] = label_[var2];
00318 vecXA[0] = label_[var1]; vecXA[1] = alpha_;
00319 vecXX[0] = label_[var1]; vecXX[1] = label_[var2];
00320 if(label_[var1]==alpha_ && label_[var2]==alpha_) {
00321 continue;
00322 }
00323 else if(label_[var1]==alpha_) {
00324 addUnary(inf, var2, factor(vecAA), factor(vecAX));
00325 }
00326 else if(label_[var2]==alpha_) {
00327 addUnary(inf, var1, factor(vecAA), factor(vecXA));
00328 }
00329 else if(label_[var1]==label_[var2]) {
00330 addPairwise(inf, var1, var2, factor(vecAA), factor(vecAX), factor(vecXA), factor(vecXX));
00331 }
00332 else{
00333 OPENGM_ASSERT(varX < numberOfVariables + numberOfAuxiliaryNodes);
00334 addPairwise(inf, var1, varX, 0, factor(vecAX), 0, 0);
00335 addPairwise(inf, var2, varX, 0, factor(vecXA), 0, 0);
00336 addUnary(inf, varX, factor(vecAA), factor(vecXX));
00337 ++varX;
00338 }
00339 }
00340 }
00341 std::vector<LabelType> state;
00342 inf.infer();
00343 inf.arg(state);
00344 OPENGM_ASSERT(state.size() == numberOfVariables + numberOfAuxiliaryNodes);
00345 for(size_t var=0; var<numberOfVariables ; ++var) {
00346 if (label_[var] != alpha_ && state[var]==0) {
00347 label_[var] = alpha_;
00348 }
00349 OPENGM_ASSERT(label_[var] < gm_.numberOfLabels(var));
00350 }
00351 }
00352 OPENGM_ASSERT(gm_.numberOfVariables() == label_.size());
00353 ValueType energy2 = gm_.evaluate(label_);
00354 visitor(*this,energy2,energy,alpha_);
00355
00356 if(AccumulationType::bop(energy2, energy)) {
00357 energy=energy2;
00358 countUnchanged = 0;
00359 }
00360 else{
00361 ++countUnchanged;
00362 }
00363 incrementAlpha();
00364 OPENGM_ASSERT(alpha_ < maxState_);
00365 }
00366 visitor.end(*this,energy,energy);
00367 return NORMAL;
00368 }
00369
00370 template<class GM, class INF>
00371 inline InferenceTermination
00372 AlphaExpansion<GM, INF>::arg
00373 (
00374 std::vector<LabelType>& arg,
00375 const size_t n
00376 ) const
00377 {
00378 if(n > 1) {
00379 return UNKNOWN;
00380 }
00381 else {
00382 OPENGM_ASSERT(label_.size() == gm_.numberOfVariables());
00383 arg.resize(label_.size());
00384 for(size_t i=0; i<label_.size(); ++i) {
00385 arg[i] = label_[i];
00386 }
00387 return NORMAL;
00388 }
00389 }
00390
00391 template<class GM, class INF>
00392 inline void
00393 AlphaExpansion<GM, INF>::setLabelOrder
00394 (
00395 std::vector<LabelType>& l
00396 ) {
00397 if(l.size() == maxState_) {
00398 labelList_=l;
00399 }
00400 }
00401
00402 template<class GM, class INF>
00403 inline void
00404 AlphaExpansion<GM, INF>::setLabelOrderRandom
00405 (
00406 unsigned int seed
00407 ) {
00408 srand(seed);
00409 labelList_.resize(maxState_);
00410 for (size_t i=0; i<maxState_;++i) {
00411 labelList_[i]=i;
00412 }
00413 random_shuffle(labelList_.begin(), labelList_.end());
00414 }
00415
00416 template<class GM, class INF>
00417 inline void
00418 AlphaExpansion<GM, INF>::setInitialLabel
00419 (
00420 std::vector<LabelType>& l
00421 ) {
00422 label_.resize(gm_.numberOfVariables());
00423 if(l.size() == label_.size()) {
00424 for(size_t i=0; i<l.size();++i) {
00425 if(l[i]>=gm_.numberOfLabels(i)) return;
00426 }
00427 for(size_t i=0; i<l.size();++i) {
00428 label_[i] = l[i];
00429 }
00430 }
00431 }
00432
00433 template<class GM, class INF>
00434 inline void
00435 AlphaExpansion<GM, INF>::setInitialLabelLocalOptimal() {
00436 label_.resize(gm_.numberOfVariables(), 0);
00437 std::vector<size_t> accVec;
00438 for(size_t i=0; i<gm_.numberOfFactors();++i) {
00439 if(gm_[i].numberOfVariables()==1) {
00440 std::vector<size_t> state(1, 0);
00441 ValueType value = gm_[i](state.begin());
00442 for(state[0]=1; state[0]<gm_.numberOfLabels(i); ++state[0]) {
00443 if(AccumulationType::bop(gm_[i](state.begin()), value)) {
00444 value = gm_[i](state.begin());
00445 label_[i] = state[0];
00446 }
00447 }
00448 }
00449 }
00450 }
00451
00452 template<class GM, class INF>
00453 inline void
00454 AlphaExpansion<GM, INF>::setInitialLabelRandom
00455 (
00456 unsigned int seed
00457 ) {
00458 srand(seed);
00459 label_.resize(gm_.numberOfVariables());
00460 for(size_t i=0; i<gm_.numberOfVariables();++i) {
00461 label_[i] = rand() % gm_.numberOfLabels(i);
00462 }
00463 }
00464
00465 template<class GM, class INF>
00466 inline void
00467 AlphaExpansion<GM, INF>::incrementAlpha() {
00468 counter_ = (counter_+1) % maxState_;
00469 alpha_ = labelList_[counter_];
00470 }
00471
00472 }
00473
00474 #endif // #ifndef OPENGM_ALPHAEXPANSION_HXX