swendsenwang.hxx

Go to the documentation of this file.
00001 #pragma once
00002 #ifndef OPENGM_SWENDSENWANG_HXX
00003 #define OPENGM_SWENDSENWANG_HXX
00004 
00005 #include <vector>
00006 #include <set>
00007 #include <stack>
00008 #include <cmath>
00009 #include <algorithm>
00010 #include <iostream>
00011 
00012 #include "opengm/opengm.hxx"
00013 #include "opengm/operations/adder.hxx"
00014 #include "opengm/operations/multiplier.hxx"
00015 #include "opengm/operations/minimizer.hxx"
00016 #include "opengm/operations/maximizer.hxx"
00017 #include "opengm/utilities/random.hxx"
00018 #include "opengm/utilities/indexing.hxx"
00019 #include "opengm/datastructures/randomaccessset.hxx"
00020 #include "opengm/datastructures/partition.hxx"
00021 #include "opengm/inference/movemaker.hxx"
00022 #include "opengm/inference/visitors/visitor.hxx"
00023 #include "opengm/functions/view_convert_function.hxx"
00024 
00025 namespace opengm {
00026 
00028 namespace detail_swendsenwang {
00029    template<class OPERATOR, class ACCUMULATOR, class PROBABILITY>
00030    struct ValueToProbability;
00031 
00032    template<class PROBABILITY>
00033    struct ValueToProbability<Multiplier, Maximizer, PROBABILITY>
00034    {
00035       typedef PROBABILITY ProbabilityType;
00036       template<class T>
00037          static ProbabilityType convert(const T x)
00038             { return static_cast<ProbabilityType>(x); }
00039    };
00040 
00041    template<class PROBABILITY>
00042    struct ValueToProbability<Adder, Minimizer, PROBABILITY>
00043    {
00044       typedef PROBABILITY ProbabilityType;
00045       template<class T>
00046          static ProbabilityType convert(const T x)
00047             { return static_cast<ProbabilityType>(std::exp(-x)); }
00048    };
00049 }
00051 
00053 template<class SW>
00054 class SwendsenWangEmptyVisitor {
00055 public:
00056    typedef SW SwendsenWangType;
00057 
00058    void operator()(const SwendsenWangType&, const size_t, const size_t,
00059       const bool, const bool) const;
00060 };
00061 
00063 template<class SW>
00064 class SwendsenWangVerboseVisitor
00065  {
00066 public:
00067    typedef SW SwendsenWangType;
00068 
00069    void operator()(const SwendsenWangType&, const size_t, const size_t,
00070       const bool, const bool) const;
00071 };
00072 
00074 template<class SW>
00075 class SwendsenWangMarginalVisitor {
00076 public:
00077    typedef SW SwendsenWangType;
00078    typedef typename SwendsenWangType::ValueType ValueType;
00079    typedef typename SwendsenWangType::GraphicalModelType GraphicalModelType;
00080    typedef typename GraphicalModelType::IndependentFactorType IndependentFactorType;
00081 
00082    // construction
00083    SwendsenWangMarginalVisitor();
00084    SwendsenWangMarginalVisitor(const GraphicalModelType&);
00085    void assign(const GraphicalModelType&);
00086 
00087    // manipulation
00088    template<class VariableIndexIterator>
00089       size_t addMarginal(VariableIndexIterator, VariableIndexIterator);
00090    size_t addMarginal(const size_t);
00091    void operator()(const SwendsenWangType&, const size_t, const size_t,
00092       const bool, const bool);
00093 
00094    // query
00095    size_t numberOfSamples() const;
00096    size_t numberOfAcceptedSamples() const;
00097    size_t numberOfRejectedSamples() const;
00098    size_t numberOfMarginals() const;
00099    const IndependentFactorType& marginal(const size_t) const;
00100 
00101 private:
00102    const GraphicalModelType* gm_;
00103    size_t numberOfSamples_;
00104    size_t numberOfAcceptedSamples_;
00105    size_t numberOfRejectedSamples_;
00106    std::vector<IndependentFactorType> marginals_;
00107    std::vector<typename GraphicalModelType::LabelType> stateCache_;
00108 };
00109 
00114 template<class GM, class ACC>
00115 class SwendsenWang 
00116 : public Inference<GM, ACC> {
00117 public:
00118    typedef GM GraphicalModelType;
00119    typedef ACC AccumulationType;
00120    OPENGM_GM_TYPE_TYPEDEFS;
00121    typedef double ProbabilityType;
00122    typedef SwendsenWangEmptyVisitor<SwendsenWang<GM, ACC> > EmptyVisitorType;
00123    typedef SwendsenWangVerboseVisitor<SwendsenWang<GM, ACC> > VerboseVisitorType;
00124    typedef TimingVisitor<SwendsenWang<GM, ACC> > TimingVisitorType;
00125 
00126    struct Parameter
00127    {
00128       Parameter
00129       (
00130          const size_t maxNumberOfSamplingSteps = 1e5,
00131          const size_t numberOfBurnInSteps = 1e5,
00132          ProbabilityType lowestAllowedProbability = 1e-6,
00133          const std::vector<LabelType>& initialState = std::vector<LabelType>()
00134       )
00135       :  maxNumberOfSamplingSteps_(maxNumberOfSamplingSteps),
00136          numberOfBurnInSteps_(numberOfBurnInSteps),
00137          lowestAllowedProbability_(lowestAllowedProbability),
00138          initialState_(initialState)
00139       {}
00140 
00141       size_t maxNumberOfSamplingSteps_;
00142       size_t numberOfBurnInSteps_;
00143       ProbabilityType lowestAllowedProbability_;
00144       std::vector<LabelType> initialState_;
00145    };
00146 
00147    SwendsenWang(const GraphicalModelType&, const Parameter& param = Parameter());
00148    virtual std::string name() const;
00149    virtual const GraphicalModelType& graphicalModel() const;
00150    virtual void reset();
00151    virtual InferenceTermination infer();
00152    template<class VISITOR>
00153       InferenceTermination infer(VISITOR&);
00154    virtual InferenceTermination arg(std::vector<LabelType>&, const size_t = 1) const;
00155 
00156    LabelType markovState(const size_t) const;
00157    ValueType markovValue() const;
00158    LabelType currentBestState(const size_t) const;
00159    ValueType currentBestValue() const;
00160 
00161 private:
00162    void computeEdgeProbabilities();
00163    void cluster(Partition<size_t>&) const;
00164    template<bool BURNED_IN, class VARIABLE_ITERATOR, class STATE_ITERATOR>
00165       bool move(VARIABLE_ITERATOR, VARIABLE_ITERATOR, STATE_ITERATOR);
00166 
00167    Parameter parameter_;
00168    const GraphicalModelType& gm_;
00169    Movemaker<GraphicalModelType> movemaker_;
00170    std::vector<RandomAccessSet<size_t> > variableAdjacency_;
00171    std::vector<std::vector<ProbabilityType> > edgeProbabilities_;
00172    std::vector<LabelType> currentBestState_;
00173    ValueType currentBestValue_;
00174 };
00175 
00176 template<class GM, class ACC>
00177 inline
00178 SwendsenWang<GM, ACC>::SwendsenWang
00179 (
00180    const typename SwendsenWang<GM, ACC>::GraphicalModelType& gm,
00181    const typename SwendsenWang<GM, ACC>::Parameter& param
00182 )
00183 :  parameter_(param),
00184    gm_(gm),
00185    movemaker_(param.initialState_.size() == gm.numberOfVariables() ? Movemaker<GM>(gm, param.initialState_.begin()) : Movemaker<GM>(gm)),
00186    variableAdjacency_(gm.numberOfVariables()),
00187    edgeProbabilities_(gm.numberOfVariables()),
00188    currentBestState_(gm.numberOfVariables()),
00189    currentBestValue_(movemaker_.value())
00190 {
00191    if(parameter_.initialState_.size() != 0 && parameter_.initialState_.size() != gm.numberOfVariables()) {
00192       throw RuntimeError("The size of the initial state does not match the number of variables.");
00193    }
00194    gm.variableAdjacencyList(variableAdjacency_);
00195    for(size_t j=0; j<gm_.numberOfVariables(); ++j) {
00196       edgeProbabilities_[j].resize(variableAdjacency_[j].size());
00197    }
00198    computeEdgeProbabilities();
00199 }
00200 
00201 template<class GM, class ACC>
00202 inline void
00203 SwendsenWang<GM, ACC>::reset()
00204 {
00205    if(parameter_.initialState_.size() == gm_.numberOfVariables()) {
00206       movemaker_.initialize(parameter_.initialState_.begin());
00207       currentBestState_.assign(parameter_.initialState_.begin(),parameter_.initialState_.end());
00208    }
00209    else if(parameter_.initialState_.size() != 0) {
00210       throw RuntimeError("The size of the initial state does not match the number of variables.");
00211    }
00212    else{
00213       movemaker_.reset();
00214       std::fill(currentBestState_.begin(),currentBestState_.end(),0);
00215    }
00216    currentBestValue_ = movemaker_.value();
00217    computeEdgeProbabilities();
00218 }
00219 
00220 template<class GM, class ACC>
00221 inline std::string
00222 SwendsenWang<GM, ACC>::name() const
00223 {
00224    return "SwendsenWang";
00225 }
00226 
00227 template<class GM, class ACC>
00228 inline const typename SwendsenWang<GM, ACC>::GraphicalModelType&
00229 SwendsenWang<GM, ACC>::graphicalModel() const
00230 {
00231    return gm_;
00232 }
00233 
00234 template<class GM, class ACC>
00235 template<class VISITOR>
00236 InferenceTermination
00237 SwendsenWang<GM, ACC>::infer
00238 (
00239    VISITOR& visitor
00240 )
00241 {
00242    Partition<size_t> partition(gm_.numberOfVariables());
00243    std::vector<size_t> representatives(gm_.numberOfVariables());
00244    std::vector<bool> visited(gm_.numberOfVariables());
00245    std::stack<size_t> stack;
00246    std::vector<size_t> variablesInCluster;
00247    std::vector<size_t> variablesAroundCluster;
00248    for(size_t j=0; j<parameter_.numberOfBurnInSteps_ + parameter_.maxNumberOfSamplingSteps_; ++j) {
00249       // cluster the variable adjacency graph by randomly removing edges
00250       cluster(partition);
00251 
00252       // draw one cluster at random
00253       partition.representatives(representatives.begin());
00254       RandomUniform<size_t> randomNumberGeneratorCluster(0, partition.numberOfSets());
00255       const size_t representative = representatives[randomNumberGeneratorCluster()];
00256       // collect all variables in and around the drawn cluster
00257       variablesInCluster.clear();
00258       variablesAroundCluster.clear();
00259       visited[representative] = true;
00260       stack.push(representative);
00261       while(!stack.empty()) {
00262          const size_t variable = stack.top();
00263          stack.pop();
00264          variablesInCluster.push_back(variable);
00265          for(size_t k=0; k<variableAdjacency_[variable].size(); ++k) {
00266             const size_t adjacentVariable = variableAdjacency_[variable][k];
00267             if(!visited[adjacentVariable]) {
00268                visited[adjacentVariable] = true;
00269                if(partition.find(adjacentVariable) == representative) { // if in cluster
00270                   stack.push(adjacentVariable);
00271                }
00272                else {
00273                   variablesAroundCluster.push_back(adjacentVariable);
00274                }
00275             }
00276          }
00277       }
00278 
00279       // clean vector visited
00280       for(size_t k=0; k<variablesInCluster.size(); ++k) {
00281          visited[variablesInCluster[k]] = false;
00282       }
00283       for(size_t k=0; k<variablesAroundCluster.size(); ++k) {
00284          visited[variablesAroundCluster[k]] = false;
00285       }
00286 
00287       // assertion testing
00288       if(!NO_DEBUG) {
00289          for(size_t k=0; k<visited.size(); ++k) {
00290             OPENGM_ASSERT(!visited[k]);
00291          }
00292          for(size_t k=0; k<variablesInCluster.size(); ++k) {
00293             OPENGM_ASSERT(gm_.numberOfLabels(variablesInCluster[k]) == gm_.numberOfLabels(representative));
00294          }
00295       }
00296 
00297       // draw a new label at random
00298       RandomUniform<size_t> randomNumberGeneratorState(0, gm_.numberOfLabels(representative));
00299       size_t targetLabel = randomNumberGeneratorState();
00300       std::vector<size_t> targetLabels(variablesInCluster.size(), targetLabel); // TODO add simpler function to movemaker
00301 
00302       if(j < parameter_.numberOfBurnInSteps_) {
00303          move<false>(variablesInCluster.begin(), variablesInCluster.end(), targetLabels.begin());
00304          visitor(*this, j, variablesInCluster.size(), true, true);
00305          continue;
00306       }
00307 
00308       // evaluate probability density function
00309       const ProbabilityType currentPDF =
00310          detail_swendsenwang::ValueToProbability<OperatorType, AccumulationType, ProbabilityType>::convert
00311             (movemaker_.value());
00312       const ProbabilityType targetPDF =
00313          detail_swendsenwang::ValueToProbability<OperatorType, AccumulationType, ProbabilityType>::convert
00314             (movemaker_.valueAfterMove(variablesInCluster.begin(), variablesInCluster.end(), targetLabels.begin()));
00315 
00316       // evaluate proposal density
00317       ProbabilityType currentValueProposal = 1;
00318       ProbabilityType targetValueProposal = 1;
00319       for(std::vector<size_t>::const_iterator vi = variablesAroundCluster.begin(); vi != variablesAroundCluster.end(); ++vi) {
00320          if(movemaker_.state(*vi) == movemaker_.state(representative)) { // *vi has old label
00321             for(size_t k=0; k<variableAdjacency_[*vi].size(); ++k) {
00322                const size_t nvi = variableAdjacency_[*vi][k];
00323                if(partition.find(nvi) == representative) { // if *nvi is in cluster
00324                   currentValueProposal *= (1.0 - edgeProbabilities_[*vi][k]);
00325                }
00326             }
00327          }
00328          else if(movemaker_.state(*vi) == targetLabel) { // *vi has new label
00329             for(size_t k=0; k<variableAdjacency_[*vi].size(); ++k) {
00330                const size_t nvi = variableAdjacency_[*vi][k];
00331                if(partition.find(nvi) == representative) { // if *nvi is in cluster
00332                   targetValueProposal *= (1.0 - edgeProbabilities_[*vi][k]);
00333                }
00334             }
00335          }
00336       }
00337 
00338       // accept or reject re-labeling
00339       const ProbabilityType metropolisHastingsProbability = (targetValueProposal / currentValueProposal) * (targetPDF / currentPDF);
00340       OPENGM_ASSERT(metropolisHastingsProbability > 0);
00341       if(metropolisHastingsProbability >= 1) { // accept
00342          move<true>(variablesInCluster.begin(), variablesInCluster.end(), targetLabels.begin());
00343          visitor(*this, j, variablesInCluster.size(), true, false);
00344       }
00345       else {
00346          RandomUniform<ProbabilityType> randomNumberGeneratorAcceptance(0, 1);
00347          if(metropolisHastingsProbability >= randomNumberGeneratorAcceptance()) { // accept
00348             move<true>(variablesInCluster.begin(), variablesInCluster.end(), targetLabels.begin());
00349             visitor(*this, j, variablesInCluster.size(), true, false);
00350          }
00351          else { // reject
00352             visitor(*this, j, variablesInCluster.size(), false, false);
00353          }
00354       }
00355    }
00356 
00357    return NORMAL;
00358 }
00359 
00360 template<class GM, class ACC>
00361 inline InferenceTermination
00362 SwendsenWang<GM, ACC>::infer()
00363 {
00364    EmptyVisitorType visitor;
00365    return infer(visitor);
00366 }
00367 
00368 template<class GM, class ACC>
00369 inline InferenceTermination
00370 SwendsenWang<GM, ACC>::arg
00371 (
00372    std::vector<LabelType>& x,
00373    const size_t N
00374 ) const {
00375    if(N == 1) {
00376       x = currentBestState_;
00377       return NORMAL;
00378    }
00379    else {
00380       return UNKNOWN;
00381    }
00382 }
00383 
00384 template<class GM, class ACC>
00385 inline typename SwendsenWang<GM, ACC>::LabelType
00386 SwendsenWang<GM, ACC>::markovState
00387 (
00388    const size_t j
00389 ) const
00390 {
00391    OPENGM_ASSERT(j < gm_.numberOfVariables());
00392    return movemaker_.state(j);
00393 }
00394 
00395 template<class GM, class ACC>
00396 inline typename SwendsenWang<GM, ACC>::ValueType
00397 SwendsenWang<GM, ACC>::markovValue() const
00398 {
00399    return movemaker_.value();
00400 }
00401 
00402 template<class GM, class ACC>
00403 inline typename SwendsenWang<GM, ACC>::LabelType
00404 SwendsenWang<GM, ACC>::currentBestState
00405 (
00406    const size_t j
00407 ) const
00408 {
00409    OPENGM_ASSERT(j < gm_.numberOfVariables());
00410    return currentBestState_[j];
00411 }
00412 
00413 template<class GM, class ACC>
00414 inline typename SwendsenWang<GM, ACC>::ValueType
00415 SwendsenWang<GM, ACC>::currentBestValue() const
00416 {
00417    return currentBestValue_;
00418 }
00419 
00420 template<class GM, class ACC>
00421 template<bool BURNED_IN, class VARIABLE_ITERATOR, class STATE_ITERATOR>
00422 inline bool SwendsenWang<GM, ACC>::move
00423 (
00424    VARIABLE_ITERATOR begin,
00425    VARIABLE_ITERATOR end,
00426    STATE_ITERATOR it
00427 )
00428 {
00429    movemaker_.move(begin, end, it);
00430    if(BURNED_IN) {
00431       if(ACC::bop(movemaker_.value(), currentBestValue_)) {
00432          currentBestValue_ = movemaker_.value();
00433          std::copy(movemaker_.stateBegin(), movemaker_.stateEnd(), currentBestState_.begin());
00434          return true;
00435       }
00436    }
00437    return false;
00438 }
00439 
00440 template<class GM, class ACC>
00441 void
00442 SwendsenWang<GM, ACC>::computeEdgeProbabilities()
00443 {
00444    std::set<size_t> factors;
00445    std::set<size_t> connectedVariables;
00446    size_t variables[] = {0, 0};
00447    for(variables[0] = 0; variables[0] < gm_.numberOfVariables(); ++variables[0]) {
00448       for(size_t j = 0; j < variableAdjacency_[variables[0]].size(); ++j) {
00449          variables[1] = variableAdjacency_[variables[0]][j];
00450          if(gm_.numberOfLabels(variables[0]) == gm_.numberOfLabels(variables[1])) {
00451             // for all pairs of connected variables, variables[0] and variables[1],
00452             // that have the same number of states, identify
00453             // - all factors connected to variables[0] or variables[1] (or both)
00454             // - all variables connected to these factors
00455             factors.clear();
00456             connectedVariables.clear();
00457 
00458             // factors that depend on at least variables[0] OR variables[1]
00459             for(size_t k = 0; k < 2; ++k) {
00460                for(typename GraphicalModelType::ConstFactorIterator it = gm_.factorsOfVariableBegin(variables[k]);
00461                it != gm_.factorsOfVariableEnd(variables[k]); ++it) {
00462                   factors.insert(*it);
00463                   for(size_t m = 0; m < gm_[*it].numberOfVariables(); ++m) {
00464                      connectedVariables.insert(gm_[*it].variableIndex(m));
00465                   }
00466                }
00467             }
00468 
00469             // factors that depend on at least variables[0] AND variables[1]
00470             /*
00471             for(typename GraphicalModelType::ConstFactorIterator it = gm_.factorsOfVariableBegin(variables[0]);
00472             it != gm_.factorsOfVariableEnd(variables[0]); ++it) {
00473                for(size_t k = 0; k<gm_[*it].numberOfVariables(); ++k) {
00474                   if(gm_[*it].variableIndex(k) == variables[1]) {
00475                      factors.insert(*it);
00476                      for(size_t m = 0; m < gm_[*it].numberOfVariables(); ++m) {
00477                         connectedVariables.insert(gm_[*it].variableIndex(m));
00478                      }
00479                      break;
00480                   }
00481                }
00482             }
00483             */
00484 
00485             // operate all found factors up
00486             IndependentFactorType localFactor(gm_,
00487                connectedVariables.begin(),
00488                connectedVariables.end(),
00489                OperatorType::template neutral<ValueType>());
00490             for(std::set<size_t>::const_iterator it = factors.begin(); it != factors.end(); ++it) {
00491                OperatorType::op(gm_[*it], localFactor);
00492             }
00493 
00494             // marginalize
00495             size_t indices[] = {0, 0};
00496             for(size_t k = 0; k < localFactor.numberOfVariables(); ++k) {
00497                if(localFactor.variableIndex(k) == variables[0]) {
00498                   indices[0] = k;
00499                }
00500                else if(localFactor.variableIndex(k) == variables[1]) {
00501                   indices[1] = k;
00502                }
00503             }
00504             ProbabilityType probEqual = 0;
00505             ProbabilityType probUnequal = 0;
00506             ShapeWalker< typename IndependentFactorType::ShapeIteratorType>
00507                walker(localFactor.shapeBegin(), localFactor.numberOfVariables());
00508             for(size_t k = 0; k < localFactor.size(); ++k, ++walker) {
00509                const ValueType value = localFactor(walker.coordinateTuple().begin());
00510                const ProbabilityType p = detail_swendsenwang::ValueToProbability<OperatorType, AccumulationType, ProbabilityType>::convert(value);
00511                if(walker.coordinateTuple()[indices[0]] == walker.coordinateTuple()[indices[1]]) {
00512                   probEqual += p;
00513                }
00514                else {
00515                   probUnequal += p;
00516                }
00517             }
00518 
00519             // normalize
00520             ProbabilityType sum = probEqual + probUnequal;
00521             if(sum == 0.0) {
00522                throw RuntimeError("Some local probabilities are exactly zero.");
00523             }
00524             probEqual /= sum;
00525             probUnequal /= sum;
00526             if(probEqual < parameter_.lowestAllowedProbability_ || probUnequal < parameter_.lowestAllowedProbability_) {
00527                throw RuntimeError("Marginal probabilities are smaller than the allowed minimum.");
00528             }
00529 
00530             edgeProbabilities_[variables[0]][j] = probUnequal;
00531          }
00532       }
00533    }
00534 }
00535 
00536 template<class GM, class ACC>
00537 void
00538 SwendsenWang<GM, ACC>::cluster
00539 (
00540    Partition<size_t>& out
00541 ) const
00542 {
00543    // randomly merge variables
00544    out.reset(gm_.numberOfVariables());
00545    opengm::RandomUniform<ProbabilityType> randomNumberGenerator(0.0, 1.0);
00546    size_t variables[] = {0, 0};
00547    for(variables[0] = 0; variables[0] < gm_.numberOfVariables(); ++variables[0]) {
00548       for(size_t j = 0; j < variableAdjacency_[variables[0]].size(); ++j) {
00549          variables[1] = variableAdjacency_[variables[0]][j];
00550          if(variables[0] < variables[1]) { // only once for each pair
00551             if(movemaker_.state(variables[0]) == movemaker_.state(variables[1])) {
00552                if(edgeProbabilities_[variables[0]][j] > randomNumberGenerator()) {
00553                   // turn edge on with probability edgeProbabilities_[variables[0]][variables[1]]
00554                   out.merge(variables[0], variables[1]);
00555                }
00556             }
00557          }
00558       }
00559    }
00560 }
00561 
00562 template<class SW>
00563 inline void
00564 SwendsenWangEmptyVisitor<SW>::operator()(
00565    const typename SwendsenWangEmptyVisitor<SW>::SwendsenWangType& sw,
00566    const size_t iteration,
00567    const size_t clusterSize,
00568    const bool accepted,
00569    const bool burningIn
00570 ) const {
00571 }
00572 
00573 template<class SW>
00574 inline void
00575 SwendsenWangVerboseVisitor<SW>::operator()(
00576    const typename SwendsenWangVerboseVisitor<SW>::SwendsenWangType& sw,
00577    const size_t iteration,
00578    const size_t clusterSize,
00579    const bool accepted,
00580    const bool burningIn
00581 ) const {
00582    std::cout << "Step " << iteration
00583       << ": " << "V_opt=" << sw.currentBestValue()
00584       << ", " << "V_markov=" << sw.markovValue()
00585       << ", " << "cs=" << clusterSize
00586       << ", " << (accepted ? "accepted" : "rejected")
00587       << ", " << (burningIn ? "burning in" : "sampling")
00588       << std::endl;
00589    //std::cout << "   arg_opt: ";
00590    //for(size_t j=0; j<sw.graphicalModel().numberOfVariables(); ++j) {
00591    //   std::cout << sw.currentBestState(j) << ' ';
00592    //}
00593    //std::cout << std::endl;
00594    //
00595    //std::cout << "   arg_markov: ";
00596    //for(size_t j=0; j<sw.graphicalModel().numberOfVariables(); ++j) {
00597    //   std::cout << sw.markovState(j) << ' ';
00598    //std::cout << std::endl;
00599 }
00600 
00601 template<class SW>
00602 inline
00603 SwendsenWangMarginalVisitor<SW>::SwendsenWangMarginalVisitor()
00604 :  gm_(NULL),
00605    numberOfSamples_(0),
00606    numberOfAcceptedSamples_(0),
00607    numberOfRejectedSamples_(0),
00608    marginals_(),
00609    stateCache_()
00610 {}
00611 
00612 template<class SW>
00613 inline
00614 SwendsenWangMarginalVisitor<SW>::SwendsenWangMarginalVisitor(
00615    const typename SwendsenWangMarginalVisitor<SW>::GraphicalModelType& gm
00616 )
00617 :  gm_(&gm),
00618    numberOfSamples_(0),
00619    numberOfAcceptedSamples_(0),
00620    numberOfRejectedSamples_(0),
00621    marginals_(),
00622    stateCache_()
00623 {}
00624 
00625 template<class SW>
00626 inline void
00627 SwendsenWangMarginalVisitor<SW>::assign(
00628     const typename SwendsenWangMarginalVisitor<SW>::GraphicalModelType& gm
00629 )
00630 {
00631     gm_ = &gm;
00632 }
00633 
00634 template<class SW>
00635 inline void
00636 SwendsenWangMarginalVisitor<SW>::operator()(
00637    const typename SwendsenWangMarginalVisitor<SW>::SwendsenWangType& sw,
00638    const size_t iteration,
00639    const size_t clusterSize,
00640    const bool accepted,
00641    const bool burningIn
00642 ) {
00643    if(!burningIn) {
00644       ++numberOfSamples_;
00645       if(accepted) {
00646          ++numberOfAcceptedSamples_;
00647       }
00648       else {
00649          ++numberOfRejectedSamples_;
00650       }
00651       for(size_t j = 0; j < marginals_.size(); ++j) {
00652          for(size_t k = 0; k < marginals_[j].numberOfVariables(); ++k) {
00653             stateCache_[k] = sw.markovState(marginals_[j].variableIndex(k));
00654          }
00655          ++marginals_[j](stateCache_.begin());
00656       }
00657    }
00658 }
00659 
00660 template<class SW>
00661 template<class VariableIndexIterator>
00662 inline size_t
00663 SwendsenWangMarginalVisitor<SW>::addMarginal(
00664    VariableIndexIterator begin,
00665    VariableIndexIterator end
00666 ) {
00667    marginals_.push_back(IndependentFactorType(*gm_, begin, end));
00668    if(marginals_.back().numberOfVariables() > stateCache_.size()) {
00669       stateCache_.resize(marginals_.back().numberOfVariables());
00670    }
00671    return marginals_.size() - 1;
00672 }
00673 
00674 template<class SW>
00675 inline size_t
00676 SwendsenWangMarginalVisitor<SW>::addMarginal(
00677    const size_t variableIndex
00678 ) {
00679    size_t variableIndices[] = {variableIndex};
00680    return addMarginal(variableIndices, variableIndices + 1);
00681 }
00682 
00683 template<class SW>
00684 inline size_t
00685 SwendsenWangMarginalVisitor<SW>::numberOfSamples() const {
00686    return numberOfSamples_;
00687 }
00688 
00689 template<class SW>
00690 inline size_t
00691 SwendsenWangMarginalVisitor<SW>::numberOfAcceptedSamples() const {
00692    return numberOfAcceptedSamples_;
00693 }
00694 
00695 template<class SW>
00696 inline size_t
00697 SwendsenWangMarginalVisitor<SW>::numberOfRejectedSamples() const {
00698    return numberOfRejectedSamples_;
00699 }
00700 
00701 template<class SW>
00702 inline size_t
00703 SwendsenWangMarginalVisitor<SW>::numberOfMarginals() const {
00704    return marginals_.size();
00705 }
00706 
00707 template<class SW>
00708 inline const typename SwendsenWangMarginalVisitor<SW>::IndependentFactorType&
00709 SwendsenWangMarginalVisitor<SW>::marginal(
00710    const size_t setIndex
00711 ) const {
00712    return marginals_[setIndex];
00713 }
00714 
00715 } // namespace opengm
00716 
00717 #endif // #ifndef OPENGM_SWENDSENWANG_HXX
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Mon Jun 17 16:31:06 2013 for OpenGM by  doxygen 1.6.3