00001 #pragma once
00002 #ifndef OPENGM_GIBBS_HXX
00003 #define OPENGM_GIBBS_HXX
00004
00005 #include <vector>
00006 #include <string>
00007 #include <iostream>
00008 #include <iomanip>
00009 #include <cstdlib>
00010 #include <cmath>
00011 #include <typeinfo>
00012
00013 #include "opengm/opengm.hxx"
00014 #include "opengm/utilities/random.hxx"
00015 #include "opengm/inference/inference.hxx"
00016 #include "opengm/inference/movemaker.hxx"
00017 #include "opengm/operations/minimizer.hxx"
00018 #include "opengm/operations/maximizer.hxx"
00019 #include "opengm/operations/adder.hxx"
00020 #include "opengm/operations/multiplier.hxx"
00021 #include "opengm/operations/integrator.hxx"
00022 #include "opengm/inference/visitors/visitor.hxx"
00023
00024 namespace opengm {
00025
00027 namespace detail_gibbs {
00028
00029 template<class OPERATOR, class ACCUMULATOR, class PROBABILITY>
00030 struct ValuePairToProbability;
00031
00032 template<class PROBABILITY>
00033 struct ValuePairToProbability<Multiplier, Maximizer, PROBABILITY>
00034 {
00035 typedef PROBABILITY ProbabilityType;
00036 template<class T>
00037 static ProbabilityType convert(const T newValue, const T oldValue)
00038 { return static_cast<ProbabilityType>(newValue) / static_cast<ProbabilityType>(oldValue); }
00039 };
00040
00041 template<class PROBABILITY>
00042 struct ValuePairToProbability<Adder, Minimizer, PROBABILITY>
00043 {
00044 typedef PROBABILITY ProbabilityType;
00045 template<class T>
00046 static ProbabilityType convert(const T newValue, const T oldValue)
00047 { return static_cast<ProbabilityType>(std::exp(oldValue - newValue)); }
00048 };
00049 }
00051
00055 template<class GIBBS>
00056 class GibbsMarginalVisitor {
00057 public:
00058 typedef GIBBS GibbsType;
00059 typedef typename GibbsType::ValueType ValueType;
00060 typedef typename GibbsType::GraphicalModelType GraphicalModelType;
00061 typedef typename GraphicalModelType::IndependentFactorType IndependentFactorType;
00062
00063
00064 GibbsMarginalVisitor();
00065 GibbsMarginalVisitor(const GraphicalModelType&);
00066 void assign(const GraphicalModelType&);
00067
00068
00069 template<class VariableIndexIterator>
00070 size_t addMarginal(VariableIndexIterator, VariableIndexIterator);
00071 size_t addMarginal(const size_t);
00072 void operator()(const GibbsType&, const ValueType, const ValueType, const size_t, const bool, const bool);
00073
00074
00075 void begin(const GibbsType&, const ValueType, const ValueType) const {}
00076 void end(const GibbsType&, const ValueType, const ValueType) const {}
00077 size_t numberOfSamples() const;
00078 size_t numberOfAcceptedSamples() const;
00079 size_t numberOfRejectedSamples() const;
00080 size_t numberOfMarginals() const;
00081 const IndependentFactorType& marginal(const size_t) const;
00082
00083 private:
00084 const GraphicalModelType* gm_;
00085 size_t numberOfSamples_;
00086 size_t numberOfAcceptedSamples_;
00087 size_t numberOfRejectedSamples_;
00088 std::vector<IndependentFactorType> marginals_;
00089 std::vector<size_t> stateCache_;
00090 };
00091
00093 template<class GM, class ACC>
00094 class Gibbs
00095 : public Inference<GM, ACC> {
00096 public:
00097 typedef ACC AccumulationType;
00098 typedef GM GraphicalModelType;
00099 OPENGM_GM_TYPE_TYPEDEFS;
00100 typedef Movemaker<GraphicalModelType> MovemakerType;
00101 typedef VerboseVisitor<Gibbs<GM, ACC> > VerboseVisitorType;
00102 typedef EmptyVisitor<Gibbs<GM, ACC> > EmptyVisitorType;
00103 typedef TimingVisitor<Gibbs<GM, ACC> > TimingVisitorType;
00104 typedef double ProbabilityType;
00105
00106 class Parameter {
00107 public:
00108 enum VariableProposal {RANDOM, CYCLIC};
00109
00110 Parameter(
00111 const size_t maxNumberOfSamplingSteps = 1e5,
00112 const size_t numberOfBurnInSteps = 1e5,
00113 const bool useTemp=false,
00114 const ValueType tmin=0.0001,
00115 const ValueType tmax=1,
00116 const IndexType periods=10,
00117 const VariableProposal variableProposal = RANDOM,
00118 const std::vector<size_t>& startPoint = std::vector<size_t>()
00119 )
00120 : maxNumberOfSamplingSteps_(maxNumberOfSamplingSteps),
00121 numberOfBurnInSteps_(numberOfBurnInSteps),
00122 variableProposal_(variableProposal),
00123 startPoint_(startPoint),
00124 useTemp_(useTemp),
00125 tempMin_(tmin),
00126 tempMax_(tmax),
00127 periods_(periods){
00128 p_=static_cast<ValueType>(maxNumberOfSamplingSteps_/periods_);
00129 }
00130 bool useTemp_;
00131 ValueType tempMin_;
00132 ValueType tempMax_;
00133 size_t periods_;
00134 ValueType p_;
00135 size_t maxNumberOfSamplingSteps_;
00136 size_t numberOfBurnInSteps_;
00137 VariableProposal variableProposal_;
00138 std::vector<size_t> startPoint_;
00139
00140
00141 };
00142
00143 Gibbs(const GraphicalModelType&, const Parameter& param = Parameter());
00144 std::string name() const;
00145 const GraphicalModelType& graphicalModel() const;
00146 void reset();
00147 InferenceTermination infer();
00148 template<class VISITOR>
00149 InferenceTermination infer(VISITOR&);
00150 void setStartingPoint(typename std::vector<LabelType>::const_iterator);
00151 virtual InferenceTermination arg(std::vector<LabelType>&, const size_t = 1) const;
00152
00153 LabelType markovState(const size_t) const;
00154 ValueType markovValue() const;
00155 LabelType currentBestState(const size_t) const;
00156 ValueType currentBestValue() const;
00157
00158 private:
00159 ValueType cosTemp(const ValueType arg,const ValueType periode,const ValueType min,const ValueType max)const{
00160 return static_cast<ValueType>(((std::cos(arg/periode)+1.0)/2.0)*(max-min))+min;
00161
00162 }
00163
00164 ValueType getTemperature(const size_t step)const{
00165 return cosTemp(
00166 static_cast<ValueType>(step),
00167 parameter_.p_,
00168 parameter_.tempMin_,
00169 parameter_.tempMax_
00170 );
00171 }
00172 Parameter parameter_;
00173 const GraphicalModelType& gm_;
00174 MovemakerType movemaker_;
00175 std::vector<size_t> currentBestState_;
00176 ValueType currentBestValue_;
00177 };
00178
00179 template<class GM, class ACC>
00180 inline
00181 Gibbs<GM, ACC>::Gibbs
00182 (
00183 const GraphicalModelType& gm,
00184 const Parameter& parameter
00185 )
00186 : parameter_(parameter),
00187 gm_(gm),
00188 movemaker_(gm),
00189 currentBestState_(gm.numberOfVariables()),
00190 currentBestValue_()
00191 {
00192 ACC::ineutral(currentBestValue_);
00193 if(parameter.startPoint_.size() != 0) {
00194 if(parameter.startPoint_.size() == gm.numberOfVariables()) {
00195 movemaker_.initialize(parameter.startPoint_.begin());
00196 currentBestState_ = parameter.startPoint_;
00197 currentBestValue_ = movemaker_.value();
00198 }
00199 else {
00200 throw RuntimeError("parameter.startPoint_.size() is neither zero nor equal to the number of variables.");
00201 }
00202 }
00203 }
00204
00205 template<class GM, class ACC>
00206 inline void
00207 Gibbs<GM, ACC>::reset() {
00208 if(parameter_.startPoint_.size() != 0) {
00209 if(parameter_.startPoint_.size() == gm_.numberOfVariables()) {
00210 movemaker_.initialize(parameter_.startPoint_.begin());
00211 currentBestState_ = parameter_.startPoint_;
00212 currentBestValue_ = movemaker_.value();
00213 }
00214 else {
00215 throw RuntimeError("parameter.startPoint_.size() is neither zero nor equal to the number of variables.");
00216 }
00217 }
00218 else {
00219 movemaker_.reset();
00220 std::fill(currentBestState_.begin(), currentBestState_.end(), 0);
00221 }
00222 }
00223
00224 template<class GM, class ACC>
00225 inline void
00226 Gibbs<GM, ACC>::setStartingPoint
00227 (
00228 typename std::vector<typename Gibbs<GM, ACC>::LabelType>::const_iterator begin
00229 ) {
00230 try{
00231 movemaker_.initialize(begin);
00232
00233 for(IndexType vi=0;vi<static_cast<IndexType>(gm_.numberOfVariables());++vi ){
00234 currentBestState_[vi]=movemaker_.state(vi);
00235 }
00236 currentBestValue_ = movemaker_.value();
00237
00238 }
00239 catch(...) {
00240 throw RuntimeError("unsuitable starting point");
00241 }
00242 }
00243
00244 template<class GM, class ACC>
00245 inline std::string
00246 Gibbs<GM, ACC>::name() const
00247 {
00248 return "Gibbs";
00249 }
00250
00251 template<class GM, class ACC>
00252 inline const typename Gibbs<GM, ACC>::GraphicalModelType&
00253 Gibbs<GM, ACC>::graphicalModel() const
00254 {
00255 return gm_;
00256 }
00257
00258 template<class GM, class ACC>
00259 inline InferenceTermination
00260 Gibbs<GM, ACC>::infer()
00261 {
00262 EmptyVisitorType visitor;
00263 return infer(visitor);
00264 }
00265
00266 template<class GM, class ACC>
00267 template<class VISITOR>
00268 InferenceTermination Gibbs<GM, ACC>::infer(
00269 VISITOR& visitor
00270 ) {
00271 visitor.begin(*this, currentBestValue_, currentBestValue_);
00272 opengm::RandomUniform<size_t> randomVariable(0, gm_.numberOfVariables());
00273 opengm::RandomUniform<ProbabilityType> randomProb(0, 1);
00274
00275 if(parameter_.useTemp_==false){
00276 for(size_t iteration = 0; iteration < parameter_.maxNumberOfSamplingSteps_ + parameter_.numberOfBurnInSteps_; ++iteration) {
00277
00278 size_t variableIndex = 0;
00279 if(this->parameter_.variableProposal_ == Parameter::RANDOM) {
00280 variableIndex = randomVariable();
00281 }
00282 else if(this->parameter_.variableProposal_ == Parameter::CYCLIC) {
00283 variableIndex < gm_.numberOfVariables() - 1 ? ++variableIndex : variableIndex = 0;
00284 }
00285
00286
00287 opengm::RandomUniform<size_t> randomLabel(0, gm_.numberOfLabels(variableIndex));
00288 const size_t label = randomLabel();
00289
00290
00291 const bool burningIn = (iteration < parameter_.numberOfBurnInSteps_);
00292 if(label != movemaker_.state(variableIndex)) {
00293 const ValueType oldValue = movemaker_.value();
00294 const ValueType newValue = movemaker_.valueAfterMove(&variableIndex, &variableIndex + 1, &label);
00295 if(AccumulationType::bop(newValue, oldValue)) {
00296 movemaker_.move(&variableIndex, &variableIndex + 1, &label);
00297 if(AccumulationType::bop(newValue, currentBestValue_) && newValue != currentBestValue_) {
00298 currentBestValue_ = newValue;
00299 for(size_t k = 0; k < currentBestState_.size(); ++k) {
00300 currentBestState_[k] = movemaker_.state(k);
00301 }
00302 }
00303 visitor(*this, newValue, currentBestValue_, iteration, true, burningIn);
00304 }
00305 else {
00306 const ProbabilityType pFlip =
00307 detail_gibbs::ValuePairToProbability<
00308 OperatorType, AccumulationType, ProbabilityType
00309 >::convert(newValue, oldValue);
00310 if(randomProb() < pFlip) {
00311 movemaker_.move(&variableIndex, &variableIndex + 1, &label);
00312 visitor(*this, newValue, currentBestValue_, iteration, true, burningIn);
00313 }
00314 else {
00315 visitor(*this, newValue, currentBestValue_, iteration, false, burningIn);
00316 }
00317 }
00318 ++iteration;
00319 }
00320 }
00321 }
00322 else {
00323 for(size_t iteration = 0; iteration < parameter_.maxNumberOfSamplingSteps_ + parameter_.numberOfBurnInSteps_; ++iteration) {
00324
00325 size_t variableIndex = 0;
00326 if(this->parameter_.variableProposal_ == Parameter::RANDOM) {
00327 variableIndex = randomVariable();
00328 }
00329 else if(this->parameter_.variableProposal_ == Parameter::CYCLIC) {
00330 variableIndex < gm_.numberOfVariables() - 1 ? ++variableIndex : variableIndex = 0;
00331 }
00332
00333
00334 opengm::RandomUniform<size_t> randomLabel(0, gm_.numberOfLabels(variableIndex));
00335 const size_t label = randomLabel();
00336
00337
00338 const bool burningIn = (iteration < parameter_.numberOfBurnInSteps_);
00339 if(label != movemaker_.state(variableIndex)) {
00340 const ValueType oldValue = movemaker_.value();
00341 const ValueType newValue = movemaker_.valueAfterMove(&variableIndex, &variableIndex + 1, &label);
00342 if(AccumulationType::bop(newValue, oldValue)) {
00343 movemaker_.move(&variableIndex, &variableIndex + 1, &label);
00344 if(AccumulationType::bop(newValue, currentBestValue_) && newValue != currentBestValue_) {
00345 currentBestValue_ = newValue;
00346 for(size_t k = 0; k < currentBestState_.size(); ++k) {
00347 currentBestState_[k] = movemaker_.state(k);
00348 }
00349 }
00350 visitor(*this, newValue, currentBestValue_, iteration, true, burningIn);
00351 }
00352 else {
00353 const ProbabilityType pFlip =
00354 detail_gibbs::ValuePairToProbability<
00355 OperatorType, AccumulationType, ProbabilityType
00356 >::convert(newValue, oldValue);
00357 if(randomProb() < pFlip*this->getTemperature(iteration)){
00358
00359 movemaker_.move(&variableIndex, &variableIndex + 1, &label);
00360 visitor(*this, newValue, currentBestValue_, iteration, true, burningIn);
00361 }
00362 else {
00363
00364 visitor(*this, newValue, currentBestValue_, iteration, false, burningIn);
00365 }
00366 }
00367 ++iteration;
00368 }
00369 }
00370 }
00371 visitor.end(*this, currentBestValue_, currentBestValue_);
00372 return NORMAL;
00373 }
00374
00375 template<class GM, class ACC>
00376 inline InferenceTermination
00377 Gibbs<GM, ACC>::arg
00378 (
00379 std::vector<LabelType>& x,
00380 const size_t N
00381 ) const {
00382 if(N == 1) {
00383 x.resize(gm_.numberOfVariables());
00384 for(size_t j = 0; j < x.size(); ++j) {
00385 x[j] = currentBestState_[j];
00386 }
00387 return NORMAL;
00388 }
00389 else {
00390 return UNKNOWN;
00391 }
00392 }
00393
00394 template<class GM, class ACC>
00395 inline typename Gibbs<GM, ACC>::LabelType
00396 Gibbs<GM, ACC>::markovState
00397 (
00398 const size_t j
00399 ) const
00400 {
00401 OPENGM_ASSERT(j < gm_.numberOfVariables());
00402 return movemaker_.state(j);
00403 }
00404
00405 template<class GM, class ACC>
00406 inline typename Gibbs<GM, ACC>::ValueType
00407 Gibbs<GM, ACC>::markovValue() const
00408 {
00409 return movemaker_.value();
00410 }
00411
00412 template<class GM, class ACC>
00413 inline typename Gibbs<GM, ACC>::LabelType
00414 Gibbs<GM, ACC>::currentBestState
00415 (
00416 const size_t j
00417 ) const
00418 {
00419 OPENGM_ASSERT(j < gm_.numberOfVariables());
00420 return currentBestState_[j];
00421 }
00422
00423 template<class GM, class ACC>
00424 inline typename Gibbs<GM, ACC>::ValueType
00425 Gibbs<GM, ACC>::currentBestValue() const
00426 {
00427 return currentBestValue_;
00428 }
00429
00430 template<class GIBBS>
00431 inline
00432 GibbsMarginalVisitor<GIBBS>::GibbsMarginalVisitor()
00433 : gm_(NULL),
00434 numberOfSamples_(0),
00435 numberOfAcceptedSamples_(0),
00436 numberOfRejectedSamples_(0),
00437 marginals_(),
00438 stateCache_()
00439 {}
00440
00441 template<class GIBBS>
00442 inline
00443 GibbsMarginalVisitor<GIBBS>::GibbsMarginalVisitor(
00444 const typename GibbsMarginalVisitor<GIBBS>::GraphicalModelType& gm
00445 )
00446 : gm_(&gm),
00447 numberOfSamples_(0),
00448 numberOfAcceptedSamples_(0),
00449 numberOfRejectedSamples_(0),
00450 marginals_(),
00451 stateCache_()
00452 {}
00453
00454 template<class GIBBS>
00455 inline void
00456 GibbsMarginalVisitor<GIBBS>::assign(
00457 const typename GibbsMarginalVisitor<GIBBS>::GraphicalModelType& gm
00458 )
00459 {
00460 gm_ = &gm;
00461 }
00462
00463 template<class GIBBS>
00464 inline void
00465 GibbsMarginalVisitor<GIBBS>::operator()(
00466 const typename GibbsMarginalVisitor<GIBBS>::GibbsType& gibbs,
00467 const typename GibbsMarginalVisitor<GIBBS>::ValueType currentValue,
00468 const typename GibbsMarginalVisitor<GIBBS>::ValueType bestValue,
00469 const size_t iteration,
00470 const bool accepted,
00471 const bool burningIn
00472 ) {
00473 if(!burningIn) {
00474 ++numberOfSamples_;
00475 if(accepted) {
00476 ++numberOfAcceptedSamples_;
00477 }
00478 else {
00479 ++numberOfRejectedSamples_;
00480 }
00481 for(size_t j = 0; j < marginals_.size(); ++j) {
00482 for(size_t k = 0; k < marginals_[j].numberOfVariables(); ++k) {
00483 stateCache_[k] = gibbs.markovState(marginals_[j].variableIndex(k));
00484 }
00485 ++marginals_[j](stateCache_.begin());
00486 }
00487 }
00488 }
00489
00490 template<class GIBBS>
00491 template<class VariableIndexIterator>
00492 inline size_t
00493 GibbsMarginalVisitor<GIBBS>::addMarginal(
00494 VariableIndexIterator begin,
00495 VariableIndexIterator end
00496 ) {
00497 marginals_.push_back(IndependentFactorType(*gm_, begin, end));
00498 if(marginals_.back().numberOfVariables() > stateCache_.size()) {
00499 stateCache_.resize(marginals_.back().numberOfVariables());
00500 }
00501 return marginals_.size() - 1;
00502 }
00503
00504 template<class GIBBS>
00505 inline size_t
00506 GibbsMarginalVisitor<GIBBS>::addMarginal(
00507 const size_t variableIndex
00508 ) {
00509 size_t variableIndices[] = {variableIndex};
00510 return addMarginal(variableIndices, variableIndices + 1);
00511 }
00512
00513 template<class GIBBS>
00514 inline size_t
00515 GibbsMarginalVisitor<GIBBS>::numberOfSamples() const {
00516 return numberOfSamples_;
00517 }
00518
00519 template<class GIBBS>
00520 inline size_t
00521 GibbsMarginalVisitor<GIBBS>::numberOfAcceptedSamples() const {
00522 return numberOfAcceptedSamples_;
00523 }
00524
00525 template<class GIBBS>
00526 inline size_t
00527 GibbsMarginalVisitor<GIBBS>::numberOfRejectedSamples() const {
00528 return numberOfRejectedSamples_;
00529 }
00530
00531 template<class GIBBS>
00532 inline size_t
00533 GibbsMarginalVisitor<GIBBS>::numberOfMarginals() const {
00534 return marginals_.size();
00535 }
00536
00537 template<class GIBBS>
00538 inline const typename GibbsMarginalVisitor<GIBBS>::IndependentFactorType&
00539 GibbsMarginalVisitor<GIBBS>::marginal(
00540 const size_t setIndex
00541 ) const {
00542 return marginals_[setIndex];
00543 }
00544
00545 }
00546
00547 #endif // #ifndef OPENGM_GIBBS_HXX