1 #include "bayesm.h"
2 
3 //Used in rmvpGibbs and rmnpGibbs---------------------------------------------------------------------------------
condmom(vec const & x,vec const & mu,mat const & sigmai,int p,int j)4 vec condmom(vec const& x, vec const& mu, mat const& sigmai, int p, int j){
5 
6 // Wayne Taylor 9/24/2014
7 
8 //function to compute moments of x[j] | x[-j]
9 //output is a vec: the first element is the conditional mean
10 //                 the second element is the conditional sd
11 
12   vec out(2);
13   int jm1 = j-1;
14   int ind = p*jm1;
15 
16   double csigsq = 1/sigmai(ind+jm1);
17   double m = 0.0;
18 
19   for(int i = 0; i<p; i++) if (i!=jm1) m += - csigsq*sigmai(ind+i)*(x[i]-mu[i]);
20 
21   out[0] = mu[jm1]+m;
22   out[1] = sqrt(csigsq);
23 
24   return (out);
25 }
26 
rtrun1(double mu,double sigma,double trunpt,int above)27 double rtrun1(double mu, double sigma, double trunpt, int above) {
28 
29 // Wayne Taylor 9/8/2014
30 
31 //function to draw truncated normal
32 //above=1 means from above b=trunpt, a=-inf
33 //above=0 means from below a=trunpt, b= +inf
34 //modified by rossi 6/05 to check arg to qnorm
35 
36 	double FA,FB,rnd,result,arg;
37 	if (above) {
38 		FA = 0.0; FB = R::pnorm(((trunpt-mu)/(sigma)),0.0,1.0,1,0);
39 	} else {
40 		FB = 1.0; FA = R::pnorm(((trunpt-mu)/(sigma)),0.0,1.0,1,0);
41 	}
42 
43   rnd = runif(1)[0]; //runif returns a NumericVector, so using [0] allows for conversion to double
44 	arg = rnd*(FB-FA)+FA;
45 	if(arg > .999999999) arg = .999999999;
46 	if(arg < .0000000001) arg = .0000000001;
47 	result = mu + sigma*R::qnorm(arg,0.0,1.0,1,0);
48 
49 	return (result);
50 }
51 
52 //Used in rhierLinearModel, rhierLinearMixture and rhierMnlRWMixture------------------------------------------------------
drawDelta(mat const & x,mat const & y,vec const & z,List const & comps,vec const & deltabar,mat const & Ad)53 mat drawDelta(mat const& x,mat const& y,vec const& z,List const& comps,vec const& deltabar,mat const& Ad){
54 
55   // Wayne Taylor 10/01/2014
56 
57   // delta = vec(D)
58   //  given z and comps (z[i] gives component indicator for the ith observation,
59   //   comps is a list of mu and rooti)
60   // y is n x p
61   // x is n x k
62   // y = xD' + U , rows of U are indep with covs Sigma_i given by z and comps
63 
64   int p = y.n_cols;
65   int k = x.n_cols;
66   int ncomp  = comps.length();
67   mat xtx = zeros<mat>(k*p,k*p);
68   mat xty = zeros<mat>(p,k); //this is the unvecced version, reshaped after the sum
69 
70   //Create the index vectors, the colAll vectors are equal to span::all but with uvecs (as required by .submat)
71   uvec colAlly(p), colAllx(k);
72   for(int i = 0; i<p; i++) colAlly(i) = i;
73   for(int i = 0; i<k; i++) colAllx(i) = i;
74 
75   //Loop through the components
76   for(int compi = 0; compi<ncomp; compi++){
77 
78     //Create an index vector ind, to be used like y[ind,]
79     uvec ind = find(z == (compi+1));
80 
81     //If there are observations in this component
82     if(ind.size()>0){
83       mat yi = y.submat(ind,colAlly);
84       mat xi = x.submat(ind,colAllx);
85 
86       List compsi = comps[compi];
87       rowvec mui = as<rowvec>(compsi[0]); //conversion from Rcpp to Armadillo requires explict declaration of variable type using as<>
88       mat rootii = trimatu(as<mat>(compsi[1])); //trimatu interprets the matrix as upper triangular
89       yi.each_row() -= mui; //subtracts mui from each row of yi
90       mat sigi = rootii*trans(rootii);
91       xtx = xtx + kron(trans(xi)*xi,sigi);
92       xty = xty + (sigi * (trans(yi)*xi));
93     }
94   }
95   xty.reshape(xty.n_rows*xty.n_cols,1);
96 
97   //vec(t(D)) ~ N(V^{-1}(xty + Ad*deltabar),V^{-1}) where V = (xtx+Ad)
98   // compute the inverse of xtx+Ad
99   mat ucholinv = solve(trimatu(chol(xtx+Ad)), eye(k*p,k*p)); //trimatu interprets the matrix as upper triangular and makes solve more efficient
100   mat Vinv = ucholinv*trans(ucholinv);
101 
102   return(Vinv*(xty+Ad*deltabar) + trans(chol(Vinv))*as<vec>(rnorm(deltabar.size())));
103 }
104 
runiregG(vec const & y,mat const & X,mat const & XpX,vec const & Xpy,double sigmasq,mat const & A,vec const & Abetabar,double nu,double ssq)105 unireg runiregG(vec const& y, mat const& X, mat const& XpX, vec const& Xpy, double sigmasq, mat const& A,
106               vec const& Abetabar, double nu, double ssq) {
107 
108 // Keunwoo Kim 09/16/2014
109 
110 // Purpose:
111 //  perform one Gibbs iteration for Univ Regression Model
112 //  only does one iteration so can be used in rhierLinearModel
113 
114 // Model:
115 //  y = Xbeta + e  e ~N(0,sigmasq)
116 //  y is n x 1
117 //  X is n x k
118 //  beta is k x 1 vector of coefficients
119 
120 // Prior:
121 //  beta ~ N(betabar,A^-1)
122 //  sigmasq ~ (nu*ssq)/chisq_nu
123 
124   unireg out_struct;
125 
126   int n = y.size();
127   int k = XpX.n_cols;
128 
129   //first draw beta | sigmasq
130   mat IR = solve(trimatu(chol(XpX/sigmasq+A)), eye(k,k)); //trimatu interprets the matrix as upper triangular and makes solve more efficient
131   vec btilde = (IR*trans(IR)) * (Xpy/sigmasq + Abetabar);
132   vec beta = btilde + IR*vec(rnorm(k));
133 
134   //now draw sigmasq | beta
135   double s = sum(square(y-X*beta));
136   sigmasq = (s + nu*ssq)/rchisq(1,nu+n)[0]; //rchisq returns a vectorized object, so using [0] allows for the conversion to double
137 
138   out_struct.beta = beta;
139   out_struct.sigmasq = sigmasq;
140 
141   return (out_struct);
142 }
143 
144 //Used in rnegbinRW and rhierNegbinRw-------------------------------------------------------------------------------------
llnegbin(vec const & y,vec const & lambda,double alpha,bool constant)145 double llnegbin(vec const& y, vec const& lambda, double alpha, bool constant){
146 
147 // Keunwoo Kim 11/02/2014
148 
149 // Computes the log-likelihood
150 
151 // Arguments
152 //      y - a vector of observation
153 //      lambda - a vector of mean parameter (=exp(X*beta))
154 //      alpha - dispersion parameter
155 //      constant - TRUE(FALSE) if it computes (un)normalized log-likeihood
156 
157 // PMF
158 //      pmf(y) = (y+alpha-1)Choose(y) * p^alpha * (1-p)^y
159 //      (y+alpha-1)Choose(y) = (alpha)*(alpha+1)*...*(alpha+y-1) / y! when y>=1 (0 when y=0)
160 
161   int i;
162   int nobs = y.size();
163   vec prob = alpha/(alpha+lambda);
164   vec logp(nobs);
165   if (constant){
166     // normalized log-likelihood
167     for (i=0; i<nobs; i++){
168       // the fourth argument "1" indicates log-density
169       logp[i] = R::dnbinom(y[i], alpha, prob[i], 1);
170     }
171   }else{
172     // unnormalized log-likelihood
173     logp = sum(alpha*log(prob) + y % log(1-prob)); //% does element-wise multiplication
174   }
175   return (sum(logp));
176 }
177 
lpostbeta(double alpha,vec const & beta,mat const & X,vec const & y,vec const & betabar,mat const & rootA)178 double lpostbeta(double alpha, vec const& beta, mat const& X, vec const& y, vec const& betabar, mat const& rootA){
179 
180 // Keunwoo Kim 11/02/2014
181 
182 // Computes log posterior for beta | alpha
183 
184 // Arguments
185 //        alpha - dispersion parameter of negative-binomial
186 //        beta - parameter of our interests
187 //        X, y - observation from data
188 //        betabar - mean of beta prior
189 //        rootA - t(rootA)%*%rootA = A (A^-1 is var-cov matrix of beta prior)
190 
191 // Prior
192 //        beta ~ N(betabar, A^-1)
193 
194   vec lambda = exp(X*beta);
195   double ll = llnegbin(y, lambda, alpha, FALSE);
196 
197   // unormalized prior
198   vec z = rootA*(beta-betabar);
199   double lprior = - 0.5*sum(z%z);
200 
201   return (ll+lprior);
202 }
203 
lpostalpha(double alpha,vec const & beta,mat const & X,vec const & y,double a,double b)204 double lpostalpha(double alpha, vec const& beta, mat const& X, vec const& y, double a, double b){
205 
206 // Keunwoo Kim 11/02/2014
207 
208 // Computes log posterior for alpha | beta
209 
210 // Arguments
211 //        alpha - dispersion parameter of negative-binomial
212 //        beta - parameter of our interests
213 //        X, y - observation from data
214 //        a,b - parameters for Gamma distribution, alpha prior
215 
216 // Prior
217 //        alpha ~ Gamma(a,b)
218 //        pdf(alpha) = b^a / Gamma(a) * alpha^(a-1) * e^(b*alpha)
219 
220   vec lambda = exp(X*beta);
221   double ll = llnegbin(y, lambda, alpha, TRUE);
222   // unormalized prior
223   double lprior = (a-1)*log(alpha) - b*alpha;
224 
225   return (ll+lprior);
226 }
227 
228 //Used in rbprobitGibbs and rordprobitGibbs-----------------------------------------------------------------------
breg1(mat const & root,mat const & X,vec const & y,vec const & Abetabar)229 vec breg1(mat const& root, mat const& X, vec const& y, vec const& Abetabar) {
230 
231 // Keunwoo Kim 06/20/2014
232 
233 // Purpose: draw from posterior for linear regression, sigmasq=1.0
234 
235 // Arguments:
236 //  root = chol((X'X+A)^-1)
237 //  Abetabar = A*betabar
238 
239 // Output: draw from posterior
240 
241 // Model: y = Xbeta + e  e ~ N(0,I)
242 
243 // Prior: beta ~ N(betabar,A^-1)
244 
245   mat cov = trans(root)*root;
246 
247   return (cov*(trans(X)*y+Abetabar) + trans(root)*vec(rnorm(root.n_cols)));
248 }
249 
rtrunVec(vec const & mu,vec const & sigma,vec const & a,vec const & b)250 vec rtrunVec(vec const& mu,vec const& sigma, vec const& a, vec const& b){
251 
252 // Keunwoo Kim 06/20/2014
253 
254 //function to draw from univariate truncated norm
255 //a is vector of lower bounds for truncation
256 //b is vector of upper bounds for truncation
257 
258   int n = mu.size();
259   vec FA(n);
260   vec FB(n);
261   vec out(n);
262   for (int i=0; i<n; i++) {
263     FA[i] = R::pnorm((a[i]-mu[i])/sigma[i],0,1,1,0);
264     FB[i] = R::pnorm((b[i]-mu[i])/sigma[i],0,1,1,0);
265     out[i] = mu[i]+sigma[i]*R::qnorm(R::runif(0,1)*(FB[i]-FA[i])+FA[i],0,1,1,0);
266   }
267 
268   return(out);
269 }
270 
271 //Used in rhierMnlDP and rhierMnlRwMixture------------------------------------------------------------------------
mnlMetropOnce(vec const & y,mat const & X,vec const & oldbeta,double oldll,double s,mat const & incroot,vec const & betabar,mat const & rootpi)272 mnlMetropOnceOut mnlMetropOnce(vec const& y, mat const& X, vec const& oldbeta,
273                                                  double oldll,double s, mat const& incroot,
274                                                  vec const& betabar, mat const& rootpi){
275 // Wayne Taylor 10/01/2014
276 
277 // function to execute rw metropolis for the MNL
278 // y is n vector with element = 1,...,j indicating which alt chosen
279 // X is nj x k matrix of xvalues for each of j alt on each of n occasions
280 // RW increments are N(0,s^2*t(inc.root)%*%inc.root)
281 // prior on beta is N(betabar,Sigma)  Sigma^-1=rootpi*t(rootpi)
282 //  inc.root, rootpi are upper triangular
283 //  this means that we are using the UL decomp of Sigma^-1 for prior
284 // oldbeta is the current
285 
286 
287 mnlMetropOnceOut metropout_struct;
288 
289 double unif;
290 vec betadraw, alphaminv;
291 
292 int stay = 0;
293 vec betac = oldbeta + s*trans(incroot)*as<vec>(rnorm(X.n_cols));
294 double cll = llmnl(betac,y,X);
295 double clpost = cll+lndMvn(betac,betabar,rootpi);
296 double ldiff = clpost-oldll-lndMvn(oldbeta,betabar,rootpi);
297 alphaminv << 1 << exp(ldiff);
298 double alpha = min(alphaminv);
299 
300      if(alpha < 1) {
301        unif = runif(1)[0]; //runif returns a NumericVector, so using [0] allows for conversion to double
302       } else {
303         unif=0;}
304      if (unif <= alpha) {
305        betadraw = betac;
306        oldll = cll;
307       } else {
308         betadraw = oldbeta;
309         stay = 1;
310       }
311 
312 metropout_struct.betadraw = betadraw;
313 metropout_struct.stay = stay;
314 metropout_struct.oldll = oldll;
315 
316 return (metropout_struct);
317 }
318 
319 //Used in rDPGibbs, rhierMnlDP, rivDP-----------------------------------------------------------------------------
rmultinomF(vec const & p)320 int rmultinomF(vec const& p){
321 
322 // Wayne Taylor 1/28/2015
323 
324   vec csp = cumsum(p);
325   double rnd = runif(1)[0]; //runif returns a NumericVector, so using [0] allows for conversion to double
326   int res = 0;
327   int psize = p.size();
328 
329   for(int i = 0; i < psize; i++){
330     if(rnd > csp[i]) res = res+1;
331   }
332 
333   return(res+1);
334 }
335 
yden(std::vector<murooti> const & thetaStar_vector,mat const & y)336 mat yden(std::vector<murooti> const& thetaStar_vector, mat const& y){
337 
338 // Wayne Taylor 2/4/2015
339 
340 // function to compute f(y | theta)
341 // computes f for all values of theta in theta list of lists
342 
343 // arguments:
344 //  thetaStar is a list of lists.  thetaStar[[i]] is a list with components, mu, rooti
345 //  y |theta[[i]] ~ N(mu,(rooti %*% t(rooti))^-1)  rooti is inverse of Chol root of Sigma
346 
347 // output:
348 //  length(thetaStar) x n array of values of f(y[j,]|thetaStar[[i]]
349 
350   int nunique = thetaStar_vector.size();
351   int n = y.n_rows;
352   int k = y.n_cols;
353   mat ydenmat = zeros<mat>(nunique,n);
354 
355   vec mu;
356   mat rooti, transy, quads;
357 
358   for(int i = 0; i < nunique; i++){
359     //now compute vectorized version of lndMvn
360     //compute y_i'RIRI'y_i for all i
361 
362     mu = thetaStar_vector[i].mu;
363     rooti = thetaStar_vector[i].rooti;
364 
365     transy = trans(y);
366     transy.each_col() -= mu; //column-wise subtraction
367 
368     quads = sum(square(trans(rooti) * transy),0); //same as colSums
369     ydenmat(i,span::all) = exp(-(k/2.0)*log(2*M_PI) + sum(log(rooti.diag())) - .5*quads);
370   }
371 
372   return(ydenmat);
373 }
374 
numcomp(ivec const & indic,int k)375 ivec numcomp(ivec const& indic, int k){
376 
377 // Wayne Taylor 1/28/2015
378 
379   //find the number of times each of k integers is in the vector indic
380   ivec ncomp(k);
381 
382   for(int comp = 0; comp < k; comp++){
383     ncomp[comp]=sum(indic == (comp+1));
384   }
385 
386   return(ncomp);
387 }
388 
thetaD(mat const & y,lambda const & lambda_struct)389 murooti thetaD(mat const& y, lambda const& lambda_struct){
390 
391 // Wayne Taylor 2/4/2015
392 
393 // function to draw from posterior of theta given data y and base prior G0(lambda)
394 
395 // here y ~ N(mu,Sigma)
396 // theta = list(mu=mu,rooti=chol(Sigma)^-1)
397 // mu|Sigma ~ N(mubar,Sigma (x) Amu-1)
398 // Sigma ~ IW(nu,V)
399 
400 // arguments:
401 //  y is n x k matrix of obs
402 //  lambda is list(mubar,Amu,nu,V)
403 
404 // output:
405 //  one draw of theta, list(mu,rooti)
406 //  Sigma=inv(rooti)%*%t(inv(rooti))
407 
408 // note: we assume that y is a matrix. if there is only one obs, y is a 1 x k matrix
409 
410   mat X = ones<mat>(y.n_rows,1);
411   mat A(1,1); A.fill(lambda_struct.Amu);
412 
413   List rout = rmultireg(y,X,trans(lambda_struct.mubar),A,lambda_struct.nu,lambda_struct.V);
414 
415   murooti out_struct;
416     out_struct.mu = as<vec>(rout["B"]); //conversion from Rcpp to Armadillo requires explict declaration of variable type using as<>
417     out_struct.rooti = solve(chol(trimatu(as<mat>(rout["Sigma"]))),eye(y.n_cols,y.n_cols)); //trimatu interprets the matrix as upper triangular and makes solve more efficient
418 
419   return(out_struct);
420 }
421 
thetaStarDraw(ivec indic,std::vector<murooti> thetaStar_vector,mat const & y,mat ydenmat,vec const & q0v,double alpha,lambda const & lambda_struct,int maxuniq)422 thetaStarIndex thetaStarDraw(ivec indic, std::vector<murooti> thetaStar_vector, mat const& y, mat ydenmat, vec const& q0v, double alpha,
423                         lambda const& lambda_struct, int maxuniq) {
424 
425 // Wayne Taylor 2/4/2015
426 
427 // indic is n x 1 vector of indicator of which of thetaStar is assigned to each observation
428 // thetaStar is list of the current components (some of which may never be used)
429 // y is n x d matrix of observations
430 // ydenmat is maxuniq x n matrix to store density evaluations - we assume first
431 // length(Thetastar) rows are filled in with density evals
432 // q0v is vector of bayes factors for new component and each observation
433 // alpha is DP process tightness prior
434 // lambda is list of priors for the base DP process measure
435 // maxuniq maximum number of mixture components
436 // yden is function to fill out an array
437 // thetaD is function to draw theta from posterior of theta given y and G0
438 
439   int n = indic.size();
440   ivec ncomp, indicC;
441   int k, inc, cntNonzero;
442   std::vector<murooti> listofone_vector(1);
443   std::vector<murooti> thetaStarC_vector;
444 
445   //draw theta_i given theta_-i
446   for(int i = 0; i<n; i++){
447    k = thetaStar_vector.size();
448    vec probs(k+1);
449    probs[k] = q0v[i]*(alpha/(alpha+(n-1)));
450 
451    //same as to indicmi = indic[-i]
452    ivec indicmi = zeros<ivec>(n-1);
453    inc = 0;
454    for(int j = 0; j<(n-1); j++){
455      if(j == i) {inc = inc + 1;}
456      indicmi[j] = indic[inc];
457      inc = inc+1;
458    }
459 
460    ncomp = numcomp(indicmi,k);
461 
462    for(int comp = 0; comp<k; comp++){
463      probs[comp] = ydenmat(comp,i)*ncomp[comp]/(alpha+(n-1));
464    }
465 
466    probs = probs/sum(probs);
467    indic[i] = rmultinomF(probs);
468 
469    if(indic[i] == (k+1)){
470      if((k+1) > maxuniq) {
471         stop("max number of comps exceeded");
472      } else {
473       listofone_vector[0] = thetaD(y(i,span::all),lambda_struct);
474       thetaStar_vector.push_back(listofone_vector[0]);
475       ydenmat(k,span::all) = yden(listofone_vector,y);
476     }}
477   }
478 
479   //clean out thetaStar of any components which have zero observations associated with them
480   //and re-write indic vector
481   k = thetaStar_vector.size();
482   indicC = zeros<ivec>(n);
483   ncomp = numcomp(indic,k);
484 
485   cntNonzero = 0;
486   for(int comp = 0; comp<k; comp++){
487    if(ncomp[comp] != 0){
488      thetaStarC_vector.push_back(thetaStar_vector[comp]);
489      cntNonzero=cntNonzero+1;
490    for(int i = 0; i<n; i++){if(indic[i] == (comp+1)) indicC[i] = cntNonzero;} //same as indicC(indic==comp) = cntNonzero;
491    }
492   }
493 
494   thetaStarIndex out_struct;
495     out_struct.indic = indicC;
496     out_struct.thetaStar_vector = thetaStarC_vector;
497 
498   return(out_struct);
499 }
500 
q0(mat const & y,lambda const & lambda_struct)501 vec q0(mat const& y, lambda const& lambda_struct){
502 
503 // Wayne Taylor 2/4/2015
504 
505 // function to compute a vector of int f(y[i]|theta) p(theta|lambda)dlambda
506 // here p(theta|lambda) is G0 the base prior
507 
508 // implemented for a multivariate normal data density and standard conjugate prior:
509 //  theta=list(mu,Sigma)
510 //  f(y|theta,eta) is N(mu,Sigma)
511 //  lambda=list(mubar,Amu,nu,V)
512 //    mu|Sigma ~ N(mubar,Sigma (x) Amu^-1)
513 //    Sigma ~ IW(nu,V)
514 
515 // arguments:
516 //  Y is n x k matrix of observations
517 //  lambda=list(mubar,Amu,nu,V)
518 
519 // output:
520 //  vector of q0 values for each obs (row of Y)
521 
522 // p. rossi 12/05
523 //  here y is matrix of observations (each row is an obs)
524 
525   int k = y.n_cols;
526   mat R = chol(lambda_struct.V);
527   double logdetR = sum(log(R.diag()));
528   double lnk1k2, constant;
529   mat transy, m, vivi, lnq0v;
530 
531   if (k > 1) {
532     vec km1(k-1); for(int i = 0; i < (k-1); i++) km1[i] = i+1; //vector of 1:k SEE SEQ_ALONG
533     lnk1k2 = (k/2.0)*log(2.0)+log((lambda_struct.nu-k)/2)+lgamma((lambda_struct.nu-k)/2)-lgamma(lambda_struct.nu/2)+sum(log(lambda_struct.nu/2-km1/2));
534   } else {
535     lnk1k2 = (k/2.0)*log(2.0)+log((lambda_struct.nu-k)/2)+lgamma((lambda_struct.nu-k)/2)-lgamma(lambda_struct.nu/2);
536   }
537 
538   constant = -(k/2.0)*log(2*M_PI)+(k/2.0)*log(lambda_struct.Amu/(1+lambda_struct.Amu)) + lnk1k2 + lambda_struct.nu*logdetR;
539 
540 // note: here we are using the fact that |V + S_i | = |R|^2 (1 + v_i'v_i)
541 //  where v_i = sqrt(Amu/(1+Amu))*t(R^-1)*(y_i-mubar), R is chol(V)
542 //  and S_i = Amu/(1+Amu) * (y_i-mubar)(y_i-mubar)'
543 
544   transy = trans(y);
545   transy.each_col() -= lambda_struct.mubar;
546 
547   m = sqrt(lambda_struct.Amu/(1+lambda_struct.Amu))*trans(solve(trimatu(R),eye(y.n_cols,y.n_cols)))*transy; //trimatu interprets the matrix as upper triangular and makes solve more efficient
548 
549   vivi = sum(square(m),0);
550 
551   lnq0v = constant - ((lambda_struct.nu+1)/2)*(2*logdetR+log(1+vivi));
552 
553   return(trans(exp(lnq0v)));
554 }
555 
seq_rcpp(double from,double to,int len)556 vec seq_rcpp(double from, double to, int len){
557 
558 // Wayne Taylor 1/28/2015
559 
560 // Same as R::seq()
561 
562   vec res(len);
563   res[len-1] = to; res[0] = from; //note the order of these two statements is important, when gridsize = 1 res[0] will be rewritten to the correct number
564   double increment = (res[len-1]-res[0])/(len-1);
565   for(int i = 1; i<(len-1); i++) res[i] = res[i-1] + increment;
566   return(res);
567 }
568 
alphaD(priorAlpha const & priorAlpha_struct,int Istar,int gridsize)569 double alphaD(priorAlpha const& priorAlpha_struct, int Istar, int gridsize){
570 
571 // Wayne Taylor 2/4/2015
572 
573 // function to draw alpha using prior, p(alpha)= (1-(alpha-alphamin)/(alphamax-alphamin))**power
574 
575   //same as seq
576   vec alpha = seq_rcpp(priorAlpha_struct.alphamin,priorAlpha_struct.alphamax-.000001,gridsize);
577 
578   vec lnprob(gridsize);
579   for(int i = 0; i<gridsize; i++){
580     lnprob[i] = Istar*log(alpha[i]) + lgamma(alpha[i]) - lgamma(priorAlpha_struct.n+alpha[i]) + priorAlpha_struct.power*log(1-(alpha[i]-priorAlpha_struct.alphamin)/(priorAlpha_struct.alphamax-priorAlpha_struct.alphamin));
581   }
582 
583   lnprob = lnprob - median(lnprob);
584   vec probs=exp(lnprob);
585   probs=probs/sum(probs);
586 
587   return(alpha(rmultinomF(probs)-1));
588 }
589 
GD(lambda const & lambda_struct)590 murooti GD(lambda const& lambda_struct){
591 
592 // Wayne Taylor 2/4/2015
593 
594 // function to draw from prior for Multivariate Normal Model
595 
596 // mu|Sigma ~ N(mubar,Sigma x Amu^-1)
597 // Sigma ~ IW(nu,V)
598 
599 // note: we must insure that mu is a vector to use most efficient lndMvn routine
600 
601   int k = lambda_struct.mubar.size();
602 
603   List Rout = rwishart(lambda_struct.nu,solve(trimatu(lambda_struct.V),eye(k,k))); //trimatu interprets the matrix as upper triangular and makes solve more efficient
604   mat Sigma = as<mat>(Rout["IW"]); //conversion from Rcpp to Armadillo requires explict declaration of variable type using as<>
605   mat root = chol(Sigma);
606   mat draws = rnorm(k);
607   mat mu = lambda_struct.mubar + (1/sqrt(lambda_struct.Amu))*trans(root)*draws;
608 
609   murooti out_struct;
610     out_struct.mu = mu;
611     out_struct.rooti = solve(trimatu(root),eye(k,k)); //trimatu interprets the matrix as upper triangular and makes solve more efficient
612 
613   return(out_struct);
614 }
615 
616 
lambdaD(lambda const & lambda_struct,std::vector<murooti> const & thetaStar_vector,vec const & alim,vec const & nulim,vec const & vlim,int gridsize)617 lambda lambdaD(lambda const& lambda_struct, std::vector<murooti> const& thetaStar_vector, vec const& alim, vec const& nulim, vec const& vlim, int gridsize){
618 
619 // Wayne Taylor 2/4/2015
620 
621 // revision history
622 //  p. rossi 7/06
623 //  vectorized 1/07
624 //  changed 2/08 to paramaterize V matrix of IW prior to nu*v*I; then mode of Sigma=nu/(nu+2)vI
625 //    this means that we have a reparameterization to v* = nu*v
626 
627 // function to draw (nu, v, a) using uniform priors
628 
629 // theta_j=(mu_j,Sigma_j)  mu_j~N(0,Sigma_j/a)  Sigma_j~IW(nu,vI)
630 //  recall E[Sigma]= vI/(nu-dim-1)
631 
632   vec lnprob, probs, rowSumslgammaarg;
633   int ind; //placeholder for matrix indexing
634   murooti thetaStari_struct; mat rootii; vec mui;
635   mat mout, rimu, arg, lgammaarg;
636   double sumdiagriri, sumlogdiag, sumquads, adraw, nudraw, vdraw;
637 
638   murooti thetaStar0_struct = thetaStar_vector[0];
639   int d = thetaStar0_struct.mu.size();
640   int Istar = thetaStar_vector.size();
641 
642   vec aseq = seq_rcpp(alim[0],alim[1],gridsize);
643   vec nuseq = d-1+exp(seq_rcpp(nulim[0],nulim[1],gridsize)); //log uniform grid
644   vec vseq = seq_rcpp(vlim[0],vlim[1],gridsize);
645 
646 // "brute" force approach would simply loop over the
647 //  "observations" (theta_j) and use log of the appropriate densities.  To vectorize, we
648 // notice that the "data" comes via various statistics:
649 //  1. sum of log(diag(rooti_j)
650 //  2. sum of tr(V%*%rooti_j%*%t(rooti_j)) where V=vI_d
651 //  3. quadratic form t(mu_j-0)%*%rooti%*%t(rooti)%*%(mu_j-0)
652 // thus, we will compute these first.
653 // for documentation purposes, we leave brute force code in comment fields
654 
655 // extract needed info from thetastar list
656 
657   //mout has the rootis in form: [t(rooti_1), t(rooti_2), ...,t(rooti_Istar)]
658   mout = zeros<mat>(d,Istar*d);
659   ind = 0;
660   for(int i = 0; i < Istar; i++){
661     thetaStari_struct = thetaStar_vector[i];
662     rootii = thetaStari_struct.rooti;
663     ind = i*d;
664     mout.submat(0, ind,d-1,ind+d-1) = trans(rootii);
665   }
666   sumdiagriri = sum(sum(square(mout),0)); //sum_i trace(rooti_i*trans(rooti_i))
667 
668 // now get diagonals of rooti
669   sumlogdiag = 0.0;
670   for(int i = 0; i < Istar; i++){
671     ind = i*d;
672     for(int j = 0; j < d; j++){
673       sumlogdiag = sumlogdiag+log(mout(j,ind+j));
674     }
675   }
676 
677   //columns of rimu contain trans(rooti_i)*mu_i
678   rimu = zeros<mat>(d,Istar);
679   for(int i = 0; i < Istar; i++){
680     thetaStari_struct = thetaStar_vector[i];
681     mui = thetaStari_struct.mu;
682     rootii = thetaStari_struct.rooti;
683     rimu(span::all,i) = trans(rootii) * mui;
684   }
685   sumquads = sum(sum(square(rimu),0));
686 
687 // draw a  (conditionally indep of nu,v given theta_j)
688   lnprob = zeros<vec>(aseq.size());
689 // for(i in seq(along=aseq)){
690 // for(j in seq(along=thetastar)){
691 // lnprob[i]=lnprob[i]+lndMvn(thetastar[[j]]$mu,c(rep(0,d)),thetastar[[j]]$rooti*sqrt(aseq[i]))}
692   lnprob = Istar*(-(d/2.0)*log(2*M_PI))-.5*aseq*sumquads+Istar*d*log(sqrt(aseq))+sumlogdiag;
693   lnprob = lnprob-max(lnprob) + 200;
694   probs = exp(lnprob);
695   probs = probs/sum(probs);
696   adraw = aseq[rmultinomF(probs)-1];
697 
698 // draw nu given v
699 
700   lnprob = zeros<vec>(nuseq.size());
701 // for(i in seq(along=nuseq)){
702 // for(j in seq(along=thetastar)){
703 // Sigma_j=crossprod(backsolve(thetastar[[j]]$rooti,diag(d)))
704 // lnprob[i]=lnprob[i]+lndIWishart(nuseq[i],V,Sigma_j)}
705 
706   //same as arg = (nuseq+1-arg)/2.0;
707   arg = zeros<mat>(gridsize,d);
708   for(int i = 0; i < d; i++) {
709     vec indvec(gridsize);
710     indvec.fill(-(i+1)+1);
711     arg(span::all,i) = indvec;
712   }
713   arg.each_col() += nuseq;
714   arg = arg/2.0;
715 
716   lgammaarg = zeros<mat>(gridsize,d);
717   for(int i = 0; i < gridsize; i++){
718     for(int j = 0; j < d; j++){
719       lgammaarg(i,j) = lgamma(arg(i,j));
720   }}
721   rowSumslgammaarg = sum(lgammaarg,1);
722 
723   lnprob = zeros<vec>(gridsize);
724   for(int i = 0; i<gridsize; i++){
725     lnprob[i] = -Istar*log(2.0)*d/2.0*nuseq[i] - Istar*rowSumslgammaarg[i] + Istar*d*log(sqrt(lambda_struct.V(0,0)))*nuseq[i] + sumlogdiag*nuseq[i];
726   }
727 
728   lnprob = lnprob-max(lnprob)+200;
729   probs = exp(lnprob);
730   probs = probs/sum(probs);
731   nudraw = nuseq[rmultinomF(probs)-1];
732 
733 // draw v given nu
734 
735   lnprob = zeros<vec>(vseq.size());
736 // for(i in seq(along=vseq)){
737 // V=vseq[i]*diag(d)
738 // for(j in seq(along=thetastar)){
739 // Sigma_j=crossprod(backsolve(thetastar[[j]]$rooti,diag(d)))
740 // lnprob[i]=lnprob[i]+lndIWishart(nudraw,V,Sigma_j)}
741 // lnprob=Istar*nudraw*d*log(sqrt(vseq))-.5*sumdiagriri*vseq
742 
743   lnprob = Istar*nudraw*d*log(sqrt(vseq*nudraw))-.5*sumdiagriri*vseq*nudraw;
744   lnprob = lnprob-max(lnprob)+200;
745   probs = exp(lnprob);
746   probs = probs/sum(probs);
747   vdraw = vseq[rmultinomF(probs)-1];
748 
749 // put back into lambda
750   lambda out_struct;
751     out_struct.mubar = zeros<vec>(d);
752     out_struct.Amu = adraw;
753     out_struct.nu = nudraw;
754     out_struct.V = nudraw*vdraw*eye(d,d);
755 
756   return(out_struct);
757 }
758 
759 //Used in llnhlogit and simnhlogit---------------------------------------------------------------------------------
root(double c1,double c2,double tol,int iterlim)760 double root(double c1, double c2, double tol, int iterlim){
761 
762 //function to find root of c1 - c2u = lnu
763 
764    int iter = 0;
765    double uold = .1;
766    double unew = .00001;
767 
768    while (iter <= iterlim && fabs(uold-unew) > tol){
769      uold = unew;
770      unew=uold + (uold*(c1 -c2*uold -  log(uold)))/(1. + c2*uold);
771      if(unew < 1.0e-50) unew=1.0e-50;
772      iter=iter+1;
773    }
774 
775    return(unew);
776 }
777 
778 //[[Rcpp::export]]
callroot(vec const & c1,vec const & c2,double tol,int iterlim)779 vec callroot(vec const& c1, vec const& c2, double tol, int iterlim){
780 
781   int n = c1.size();
782   vec u = zeros<vec>(n);
783 
784   for(int i = 0; i<n; i++){
785     u[i] = root(c1[i],c2[i],tol,iterlim);
786   }
787 
788   return(u);
789 }
790