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
00083 SwendsenWangMarginalVisitor();
00084 SwendsenWangMarginalVisitor(const GraphicalModelType&);
00085 void assign(const GraphicalModelType&);
00086
00087
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
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
00250 cluster(partition);
00251
00252
00253 partition.representatives(representatives.begin());
00254 RandomUniform<size_t> randomNumberGeneratorCluster(0, partition.numberOfSets());
00255 const size_t representative = representatives[randomNumberGeneratorCluster()];
00256
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) {
00270 stack.push(adjacentVariable);
00271 }
00272 else {
00273 variablesAroundCluster.push_back(adjacentVariable);
00274 }
00275 }
00276 }
00277 }
00278
00279
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
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
00298 RandomUniform<size_t> randomNumberGeneratorState(0, gm_.numberOfLabels(representative));
00299 size_t targetLabel = randomNumberGeneratorState();
00300 std::vector<size_t> targetLabels(variablesInCluster.size(), targetLabel);
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
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
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)) {
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) {
00324 currentValueProposal *= (1.0 - edgeProbabilities_[*vi][k]);
00325 }
00326 }
00327 }
00328 else if(movemaker_.state(*vi) == targetLabel) {
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) {
00332 targetValueProposal *= (1.0 - edgeProbabilities_[*vi][k]);
00333 }
00334 }
00335 }
00336 }
00337
00338
00339 const ProbabilityType metropolisHastingsProbability = (targetValueProposal / currentValueProposal) * (targetPDF / currentPDF);
00340 OPENGM_ASSERT(metropolisHastingsProbability > 0);
00341 if(metropolisHastingsProbability >= 1) {
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()) {
00348 move<true>(variablesInCluster.begin(), variablesInCluster.end(), targetLabels.begin());
00349 visitor(*this, j, variablesInCluster.size(), true, false);
00350 }
00351 else {
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
00452
00453
00454
00455 factors.clear();
00456 connectedVariables.clear();
00457
00458
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
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
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
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
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
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]) {
00551 if(movemaker_.state(variables[0]) == movemaker_.state(variables[1])) {
00552 if(edgeProbabilities_[variables[0]][j] > randomNumberGenerator()) {
00553
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
00590
00591
00592
00593
00594
00595
00596
00597
00598
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 }
00716
00717 #endif // #ifndef OPENGM_SWENDSENWANG_HXX