1 #include <stddef.h>
2 #include <stdio.h>
3 #include <math.h>
4 #include <Rmath.h>
5 #include <R_ext/Utils.h>
6 #include <R.h>
7 #include "vector.h"
8 #include "subroutines.h"
9 #include "rand.h"
10 #include "bayes.h"
11 #include "sample.h"
12 
13 /* Normal Parametric Model for RxC (with R >= 2, C >= 2) Tables */
cBaseRC(double * pdX,double * pdY,double * pdWmin,double * pdWmax,int * pin_samp,int * pin_col,int * pin_row,int * reject,int * maxit,int * n_gen,int * burn_in,int * pinth,int * verbose,int * pinu0,double * pdtau0,double * mu0,double * pdS0,double * pdMu,double * pdSigma,int * parameter,double * pdSmu,double * pdSSigma,double * pdSW)14 void cBaseRC(
15 	     /*data input */
16 	     double *pdX,     /* X */
17 	     double *pdY,     /* Y */
18 	     double *pdWmin,  /* lower bounds */
19 	     double *pdWmax,  /* uppwer bounds */
20 	     int *pin_samp,   /* sample size */
21 	     int *pin_col,    /* number of columns */
22 	     int *pin_row,    /* number of rows */
23 
24 	     /*MCMC draws */
25 	     int *reject,     /* whether to use rejection sampling */
26 	     int *maxit,      /* max number of iterations for
27 				 rejection sampling */
28 	     int *n_gen,      /* number of gibbs draws */
29 	     int *burn_in,    /* number of draws to be burned in */
30 	     int *pinth,      /* keep every nth draw */
31 	     int *verbose,    /* 1 for output monitoring */
32 
33 	     /* prior specification*/
34 	     int *pinu0,      /* prior df parameter for InvWish */
35 	     double *pdtau0,  /* prior scale parameter for Sigma */
36 	     double *mu0,     /* prior mean for mu */
37 	     double *pdS0,    /* prior scale for Sigma */
38 
39 	     /* starting values */
40 	     double *pdMu,
41 	     double *pdSigma,
42 
43 	     /* storage */
44 	     int *parameter,  /* 1 if save population parameter */
45 	     double *pdSmu,
46 	     double *pdSSigma,
47 	     double *pdSW
48 	     ){
49 
50   /* some integers */
51   int n_samp = *pin_samp;    /* sample size */
52   int nth = *pinth;          /* keep every pth draw */
53   int n_col = *pin_col;      /* number of columns */
54   int n_dim = *pin_row-1;    /* number of rows - 1 */
55 
56   /* prior parameters */
57   double tau0 = *pdtau0;                     /* prior scale */
58   int nu0 = *pinu0;                          /* prior degrees of freedom */
59   double **S0 = doubleMatrix(n_col, n_col);  /* prior scale for InvWish */
60 
61   /* data */
62   double **Y = doubleMatrix(n_samp, n_dim);               /* Y */
63   double **X = doubleMatrix(n_samp, n_col);               /* X */
64   double ***W = doubleMatrix3D(n_samp, n_dim, n_col);     /* W */
65   double ***Wstar = doubleMatrix3D(n_col, n_samp, n_dim); /* logratio(W) */
66   double **Wsum = doubleMatrix(n_samp, n_col);            /* sum_{r=1}^{R-1} W_{irc} */
67   double **SWstar = doubleMatrix(n_col, n_dim);
68 
69   /* The lower and upper bounds of U = W*X/Y **/
70   double ***minU = doubleMatrix3D(n_samp, n_dim, n_col);
71   double *maxU = doubleArray(n_col);
72 
73   /* model parameters */
74   double **mu = doubleMatrix(n_col, n_dim);                 /* mean */
75   double ***Sigma = doubleMatrix3D(n_col, n_dim, n_dim);    /* covariance */
76   double ***InvSigma = doubleMatrix3D(n_col, n_dim, n_dim); /* inverse */
77 
78   /* misc variables */
79   int i, j, k, l, main_loop;   /* used for various loops */
80   int itemp, counter;
81   int itempM = 0;           /* for mu */
82   int itempS = 0;           /* for Sigma */
83   int itempW = 0;           /* for W */
84   int itempC = 0;           /* control nth draw */
85   int progress = 1, itempP = ftrunc((double) *n_gen/10);
86   double dtemp, dtemp1;
87   double *param = doubleArray(n_col);   /* Dirichlet parameters */
88   double *dvtemp = doubleArray(n_col);
89   double *dvtemp1 = doubleArray(n_col);
90 
91   /* get random seed */
92   GetRNGstate();
93 
94   /* read X */
95   itemp = 0;
96   for (k = 0; k < n_col; k++)
97     for (i = 0; i < n_samp; i++)
98       X[i][k] = pdX[itemp++];
99 
100   /* read Y */
101   itemp = 0;
102   for (j = 0; j < n_dim; j++)
103     for (i = 0; i < n_samp; i++)
104       Y[i][j] = pdY[itemp++];
105 
106   /* compute bounds on U */
107   itemp = 0;
108   for (k = 0; k < n_col; k++)
109     for (j = 0; j < n_dim; j++)
110       for (i = 0; i < n_samp; i++)
111 	minU[i][j][k] = fmax2(0, (X[i][k]+Y[i][j]-1)/Y[i][j]);
112 
113   /* initial values for mu and Sigma */
114   itemp = 0;
115   for (k = 0; k < n_col; k++)
116     for (j = 0; j < n_dim; j++)
117       mu[k][j] = pdMu[itemp++];
118   itemp = 0;
119   for (k = 0; k < n_col; k++)
120     for (j = 0; j < n_dim; j++)
121       for (i = 0; i < n_dim; i++)
122 	Sigma[k][j][i] = pdSigma[itemp++];
123   for (k = 0; k < n_col; k++)
124     dinv(Sigma[k], n_dim, InvSigma[k]);
125 
126   /* initial values for W */
127   for (k = 0; k < n_col; k++)
128     param[k] = 1.0;
129   for (i = 0; i < n_samp; i++) {
130     for (k = 0; k < n_col; k++)
131       Wsum[i][k] = 0.0;
132     for (j = 0; j < n_dim; j++) {
133       counter = 0; itemp = 1;
134       while (itemp > 0) { /* first try rejection sampling */
135 	rDirich(dvtemp, param, n_col);
136 	itemp = 0;
137 	for (k = 0; k < n_col; k++) {
138 	  if (dvtemp[k] < minU[i][j][k] ||
139 	      dvtemp[k] > fmin2(1, X[i][k]*(1-Wsum[i][k])/Y[i][j]))
140 	    itemp++;
141 	}
142 	if (itemp < 1)
143 	  for (k = 0; k < n_col; k++) {
144 	    W[i][j][k] = dvtemp[k]*Y[i][j]/X[i][k];
145 	    Wsum[i][k] += W[i][j][k];
146 	  }
147 	counter++;
148 	if (counter > *maxit && itemp > 0) { /* if rejection sampling fails, then
149 				   use midpoints of bounds */
150 	  itemp = 0;
151 	  dtemp = Y[i][j]; dtemp1 = 1;
152 	  for (k = 0; k < n_col-1; k++) {
153 	    W[i][j][k] = 0.25*(fmax2(0,(X[i][k]/dtemp1+dtemp-1)*dtemp1/X[i][k])+
154 			      fmin2(1-Wsum[i][k],dtemp*dtemp1/X[i][k]));
155 	    dtemp -= W[i][j][k]*X[i][k]/dtemp1;
156 	    dtemp1 -= X[i][k];
157 	    Wsum[i][k] += W[i][j][k];
158 	  }
159 	  W[i][j][n_col-1] = dtemp;
160 	  Wsum[i][n_col-1] += dtemp;
161 	}
162 	R_CheckUserInterrupt();
163       }
164       for (l = 0; l < n_dim; l++)
165 	for (k = 0; k < n_col; k++)
166 	  Wstar[k][i][l] = log(W[i][l][k])-log(1-Wsum[i][k]);
167     }
168   }
169 
170   /* read the prior */
171   itemp = 0;
172   for(k = 0; k < n_dim; k++)
173     for(j = 0; j < n_dim; j++)
174       S0[j][k] = pdS0[itemp++];
175 
176   /*** Gibbs sampler! ***/
177   if (*verbose)
178     Rprintf("Starting Gibbs sampler...\n");
179   for(main_loop = 0; main_loop < *n_gen; main_loop++){
180     /** update W, Wstar given mu, Sigma **/
181     for (i = 0; i < n_samp; i++) {
182       /* sampling W through Metropolis Step for each row */
183       for (j = 0; j < n_dim; j++) {
184 	/* computing upper bounds for U */
185 	for (k = 0; k < n_col; k++) {
186 	  Wsum[i][k] -= W[i][j][k];
187 	  maxU[k] = fmin2(1, X[i][k]*(1-Wsum[i][k])/Y[i][j]);
188 	}
189 	/** MH step **/
190 	/* Sample a candidate draw of W from truncated Dirichlet */
191 	l = 0; itemp = 1;
192 	while (itemp > 0) {
193 	  rDirich(dvtemp, param, n_col);
194 	  itemp = 0;
195 	  for (k = 0; k < n_col; k++)
196 	    if (dvtemp[k] > maxU[k] || dvtemp[k] < minU[i][j][k])
197 	      itemp++;
198 	  l++;
199 	  if (l > *maxit)
200 	    error("rejection algorithm failed because bounds are too tight.\n increase maxit or use gibbs sampler instead.");
201 	}
202 	/* get W and its log-ratio transformation */
203 	for (k = 0; k < n_col; k++) {
204 	  dvtemp[k] = dvtemp[k]*Y[i][j]/X[i][k];
205 	  dvtemp1[k] = Wsum[i][k]+dvtemp[k];
206 	}
207 	for (k = 0; k < n_col; k++)
208 	  for (l = 0; l < n_dim; l++)
209 	    if (l == j)
210 	      SWstar[k][l] = log(dvtemp[k])-log(1-dvtemp1[k]);
211 	    else
212 	      SWstar[k][l] = log(W[i][j][k])-log(1-dvtemp1[k]);
213 	/* computing acceptance ratio */
214 	dtemp = 0; dtemp1 = 0;
215 	for (k= 0; k < n_col; k++) {
216 	  dtemp += dMVN(SWstar[k], mu[k], InvSigma[k], n_dim, 1);
217 	  dtemp1 += dMVN(Wstar[k][i], mu[k], InvSigma[k], n_dim, 1);
218 	  dtemp -= log(dvtemp[k]);
219 	  dtemp1 -= log(W[i][j][k]);
220 	}
221 	if (unif_rand() < fmin2(1, exp(dtemp-dtemp1)))
222 	  for (k = 0; k < n_col; k++)
223 	    W[i][j][k] = dvtemp[k];
224 	/* updating Wsum and Wstar with new draws */
225 	for (k = 0; k < n_col; k++) {
226 	  Wsum[i][k] += W[i][j][k];
227 	  for (l = 0; l < n_dim; l++)
228 	    Wstar[k][i][l] = log(W[i][l][k])-log(1-Wsum[i][k]);
229 	}
230       }
231     }
232 
233     /* update mu, Sigma given wstar using effective sample of Wstar */
234     for (k = 0; k < n_col; k++)
235       NIWupdate(Wstar[k], mu[k], Sigma[k], InvSigma[k], mu0, tau0,
236 		nu0, S0, n_samp, n_dim);
237 
238     /*store Gibbs draw after burn-in and every nth draws */
239     if (main_loop >= *burn_in){
240       itempC++;
241       if (itempC==nth){
242 	for (k = 0; k < n_col; k++)
243 	  for (j = 0; j < n_dim; j++) {
244 	    pdSmu[itempM++]=mu[k][j];
245 	    for (i = 0; i < n_dim; i++)
246 	      if (j <= i)
247 		pdSSigma[itempS++]=Sigma[k][j][i];
248 	  }
249 	for(i = 0; i < n_samp; i++)
250 	  for (k = 0; k < n_col; k++)
251 	    for (j = 0; j < n_dim; j++)
252 	      pdSW[itempW++] = W[i][j][k];
253 	itempC=0;
254       }
255     }
256 
257     if (*verbose)
258       if (itempP == main_loop) {
259 	Rprintf("%3d percent done.\n", progress*10);
260 	itempP+=ftrunc((double) *n_gen/10); progress++;
261 	R_FlushConsole();
262       }
263     R_CheckUserInterrupt();
264   } /* end of Gibbs sampler */
265   if (*verbose)
266     Rprintf("100 percent done.\n");
267 
268   /** write out the random seed **/
269   PutRNGstate();
270 
271   /* Freeing the memory */
272   FreeMatrix(S0, n_col);
273   FreeMatrix(X, n_samp);
274   FreeMatrix(Y, n_samp);
275   Free3DMatrix(W, n_samp, n_dim);
276   Free3DMatrix(Wstar, n_col, n_samp);
277   FreeMatrix(Wsum, n_samp);
278   Free3DMatrix(minU, n_samp, n_dim);
279   FreeMatrix(mu, n_col);
280   Free3DMatrix(Sigma, n_col, n_dim);
281   Free3DMatrix(InvSigma, n_col, n_dim);
282   free(param);
283   free(dvtemp);
284 } /* main */
285 
286