1 //////////////////////////////////////////////////////////////////////////
2 // cMCMCpoisson.cc is C++ code to estimate a Poisson regression model with
3 //   a multivariate normal prior
4 //
5 // Andrew D. Martin
6 // Dept. of Political Science
7 // Washington University in St. Louis
8 // admartin@wustl.edu
9 //
10 // Kevin M. Quinn
11 // Dept. of Government
12 // Harvard University
13 // kevin_quinn@harvard.edu
14 //
15 // This software is distributed under the terms of the GNU GENERAL
16 // PUBLIC LICENSE Version 2, June 1991.  See the package LICENSE
17 // file for more information.
18 //
19 // updated to the new version of Scythe 7/26/2004 KQ
20 // updated to Scythe 1.0.X 7/7/2007 ADM
21 //
22 // Copyright (C) 2003-2007 Andrew D. Martin and Kevin M. Quinn
23 // Copyright (C) 2007-present Andrew D. Martin, Kevin M. Quinn,
24 //    and Jong Hee Park
25 //////////////////////////////////////////////////////////////////////////
26 
27 
28 #ifndef CMCMCPOISSON_CC
29 #define CMCMCPOISSON_CC
30 
31 #include "MCMCrng.h"
32 #include "MCMCfcds.h"
33 #include "matrix.h"
34 #include "distributions.h"
35 #include "stat.h"
36 #include "la.h"
37 #include "ide.h"
38 #include "smath.h"
39 #include "rng.h"
40 #include "mersenne.h"
41 #include "lecuyer.h"
42 
43 #include <R.h>           // needed to use Rprintf()
44 #include <R_ext/Utils.h> // needed to allow user interrupts
45 
46 using namespace std;
47 using namespace scythe;
48 
poisson_logpost(const Matrix<> & Y,const Matrix<> & X,const Matrix<> & beta,const Matrix<> & beta_prior_mean,const Matrix<> & beta_prior_prec)49 static double poisson_logpost(const Matrix<>& Y,
50 			      const Matrix<>& X,
51 			      const Matrix<>& beta,
52 			      const Matrix<>& beta_prior_mean,
53 			      const Matrix<>& beta_prior_prec){
54 
55   // likelihood
56   const Matrix<> eta = X * beta;
57   const Matrix<> mu = exp(eta);
58   double loglike = 0.0;
59   for (unsigned int i=0; i<Y.rows(); ++i)
60     loglike += -mu[i] + Y[i] * eta[i];
61 
62   // prior
63   double logprior = 0.0;
64   if (beta_prior_prec(0,0) != 0){
65     logprior = lndmvn(beta, beta_prior_mean, invpd(beta_prior_prec));
66   }
67 
68   return (loglike + logprior);
69 }
70 
71 
72 /* MCMCpoisson implementation.  Takes Matrix<> reference and fills with the
73  * posterior.
74  */
75 template <typename RNGTYPE>
MCMCpoisson_impl(rng<RNGTYPE> & stream,const Matrix<> & Y,const Matrix<> & X,const Matrix<> & tune,Matrix<> & beta,const Matrix<> & b0,const Matrix<> & B0,const Matrix<> & V,unsigned int burnin,unsigned int mcmc,unsigned int thin,unsigned int verbose,Matrix<> & result)76 void MCMCpoisson_impl (rng<RNGTYPE>& stream, const Matrix<>& Y,
77 		       const Matrix<>& X, const Matrix<>& tune, Matrix<>& beta, const Matrix<>& b0,
78 		       const Matrix<>& B0,  const Matrix<>& V, unsigned int burnin,
79 		       unsigned int mcmc, unsigned int thin, unsigned int verbose,  Matrix<>& result) {
80 
81   // define constants
82   const unsigned int tot_iter = burnin + mcmc;  // total number iterations
83   const unsigned int nstore = mcmc / thin;      // number of draws to store
84   const unsigned int k = X.cols();
85 
86   // storage matrix or matrices
87   Matrix<> storemat(nstore, k);
88 
89   // proposal parameters
90   const Matrix<> propV = tune * invpd(B0 + invpd(V)) * tune;
91   const Matrix<> propC = cholesky(propV) ;
92 
93   double logpost_cur = poisson_logpost(Y, X, beta, b0, B0);
94 
95   // MCMC loop
96   int count = 0;
97   int accepts = 0;
98   for (unsigned int iter = 0; iter < tot_iter; ++iter){
99 
100     // sample beta
101     const Matrix<> beta_can = gaxpy(propC, stream.rnorm(k,1,0,1), beta);
102     const double logpost_can = poisson_logpost(Y,X,beta_can, b0, B0);
103     const double ratio = ::exp(logpost_can - logpost_cur);
104 
105     if (stream.runif() < ratio){
106       beta = beta_can;
107       logpost_cur = logpost_can;
108       ++accepts;
109     }
110 
111     // store values in matrices
112     if (iter >= burnin && (iter % thin==0)){
113       storemat(count,_) = beta;
114       ++count;
115     }
116 
117     // print output to stdout
118     if(verbose > 0 && iter % verbose == 0){
119       Rprintf("\n\nMCMCpoisson iteration %i of %i \n", (iter+1), tot_iter);
120       Rprintf("beta = \n");
121       for (unsigned int j=0; j<k; ++j)
122 	Rprintf("%10.5f\n", beta[j]);
123       Rprintf("Metropolis acceptance rate for beta = %3.5f\n\n",
124 	      static_cast<double>(accepts) /
125 	      static_cast<double>(iter+1));
126     }
127 
128     R_CheckUserInterrupt(); // allow user interrupts
129   }// end MCMC loop
130 
131   result = storemat;
132   if (verbose > 0){
133     Rprintf("\n\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
134     Rprintf("The Metropolis acceptance rate for beta was %3.5f",
135 	    static_cast<double>(accepts) / static_cast<double>(tot_iter));
136     Rprintf("\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
137   }
138 }
139 extern "C"{
cMCMCpoisson(double * sampledata,const int * samplerow,const int * samplecol,const double * Ydata,const int * Yrow,const int * Ycol,const double * Xdata,const int * Xrow,const int * Xcol,const int * burnin,const int * mcmc,const int * thin,const double * tunedata,const int * tunerow,const int * tunecol,const int * uselecuyer,const int * seedarray,const int * lecuyerstream,const int * verbose,const double * betastartdata,const int * betastartrow,const int * betastartcol,const double * b0data,const int * b0row,const int * b0col,const double * B0data,const int * B0row,const int * B0col,const double * Vdata,const int * Vrow,const int * Vcol)140   void cMCMCpoisson(double *sampledata, const int *samplerow,
141 		   const int *samplecol, const double *Ydata,
142 		   const int *Yrow, const int *Ycol, const double *Xdata,
143 		   const int *Xrow, const int *Xcol, const int *burnin,
144 		   const int *mcmc, const int *thin, const double *tunedata,
145 		   const int *tunerow, const int *tunecol, const int *uselecuyer,
146 		   const int *seedarray, const int *lecuyerstream,
147 		   const int *verbose, const double *betastartdata,
148 		   const int *betastartrow, const int *betastartcol,
149 		   const double *b0data, const int *b0row, const int *b0col,
150 		   const double *B0data, const int *B0row, const int *B0col,
151 		   const double *Vdata, const int *Vrow, const int *Vcol) {
152 
153    // pull together Matrix objects
154     const Matrix <> Y(*Yrow, *Ycol, Ydata);
155     const Matrix <> X(*Xrow, *Xcol, Xdata);
156     const Matrix <> tune(*tunerow, *tunecol, tunedata);
157     Matrix <> beta(*betastartrow, *betastartcol,
158       betastartdata);
159     const Matrix <> b0(*b0row, *b0col, b0data);
160     const Matrix <> B0(*B0row, *B0col, B0data);
161     const Matrix <> V(*Vrow, *Vcol, Vdata);
162 
163     Matrix<> storagematrix;
164     MCMCPACK_PASSRNG2MODEL(MCMCpoisson_impl, Y, X, tune, beta, b0, B0,
165 			   V, *burnin, *mcmc, *thin, *verbose, storagematrix);
166 
167    const unsigned int size = *samplerow * *samplecol;
168    for (unsigned int i=0; i<size; ++i)
169      sampledata[i] = storagematrix(i);
170   }
171 }
172 
173 #endif
174