tristanz / ScytheMCMC (http://bytebucket.org/tristanz/scythemcmc/wiki/html/index.html)

A Scythe Markov Chain Monte Carlo C++ Framework

Clone this repository (size: 1.0 MB): HTTPS / SSH
$ hg clone http://bitbucket.org/tristanz/scythemcmc
commit 12: fd1ece924824
parent 11: 6ceff113f5e0
branch: default
Autoformatting
Tristan Zajonc / tristanz
15 months ago

Changed (Δ155 bytes):

raw changeset »

src/mcmc.h (193 lines added, 184 lines removed)

Up to file-list src/mcmc.h:

15
15
    code needed to write custom MCMC routines.  It also provides common MCMC step types, including Gibbs, Metropolis-Hastings,
16
16
    and Slice sampling.  Users can experiment with which sampling steps provide the best results and implement their own sampling
17
17
    steps as desired.
18
    
18
19
19
    Scythe MCMC was motivated with the need to combine simpler samplers, such as univariate slice sampling, with more specialized
20
20
    samplers for particular problems.  Future versions of Scythe MCMC will include common samplers for nonparametric Bayesian models,
21
21
    including a Collapsed Gibbs sampler for the Dirichlet Process, and Slice samplers for the Dirichlet Process and Indian Buffet Process.
22
    
22
23
23
    There are many choices for writing MCMC samplers.  Scythe MCMC is similar to, and heavily inspired by,
24
24
    <a href="http://darwin.eeb.uconn.edu/mcmc++/mcmc++.html">MCMC++</a>, but is based
25
    on the Scythe, which provides convenient matrix types, random number generators, 
26
    and probability distributions. Scythe MCMC is different in focus from 
25
    on the Scythe, which provides convenient matrix types, random number generators,
26
    and probability distributions. Scythe MCMC is different in focus from
27
27
    <a href="http://mcmcpack.wustl.edu/wiki/index.php/Main_Page">MCMCPack</a>, which
28
28
    is also based on Scythe and interfaces with R.  Users wishing to distribute a specific model to R users
29
29
    should consider contributing to MCMCPack directly. Unlike MCMCPack, Scythe MCMC makes no attempt to interface with R
32
32
    development of samplers for many models.
33
33
34
34
    Even though implementing models in ScytheMCMC requires more work than
35
    implementing comparable models in <a href="http://mathstat.helsinki.fi/openbugs/">Bugs</a> 
35
    implementing comparable models in <a href="http://mathstat.helsinki.fi/openbugs/">Bugs</a>
36
36
    or <a href="http://www-ice.iarc.fr/~martyn/software/jags/">JAGS</a>, Scythe MCMC generally
37
37
    leads to faster samplers that can exploit the particular structure of a given problem.  It also
38
38
    allows development of models that cannot be sampled effectively using either Bugs or Jags, such
52
52
       - Collapsed gibbs samplers for Dirichlet Process,
53
53
       - Slice sampler for Dirichlet Process and Indian Buffet Process.
54
54
    - MIT License.
55
    
55
56
56
    \section gettingstarted GETTING STARTED
57
    
57
58
58
59
59
    \section license MIT LICENSE
60
60
@@ -108,9 +108,9 @@ using namespace scythe;
108
108
using namespace std;
109
109
110
110
/// Scythe column-oriented double matrix typedef.
111
typedef Matrix<double,Col> matrix; 
111
typedef Matrix<double, Col> matrix;
112
112
/// Scythe column-oriented integer matrix typedef.
113
typedef Matrix<int,Col> imatrix;
113
typedef Matrix<int, Col> imatrix;
114
114
/// Pair typedef for integers.  Used to store (x, y) coordinates of a matrix location.
115
115
typedef pair<int, int> ipair;
116
116
@@ -119,7 +119,7 @@ double dInf = std::numeric_limits<double
119
119
double iInf = std::numeric_limits<int>::infinity();
120
120
121
121
/// Global Mersenne-Twister random number generator.
122
mersenne myrng; 
122
mersenne myrng;
123
123
124
124
125
125
/*! \brief Basic MCMC options.
@@ -129,7 +129,7 @@ mersenne myrng;
129
129
 */
130
130
struct MCMCOptions {
131
131
  /// Sample size. (iterations - burnin)/(thin + 1).
132
  int sample_size; 
132
  int sample_size;
133
133
  /// Thinning interval
134
134
  int thin;
135
135
  /// Burn in period.
@@ -159,8 +159,8 @@ bool FileExists(string strFilename) {
159
159
  int intStat;
160
160
161
161
  // Attempt to get the file attributes
162
  intStat = stat(strFilename.c_str(),&stFileInfo);
163
  if(intStat == 0) {
162
  intStat = stat(strFilename.c_str(), &stFileInfo);
163
  if (intStat == 0) {
164
164
    // We were able to get the file attributes
165
165
    // so the file obviously exists.
166
166
    blnReturn = true;
@@ -173,7 +173,7 @@ bool FileExists(string strFilename) {
173
173
    // more details on why stat failed.
174
174
    blnReturn = false;
175
175
  }
176
  
176
177
177
  return(blnReturn);
178
178
}
179
179
@@ -181,12 +181,11 @@ bool FileExists(string strFilename) {
181
181
 *
182
182
 */
183
183
template <class T>
184
inline string to_csv (const T& t)
185
{
184
inline string to_csv (const T& t) {
186
185
  std::stringstream ss;
187
186
  ss << t;
188
187
  string s = ss.str();
189
  replace(s.begin(),s.end(),' ', ',');
188
  replace(s.begin(), s.end(), ' ', ',');
190
189
  return s;
191
190
}
192
191
@@ -209,7 +208,7 @@ inline string to_csv (const T& t)
209
208
     Example: ./base_model --config-file=base_model.cfg --out-file=out.txt --chains=1 --sample-size=1000
210
209
              --burnin=0 --thin=1 --random-seed=12345
211
210
</pre>
212
*/         
211
*/
213
212
void ShowUsage() {
214
213
  cout << "  Usage:" << endl
215
214
       << "    --help \t\t\t displays help message" << endl
@@ -220,7 +219,7 @@ void ShowUsage() {
220
219
       << "    --burnin=arg \t\t burn in period" << endl
221
220
       << "    --thin=arg \t\t\t thinning iterval (0 = no thinning)" << endl
222
221
       << "    --random-seed=arg \t\t random number seed" << endl << endl;
223
       
222
224
223
  cout << "  Example: ./base_model --config-file=base_model.cfg --out-file=out.txt --chains=1 --sample-size=1000" << endl
225
224
       << "\t   --burnin=0 --thin=1 --random-seed=12345" << endl << endl;
226
225
}
@@ -235,7 +234,7 @@ void ShowUsage() {
235
234
*/
236
235
void DefaultStartUp(int argc, char* argv[]) {
237
236
  cout << "ScytheMCMC v. " << SCYTHE_MCMC_VERSION << endl << endl;
238
  
237
239
238
  // Config parser is based on SimpleOpt Library.
240
239
  // See: http://code.jellycan.com/simpleopt/
241
240
  enum { OPT_SAMPLE_SIZE, OPT_THIN, OPT_BURNIN, OPT_CHAINS, OPT_RANDOM_SEED, OPT_CONFIG_FILE, OPT_OUT_FILE, OPT_HELP };
@@ -255,71 +254,70 @@ void DefaultStartUp(int argc, char* argv
255
254
  int setflags = 0;
256
255
  while (args.Next()) {
257
256
    if (args.LastError() == SO_SUCCESS) {
258
      switch(args.OptionId()) {
259
        case OPT_HELP:
260
          ShowUsage();
261
          exit(0);
262
          break;
263
        case OPT_CONFIG_FILE:
264
          setflags++;
265
          mcmc_options.config_file = args.OptionArg();
266
          break;
267
        case OPT_OUT_FILE:
268
          setflags++;
269
          mcmc_options.out_file = args.OptionArg();
270
          break;
271
        case OPT_CHAINS:
272
          setflags++;
273
          mcmc_options.chains = atoi(args.OptionArg());
274
          break;
275
        case OPT_SAMPLE_SIZE:
276
          setflags++;
277
          mcmc_options.sample_size = atoi(args.OptionArg());
278
          break;
279
        case OPT_BURNIN:
280
          setflags++;
281
          mcmc_options.burnin = atoi(args.OptionArg());
282
          break;
283
        case OPT_THIN:
284
          setflags++;
285
          mcmc_options.thin = atoi(args.OptionArg());
286
          break;
287
        case OPT_RANDOM_SEED:
288
          setflags++;
289
          mcmc_options.random_seed = atoi(args.OptionArg());
290
          break;
257
      switch (args.OptionId()) {
258
      case OPT_HELP:
259
        ShowUsage();
260
        exit(0);
261
        break;
262
      case OPT_CONFIG_FILE:
263
        setflags++;
264
        mcmc_options.config_file = args.OptionArg();
265
        break;
266
      case OPT_OUT_FILE:
267
        setflags++;
268
        mcmc_options.out_file = args.OptionArg();
269
        break;
270
      case OPT_CHAINS:
271
        setflags++;
272
        mcmc_options.chains = atoi(args.OptionArg());
273
        break;
274
      case OPT_SAMPLE_SIZE:
275
        setflags++;
276
        mcmc_options.sample_size = atoi(args.OptionArg());
277
        break;
278
      case OPT_BURNIN:
279
        setflags++;
280
        mcmc_options.burnin = atoi(args.OptionArg());
281
        break;
282
      case OPT_THIN:
283
        setflags++;
284
        mcmc_options.thin = atoi(args.OptionArg());
285
        break;
286
      case OPT_RANDOM_SEED:
287
        setflags++;
288
        mcmc_options.random_seed = atoi(args.OptionArg());
289
        break;
291
290
      }
292
    } 
293
    else {
291
    } else {
294
292
      cout << "Invalid argument: " << args.OptionText() << endl;
295
293
      exit(1);
296
294
    }
297
295
  }
298
  
296
299
297
  // Check that all required flags are set.
300
  if(setflags != 7) {
298
  if (setflags != 7) {
301
299
    ShowUsage();
302
300
    exit(1);
303
301
  }
304
302
305
303
  // Check argument values.
306
  if(mcmc_options.sample_size <= 0) {
304
  if (mcmc_options.sample_size <= 0) {
307
305
    cout << "Sample size must be positive.\n";
308
306
    exit(1);
309
307
  }
310
  if(mcmc_options.burnin < 0) {
308
  if (mcmc_options.burnin < 0) {
311
309
    cout << "Burn in cannot be negative.\n";
312
310
    exit(1);
313
311
  }
314
  if(mcmc_options.thin < 0) {
312
  if (mcmc_options.thin < 0) {
315
313
    cout << "Thinning interval cannot be negative.\n";
316
314
    exit(1);
317
315
  }
318
  if(!FileExists(mcmc_options.config_file)) {
316
  if (!FileExists(mcmc_options.config_file)) {
319
317
    cout << "Config file does not exist.\n";
320
318
    exit(1);
321
319
  }
322
  
320
323
321
  // Seed random number generator.
324
322
  myrng.initialize(mcmc_options.random_seed);
325
323
@@ -334,7 +332,7 @@ void DefaultStartUp(int argc, char* argv
334
332
}
335
333
336
334
337
/*! \brief Main parameter class. 
335
/*! \brief Main parameter class.
338
336
 *
339
337
 * The model is defined as many instances of parameter subclasses.  Different Step types require different methods
340
338
 * to be implemented in each Parameter subclass.
@@ -348,7 +346,7 @@ void DefaultStartUp(int argc, char* argv
348
346
 * GibbsStep:
349
347
 *   - Parameter::StartingValue
350
348
 *   - Parameter::RandomPosterior
351
 * 
349
 *
352
350
 * Metropolis-Hastings:
353
351
 *   - Parameter::StartingValue
354
352
 *   - Parameter::LogDensity
@@ -363,25 +361,25 @@ void DefaultStartUp(int argc, char* argv
363
361
 * \section examples Examples:
364
362
 *
365
363
 * \subsection example1 Normal mean parameter with normal prior, known standard deviation:
366
 * 
364
 *
367
365
 \code
368
366
 // Priors
369
367
 double mean_mu = 0;
370
368
 double mean_sigma = 2;
371
 
369
372
370
 // Parameters
373
371
 double mean = 0; // free parameter
374
372
 double sd = 1; // known
375
 
373
376
374
 // Data
377
375
 matrix X('X.txt');
378
 
376
379
377
 // Define the mean parameter, implementing methods required for GibbsStep.
380
 class MeanParameter : public Parameter {
378
 class MeanParameter : public Parameter<double> {
381
379
 public:
382
380
   /// Default constructors that call base constructors. (REQUIRED)
383
   MeanParameter() : Parameter() {}
384
   MeanParameter(bool track, string name) : Parameter(track, name) {}
381
   MeanParameter() : Parameter<double>() {}
382
   MeanParameter(bool track, string name) : Parameter<double>(track, name) {}
385
383
386
384
  /// Draw a random value from analytical posterior for GibbsStep.
387
385
  double RandomPosterior() {
@@ -422,39 +420,49 @@ public:
422
420
   * \param label Label of parameter for tracking purposes.
423
421
  */
424
422
  Parameter(bool track, string label) : track_(track), label_(label) {}
425
  
423
426
424
  /// Function for deterministic nodes.
427
425
  /// \return Function value.
428
  virtual ParameterStorageType Function() { return 0.0; };
429
  
426
  virtual ParameterStorageType Function() {
427
    return 0.0;
428
  };
429
430
430
  /// Starting value.
431
431
  /// \return Starting value.
432
  virtual ParameterStorageType StartingValue() { return 0.0; };
433
  
432
  virtual ParameterStorageType StartingValue() {
433
    return 0.0;
434
  };
435
434
436
  /// Log of the probability density (plus constant)
435
437
  /// \param value Value of parameter to evaluate density at.
436
438
  /// \return Log of probability density (plus constant)
437
  virtual double LogDensity(double value) { return 0.0; }
439
  virtual double LogDensity(double value) {
440
    return 0.0;
441
  }
438
442
439
443
  /// Return a random draw from the posterior.
440
444
  /// Random draw from posterior is called by GibbsStep.
441
445
  /// \return Random draw from posterior.
442
  virtual ParameterStorageType RandomPosterior() { return 0.0; }
443
  
446
  virtual ParameterStorageType RandomPosterior() {
447
    return 0.0;
448
  }
449
444
450
  /// Value of parameter.
445
451
  /// \return Parameter value
446
  virtual ParameterStorageType Value() { return 0.0; };
452
  virtual ParameterStorageType Value() {
453
    return 0.0;
454
  };
447
455
448
456
  /// Save a new value of the parameter.
449
457
  /// \param new_value New value to save.
450
458
  virtual void Save(double new_value) {};
451
  
459
452
460
  /// Parameter is tracked / saved.
453
461
  /// \return True if parameter is tracked.
454
462
  bool Track() {
455
463
    return track_;
456
464
  }
457
  
465
458
466
  /// String label of parameter.
459
467
  /// \return Label of parameter, for purposes of saving output.
460
468
  string Label() {
@@ -480,7 +488,7 @@ private:
480
488
 *
481
489
 * \ingroup steps
482
490
 *
483
 * The step (Gibbs, Metropolis-Hastings, Slice, etc) describes how the sampler 
491
 * The step (Gibbs, Metropolis-Hastings, Slice, etc) describes how the sampler
484
492
 * calculates the next value of each parameter.  The key function is Step::DoStep, which is
485
493
 * equivalent to the Execute function in a <a href="http://en.wikipedia.org/wiki/Command_pattern">Command Pattern</a>.
486
494
 * Samplers consists of a many of steps.
@@ -496,34 +504,40 @@ public:
496
504
  /*! \brief Take step.
497
505
   *
498
506
   * Executes the main step function, such as taking a MH step or deterministic step.
499
   */ 
507
   */
500
508
  virtual void DoStep() {}
501
509
  /*! \brief Set starting value.
502
510
   *
503
511
   *  Calls the parameter's Parameter::Starting function and then saves the result using Parameter::Save.
504
512
   */
505
513
  virtual void Start() {}
506
  
514
507
515
  /*! \brief Return parameter value
508
516
   *
509
517
   * \return String representation of parameter value for csv output.
510
518
   * \see Parameter::Value
511
519
   */
512
  virtual string ParameterValue() { return ""; }
513
  
520
  virtual string ParameterValue() {
521
    return "";
522
  }
523
514
524
  /*! \brief Return parameter label
515
525
   *
516
526
   * \return The label of the parameter associated with the step instance.
517
527
   * \see Parameter::Label
518
528
   */
519
  virtual string ParameterLabel() { return ""; }
529
  virtual string ParameterLabel() {
530
    return "";
531
  }
520
532
521
533
  /*! Return the tracking status
522
534
   *
523
535
   * \return The tracking status of the parameter associated with the step instance.
524
536
   * \see Parameter::Track
525
537
   */
526
  virtual bool ParameterTrack() { return true; }
538
  virtual bool ParameterTrack() {
539
    return true;
540
  }
527
541
};
528
542
529
543
/*! \brief Gibbs step.
@@ -531,7 +545,7 @@ public:
531
545
 * \ingroup steps
532
546
 *
533
547
 * A univariate Gibbs step draws from the Parameter::RandomPosterior function of a Parameter and then saves the result
534
 * using Parameter:Save. 
548
 * using Parameter:Save.
535
549
 */
536
550
template <typename ParameterType, typename ParameterStorageType>
537
551
class GibbsStep: public Step {
@@ -556,25 +570,25 @@ public:
556
570
  }
557
571
558
572
  string ParameterLabel() {
559
      return parameter_.Label();
573
    return parameter_.Label();
560
574
  }
561
575
562
576
  string ParameterValue() {
563
      return to_csv<ParameterStorageType>(parameter_.Value());
577
    return to_csv<ParameterStorageType>(parameter_.Value());
564
578
  }
565
579
566
580
  bool ParameterTrack() {
567
      return parameter_.Track();
581
    return parameter_.Track();
568
582
  }
569
583
private:
570
584
  /// Parameter associated with step instance.
571
  ParameterType parameter_;  
585
  ParameterType parameter_;
572
586
};
573
587
574
588
/*! \brief Deterministic function step.
575
589
 *
576
590
 * \ingroup steps
577
 * 
591
 *
578
592
 * Deterministic nodes can be helpful to track summary statistics or to reduce computations through intermediate use
579
593
 * of sufficient statistics across multiple parameters.  FunctionStep calls the parameters Parameter::Function method
580
594
 * and saves the result using Parameter::Save.
@@ -609,32 +623,32 @@ public:
609
623
  }
610
624
611
625
  string ParameterLabel() {
612
      return parameter_.Label();
626
    return parameter_.Label();
613
627
  }
614
628
615
629
  string ParameterValue() {
616
      return to_csv<ParameterStorageType>(parameter_.Value());
630
    return to_csv<ParameterStorageType>(parameter_.Value());
617
631
  }
618
632
619
633
  bool ParameterTrack() {
620
      return parameter_.Track();
634
    return parameter_.Track();
621
635
  }
622
636
private:
623
637
  /// Parameter associated with step instance.
624
  ParameterType parameter_;  
638
  ParameterType parameter_;
625
639
};
626
640
627
641
/*! \defgroup proposals Metropolis-Hastings Proposals
628
 * 
642
 *
629
643
 * The MetropStep Metropolis-Hastings class requires both a Parameter instance
630
644
 * and a Proposal instance.  Proposal instances define a Draw and LogDensity method.
631
645
 * The constructor should set a tuning parameter.
632
646
 *
633
647
 * MetroStep::DoStep uses the Draw method to draw new proposed values for the parameter
634
 * and the LogDensity to calculate the proposal terms in the acceptance \f$\alpha\f$.  For 
648
 * and the LogDensity to calculate the proposal terms in the acceptance \f$\alpha\f$.  For
635
649
 * symmetric proposal distributions returning 0.0 is enough.
636
650
 */
637
 
651
638
652
/*! \brief Normal proposal for Metropolis-Hastings.
639
653
 *
640
654
 *  \ingroup proposals
@@ -649,7 +663,7 @@ public:
649
663
   * \param standard_deviation Tuning parameter for normal proposal.
650
664
   */
651
665
  NormalProposal(double standard_deviation) : standard_deviation_(standard_deviation) {}
652
  
666
653
667
  /*! \brief Draw from normal proposal
654
668
   *
655
669
   * \param starting_value Starting value.
@@ -657,7 +671,7 @@ public:
657
671
  double Draw(double starting_value) {
658
672
    return myrng.rnorm(starting_value, standard_deviation_);
659
673
  }
660
  
674
661
675
  /*! \brief Log probability of proposal new value, given starting value.
662
676
   *
663
677
   * \note Needs to be implemented but can be 0.0 if proposal is symmetric, which it is.
@@ -667,14 +681,14 @@ public:
667
681
  double LogDensity(double new_value, double starting_value) {
668
682
    return 0.0; // Symmetric, doesn't matter.
669
683
  }
670
  
684
671
685
private:
672
686
  double standard_deviation_;
673
687
};
674
688
675
689
676
690
/*! \brief Beta proposal for Metropolis-Hastings.
677
 *  
691
 *
678
692
 * \ingroup proposals
679
693
 *
680
694
 * Useful proposal type for parameters with support between 0 and 1.
@@ -704,9 +718,9 @@ public:
704
718
   * \param idenominator Tuning parameter equal to the inverse denominator \f$1/d\f$ of a Beta distribution.
705
719
   */
706
720
  BetaProposal(double idenominator) {
707
    denom_ = 1/idenominator;
721
    denom_ = 1 / idenominator;
708
722
  }
709
  
723
710
724
  /*! \brief Draw from Beta proposal
711
725
   *
712
726
   * \param starting_value Starting value (mean of Beta distribution).
@@ -716,9 +730,9 @@ public:
716
730
    double beta = alpha - denom_;
717
731
    return myrng.rbeta(alpha, beta);
718
732
  }
719
  
733
720
734
  /*! \brief Log probability of proposal new value, given starting value.
721
   * 
735
   *
722
736
   * \param starting_value Starting value.
723
737
   * \param new_value Proposed new value.
724
738
   */
@@ -727,19 +741,19 @@ public:
727
741
    double beta = alpha - denom_;
728
742
    return dbeta(new_value, alpha, beta);
729
743
  }
730
  
744
731
745
private:
732
746
  double denom_;
733
747
};
734
748
735
749
736
750
/*! \brief Log normal proposal for Metropolis-Hastings.
737
 *  
751
 *
738
752
 * \ingroup proposals
739
753
 *
740
754
 * Useful proposal type for parameters with support between 0 and positive infinity.
741
755
 *
742
 * For convenience, the log normal proposal is parameterized using the unlogged mean (starting value) 
756
 * For convenience, the log normal proposal is parameterized using the unlogged mean (starting value)
743
757
 * and the (positive) log standard deviation.  This differs from how scythe::dlnorm is parameterized.
744
758
 *
745
759
 */
@@ -754,7 +768,7 @@ public:
754
768
   * \param logsd Tuning parameter equal to the log standard deviation.
755
769
   */
756
770
  LogNormalProposal(double logsd) : logsd_(logsd) {}
757
  
771
758
772
  /*! \brief Draw from log normal proposal
759
773
   *
760
774
   * \param starting_value Starting value (unlogged mean of log normal).
@@ -763,9 +777,9 @@ public:
763
777
    double logmean = log(starting_value);
764
778
    return myrng.rlnorm(logmean, logsd_);
765
779
  }
766
  
780
767
781
  /*! \brief Log probability of proposal new value, given starting value.
768
   * 
782
   *
769
783
   * \param starting_value Starting value.
770
784
   * \param new_value Proposed new value.
771
785
   */
@@ -773,7 +787,7 @@ public:
773
787
    double logmean = log(starting_value);
774
788
    return dlnorm(new_value, logmean, logsd_);
775
789
  }
776
  
790
777
791
private:
778
792
  double logsd_;
779
793
};
@@ -781,7 +795,7 @@ private:
781
795
/*! \brief Metropolis Hastings step
782
796
 *
783
797
 * \ingroup steps
784
 * 
798
 *
785
799
 * Basic univariate Metropolis-Hastings step.  Requires both a Parameter and Proposal instance.
786
800
 */
787
801
template <typename ParameterType, typename ProposalType>
@@ -796,7 +810,7 @@ public:
796
810
   *  \param proposal A Proposal instance that implements Proposal::LogDensity and Proposal::Draw.
797
811
   */
798
812
  MetropStep(ParameterType parameter, ProposalType proposal) : parameter_(parameter), proposal_(proposal) {}
799
  
813
800
814
  /*! \brief Take a function step for the parameter.
801
815
   *
802
816
   *  Calculates the value of Parameter::Function and then saves the result using Parameter::Save.
@@ -807,26 +821,26 @@ public:
807
821
    double old_value = parameter_.Value();
808
822
    // MH accept/reject criteria
809
823
    double alpha = parameter_.LogDensity(new_value) - parameter_.LogDensity(old_value)
810
      + proposal_.LogDensity(old_value, new_value) - proposal_.LogDensity(new_value, old_value);
811
    if(myrng.runif() < min(exp(alpha), 1.0)) {
824
                   + proposal_.LogDensity(old_value, new_value) - proposal_.LogDensity(new_value, old_value);
825
    if (myrng.runif() < min(exp(alpha), 1.0)) {
812
826
      parameter_.Save(new_value);
813
827
    }
814
828
  }
815
   
829
816
830
  void Start() {
817
831
    parameter_.Save(parameter_.StartingValue());
818
832
  }
819
833
820
834
  string ParameterLabel() {
821
      return parameter_.Label();
835
    return parameter_.Label();
822
836
  }
823
837
824
838
  string ParameterValue() {
825
      return to_csv<double>(parameter_.Value());
839
    return to_csv<double>(parameter_.Value());
826
840
  }
827
841
828
842
  bool ParameterTrack() {
829
      return parameter_.Track();
843
    return parameter_.Track();
830
844
  }
831
845
private:
832
846
  /// Parameter associated with step instance.
@@ -840,7 +854,7 @@ private:
840
854
 *
841
855
 * Basic univariate slice sampling step with stepping out and shrinkage. Performs a slice sampling update from an initial
842
856
 * point to a new point that leaves invariant the distribution with the specifified log density functions.
843
 * 
857
 *
844
858
 * The log desnity function may return -Inf for points outside the support of the distribution.
845
859
 * If a lower and/or upper bound is specified for the support, the log density function will not be called outside
846
860
 * such limits.
@@ -864,9 +878,9 @@ public:
864
878
   *  \param lower Lower bound on the support of the distribution (default = -Infinity)
865
879
   *  \param upper Upper bound on the support of the distribution (default = Infinity)
866
880
   */
867
  SliceStep(ParameterType parameter, double w = 1.0, double lower=-dInf, double upper=dInf) : 
868
    parameter_(parameter), w_(w), lower_(lower), upper_(upper) {}
869
  
881
  SliceStep(ParameterType parameter, double w = 1.0, double lower = -dInf, double upper = dInf) :
882
      parameter_(parameter), w_(w), lower_(lower), upper_(upper) {}
883
870
884
  /*! \brief Take a slice sampling step for the parameter.
871
885
   *
872
886
   */
@@ -874,83 +888,82 @@ public:
874
888
    // Find the log density at the initial point.
875
889
    double x0 = parameter_.Value();
876
890
    double gx0 = parameter_.LogDensity(x0);
877
    
891
878
892
    // Determine slice level, in log terms
879
893
    double logy = gx0 - myrng.rexp(1);
880
    
894
881
895
    //Find the initial interval to sample from.
882
896
    double u = myrng.runif() * w_;
883
897
    double L = x0 - u;
884
898
    double R = x0 + (w_ - u);
885
    
899
886
900
    // Expand the interval until its ends are outside the slice, or
887
901
    // until the limit on steps is reached.
888
    
902
889
903
    // allow infinite steps... could hang!
890
904
    // FIXME: Add check for too many iterations and exit with error message.
891
    while(true) {
892
      if(L <= lower_) {
905
    while (true) {
906
      if (L <= lower_) {
893
907
        break;
894
908
      }
895
      if(parameter_.LogDensity(L) <= logy) {
909
      if (parameter_.LogDensity(L) <= logy) {
896
910
        break;
897
911
      }
898
912
      L = L - w_;
899
913
    }
900
    
901
    while(true) {
902
      if(R >= upper_) {
914
915
    while (true) {
916
      if (R >= upper_) {
903
917
        break;
904
918
      }
905
      if(parameter_.LogDensity(R) <= logy) {
919
      if (parameter_.LogDensity(R) <= logy) {
906
920
        break;
907
921
      }
908
922
      R = R + w_;
909
923
    }
910
    
924
911
925
    // Shrink interval to lower and upper bounds.
912
    if(L < lower_) {
926
    if (L < lower_) {
913
927
      L = lower_;
914
928
    }
915
    if(R > upper_) {
929
    if (R > upper_) {
916
930
      R = upper_;
917
931
    }
918
    
932
919
933
    // Sample from the interval, shrinking it on each rejection
920
934
    double x1, gx1;
921
    while(true) {
935
    while (true) {
922
936
      x1 = myrng.runif() * (R - L) + L;  // Sample between L and R, uniformly.
923
937
      gx1 = parameter_.LogDensity(x1);
924
      if(gx1 >= logy) {
938
      if (gx1 >= logy) {
925
939
        break;
926
940
      }
927
      
928
      if(x1 > x0) {
941
942
      if (x1 > x0) {
929
943
        R = x1;
930
      }
931
      else {
944
      } else {
932
945
        L = x1;
933
946
      }
934
947
    }
935
    
948
936
949
    // Save the point sampled
937
950
    parameter_.Save(x1);
938
951
  }
939
   
952
940
953
  void Start() {
941
954
    parameter_.Save(parameter_.StartingValue());
942
955
  }
943
956
944
957
  string ParameterLabel() {
945
      return parameter_.Label();
958
    return parameter_.Label();
946
959
  }
947
960
948
961
  string ParameterValue() {
949
      return to_csv<double>(parameter_.Value());
962
    return to_csv<double>(parameter_.Value());
950
963
  }
951
964
952
965
  bool ParameterTrack() {
953
      return parameter_.Track();
966
    return parameter_.Track();
954
967
  }
955
968
private:
956
969
  /// Parameter associated with step instance.
@@ -993,7 +1006,7 @@ public:
993
1006
    // Add step to step stack.
994
1007
    steps_.push_back(step);
995
1008
    // Add index to tracking stack, if necessary tracked.
996
    if(steps_.back().ParameterTrack()) {
1009
    if (steps_.back().ParameterTrack()) {
997
1010
      tracks_.push_back(steps_.size() - 1);
998
1011
    }
999
1012
  }
@@ -1003,18 +1016,17 @@ public:
1003
1016
   * \param progress Display a progress bar.
1004
1017
   */
1005
1018
  void Iterate(int number_of_iterations, bool progress = false) {
1006
    if(progress) {
1019
    if (progress) {
1007
1020
      boost::progress_display show_progress(number_of_iterations);
1008
      for(int iter = 0; iter < number_of_iterations; ++iter) {
1009
        for(int i = 0; i < steps_.size(); ++i) {
1021
      for (int iter = 0; iter < number_of_iterations; ++iter) {
1022
        for (int i = 0; i < steps_.size(); ++i) {
1010
1023
          steps_[i].DoStep();
1011
1024
        }
1012
1025
        ++show_progress;
1013
1026
      }
1014
    }
1015
    else {
1016
      for(int iter = 0; iter < number_of_iterations; ++iter) {
1017
        for(int i = 0; i < steps_.size(); ++i) {
1027
    } else {
1028
      for (int iter = 0; iter < number_of_iterations; ++iter) {
1029
        for (int i = 0; i < steps_.size(); ++i) {
1018
1030
          steps_[i].DoStep();
1019
1031
        }
1020
1032
      }
@@ -1028,32 +1040,31 @@ public:
1028
1040
  void Run() {
1029
1041
    // Timer
1030
1042
    boost::timer timer;
1031
    
1043
1032
1044
    // Status of sampler...
1033
1045
    cout << "Running sampler..." << endl;
1034
1046
    cout << "Number of steps added: " << NumberOfSteps() << endl;
1035
1047
    cout << "Number of tracked steps added: " << NumberOfTrackedSteps() << endl;
1036
    
1048
1037
1049
    // Opening output file
1038
1050
    cout << "Opening output file: " << out_file_ << endl;
1039
1051
    ofstream outfile(out_file_.c_str());
1040
    if(!outfile.is_open()) {
1052
    if (!outfile.is_open()) {
1041
1053
      cerr << "ERROR: Cannot open file!";
1042
1054
      exit(1);
1043
1055
    }
1044
    
1045
    for(int k = 0; k < tracks_.size(); ++k) {
1046
      if(k == tracks_.size() - 1) {
1056
1057
    for (int k = 0; k < tracks_.size(); ++k) {
1058
      if (k == tracks_.size() - 1) {
1047
1059
        outfile << steps_[tracks_[k]].ParameterLabel() << endl;
1048
      } 
1049
      else {
1060
      } else {
1050
1061
        outfile << steps_[tracks_[k]].ParameterLabel() << ",";
1051
1062
      }
1052
1063
    }
1053
1064
1054
1065
    // Setting starting value:
1055
1066
    cout << "Setting starting values..." << endl;
1056
    for(int i = 0; i < steps_.size(); ++i) {
1067
    for (int i = 0; i < steps_.size(); ++i) {
1057
1068
      steps_[i].Start();
1058
1069
    }
1059
1070
@@ -1063,23 +1074,22 @@ public:
1063
1074
1064
1075
    cout << endl << "Sampling..." << endl;
1065
1076
    boost::progress_display show_progress(sample_size_);
1066
    for(int i = 0; i < sample_size_; ++i) {
1077
    for (int i = 0; i < sample_size_; ++i) {
1067
1078
      Iterate(thin_ + 1);
1068
1079
      // Save data
1069
      for(int k = 0; k < tracks_.size(); ++k) {
1070
        if(k == tracks_.size() - 1) {
1080
      for (int k = 0; k < tracks_.size(); ++k) {
1081
        if (k == tracks_.size() - 1) {
1071
1082
          outfile << steps_[tracks_[k]].ParameterValue() << endl;
1072
        } 
1073
        else {
1083
        } else {
1074
1084
          outfile << steps_[tracks_[k]].ParameterValue() << ",";
1075
1085
        }
1076
1086
      }
1077
1087
      //Show progress
1078
1088
      ++show_progress;
1079
1089
    }
1080
    
1090
1081
1091
    outfile.close();
1082
    
1092
1083
1093
    cout << "Total elapsed time: " << timer.elapsed() << " seconds" << endl;
1084
1094
  }
1085
1095
  /*! \brief Number of steps in one sampler iteration.
@@ -1111,16 +1121,15 @@ private:
1111
1121
 *  Useful if === is too strict.
1112
1122
 */
1113
1123
bool approx_equal(double a, double b) {
1114
  return abs(a-b) <= numeric_limits<double>::epsilon() ? true : false;
1124
  return abs(a - b) <= numeric_limits<double>::epsilon() ? true : false;
1115
1125
}
1116
1126
1117
1127
/// Fast sum of log of dnorms
1118
1128
template <typename T, matrix_order PO, matrix_style PS>
1119
double sum_fast_log_dnorm(const Matrix<T,PO,PS> &A, const double mean, const double sd)
1120
{
1129
double sum_fast_log_dnorm(const Matrix<T, PO, PS> &A, const double mean, const double sd) {
1121
1130
  double result = 0;
1122
1131
1123
  for(int i = 0; i < A.size(); ++i) {
1132
  for (int i = 0; i < A.size(); ++i) {
1124
1133
    // Slower part here is A[i], can this be speed up using an iterator?
1125
1134
    result += fast_log_dnorm(A[i], mean, sd);
1126
1135
  }
@@ -1129,7 +1138,7 @@ double sum_fast_log_dnorm(const Matrix<T
1129
1138
1130
1139
/// Fast log of dnorm for mean parameter
1131
1140
double fast_log_dnorm(const double x, const double mean, const double sd) {
1132
  return -pow((x - mean),2)/(2*pow(sd,2));
1141
  return -pow((x - mean), 2) / (2*pow(sd, 2));
1133
1142
}
1134
1143
1135
1144