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