1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
|
#ifndef METROPHASTING_H
#define METROPHASTING_H
#include <iostream>
#include <cstdlib>
#include "chartdir.h"
#include <string>
#include <sstream>
#include <array>
#include <gsl/gsl_sf_gamma.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_blas.h>
#include <gsl/gsl_linalg.h>
#include <ctime>
#include <stdio.h>
int rmvnorm(const gsl_rng *r, const int n, const gsl_vector *mean, const gsl_matrix *var, gsl_vector *result);
double target(double x[2]);
/*
MH() is the main function
n_sim: number of simulations, pointer
mat: stores the generated samples. A matrix with dimension n_sim by 2, pointer
*/
/*In this case I have changed the datatype of n_sim from double to int
*without the pointer so double *n_sim is change to int n_sim */
void MH(const int n_sim, double * mat, double stdDev) {
//in our case the sample is 2 dimensional
int n = 2;
//define standard deviation
//double sd = 1.5;
double sd = stdDev;
//initial values are 0,0
double can[2] = { 0,0 };
double update[2], uni, accept;
int i, j;
//const gsl_rng_type * T;
gsl_rng *r = gsl_rng_alloc(gsl_rng_mt19937);
/*Define random number t-Mersenne random twister*/
//srand(time(0)); //added
long seed = (long)time(NULL);
/*Define a seed for r*-previous code was time(NULL)*/
gsl_rng_set(r, seed); /*Initiate the random number generator with seed*/
gsl_vector *mean = gsl_vector_alloc(n);
gsl_matrix *var = gsl_matrix_alloc(n, n);
gsl_vector *result = gsl_vector_alloc(n);
//set up variance matrix
gsl_matrix_set(var, 0, 0, pow(sd, 2));
gsl_matrix_set(var, 1, 1, pow(sd, 2));
gsl_matrix_set(var, 0, 1, 0);
gsl_matrix_set(var, 1, 0, 0);
//start Metropolis Hasting algorithm
for (i = 0; i < n_sim; i++) {
//set up the mean vector
gsl_vector_set(mean, 0, can[0]);
gsl_vector_set(mean, 1, can[1]);
//block update, use multivariate normal random sample generator
rmvnorm(r, n, mean, var, result);
//store the sample
for (j = 0; j < n; j++) {
update[j] = gsl_vector_get(result, j);
}
/*now calculate the acceptance rate and see whether the sample is accepted or not
*/
uni = gsl_rng_uniform(r);
accept = target(update) / target(can);
if (uni < accept) {
//if acceptance rate is large enough, accept the update
can[0] = update[0];
can[1] = update[1];
mat[2 * i] = update[0];
mat[2 * i + 1] = update[1];
//printf("\%f\t\%f\n",can[0],can[1]);
}
else {
//otherwise do not update
mat[2 * i] = can[0];
mat[2 * i + 1] = can[1];
//printf("\%f\t\%f\n",can[0],can[1]);
}
}
gsl_vector_free(result);
gsl_vector_free(mean);
}
//random multivariate normal sample generator
int rmvnorm(const gsl_rng *r, const int n, const gsl_vector *mean, const gsl_matrix *var, gsl_vector *result) {
/* multivariate normal distribution random number generator */
/*
* n dimension of the random vector
* mean vector of means of size n
* (var) variance variance matrix of dimension n x n
*result output variable with a single random vector normal distribution generation
*/
int k;
gsl_matrix *work = gsl_matrix_alloc(n, n);
gsl_matrix_memcpy(work, var);
gsl_linalg_cholesky_decomp(work);
for (k = 0; k<n; k++)
gsl_vector_set(result, k, gsl_ran_ugaussian(r));
gsl_blas_dtrmv(CblasLower, CblasNoTrans, CblasNonUnit, work, result);
gsl_vector_add(result, mean);
gsl_matrix_free(work);
return 0;
}
//the posterior PDF
double target(double x[2]) {
return exp(-pow(x[0], 2) - pow(x[1] * x[0], 2) - pow(x[1], 2));
}
#endif /*METROPHASTING_H*/
| |