gibbs.hxx

Go to the documentation of this file.
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    // construction
00064    GibbsMarginalVisitor();
00065    GibbsMarginalVisitor(const GraphicalModelType&);
00066    void assign(const GraphicalModelType&);
00067 
00068    // manipulation
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    // query
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       //if(v<
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          // select variable
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          // draw label
00287          opengm::RandomUniform<size_t> randomLabel(0, gm_.numberOfLabels(variableIndex));
00288          const size_t label = randomLabel();
00289 
00290          // move
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          // select variable
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          // draw label
00334          opengm::RandomUniform<size_t> randomLabel(0, gm_.numberOfLabels(variableIndex));
00335          const size_t label = randomLabel();
00336 
00337          // move
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                   //std::cout<<"temp="<<this->getTemperature(iteration)<<"\n";
00359                   movemaker_.move(&variableIndex, &variableIndex + 1, &label); 
00360                   visitor(*this, newValue, currentBestValue_, iteration, true, burningIn);
00361                }
00362                else {
00363                   //std::cout<<"temp="<<this->getTemperature(iteration)<<"\n";
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 } // namespace opengm
00546 
00547 #endif // #ifndef OPENGM_GIBBS_HXX
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Mon Jun 17 16:31:02 2013 for OpenGM by  doxygen 1.6.3