00001 #ifndef _BETA_CHAINBUNDLE_
00002
00003 #include <vector>
00004 #include <RandomLib/Random.hpp>
00005
00006 using std::vector;
00007 using RandomLib::Random;
00008
00019
00020 template <typename T>
00021 class chainBundle
00022 {
00023
00024 public:
00025
00026 explicit chainBundle(Random &random);
00027 ~chainBundle();
00028
00030
00032
00033 int nChains() { return (int)mChains.size(); }
00034 T* chain(const int i) { return mChains.at(i); }
00035
00036 double stepSize() { return mStepSize; }
00037 double nLeapfrog() { return mNumLeapfrog; }
00038
00039 double ESS(int i) { return mESS(i); }
00040 double minESS() { return mESS.minCoeff(); }
00041
00042 vector<VectorXd>& samples() { return mSamples; }
00043
00045
00047
00052 void setVerbosity(const unsigned int v) { mVerbosity = v; }
00053
00054 void setNumSubsample(const int n) { mNumSubsample = n; }
00055 void setNumLeapfrog(const int n) { mNumLeapfrog = n; }
00056 void setWindowSize(const int n);
00057
00058 void setStepSize(const double s) { mStepSize = s; }
00059 void setStepSizeJitter(const double j);
00060 void setStepSizeJerk(const double j);
00061 void setProbStepSizeJerk(const double p);
00062
00063 void setTemperAlpha(const double a) { mTemperAlpha = a; }
00064
00065 void setAdaptIntTime(double t) { mAdaptIntTime = t; }
00066 void setAdaptTargetAccept(double a) { mAdaptTargetAccept = a; }
00067 void setAdaptMaxLeapfrog(int n) { mAdaptMaxLeapfrog = n; }
00068
00069 void storeSamples(const bool store = true) { mStoreSamples = store; }
00070
00071 void setMaxLagDisplay(int n) { mMaxLagDisplay = n; }
00072 void setMaxLagCalc(int n) { mMaxLagCalc = n; }
00073
00074 void useExternalMoments(VectorXd& mean, VectorXd& var) { mUseExternalMoments = true; mExternalMean = &mean; mExternalVar = &var; }
00075
00077 void addChain(T* object) { mChains.push_back(object); }
00078
00080
00082
00083 void evolve(T* chain, const double epsilon);
00084 void verboseEvolve(T* chain, const double epsilon);
00085
00086 void engageAdaptation() { mAdaptStepSize = true; }
00087 void disengageAdaptation() { mAdaptStepSize = false; }
00088
00089 void initAdaptation();
00090 void updateAdaptation(double metropolisProb);
00091
00092 void transition();
00093 void transition(int i);
00094 bool transition(T* chain);
00095
00096 void saveTrajectory(std::ofstream& outputFile, const int i = 0);
00097
00098 void checkIntError(const int i, const int N, const int f = 1);
00099
00100 void seed(const double min, const double max);
00101 void seed(const int i, const double min, const double max);
00102 void burn(const int nBurn = 100, const int nCheck = 100, const double minR = 1.1, const bool verbose = true);
00103
00104 void clearSamples();
00105 void computeSummaryStats(const int b, const bool verbose = true, std::ofstream* outputFile = NULL);
00106
00107 protected:
00108
00109
00110 bool mStoreSamples;
00111 bool mAdaptStepSize;
00112 bool mRefStats;
00113 bool mChar;
00114 bool mConstraint;
00115 bool mUseExternalMoments;
00116
00117
00118 unsigned int mVerbosity;
00119
00120
00121 Random mRandom;
00122
00123
00124 int mNumSubsample;
00125 int mNumLeapfrog;
00126 int mWindowSize;
00127
00128 double mStepSize;
00129 double mStepSizeJitter;
00130 double mStepSizeJerk;
00131 double mProbStepSizeJerk;
00132
00133 int mNumFixedPoint;
00134
00135 double mTemperAlpha;
00136
00137 double mAdaptTargetAccept;
00138 double mAdaptIntTime;
00139 int mAdaptMaxLeapfrog;
00140 double mAdaptMu;
00141 double mAdaptLogEpsBar;
00142 double mAdaptHBar;
00143 double mAdaptCounter;
00144 double mAdaptGamma;
00145 double mAdaptKappa;
00146 double mAdaptT0;
00147
00148
00149 int mNumSamples;
00150 vector<VectorXd> mSamples;
00151 vector<double> mSampleE;
00152
00153 int mMaxLagDisplay;
00154 int mMaxLagCalc;
00155
00157 VectorXd mESS;
00158
00159 VectorXd* mExternalMean;
00160 VectorXd* mExternalVar;
00161
00162
00163 vector<T*> mChains;
00164 typename vector<T*>::iterator mIt;
00165
00166
00167
00169 virtual bool fConstraint(T* chain) { return !(chain->supportViolated()); }
00170
00172 virtual const VectorXd& fNormal(T* chain) { return chain->supportNormal(); }
00173
00174 double fLogSumExp(double a, double b);
00175
00176 };
00177
00178
00179 #include "math.h"
00180 #include <iostream>
00181 #include <iomanip>
00182 #include <fstream>
00183
00184 using std::cout;
00185 using std::endl;
00186 using std::flush;
00187
00191 template <typename T>
00192 chainBundle<T>::chainBundle(Random& random):
00193 mRandom(random),
00194 mESS(VectorXd::Zero(1))
00195 {
00196
00197 mStoreSamples = true;
00198 mAdaptStepSize = false;
00199 mRefStats = false;
00200 mChar = false;
00201 mConstraint = true;
00202 mUseExternalMoments = false;
00203
00204 mVerbosity = 0;
00205
00206 mNumSubsample = 1;
00207 mNumLeapfrog = 150;
00208 mWindowSize = 10;
00209
00210 mStepSize = 0.1;
00211 mStepSizeJitter = 0.05;
00212 mStepSizeJerk = 0.1;
00213 mProbStepSizeJerk = 0.0;
00214
00215 mTemperAlpha = 0.0;
00216
00217 mAdaptTargetAccept = 0.65;
00218 mAdaptIntTime = 10;
00219 mAdaptMaxLeapfrog = 1000;
00220 mAdaptMu = 0;
00221 mAdaptLogEpsBar = 0;
00222 mAdaptHBar = 0;
00223 mAdaptCounter = 0;
00224 mAdaptGamma = 0.05;
00225 mAdaptKappa = 0.75;
00226 mAdaptT0 = 10;
00227
00228 mNumSamples = 0;
00229
00230 mMaxLagDisplay = 10;
00231 mMaxLagCalc = 50;
00232
00233 mExternalMean = 0;
00234 mExternalVar = 0;
00235
00236 }
00237
00238
00241
00242 template <typename T>
00243 chainBundle<T>::~chainBundle()
00244 {
00245 for(mIt = mChains.begin(); mIt != mChains.end(); ++mIt) delete *mIt;
00246 mChains.clear();
00247
00248 clearSamples();
00249
00250 }
00251
00253
00254 template <typename T>
00255 void chainBundle<T>::setWindowSize(const int n)
00256 {
00257
00258 if(n > 0.5 * mNumLeapfrog)
00259 {
00260 cout << "chainBundle::setWindowSize() - Reject/Accept window must not be larger"
00261 << " than half of the total leapfrog steps!" << endl;
00262 return;
00263 }
00264
00265 if(n < 2)
00266 {
00267
00268
00269
00270 }
00271
00272 mWindowSize = n;
00273
00274 }
00275
00277
00278 template <typename T>
00279 void chainBundle<T>::setStepSizeJitter(const double j)
00280 {
00281
00282 if(j < 0 || j > 1)
00283 {
00284 cout << "chainBundle::setStepSizeJitter() - Step size jitter must lie between 0 and 1!" << endl;
00285 return;
00286 }
00287
00288 mStepSizeJitter = j;
00289
00290 }
00291
00293
00294 template <typename T>
00295 void chainBundle<T>::setStepSizeJerk(const double j)
00296 {
00297
00298 if(j < 0)
00299 {
00300 cout << "chainBundle::setStepSizeJerk() - Step size jerk cannot be negative!" << endl;
00301 return;
00302 }
00303
00304 mStepSizeJitter = j;
00305
00306 }
00307
00309
00310 template <typename T>
00311 void chainBundle<T>::setProbStepSizeJerk(const double p)
00312 {
00313
00314 if(p < 0 || p > 1)
00315 {
00316 cout << "chainBundle::setProbStepSizeJerk() - Step size jerk probability must lie between 0 and 1!" << endl;
00317 return;
00318 }
00319
00320 mProbStepSizeJerk = p;
00321
00322 }
00323
00325
00326 template <typename T>
00327 void chainBundle<T>::clearSamples()
00328 {
00329 mSamples.clear();
00330 mSampleE.clear();
00331 for(mIt = mChains.begin(); mIt != mChains.end(); ++mIt) (*mIt)->clearHistory();
00332
00333 }
00334
00347
00348 template <typename T>
00349 void chainBundle<T>::computeSummaryStats(const int b, const bool verbose, std::ofstream* outputFile)
00350 {
00351
00352 cout.precision(6);
00353 int acceptWidth = 14;
00354
00355 if(mSamples.size() == 0)
00356 {
00357 cout << "Cannot compute summary stats without any samples!" << endl;
00358 return;
00359 }
00360
00361 if(verbose)
00362 {
00363
00364 cout << "Displaying summary statistics..." << endl << endl;
00365
00366 cout << " " << std::setw(5 * acceptWidth / 2) << std::setfill('-') << "" << std::setfill(' ') << endl;
00367 cout << " "
00368 << std::setw(acceptWidth / 2) << std::left << "Chain"
00369 << std::setw(acceptWidth) << std::left << "Global"
00370 << std::setw(acceptWidth) << std::left << "Local"
00371 << std::endl;
00372 cout << " "
00373 << std::setw(acceptWidth / 2) << std::left << ""
00374 << std::setw(acceptWidth) << std::left << "Accept Rate"
00375 << std::setw(acceptWidth) << std::left << "Accept Rate"
00376 << std::endl;
00377 cout << " " << std::setw(5 * acceptWidth / 2) << std::setfill('-') << "" << std::setfill(' ') << endl;
00378
00379 for(int i = 0; i < mChains.size(); ++i)
00380 {
00381 cout << " "
00382 << std::setw(acceptWidth / 2) << std::left << i
00383 << std::setw(acceptWidth) << std::left << (mChains.at(i))->acceptRate()
00384 << std::setw(acceptWidth) << std::left << (mChains.at(i))->movingAcceptRate()
00385 << endl;
00386 }
00387 cout << " " << std::setw(5 * acceptWidth / 2) << std::setfill('-') << "" << std::setfill(' ') << endl;
00388 cout << endl;
00389
00390 }
00391
00392 int nSamples = (int)mSamples.size();
00393 int nBatch = nSamples / b;
00394 int nLag = nBatch / 2;
00395
00396 nLag = nLag > mMaxLagCalc ? mMaxLagDisplay : nLag;
00397 int nLagDisplay = nLag > mMaxLagDisplay ? mMaxLagDisplay : nLag;
00398
00399 if(verbose)
00400 {
00401 cout << "\tUsing " << nBatch << " batches of " << b << " samples"
00402 << " (" << nSamples % b << " samples clipped)" << endl << endl;
00403 }
00404
00405
00406 double batchPotential;
00407 double sumPotential = 0;
00408 double sumPotential2 = 0;
00409
00410 long dim = chain(0)->dim();
00411 if(outputFile) *outputFile << "DIM " << dim << endl << endl;
00412
00413 VectorXd batchSample(dim);
00414 VectorXd sum(VectorXd::Zero(dim));
00415 VectorXd sum2(VectorXd::Zero(dim));
00416
00417 MatrixXd autoCorr = MatrixXd::Zero(dim, nLag);
00418 mESS.resize(dim);
00419
00420 vector<VectorXd> batchSamples;
00421
00422 vector<double>::const_iterator eIt = mSampleE.begin();
00423 vector<VectorXd>::const_iterator it = mSamples.begin();
00424
00425
00426 if(outputFile) *outputFile << "BEGINSAMPLES" << endl;
00427
00428 for(int n = 0; n < nBatch; ++n)
00429 {
00430
00431 batchPotential = 0;
00432 batchSample.setZero();
00433
00434
00435 for(int m = 0; m < b; ++m, ++eIt, ++it)
00436 {
00437
00438
00439 batchPotential += *eIt;
00440 batchSample += (*it);
00441
00442
00443 if(outputFile)
00444 {
00445 *outputFile << n * b + m << "\t" << *eIt << flush;
00446 for(int i = 0; i < dim; ++i)
00447 {
00448 *outputFile << "\t" << (*it)(i) << flush;
00449 }
00450 *outputFile << endl;
00451 }
00452 }
00453
00454
00455 batchPotential /= b;
00456 sumPotential += batchPotential;
00457 sumPotential2 += batchPotential * batchPotential;
00458
00459 batchSample /= (double)b;
00460 batchSamples.push_back(VectorXd(batchSample));
00461
00462 sum += batchSample;
00463 sum2 += batchSample.array().square().matrix();
00464
00465 }
00466
00467 if(outputFile) *outputFile << "ENDSAMPLES" << endl << endl;
00468
00469
00470 sumPotential /= (double)nBatch;
00471 sumPotential2 = sumPotential2 / (double)nBatch - sumPotential * sumPotential;
00472
00473 sum /= (double)nBatch;
00474
00475 sum2 /= (double)nBatch;
00476 sum2 -= sum.array().square().matrix();
00477 sum2 *= b / nSamples;
00478
00479
00480 VectorXd gamma(dim);
00481 VectorXd one(dim);
00482 VectorXd two(dim);
00483
00484 if(!mUseExternalMoments) mExternalMean = ∑
00485
00486 for(int k = 0; k < nLag; ++k)
00487 {
00488
00489 gamma = autoCorr.col(k);
00490
00491 vector<VectorXd>::iterator itOne = batchSamples.begin();
00492
00493 vector<VectorXd>::iterator itTwo = itOne;
00494 for(int j = 0; j < k; ++j) ++itTwo;
00495
00496 for(int n = 0; n < nBatch - k; ++n, ++itOne, ++itTwo)
00497 {
00498 one = *itOne - *mExternalMean;
00499 two = *itTwo - *mExternalMean;
00500 gamma += one.cwiseProduct(two);
00501 }
00502
00503 gamma /= (double)nBatch;
00504
00505
00506 if(k == 0)
00507 {
00508 for(int i = 0; i < dim; ++i) autoCorr(i, k) = gamma(i);
00509 continue;
00510 }
00511
00512 one = gamma.cwiseQuotient(autoCorr.col(0));
00513
00514 if(mUseExternalMoments) one = gamma.cwiseQuotient(*mExternalVar);
00515 else one = gamma.cwiseQuotient(autoCorr.col(0));
00516
00517 for(int i = 0; i < dim; ++i) autoCorr(i, k) = one(i);
00518
00519 }
00520
00521 autoCorr.col(0).setOnes();
00522
00523
00524 for(int i = 0; i < dim; ++i)
00525 {
00526
00527 mESS(i) = 0;
00528
00529 double gamma = 0;
00530 double Gamma = 0;
00531 double oldGamma = 1;
00532
00533 for(int k = 1; k < nLag; ++k)
00534 {
00535
00536 gamma = autoCorr(i, k);
00537
00538
00539 if(k % 2 == 0)
00540 {
00541
00542 Gamma += gamma;
00543
00544
00545 if(Gamma > oldGamma) Gamma = oldGamma;
00546
00547 oldGamma = Gamma;
00548
00549
00550 if(Gamma <= 0) break;
00551
00552
00553 mESS(i) += Gamma;
00554
00555 }
00556
00557 else
00558 {
00559 Gamma = gamma;
00560 }
00561
00562
00563
00564 }
00565
00566 mESS(i) = (double)nBatch / (1.0 + 2 * mESS(i) );
00567
00568 }
00569
00570
00571 if(verbose)
00572 {
00573 cout << "\tV ~ " << sumPotential << " +/- " << sqrt(sumPotential2) << endl;
00574 cout << "\tSmallest Effective Sample Size is " << minESS() << endl << endl;
00575 }
00576
00577 double whiteNoise = 2.0 / sqrt((double)nBatch);
00578
00579 if(outputFile)
00580 {
00581
00582 *outputFile << "WHITENOISE " << whiteNoise << endl << endl;
00583 *outputFile << "BEGINAUTOCORR" << endl;
00584
00585 for(int k = 0; k < nLag; ++k)
00586 {
00587
00588 *outputFile << k << flush;
00589
00590 for(int i = 0; i < dim; ++i)
00591 {
00592 *outputFile << "\t" << autoCorr(i, k) << flush;
00593 }
00594
00595 *outputFile << endl;
00596
00597 }
00598
00599 *outputFile << "ENDAUTOCORR" << endl;
00600
00601 }
00602
00603 if(verbose)
00604 {
00605
00606 for(int i = 0; i < dim; ++i)
00607 {
00608
00609 cout << "\t" << std::setw(4 * acceptWidth) << std::setfill('-') << "" << std::setfill(' ') << endl;
00610 cout << "\tVariable " << i << endl;
00611 cout << "\t" << std::setw(4 * acceptWidth) << std::setfill('-') << "" << std::setfill(' ') << endl;
00612 cout << endl;
00613
00614 cout << "\t\tMean = " << sum[i] << endl;
00615 cout << "\t\tMonte Carlo Standard Error = " << sqrt(sum2[i]) << endl;
00616 cout << "\t\tEffective Sample Size = " << mESS(i) << endl << endl;
00617
00618 cout << endl << "\t\tAutocorrelation:" << endl;
00619 cout << "\t\t\tWhite noise correlation = " << whiteNoise << endl << endl;
00620
00621
00622 for(int k = 0; k < nLagDisplay; ++k)
00623 {
00624 double g = autoCorr(i, k);
00625 cout << "\t\t\tgamma_{" << k << "} = " << g << flush;
00626 if(g > whiteNoise && k > 0) cout << " (Larger than expected fluctuation from white noise!)" << flush;
00627 cout << endl;
00628 }
00629
00630 cout << endl;
00631
00632 }
00633
00634 cout << "\t" << std::setw(4 * acceptWidth) << std::setfill('-') << "" << std::setfill(' ') << endl;
00635
00636 }
00637
00638
00639 batchSamples.clear();
00640
00641 return;
00642
00643 }
00644
00659
00660 template <typename T>
00661 void chainBundle<T>::evolve(T* chain, const double epsilon)
00662 {
00663
00664
00665 if(mConstraint) chain->beginEvolveP(0.5 * epsilon);
00666
00667
00668 chain->evolveQ(epsilon);
00669
00670
00671 mConstraint = fConstraint(chain);
00672
00673
00674 if(mConstraint) chain->finishEvolveP(0.5 * epsilon);
00675 else chain->bounceP(fNormal(chain));
00676
00677 }
00678
00684
00685 template <typename T>
00686 void chainBundle<T>::verboseEvolve(T* chain, const double epsilon)
00687 {
00688
00689
00690
00691 std::cout.precision(6);
00692 int width = 14;
00693 int nColumn = 4;
00694
00695 std::cout << "Verbose Hamiltonian Evolution, Step Size = " << epsilon << ":" << std::endl;
00696 std::cout << " " << std::setw(nColumn * width) << std::setfill('-') << "" << std::setfill(' ') << std::endl;
00697 std::cout << " "
00698 << std::setw(width) << std::left << "Poisson"
00699 << std::setw(width) << std::left << "Initial"
00700 << std::setw(width) << std::left << "Current"
00701 << std::setw(width) << std::left << "DeltaH"
00702 << std::endl;
00703 std::cout << " "
00704 << std::setw(width) << std::left << "Operator"
00705 << std::setw(width) << std::left << "Hamiltonian"
00706 << std::setw(width) << std::left << "Hamiltonian"
00707 << std::setw(width) << std::left << "/ Stepsize^{2}"
00708 << std::endl;
00709 std::cout << " " << std::setw(nColumn * width) << std::setfill('-') << "" << std::setfill(' ') << std::endl;
00710
00711 double H0 = chain->H();
00712
00713
00714 if(mConstraint) chain->beginEvolveP(0.5 * epsilon);
00715
00716 double H1 = chain->H();
00717
00718 std::cout << " "
00719 << std::setw(width) << std::left << "hat{V}/2"
00720 << std::setw(width) << std::left << H0
00721 << std::setw(width) << std::left << H1
00722 << std::setw(width) << std::left << (H1 - H0) / (epsilon * epsilon)
00723 << std::endl;
00724
00725
00726 chain->evolveQ(epsilon);
00727
00728 double H2 = chain->H();
00729
00730 std::cout << " "
00731 << std::setw(width) << std::left << "hat{T}"
00732 << std::setw(width) << std::left << H0
00733 << std::setw(width) << std::left << H2
00734 << std::setw(width) << std::left << (H2 - H0) / (epsilon * epsilon)
00735 << std::endl;
00736
00737
00738 mConstraint = fConstraint(chain);
00739
00740
00741 if(mConstraint) chain->finishEvolveP(0.5 * epsilon);
00742 else chain->bounceP(fNormal(chain));
00743
00744 double H3 = chain->H();
00745
00746 std::cout << " "
00747 << std::setw(width) << std::left << "hat{V}/2"
00748 << std::setw(width) << std::left << H0
00749 << std::setw(width) << std::left << H3
00750 << std::setw(width) << std::left << (H3 - H0) / (epsilon * epsilon)
00751 << std::endl;
00752
00753 std::cout << " " << std::setw(nColumn * width) << std::setfill('-') << "" << std::setfill(' ') << std::endl;
00754
00755 }
00756
00759
00760 template <typename T>
00761 void chainBundle<T>::initAdaptation()
00762 {
00763
00764 mAdaptMu = log(mStepSize / (1 - mStepSize) );
00765 mAdaptLogEpsBar = log(mStepSize / (1 - mStepSize) );
00766
00767 mAdaptHBar = 0;
00768 mAdaptCounter = 0;
00769
00770 mNumLeapfrog = (int)(mAdaptIntTime / mStepSize);
00771 mNumLeapfrog = mNumLeapfrog < 1 ? 1 : mNumLeapfrog;
00772 mNumLeapfrog = mNumLeapfrog > mAdaptMaxLeapfrog ? mAdaptMaxLeapfrog : mNumLeapfrog;
00773
00774 }
00775
00778
00779 template <typename T>
00780 void chainBundle<T>::updateAdaptation(double metropolisProb)
00781 {
00782
00783 metropolisProb = metropolisProb > 1 ? 1 : metropolisProb;
00784
00785
00786 ++mAdaptCounter;
00787
00788 double delta = 1.0 / (mAdaptCounter + mAdaptT0);
00789
00790 mAdaptHBar = (1.0 - delta) * mAdaptHBar + delta * (mAdaptTargetAccept - metropolisProb);
00791
00792 double logEps = mAdaptMu - mAdaptHBar * sqrt(mAdaptCounter) / mAdaptGamma;
00793 delta = exp( - mAdaptKappa * log( mAdaptCounter ) );
00794
00795 mAdaptLogEpsBar = (1.0 - delta) * mAdaptLogEpsBar + delta * logEps;
00796
00797
00798 mStepSize = 1.0 / ( 1.0 + exp(-mAdaptLogEpsBar) );
00799
00800
00801 mNumLeapfrog = (int)(mAdaptIntTime / mStepSize);
00802 mNumLeapfrog = mNumLeapfrog < 1 ? 1 : mNumLeapfrog;
00803 mNumLeapfrog = mNumLeapfrog > mAdaptMaxLeapfrog ? mAdaptMaxLeapfrog : mNumLeapfrog;
00804
00805 }
00806
00808
00809 template <typename T>
00810 void chainBundle<T>::transition()
00811 {
00812 for(mIt = mChains.begin(); mIt != mChains.end(); ++mIt) transition(*mIt);
00813 }
00814
00817
00818 template <typename T>
00819 void chainBundle<T>::transition(int i)
00820 {
00821
00822 if(i < 0 || i >= mChains.size())
00823 {
00824 cout << "chainBundle::transition() - Bad chain index " << i << "!" << endl;
00825 return;
00826 }
00827
00828 transition(mChains.at(i));
00829
00830 return;
00831
00832 }
00833
00838
00839 template <typename T>
00840 void chainBundle<T>::saveTrajectory(std::ofstream& outputFile, const int i)
00841 {
00842
00843 outputFile << mStepSize << "\t" << mNumLeapfrog << endl << endl;
00844
00845 chain(i)->prepareEvolution();
00846 chain(i)->sampleP(mRandom);
00847
00848 outputFile << 0 << "\t" << chain(i)->H() << "\t" << chain(i)->T() << "\t" << chain(i)->V() << flush;
00849
00850 for(int j = 0; j < chain(i)->dim(); ++j) outputFile << "\t" << chain(i)->q()(j) << flush;
00851 for(int j = 0; j < chain(i)->dim(); ++j) outputFile << "\t" << chain(i)->p()(j) << flush;
00852 outputFile << endl;
00853
00854 for(int n = 0; n < mNumLeapfrog; ++n)
00855 {
00856
00857 evolve(chain(i), mStepSize);
00858
00859 outputFile << n + 1 << "\t" << chain(i)->H() << "\t" << chain(i)->T() << "\t" << chain(i)->V() << flush;
00860
00861 for(int j = 0; j < chain(i)->dim(); ++j) outputFile << "\t" << chain(i)->q()(j) << flush;
00862 for(int j = 0; j < chain(i)->dim(); ++j) outputFile << "\t" << chain(i)->p()(j) << flush;
00863 outputFile << endl;
00864
00865 }
00866
00867 outputFile.close();
00868
00869 return;
00870
00871 }
00872
00881
00882 template <typename T>
00883 bool chainBundle<T>::transition(T* chain)
00884 {
00885
00886
00887 if(mNumSamples == 0)
00888 {
00889
00890 mConstraint = fConstraint(chain);
00891
00892 if(!mConstraint)
00893 {
00894 cout << "chainBundle::transition() - Initial chain parameters in violation "
00895 << "of constraints, aborting the transition!" << endl;
00896 return false;
00897 }
00898
00899 }
00900
00901 bool accept = true;
00902
00903 for(int n = 0; n < mNumSubsample; ++n)
00904 {
00905
00906
00907
00908 double stepSize = mStepSize;
00909
00910 if(mRandom.Prob<double>(mProbStepSizeJerk))
00911 {
00912 stepSize *= mStepSizeJerk;
00913 }
00914 else
00915 {
00916 stepSize *= 1.0 + mStepSizeJitter * (2.0 * mRandom.FloatU() - 1.0);
00917 }
00918
00919
00920 chain->prepareEvolution();
00921
00922
00923 chain->sampleP(mRandom);
00924
00926
00928
00929
00930 chain->saveAsRejectSample();
00931 double logSumRejectProb = -chain->H();
00932
00933 if(mWindowSize > 0)
00934 {
00935
00936
00937 stepSize *= -1;
00938
00939 chain->saveCurrentPoint();
00940 int s = mRandom.Integer(mWindowSize);
00941
00942 for(int t = 0; t < s; ++t)
00943 {
00944
00945 evolve(chain, stepSize);
00946
00947
00948 if(mConstraint)
00949 {
00950 double Hplus = chain->H();
00951 logSumRejectProb = fLogSumExp(logSumRejectProb, -Hplus);
00952 if( mRandom.Prob<double>( exp(-Hplus - logSumRejectProb) ) ) chain->saveAsRejectSample();
00953 }
00954
00955 }
00956
00957
00958 stepSize *= -1;
00959
00960 chain->restoreStoredPoint();
00961
00962 for(int t = 0; t < mWindowSize - s - 1; ++t)
00963 {
00964
00965 evolve(chain, stepSize);
00966
00967
00968 if(mConstraint)
00969 {
00970 double Hplus = chain->H();
00971 logSumRejectProb = fLogSumExp(logSumRejectProb, -Hplus);
00972 if( mRandom.Prob<double>( exp(-Hplus - logSumRejectProb) ) ) chain->saveAsRejectSample();
00973 }
00974
00975 }
00976
00977 }
00978
00980
00982
00983 if(mVerbosity >= 2)
00984 {
00985 cout << "Beginning leapfrog:" << endl;
00986 cout << endl;
00987 chain->displayState();
00988 cout << endl;
00989 }
00990
00991 if(mTemperAlpha) chain->p() *= sqrt(mTemperAlpha);
00992
00993
00994 double m = 0.5 * (mNumLeapfrog - 2 * mWindowSize);
00995
00996 for(unsigned int t = 0; t < mNumLeapfrog - 2 * mWindowSize; ++t)
00997 {
00998
00999
01000 if(chain->isNaN())
01001 {
01002 if(mVerbosity >= 1) cout << "Immediately rejecting a NaN state..." << endl;
01003 break;
01004 }
01005
01006
01007 evolve(chain, stepSize);
01008
01009
01010 if(mTemperAlpha)
01011 {
01012 if(t < m) chain->p() *= sqrt(mTemperAlpha);
01013 else if(t >= m) chain->p() /= sqrt(mTemperAlpha);
01014 }
01015
01016 }
01017
01018 if(mVerbosity >= 2)
01019 {
01020 cout << "Ending leapfrog:" << endl;
01021 cout << endl;
01022 chain->displayState();
01023 cout << endl;
01024 }
01025
01027
01029
01030 double logSumAcceptProb = 0;
01031 bool goodAcceptSample = false;
01032
01033 if(!chain->isNaN())
01034 {
01035
01036
01037 if(mConstraint)
01038 {
01039 chain->saveAsAcceptSample();
01040 logSumAcceptProb = -chain->H();
01041 goodAcceptSample = true;
01042 }
01043
01044 if(mWindowSize > 0)
01045 {
01046
01047 for(int t = 0; t < mWindowSize - 1; ++t)
01048 {
01049
01050 evolve(chain, stepSize);
01051
01052
01053 if(mConstraint)
01054 {
01055
01056
01057 if(chain->isNaN())
01058 {
01059 if(mVerbosity >= 1) cout << "Immediately rejecting a NaN state..." << endl;
01060 break;
01061 }
01062
01063 double Hplus = chain->H();
01064
01065
01066 if(!goodAcceptSample)
01067 {
01068 logSumAcceptProb = -Hplus;
01069 chain->saveAsAcceptSample();
01070 goodAcceptSample = true;
01071 }
01072 else
01073 {
01074 logSumAcceptProb = fLogSumExp(logSumAcceptProb, -Hplus);
01075 if( mRandom.Prob<double>( exp(-Hplus - logSumRejectProb) ) ) chain->saveAsAcceptSample();
01076 }
01077
01078 }
01079
01080 }
01081
01082 }
01083 else
01084 {
01085
01086 if(!mConstraint)
01087 {
01088 chain->saveAsAcceptSample();
01089 goodAcceptSample = false;
01090 }
01091
01092 }
01093
01094 }
01095
01097
01099
01100 double metropolisProb = 0;
01101 if(goodAcceptSample) metropolisProb = exp(logSumAcceptProb - logSumRejectProb);
01102 if(metropolisProb != metropolisProb) metropolisProb = 0;
01103
01104 if(metropolisProb > 1) accept = true;
01105 else accept = mRandom.Prob<double>(metropolisProb);
01106
01107 chain->sampleWindows(accept);
01108
01109 if(mVerbosity >= 2)
01110 {
01111 if(accept) cout << "Accepting proposed sample with" << endl;
01112 else cout << "Rejecting proposed sample with" << endl;
01113
01114 cout << " log(p_{accept window}) = " << logSumAcceptProb << endl;
01115 cout << " log(p_{reject window}) = " << logSumRejectProb << endl;
01116 cout << " p(accept window) = " << metropolisProb << endl << endl;
01117
01118 }
01119
01120 chain->updateMetroStats(accept, metropolisProb > 1 ? 1.0 : metropolisProb);
01121
01122 if(mAdaptStepSize) updateAdaptation(metropolisProb);
01123
01124 }
01125
01126
01127 if(mStoreSamples)
01128 {
01129 mSamples.push_back(VectorXd(chain->q()));
01130 mSampleE.push_back(chain->V());
01131 }
01132
01133 ++mNumSamples;
01134
01135 return accept;
01136
01137 }
01138
01145
01146 template <typename T>
01147 void chainBundle<T>::checkIntError(int i, int N, int f)
01148 {
01149
01150 if(i < 0 || i >= mChains.size())
01151 {
01152 cout << "chainBundle::checkIntError() - Bad chain index " << i << "!" << endl;
01153 return;
01154 }
01155
01156
01157 mChains.at(i)->prepareEvolution();
01158 mChains.at(i)->sampleP(mRandom);
01159
01160 mChains.at(i)->displayState();
01161
01162 double initH = mChains.at(i)->H();
01163
01164
01165 std::cout.precision(6);
01166 int width = 12;
01167 int nColumn = 4;
01168
01169 std::cout << "Displaying the integration error of chain " << i << ":" << std::endl;
01170 std::cout << " " << std::setw(nColumn * width) << std::setfill('-') << "" << std::setfill(' ') << std::endl;
01171 std::cout << " "
01172 << std::setw(width) << std::left << "Step"
01173 << std::setw(width) << std::left << "H_{0}"
01174 << std::setw(width) << std::left << "H_{i}"
01175 << std::setw(width) << std::left << "H_{0} - H_{i}"
01176 << std::endl;
01177 std::cout << " " << std::setw(nColumn * width) << std::setfill('-') << "" << std::setfill(' ') << std::endl;
01178
01179
01180 for(int n = 0; n < N; ++n)
01181 {
01182
01183 evolve(mChains.at(i), mStepSize);
01184
01185 if(!(n % f))
01186 {
01187 std::cout << " "
01188 << std::setw(width) << std::left << n
01189 << std::setw(width) << std::left << initH
01190 << std::setw(width) << std::left << mChains.at(i)->H()
01191 << std::setw(width) << std::left << initH - mChains.at(i)->H()
01192 << std::endl;
01193 }
01194
01195 }
01196
01197 std::cout << " " << std::setw(nColumn * width) << std::setfill('-') << "" << std::setfill(' ') << std::endl;
01198 std::cout << std::endl;
01199
01200 }
01201
01205
01206 template <typename T>
01207 void chainBundle<T>::seed(const double min, const double max)
01208 {
01209 for(int i = 0; i < mChains.at(0)->dim(); ++i) seed(i, min, max);
01210 }
01211
01216
01217 template <typename T>
01218 void chainBundle<T>::seed(const int i, const double min, const double max)
01219 {
01220
01221 if(i < 0 || i >= mChains.at(0)->dim())
01222 {
01223 cout << "chainBundle::seed() - Bad parameter index!" << endl;
01224 return;
01225 }
01226
01227 for(mIt = mChains.begin(); mIt != mChains.end(); ++mIt)
01228 {
01229 (*mIt)->q()(i) = (max - min) * mRandom.FloatU<double>() + min;
01230 }
01231
01232 }
01233
01245
01246 template <typename T>
01247 void chainBundle<T>::burn(const int nBurn, const int nCheck, const double minR, const bool verbose)
01248 {
01249
01250
01251 long dim = mChains.at(0)->dim();
01252 double m = (double)mChains.size();
01253 double n = (double)nCheck;
01254
01255 VectorXd R(dim);
01256
01257 VectorXd* chainSum[(int)m];
01258 for(int i = 0; i < m; ++i) chainSum[i] = new VectorXd(dim);
01259 VectorXd ensembleSum(dim);
01260 VectorXd ensembleSum2(dim);
01261 VectorXd chainSum2(dim);
01262
01263 bool burning = true;
01264
01265 int nPerLine = 5;
01266 int nLines = (int)dim / nPerLine;
01267
01268 cout.precision(6);
01269 int width = 12;
01270 int totalWidth = width + 8;
01271 int borderWidth = ((int)dim < nPerLine ? (int)dim : nPerLine) * totalWidth + 4;
01272
01273 int acceptWidth = 14;
01274
01276
01278
01279
01280 bool sampleFlag = mStoreSamples;
01281 mStoreSamples = false;
01282
01283
01284 if(verbose) cout << endl << "Burn, baby, burn" << flush;
01285
01286 for(int i = 0; i < nBurn; ++i)
01287 {
01288 transition();
01289 if(verbose) if(i % 10 == 0) cout << "." << flush;
01290 }
01291
01292 if(verbose) cout << endl << endl;
01293 if(verbose) cout << "Computing diagnostics:" << endl;
01294 if(verbose) cout << " " << std::setw(borderWidth) << std::setfill('-') << "" << std::setfill(' ') << endl;
01295
01296 while(burning)
01297 {
01298
01299 ensembleSum.setZero();
01300 ensembleSum2.setZero();
01301 for(int i = 0; i < m; ++i) (chainSum[i])->setZero();
01302 chainSum2.setZero();
01303
01304
01305 for(int i = 0; i < nCheck; ++i)
01306 {
01307
01308 transition();
01309
01310 mIt = mChains.begin();
01311 for(int j = 0; j < m; ++j, ++mIt)
01312 {
01313
01314 VectorXd& q = (*mIt)->q();
01315
01316 ensembleSum += q;
01317 ensembleSum2 += q.cwiseAbs2();
01318
01319 *(chainSum[j]) += q;
01320
01321 }
01322
01323 }
01324
01325
01326 double a = (n - 1) / n;
01327 double b = m / (m - 1);
01328
01329 for(int j = 0; j < m; ++j)
01330 {
01331 chainSum2 += (chainSum[j])->cwiseAbs2();
01332 }
01333
01334 ensembleSum = ensembleSum.cwiseAbs2();
01335 ensembleSum = ensembleSum.cwiseQuotient(chainSum2);
01336 ensembleSum /= m;
01337 ensembleSum = VectorXd::Ones(dim) - ensembleSum;
01338
01339 ensembleSum2 = ensembleSum2.cwiseQuotient(chainSum2);
01340 ensembleSum2 *= n;
01341 ensembleSum2 = VectorXd::Ones(dim) - ensembleSum2;
01342
01343 R = a * (VectorXd::Ones(dim) - b * ensembleSum.cwiseQuotient(ensembleSum2));
01344
01345 burning = false;
01346 for(int i = 0; i < dim; ++i) burning |= (R[i] > minR);
01347
01348
01349 if(verbose && burning)
01350 {
01351 cout << " Diagnostic test failed," << endl;
01352
01353 int k = 0;
01354 for(int i = 0; i < nLines; ++i)
01355 {
01356
01357 cout << " " << flush;
01358 for(int j = 0; j < nPerLine; ++j, ++k)
01359 {
01360 cout << "R_{" << k << "} = " << std::setw(width) << std::left << R[k] << flush;
01361 }
01362
01363 cout << endl;
01364
01365 }
01366
01367 if(dim % nPerLine > 0)
01368 {
01369
01370 cout << " " << flush;
01371 for(int i = 0; i < dim % nPerLine; ++i, ++k)
01372 {
01373 cout << "R_{" << k << "} = " << std::setw(width) << std::left << R[k] << flush;
01374 }
01375 cout << endl;
01376
01377 }
01378
01379 cout << " " << std::setw(borderWidth) << std::setfill('-') << "" << std::setfill(' ') << endl;
01380
01381 }
01382
01383 }
01384
01385
01386 if(verbose)
01387 {
01388
01389 cout << " Markov chains converged with" << endl;
01390
01391 int k = 0;
01392 for(int i = 0; i < nLines; ++i)
01393 {
01394
01395 cout << " " << flush;
01396 for(int j = 0; j < nPerLine; ++j, ++k)
01397 {
01398 cout << "R_{" << k << "} = " << std::setw(width) << std::left << R[k] << flush;
01399 }
01400
01401 cout << endl;
01402
01403 }
01404
01405 if(dim % nPerLine > 0)
01406 {
01407
01408 cout << " " << flush;
01409 for(int i = 0; i < dim % nPerLine; ++i, ++k)
01410 {
01411 cout << "R_{" << k << "} = " << std::setw(width) << std::left << R[k] << flush;
01412 }
01413 cout << endl;
01414
01415 }
01416
01417 cout << " " << std::setw(borderWidth) << std::setfill('-') << "" << std::setfill(' ') << endl;
01418
01419 cout << endl;
01420
01421 cout << " " << std::setw(5 * acceptWidth / 2) << std::setfill('-') << "" << std::setfill(' ') << endl;
01422 cout << " "
01423 << std::setw(acceptWidth / 2) << std::left << "Chain"
01424 << std::setw(acceptWidth) << std::left << "Global"
01425 << std::setw(acceptWidth) << std::left << "Local"
01426 << std::endl;
01427 cout << " "
01428 << std::setw(acceptWidth / 2) << std::left << ""
01429 << std::setw(acceptWidth) << std::left << "Accept Rate"
01430 << std::setw(acceptWidth) << std::left << "Accept Rate"
01431 << std::endl;
01432 cout << " " << std::setw(5 * acceptWidth / 2) << std::setfill('-') << "" << std::setfill(' ') << endl;
01433
01434 for(int i = 0; i < mChains.size(); ++i)
01435 {
01436 cout << " "
01437 << std::setw(acceptWidth / 2) << std::left << i
01438 << std::setw(acceptWidth) << std::left << (mChains.at(i))->acceptRate()
01439 << std::setw(acceptWidth) << std::left << (mChains.at(i))->movingAcceptRate()
01440 << endl;
01441 }
01442 cout << " " << std::setw(5 * acceptWidth / 2) << std::setfill('-') << "" << std::setfill(' ') << endl;
01443 cout << endl;
01444
01445 }
01446
01447 mChar = true;
01448
01449
01450 mStoreSamples = sampleFlag;
01451
01452 return;
01453
01454 }
01455
01461
01462 template <typename T>
01463 double chainBundle<T>::fLogSumExp(double a, double b)
01464 {
01465
01466 if(a > b)
01467 {
01468 return a + log( 1.0 + exp(b - a) );
01469 }
01470 else
01471 {
01472 return b + log( 1.0 + exp(a - b) );
01473 }
01474
01475 }
01476
01477 #define _BETA_CHAINBUNDLE_
01478 #endif