⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mcmcfcds.h

📁 使用R语言的马尔科夫链蒙特卡洛模拟(MCMC)源代码程序。
💻 H
字号:
// MCMCfcds.h is the header file for MCMCfcds.cc. It contains declarations // for a number of functions that produce draws from full conditional // distributions. //// Andrew D. Martin// Dept. of Political Science// Washington University in St. Louis// admartin@wustl.edu//// Kevin M. Quinn// Dept. of Government// Harvard University// kevin_quinn@harvard.edu// // This software is distributed under the terms of the GNU GENERAL// PUBLIC LICENSE Version 2, June 1991.  See the package LICENSE// file for more information.//// Copyright (C) 2004 Andrew D. Martin and Kevin M. Quinn// // KQ 6/10/2004// DBP 7/01/2007 [ported to scythe 1.0.x (partial)]#ifndef MCMCFCDS_H#define MCMCFCDS_H#include "matrix.h"#include "rng.h"#include "stat.h"#include "smath.h"#include "ide.h"#include "la.h"#include "distributions.h"#include <iostream>using namespace std;using namespace scythe;// linear regression with Gaussian errors beta draw // (multivariate Normal prior)// regression model is y = X * beta + epsilon,  epsilon ~ N(0,sigma2)// XpX is X'X// XpY is X'y// b0 is the prior mean of beta// B0 is the prior precision (the inverse variance) of betatemplate <typename RNGTYPE>Matrix<double> NormNormregress_beta_draw (const Matrix<>& XpX, const Matrix<>& XpY,         const Matrix<>& b0, const Matrix<>& B0, double sigma2,         rng<RNGTYPE>& stream){  // this function gets the cross-product matrix X'X and the matrix X'Y  // to minimize the amount of computation within the function  const unsigned int k = XpX.cols ();  const double sig2_inv = 1.0 / sigma2;  const Matrix<> sig_beta = invpd (B0 + XpX * sig2_inv);  const Matrix<> C = cholesky (sig_beta);  const Matrix<> betahat = sig_beta * gaxpy(B0, b0, XpY*sig2_inv);  return( gaxpy(C, stream.rnorm(k,1, 0, 1), betahat) );}// linear regression with Gaussian errors sigma2 draw // (inverse-Gamma  prior)// regression model is y = X * beta + epsilon,  epsilon ~ N(0,sigma2)// c0/2 is the prior shape parameter for sigma2// d0/2 is the prior scale parameter for sigma2 template <typename RNGTYPE>doubleNormIGregress_sigma2_draw (const Matrix <> &X, const Matrix <> &Y,         const Matrix <> &beta, double c0, double d0,         rng<RNGTYPE>& stream){    const Matrix <> e = gaxpy(X, (-1*beta), Y);  const Matrix <> SSE = crossprod (e);   const double c_post = (c0 + X.rows ()) * 0.5;  const double d_post = (d0 + SSE[0]) * 0.5;  return  stream.rigamma (c_post, d_post);   }// update latent data for standard item response models// only works for 1 dimensional casetemplate <typename RNGTYPE>void irt_Z_update1 (Matrix<>& Z, const Matrix<int>& X,         const Matrix<>& theta, const Matrix<>& eta, rng<RNGTYPE>& stream){  // define constants  const unsigned int J = theta.rows();  const unsigned int K = eta.rows();    // perform update from truncated Normal / standard Normals  for (unsigned int i = 0; i < J; ++i) {    for (unsigned int j = 0; j < K; ++j){      const double Z_mean = -eta(j,0) + theta(i) * eta(j,1);      if (X(i,j) == 1) {        Z(i,j) = stream.rtbnorm_combo(Z_mean, 1.0, 0);      } else if (X(i,j) == 0) {        Z(i,j) = stream.rtanorm_combo(Z_mean, 1.0, 0);      } else {        Z(i,j) = stream.rnorm(Z_mean, 1.0);      }    }  }}// update item (case, roll call)  parameters for item response model// note: works only for one-dimensional casetemplate <typename RNGTYPE>void irt_eta_update1 (Matrix<>& eta, const Matrix<>& Z,     const Matrix<>& theta, const Matrix<>& AB0, const Matrix<>& AB0ab0,      rng<RNGTYPE>& stream){    // define constants  const unsigned int J = theta.rows();  const unsigned int K = Z.cols();  // perform update   //const Matrix<double> Ttheta_star = t(cbind(-1.0*ones<double>(J,1),theta)); // only needed for option 2  const Matrix<> tpt(2,2);  for (unsigned int i = 0; i < J; ++i) {    const double theta_i = theta(i);    tpt(0,1) -= theta_i;    tpt(1,1) += std::pow(theta_i, 2.0);  }  tpt(1,0) = tpt(0,1);  tpt(0,0) = J;  const Matrix<> eta_post_var = invpd(tpt + AB0);  const Matrix<> eta_post_C = cholesky(eta_post_var);    for (unsigned int k = 0; k < K; ++k) {        const Matrix<> TZ(2, 1);    for (unsigned int j = 0; j < J; ++j) {      TZ[0] -= Z(j,k);      TZ[1] += Z(j,k) * theta[j];    }    const Matrix<> eta_post_mean = eta_post_var * (TZ + AB0ab0);         const Matrix<> new_eta = gaxpy(eta_post_C, stream.rnorm(2, 1, 0, 1),                                    eta_post_mean);     eta(k,0) = new_eta(0);     eta(k,1) = new_eta(1);  }}// update ability parameters (ideal points) for one dimensional // item response model // note: works only for one-dimensional casetemplate <typename RNGTYPE>void irt_theta_update1 (Matrix<>& theta, const Matrix<>& Z,     const Matrix<>& eta, double t0, double T0, const Matrix<>& theta_eq,    const Matrix<>& theta_ineq, rng<RNGTYPE>& stream){    const unsigned int J = Z.rows();  const unsigned int K = Z.cols();  // perform update from multivariate Normal  const double T0t0 = T0*t0;  const Matrix<> alpha = eta(_, 0);  const Matrix<> beta =  eta(_, 1);  //const Matrix<double> tbeta = t(beta);  // only neede for option 2  //const Matrix<double> talpha = t(alpha); // only needed for option 2  // calculate the posterior variance outside the justice specific loop  double theta_post_var = T0;  for (unsigned int i = 0; i < K; ++i)    theta_post_var += std::pow(beta(i), 2.0);  theta_post_var = 1.0 / theta_post_var;  const double theta_post_sd = std::sqrt(theta_post_var);  // sample for each justice  for (unsigned int j = 0; j < J; ++j) {    // no equality constraints     if (theta_eq(j) == -999) {      double betaTZjalpha = 0;      for (unsigned int k = 0; k < K; ++k)        betaTZjalpha += beta(k) * (Z(j,k) + alpha(k));         const double theta_post_mean = theta_post_var           * (T0t0 + betaTZjalpha);        if (theta_ineq(j) == 0) { // no inequality constraint          theta(j) = theta_post_mean + stream.rnorm(0.0, theta_post_sd);         } else if (theta_ineq(j) > 0) { // theta[j] > 0          theta(j) = stream.rtbnorm_combo(theta_post_mean, theta_post_var,              0);          } else { // theta[j] < 0          theta(j) = stream.rtanorm_combo(theta_post_mean, theta_post_var,              0);  	          }    } else { // equality constraints      theta(j) = theta_eq(j);    }  } }// factor analysis model with normal mean 0, precision F0 prior on // factor scores// X follows a multivariate normal distribution// Lambda is the matrix of factor loadings// Psi_inv is the inverse of the uniqueness matrix// N is number of observations// D is the number of factors// this function draws the factor scores////                      IMPORTANT// ***********Psi_inv IS ASSUMED TO DIAGONAL ***********template <typename RNGTYPE>void NormNormfactanal_phi_draw(Matrix<> &phi,  			  const Matrix<> &F0, 			  const Matrix<> &Lambda,			  const Matrix<> &Psi_inv,			  const Matrix<> &X,			  const int& N, const int& D,			  rng <RNGTYPE>& stream){  // If Psi_inv is *not* diagonal then use:  // Matrix<double> phi_post_var = invpd(F0 + t(Lambda) * Psi_inv *   //                                     Lambda);  //Instead of the following 2 lines:   const Matrix<> AAA = scythe::sqrt(Psi_inv) * Lambda;  const Matrix<> phi_post_var = invpd(F0 + crossprod(AAA));   const Matrix<> phi_post_C = cholesky(phi_post_var);  for (int i=0; i<N; ++i){    const Matrix<> phi_post_mean = phi_post_var *       (t(Lambda) * Psi_inv * t(X(i,_)));    const Matrix<> phi_samp = gaxpy(phi_post_C, stream.rnorm(D, 1, 0.0, 1.0), 				    phi_post_mean);     for (int j=0; j<D; ++j)      phi(i,j) = phi_samp(j);  }    }// samples the Psi matrix for a Normal theory factor model with IG // prior on diag elements of Psitemplate <typename RNGTYPE>void NormIGfactanal_Psi_draw(Matrix<> &Psi, const Matrix<> &X,			const Matrix<> &phi, 			const Matrix<> &Lambda,			const Matrix<> &a0,			const Matrix<> &b0,			const int& K, const int& N,			rng<RNGTYPE>& stream){  for (int i=0; i<K; ++i){    const Matrix<double> epsilon = gaxpy(phi, -1*(t(Lambda(i,_))), X(_,i));    const Matrix<double>  SSE = crossprod(epsilon);    const double a1 = (a0[i] + N)*0.5;    const double b1 = (b0[i] + SSE[0])*0.5;    Psi(i,i) = stream.rigamma(a1, b1);  }    }// Psi_inv assumed diagnonal// this function draws the factor loading matrixtemplate <typename RNGTYPE>void NormNormfactanal_Lambda_draw(Matrix<>& Lambda, 			     const Matrix<bool> &Lambda_free_indic,			     const Matrix<> &Lambda_prior_mean,			     const Matrix<> &Lambda_prior_prec,			     const Matrix<> &phi,			     const Matrix<> &X,			     const Matrix<> &Psi_inv,			     const Matrix<> &Lambda_ineq,			     const unsigned int D, const unsigned int K,            rng<RNGTYPE>& stream){  for (unsigned int i = 0; i < K; ++i) {    const Matrix<bool> free_indic = t(Lambda_free_indic(i,_));    // end replacement    if (sumc(free_indic)(0) > 0 && sumc(! free_indic)(0) > 0) {       // both constrnd & unconstrnd      const Matrix<> phifree_i =  t(selif(t(phi), free_indic));      const Matrix<> mulamfree_i = selif(t(Lambda_prior_mean(i,_)), 					 free_indic); // prior mean      const Matrix<> hold = selif(t(Lambda_prior_prec(i,_)), 				  free_indic);       Matrix<> sig2lamfree_inv_i 	= eye<double>(hold.rows()); // prior prec				      for (unsigned int j = 0; j < (hold.rows()); ++j)	sig2lamfree_inv_i(j,j) = hold[j];      const Matrix<> Lambdacon_i = selif(t(Lambda(i,_)), ! free_indic);       const Matrix<> phicon_i  = t(selif(t(phi), ! free_indic));      const Matrix<> newX_i = gaxpy((-1.0*phicon_i), Lambdacon_i, 				    X(_,i));      const Matrix<> Lam_post_var = invpd(sig2lamfree_inv_i + 					  Psi_inv(i,i) * crossprod(phifree_i));      const Matrix<> Lam_post_C = cholesky(Lam_post_var);      const Matrix<> Lam_post_mean = Lam_post_var * 	(sig2lamfree_inv_i * mulamfree_i + Psi_inv(i,i) * 	 t(phifree_i) * newX_i);				      Matrix<> Lambdafree_i = 	gaxpy(Lam_post_C, stream.rnorm(hold.rows(), 1, 0, 1),Lam_post_mean);                  // check to see if inequality constraints hold      const Matrix<> Lambda_ineq_vec = Lambda_ineq(i,_);      double ineq_holds = 0;      int Lam_count = 0;      for (unsigned int j = 0; j < D; ++j) {	if (free_indic(j)){ 	  ineq_holds = std::min(ineq_holds, Lambda_ineq_vec(j) * 				Lambdafree_i(Lam_count)); 	  ++Lam_count;	}      }      while (ineq_holds < 0) {	Lambdafree_i = gaxpy(Lam_post_C, stream.rnorm(hold.rows(), 1, 0, 1),			     Lam_post_mean);	Lam_count = 0;	double test = 0;	for (unsigned int j = 0; j < D; ++j) {	  if (free_indic(j) == 1) {	    Matrix<> prodcheck = Lambda_ineq_vec(j) 	      * Lambdafree_i(Lam_count);	    test = std::min(test, prodcheck(0));	    ++Lam_count;	  }	} 	ineq_holds = test;       }      // put draw into Lambda      Lam_count = 0;      for (unsigned int j = 0; j < D; ++j) { 	if (free_indic(j) == 1) {	  Lambda(i,j) = Lambdafree_i(Lam_count);	  ++Lam_count; 	}       }    } else  if (sumc(free_indic)(0) > 0) { // just unconstrained      const Matrix<> phifree_i =  t(selif(t(phi), free_indic));      const Matrix<> mulamfree_i = selif(t(Lambda_prior_mean(i,_)), 					 free_indic); // prior mean      const Matrix<> hold = selif(t(Lambda_prior_prec(i,_)), free_indic);      Matrix<> sig2lamfree_inv_i = eye<double>(hold.rows()); // prior prec			      for (unsigned int j = 0; j < hold.rows(); ++j)	sig2lamfree_inv_i(j,j) = hold(j); 			      const Matrix<> Lam_post_var = invpd(sig2lamfree_inv_i + 					  Psi_inv(i,i) * crossprod(phifree_i));      const Matrix<> Lam_post_C = cholesky(Lam_post_var);      const Matrix<> Lam_post_mean = Lam_post_var * (sig2lamfree_inv_i 						     * mulamfree_i + 						     Psi_inv(i,i) * 						     t(phifree_i) * X(_,i));      Matrix<> Lambdafree_i = gaxpy(Lam_post_C, 				    stream.rnorm(hold.rows(), 1, 0, 1), 				    Lam_post_mean);      // check to see if inequality constraints hold      Matrix<> Lambda_ineq_vec = Lambda_ineq(i,_);       double ineq_holds = 0;      for (unsigned int j = 0; j < D; ++j) { 	ineq_holds = std::min(ineq_holds, Lambda_ineq_vec(j)			      * Lambdafree_i(j));       } 			      while (ineq_holds < 0) {	Lambdafree_i = gaxpy(Lam_post_C, stream.rnorm(hold.rows(), 1, 0, 1),			     Lam_post_mean); 	double test = 0; 	for (unsigned int j = 0; j < D; ++j) { 	  //if (free_indic[j]==1) 	  double prodcheck = Lambda_ineq_vec[j]*Lambdafree_i[j]; 	  test = std::min(test, prodcheck);	} 					ineq_holds = test;       }      // put draw into Lambda       for (unsigned int j = 0; j < D; ++j) { 	Lambda(i,j) = Lambdafree_i(j);       }    }  }        //    return(Lambda);}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -