/src/C/factor_model_util.c

http://github.com/beechung/Latent-Factor-Models · C · 1148 lines · 827 code · 170 blank · 151 comment · 429 complexity · fdd3e70f2ce58d51fe86ff8ea227cf07 MD5 · raw file

  1. /*
  2. Copyright (c) 2011, Yahoo! Inc. All rights reserved.
  3. Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
  4. Author: Bee-Chung Chen
  5. */
  6. #include <R.h>
  7. #include <Rinternals.h>
  8. #include <Rmath.h>
  9. #include <R_ext/Lapack.h>
  10. #include <stdio.h>
  11. #include <time.h>
  12. #include "util.h"
  13. void gaussianPosterior_mainEffect(
  14. // OUTPUT
  15. double* outSample, double* outMean, double* outVar,
  16. //INPUT
  17. const int* option /*1:Sample, 2:Mean&Var, 3:Sample&Mean&Var*/,
  18. const int* thisEffIndex /*user or item*/,
  19. const double* rest /*o in the paper*/,
  20. const double* fittedEff /*g0*x_user or d0*x_item*/,
  21. const double* multiplier /*NULL*/,
  22. const double* var_y, const double* var_eff /*var_alpha or var_beta*/,
  23. const int* nObs, const int* nThisEff, const int* nVar_y, const int* nVar_eff,
  24. // OTHER
  25. const int* debug
  26. ){
  27. int outputSample=0, outputMeanVar=0;
  28. if(*option == 1){
  29. outputSample = 1; outputMeanVar = 0;
  30. }else if(*option == 2){
  31. outputSample = 0; outputMeanVar = 1;
  32. }else if(*option == 3){
  33. outputSample = 1; outputMeanVar = 1;
  34. }else error("Unknown option: %d", *option);
  35. double *sum_ivar = (double*)Calloc(*nThisEff, double); // sum_ivar[effect_i] = sum_{k having effect_i} 1/var_y[k]
  36. double *sum_o = (double*)Calloc(*nThisEff, double); // sum_o[effect_i] = sum_{k having effect_i} o[k]/var_y[k]
  37. for(int k=0; k<*nObs; k++){
  38. const int thisIndex = thisEffIndex[k]-1;
  39. if(*debug > 0) CHK_C_INDEX(thisIndex, *nThisEff);
  40. double o = rest[k]; // for alpha and beta: o. for gamma: o * x_dyad * b
  41. double square = 1; // for alpha and beta: 1. for gamma: (x_dyad * b)^2
  42. if(multiplier != NULL){
  43. o *= multiplier[k];
  44. square = multiplier[k] * multiplier[k];
  45. }
  46. if((*nVar_y) == 1){
  47. sum_ivar[thisIndex] += square / var_y[0];
  48. sum_o[ thisIndex] += o / var_y[0];
  49. }else if((*nVar_y) == (*nObs)){
  50. sum_ivar[thisIndex] += square / var_y[k];
  51. sum_o[ thisIndex] += o / var_y[k];
  52. }else error("nVar_y = %d, nObs = %d", *nVar_y, *nObs);
  53. }
  54. if(outputSample) GetRNGstate();
  55. for(int i=0; i<*nThisEff; i++){
  56. double mean = 0, var=0;
  57. if((*nVar_eff) == 1){
  58. var = 1.0 / (sum_ivar[i] + (1.0 / var_eff[0]));
  59. mean = var * (sum_o[i] + (fittedEff[i] / var_eff[0]));
  60. }else if((*nVar_eff) == (*nThisEff)){
  61. var = 1.0 / (sum_ivar[i] + (1.0 / var_eff[i]));
  62. mean = var * (sum_o[i] + (fittedEff[i] / var_eff[i]));
  63. }else error("nVar_eff = %d, nThisEff = %d", *nVar_eff, *nThisEff);
  64. if(outputMeanVar){
  65. outMean[i] = mean;
  66. outVar[i] = var;
  67. }
  68. if(outputSample){
  69. outSample[i] = rnorm(mean, sqrt(var));
  70. }
  71. }
  72. if(outputSample) PutRNGstate();
  73. Free(sum_ivar);
  74. Free(sum_o);
  75. }
  76. SEXP gaussianPosterior_mainEffect_Call(
  77. // OUTPUT
  78. SEXP outSample, SEXP outMean, SEXP outVar,
  79. //INPUT
  80. SEXP option /*1:Sample, 2:Mean&Var, 3:Sample&Mean&Var*/,
  81. SEXP thisEffIndex /*user or item*/,
  82. SEXP rest /*o in the paper*/,
  83. SEXP fittedEff /*g0*x_user or d0*x_item*/,
  84. SEXP multiplier /*NULL*/,
  85. SEXP var_y, SEXP var_eff /*var_alpha or var_beta*/,
  86. SEXP nObs, SEXP nThisEff, SEXP nVar_y, SEXP nVar_eff,
  87. // OTHER
  88. SEXP debug
  89. ){
  90. gaussianPosterior_mainEffect(
  91. // OUTPUT
  92. MY_REAL(outSample), MY_REAL(outMean), MY_REAL(outVar),
  93. //INPUT
  94. MY_INTEGER(option) /*1:Sample, 2:Mean&Var, 3:Sample&Mean&Var*/,
  95. MY_INTEGER(thisEffIndex) /*user or item*/,
  96. MY_REAL(rest) /*o in the paper*/,
  97. MY_REAL(fittedEff) /*g0*x_user or d0*x_item*/,
  98. MY_REAL(multiplier) /*NULL*/,
  99. MY_REAL(var_y), MY_REAL(var_eff) /*var_alpha or var_beta*/,
  100. MY_INTEGER(nObs), MY_INTEGER(nThisEff), MY_INTEGER(nVar_y), MY_INTEGER(nVar_eff),
  101. // OTHER
  102. MY_INTEGER(debug)
  103. );
  104. return R_NilValue;
  105. }
  106. void gaussianPosterior_2WayInteraction(
  107. // OUTPUT
  108. double* sample, double* posteriorMean, double* posteriorVar,
  109. // INPUT
  110. const int* option /*1:Sample, 2:Mean&Var, 3:Sample&Mean&Var*/,
  111. const int* thisEffIndex /*user or item*/, const int* otherEffIndex /*item or user*/, const double* obs /*o in the paper*/,
  112. const double* priorMean /*Gw or Dz*/, const double* otherEff /*v or u*/,
  113. const double* obsVar, const double* priorVar /*var_u or var_v*/,
  114. const int* nObs, const int* nLevelsThisEff, const int* nLevelsOtherEff,
  115. const int* nFactors, const int* nObsVar, const int *nPriorVar,
  116. const int* obsIndex, const int* oiStart, const int* oiNum,
  117. // OTHER
  118. const int* debug
  119. ){
  120. double *sum_vv /*nFactors x nFactors*/, *sum_ov /*nFactors x 1*/, o, *vj /*nFactors x 1*/, *Gwi /*nFactors x 1*/,
  121. *work, size, *mean, *var, *temp, *rnd;
  122. int i,j,k,m, thisIndex, otherIndex, outputSample, outputMeanVar, oIndex, lwork=-1, info, symCheck;
  123. char jobz = 'V', uplo = 'L';
  124. symCheck = (*debug) - 2;
  125. if(*option == 1){
  126. outputSample = 1; outputMeanVar = 0;
  127. }else if(*option == 2){
  128. outputSample = 0; outputMeanVar = 1;
  129. }else if(*option == 3){
  130. outputSample = 1; outputMeanVar = 1;
  131. }else error("Unknown option: %d", *option);
  132. vj = (double*)Calloc(*nFactors, double);
  133. Gwi = (double*)Calloc(*nFactors, double);
  134. sum_ov = (double*)Calloc(*nFactors, double);
  135. sum_vv = (double*)Calloc((*nFactors)*(*nFactors), double);
  136. mean = (double*)Calloc(*nFactors, double);
  137. var = (double*)Calloc((*nFactors)*(*nFactors), double);
  138. temp = (double*)Calloc((*nFactors)*(*nFactors), double);
  139. if(outputSample) GetRNGstate();
  140. for(i=0; i<*nLevelsThisEff; i++){
  141. thisIndex = i+1;
  142. for(j=0; j<*nFactors; j++) sum_ov[j] = 0;
  143. for(j=0; j<(*nFactors)*(*nFactors); j++) sum_vv[j] = 0;
  144. for(j=0; j<oiNum[i]; j++){
  145. oIndex = obsIndex[R_VEC(oiStart[i]+j)];
  146. otherIndex = otherEffIndex[R_VEC(oIndex)];
  147. if(*debug > 0) CHK_R_INDEX(oIndex, *nObs);
  148. if(*debug > 0) CHK_R_INDEX(otherIndex, *nLevelsOtherEff);
  149. if(*debug > 1) if(thisEffIndex[R_VEC(oIndex)] != i+1) error("error in obsIndex, oiStart, oiNum\n");
  150. o = obs[R_VEC(oIndex)];
  151. for(k=1; k<=*nFactors; k++) vj[R_VEC(k)] = otherEff[R_MAT(otherIndex,k,*nLevelsOtherEff)];
  152. double var_y_thisObs = 0;
  153. if((*nObsVar) == 1) var_y_thisObs = obsVar[0];
  154. else if((*nObsVar) == (*nObs)) var_y_thisObs = obsVar[R_VEC(oIndex)];
  155. else error("nVar_y = %d, nObs = %d", *nObsVar, *nObs);
  156. for(k=0; k<*nFactors; k++) sum_ov[k] += (o * vj[k]) / var_y_thisObs;
  157. for(k=0; k<*nFactors; k++)
  158. for(m=0; m<*nFactors; m++) sum_vv[C_MAT(k,m,*nFactors)] += (vj[k] * vj[m]) / var_y_thisObs;
  159. }
  160. for(k=1; k<=*nFactors; k++) Gwi[R_VEC(k)] = priorMean[R_MAT(thisIndex,k,*nLevelsThisEff)];
  161. if((*nPriorVar) == 1){
  162. for(k=0; k<*nFactors; k++) sum_vv[C_MAT(k,k,*nFactors)] += (1/priorVar[0]);
  163. for(k=0; k<*nFactors; k++) Gwi[k] /= priorVar[0];
  164. }else if((*nPriorVar) == (*nLevelsThisEff)*(*nFactors)*(*nFactors)){
  165. for(k=0; k<*nFactors; k++)
  166. for(m=0; m<*nFactors; m++) temp[C_MAT(k,m,*nFactors)] = priorVar[C_3DA(i,k,m,*nLevelsThisEff,*nFactors)];
  167. sym_inv_byCholesky(temp, nFactors, &symCheck);
  168. // Now, temp is var_u[i]^-1
  169. for(k=0; k<*nFactors; k++)
  170. for(m=0; m<*nFactors; m++) sum_vv[C_MAT(k,m,*nFactors)] += temp[C_MAT(k,m,*nFactors)];
  171. // reuse the space of vj
  172. for(k=0; k<*nFactors; k++) vj[k] = Gwi[k];
  173. for(k=0; k<*nFactors; k++){
  174. Gwi[k] = 0;
  175. for(m=0; m<*nFactors; m++) Gwi[k] += temp[C_MAT(k,m,*nFactors)] * vj[m];
  176. }
  177. }else error("nVar_eff = %d, nThisEff = %d", *nPriorVar, *nLevelsThisEff);
  178. // Now, sum_vv = var^-1
  179. // Gwi = var_u[i]^-1 G wi
  180. if((*nFactors) == 1){
  181. var[0] = 1/sum_vv[0];
  182. mean[0] = var[0] * (sum_ov[0] + Gwi[0]);
  183. if(outputSample){
  184. sample[i] = rnorm(mean[0], sqrt(var[0]));
  185. }
  186. if(outputMeanVar){
  187. posteriorMean[i] = mean[0];
  188. posteriorVar[i] = var[0];
  189. }
  190. }else{
  191. double *eigen_val, *eigen_vec;
  192. eigen_val = vj;
  193. eigen_vec = sum_vv;
  194. if(*debug > 2) CHK_SYMMETRIC(eigen_vec, *nFactors);
  195. //
  196. // Compute the variance-covariance matrix
  197. //
  198. // Allocate workspace for eigen value decomposition (only allocate once)
  199. if(lwork == -1){
  200. F77_NAME(dsyev)(&jobz, &uplo, nFactors, eigen_vec, nFactors, eigen_val, &size, &lwork, &info);
  201. if(info != 0) error("error in dsyev(...)");
  202. lwork = (int)size;
  203. work = (double*)Calloc(lwork, double);
  204. }
  205. F77_NAME(dsyev)(&jobz, &uplo, nFactors, eigen_vec, nFactors, eigen_val, work, &lwork, &info);
  206. if(info != 0) error("error in dsyev(...)");
  207. for(j=0; j<*nFactors; j++) eigen_val[j] = 1/eigen_val[j];
  208. // Now, eigen_val, eigen_vec are the eigen values and vectors of var
  209. for(j=0; j<*nFactors; j++)
  210. for(k=0; k<*nFactors; k++) temp[C_MAT(j,k,*nFactors)] = eigen_vec[C_MAT(j,k,*nFactors)] * eigen_val[k];
  211. for(j=0; j<*nFactors; j++)
  212. for(k=0; k<*nFactors; k++){
  213. var[C_MAT(j,k,*nFactors)] = 0;
  214. for(m=0; m<*nFactors; m++) var[C_MAT(j,k,*nFactors)] += temp[C_MAT(j,m,*nFactors)] * eigen_vec[C_MAT(k,m,*nFactors)];
  215. }
  216. // Now, var is the variance-covariance matrix
  217. //
  218. // Compute the mean vector
  219. //
  220. // print_vector("sum_ov: ", sum_ov, *nFactors);
  221. // print_vector("Gwi: ", Gwi, *nFactors);
  222. for(j=0; j<*nFactors; j++) sum_ov[j] += Gwi[j];
  223. for(j=0; j<*nFactors; j++){
  224. mean[j] = 0;
  225. for(k=0; k<*nFactors; k++) mean[j] += var[C_MAT(j,k,*nFactors)] * sum_ov[k];
  226. }
  227. if(outputMeanVar){
  228. for(j=0; j<*nFactors; j++) posteriorMean[C_MAT(i,j,*nLevelsThisEff)] = mean[j];
  229. for(j=0; j<*nFactors; j++)
  230. for(k=0; k<*nFactors; k++) posteriorVar[C_3DA(i,j,k,*nLevelsThisEff,*nFactors)] = var[C_MAT(j,k,*nFactors)];
  231. }
  232. // DEBUG CODE
  233. // if(i==38){
  234. // printf("i = %d\n",i);
  235. // print_vector("mean: ", mean, *nFactors);
  236. // print_matrix(" var: ", var, *nFactors, *nFactors);
  237. // }
  238. if(*debug >= 2 && oiNum[i] == 0){
  239. for(k=1; k<=*nFactors; k++){
  240. CHK_SAME_NUMBER("mean[k] != fittedEff[k]", mean[R_VEC(k)], priorMean[R_MAT(thisIndex,k,*nLevelsThisEff)]);
  241. }
  242. if((*nPriorVar) == 1){
  243. for(j=0; j<*nFactors; j++)
  244. for(k=0; k<*nFactors; k++){
  245. if(j==k){ CHK_SAME_NUMBER("var != var_eff", var[C_MAT(j,k,*nFactors)], priorVar[0]);}
  246. else{ CHK_SAME_NUMBER("var != var_eff", var[C_MAT(j,k,*nFactors)], 0);}
  247. }
  248. }else{
  249. for(j=0; j<*nFactors; j++)
  250. for(k=0; k<*nFactors; k++){
  251. CHK_SAME_NUMBER("var != var_eff", var[C_MAT(j,k,*nFactors)], priorVar[C_3DA(i,j,k,*nLevelsThisEff,*nFactors)]);
  252. }
  253. }
  254. }
  255. //
  256. // Generate the random vector
  257. //
  258. if(outputSample){
  259. // reuse the space allocated for Gwi
  260. rnd = Gwi;
  261. // DEBUG CODE
  262. // if(i==38){
  263. // print_vector("eigenvalue: ", eigen_val, *nFactors);
  264. // Rprintf("eigenvector:\n"); print_matrix(" ", eigen_vec, *nFactors, *nFactors);
  265. // }
  266. for(j=0; j<*nFactors; j++) eigen_val[j] = sqrt(eigen_val[j]);
  267. for(j=0; j<*nFactors; j++)
  268. for(k=0; k<*nFactors; k++) temp[C_MAT(j,k,*nFactors)] = eigen_vec[C_MAT(j,k,*nFactors)] * eigen_val[k];
  269. for(j=0; j<*nFactors; j++) rnd[j] = norm_rand();
  270. // DEBUG CODE
  271. // if(i==38){
  272. // Rprintf("temp:\n");
  273. // print_matrix(" ", temp, *nFactors, *nFactors);
  274. // print_vector("rnd: ", rnd, *nFactors);
  275. // }
  276. for(j=0; j<*nFactors; j++){
  277. sample[C_MAT(i,j,*nLevelsThisEff)] = mean[j];
  278. for(k=0; k<*nFactors; k++) sample[C_MAT(i,j,*nLevelsThisEff)] += temp[C_MAT(j,k,*nFactors)] * rnd[k];
  279. }
  280. }
  281. }
  282. }
  283. if(outputSample) PutRNGstate();
  284. Free(sum_ov);
  285. Free(sum_vv);
  286. Free(vj);
  287. Free(Gwi);
  288. Free(mean);
  289. Free(var);
  290. Free(temp);
  291. if(lwork > 0) Free(work);
  292. }
  293. void gaussianPosterior_SelfInteraction(
  294. // IN/OUT
  295. double* sample /* v */,
  296. // OUTPUT
  297. double* posteriorMean, double* posteriorVar,
  298. // INPUT
  299. const int* option /*1:Sample only, 2:Sample&Mean&Var, 3:Sample&Mean&Var*/,
  300. const int* fromIndex, const int* toIndex, const double* obs /*o in the paper*/,
  301. const double* priorMean /*Gx_user*/,
  302. const double* obsVar, const double* priorVar /* var_v */,
  303. const int* nObs, const int* nLevelsThisEff, const int* nFactors,
  304. const int* nObsVar, const int *nPriorVar,
  305. const int* author_obsIndex, const int* author_oiStart, const int* author_oiNum,
  306. const int* voter_obsIndex, const int* voter_oiStart, const int* voter_oiNum,
  307. // OTHER
  308. const int* debug
  309. ){
  310. double *sum_vv /*nFactors x nFactors*/, *sum_ov /*nFactors x 1*/, o, *vj /*nFactors x 1*/, *Gwi /*nFactors x 1*/,
  311. *work, size, *mean, *var, *temp, *rnd;
  312. int i,j,k,m, thisIndex, otherIndex, outputMeanVar, oIndex, lwork=-1, info, symCheck, role;
  313. char jobz = 'V', uplo = 'L';
  314. symCheck = (*debug) - 2;
  315. if(*option == 1){
  316. outputMeanVar = 0;
  317. }else if(*option == 2){
  318. outputMeanVar = 1;
  319. }else if(*option == 3){
  320. outputMeanVar = 1;
  321. }else error("Unknown option: %d", *option);
  322. vj = (double*)Calloc(*nFactors, double);
  323. Gwi = (double*)Calloc(*nFactors, double);
  324. sum_ov = (double*)Calloc(*nFactors, double);
  325. sum_vv = (double*)Calloc((*nFactors)*(*nFactors), double);
  326. mean = (double*)Calloc(*nFactors, double);
  327. var = (double*)Calloc((*nFactors)*(*nFactors), double);
  328. temp = (double*)Calloc((*nFactors)*(*nFactors), double);
  329. GetRNGstate();
  330. for(i=0; i<*nLevelsThisEff; i++){
  331. thisIndex = i+1;
  332. for(j=0; j<*nFactors; j++) sum_ov[j] = 0;
  333. for(j=0; j<(*nFactors)*(*nFactors); j++) sum_vv[j] = 0;
  334. int nObs_for_i = 0;
  335. // begin: compute sum_ov and sum_vv
  336. for(role=0; role<2; role++){
  337. int *obsIndex = NULL, *oiNum = NULL, *oiStart=NULL, *thisEffIndex=NULL, *otherEffIndex=NULL;
  338. if(role == 0){
  339. // user i is an author
  340. obsIndex = (int*)author_obsIndex; oiNum = (int*)author_oiNum; oiStart = (int*)author_oiStart;
  341. thisEffIndex = (int*)toIndex; otherEffIndex = (int*)fromIndex;
  342. }else if(role == 1){
  343. // user i is an voter
  344. obsIndex = (int*)voter_obsIndex; oiNum = (int*)voter_oiNum; oiStart = (int*)voter_oiStart;
  345. thisEffIndex = (int*)fromIndex; otherEffIndex = (int*)toIndex;
  346. }else DIE_HERE;
  347. for(j=0; j<oiNum[i]; j++){
  348. nObs_for_i++;
  349. oIndex = obsIndex[R_VEC(oiStart[i]+j)];
  350. otherIndex = otherEffIndex[R_VEC(oIndex)];
  351. if(otherIndex == i+1) error("self votes are not allowed");
  352. if(*debug > 0) CHK_R_INDEX(oIndex, *nObs);
  353. if(*debug > 0) CHK_R_INDEX(otherIndex, *nLevelsThisEff);
  354. if(*debug > 1) if(thisEffIndex[R_VEC(oIndex)] != i+1) error("error in obsIndex, oiStart, oiNum\n");
  355. o = obs[R_VEC(oIndex)];
  356. for(k=1; k<=*nFactors; k++) vj[R_VEC(k)] = sample[R_MAT(otherIndex,k,*nLevelsThisEff)];
  357. double var_y_thisObs = 0;
  358. if((*nObsVar) == 1) var_y_thisObs = obsVar[0];
  359. else if((*nObsVar) == (*nObs)) var_y_thisObs = obsVar[R_VEC(oIndex)];
  360. else error("nVar_y = %d, nObs = %d", *nObsVar, *nObs);
  361. for(k=0; k<*nFactors; k++) sum_ov[k] += (o * vj[k]) / var_y_thisObs;
  362. for(k=0; k<*nFactors; k++)
  363. for(m=0; m<*nFactors; m++) sum_vv[C_MAT(k,m,*nFactors)] += (vj[k] * vj[m]) / var_y_thisObs;
  364. }
  365. }
  366. // end: compute sum_ov and sum_vv
  367. for(k=1; k<=*nFactors; k++) Gwi[R_VEC(k)] = priorMean[R_MAT(thisIndex,k,*nLevelsThisEff)];
  368. if((*nPriorVar) == 1){
  369. for(k=0; k<*nFactors; k++) sum_vv[C_MAT(k,k,*nFactors)] += (1/priorVar[0]);
  370. for(k=0; k<*nFactors; k++) Gwi[k] /= priorVar[0];
  371. }else if((*nPriorVar) == (*nLevelsThisEff)*(*nFactors)*(*nFactors)){
  372. for(k=0; k<*nFactors; k++)
  373. for(m=0; m<*nFactors; m++) temp[C_MAT(k,m,*nFactors)] = priorVar[C_3DA(i,k,m,*nLevelsThisEff,*nFactors)];
  374. sym_inv_byCholesky(temp, nFactors, &symCheck);
  375. // Now, temp is var_u[i]^-1
  376. for(k=0; k<*nFactors; k++)
  377. for(m=0; m<*nFactors; m++) sum_vv[C_MAT(k,m,*nFactors)] += temp[C_MAT(k,m,*nFactors)];
  378. // reuse the space of vj
  379. for(k=0; k<*nFactors; k++) vj[k] = Gwi[k];
  380. for(k=0; k<*nFactors; k++){
  381. Gwi[k] = 0;
  382. for(m=0; m<*nFactors; m++) Gwi[k] += temp[C_MAT(k,m,*nFactors)] * vj[m];
  383. }
  384. }else error("nVar_eff = %d, nThisEff = %d", *nPriorVar, *nLevelsThisEff);
  385. // Now, sum_vv = var^-1
  386. // Gwi = var_u[i]^-1 G wi
  387. if((*nFactors) == 1){
  388. var[0] = 1/sum_vv[0];
  389. mean[0] = var[0] * (sum_ov[0] + Gwi[0]);
  390. sample[i] = rnorm(mean[0], sqrt(var[0]));
  391. if(outputMeanVar){
  392. posteriorMean[i] = mean[0];
  393. posteriorVar[i] = var[0];
  394. }
  395. }else{
  396. double *eigen_val, *eigen_vec;
  397. eigen_val = vj;
  398. eigen_vec = sum_vv;
  399. if(*debug > 2) CHK_SYMMETRIC(eigen_vec, *nFactors);
  400. //
  401. // Compute the variance-covariance matrix
  402. //
  403. // Allocate workspace for eigen value decomposition (only allocate once)
  404. if(lwork == -1){
  405. F77_NAME(dsyev)(&jobz, &uplo, nFactors, eigen_vec, nFactors, eigen_val, &size, &lwork, &info);
  406. if(info != 0) error("error in dsyev(...)");
  407. lwork = (int)size;
  408. work = (double*)Calloc(lwork, double);
  409. }
  410. F77_NAME(dsyev)(&jobz, &uplo, nFactors, eigen_vec, nFactors, eigen_val, work, &lwork, &info);
  411. if(info != 0) error("error in dsyev(...)");
  412. for(j=0; j<*nFactors; j++) eigen_val[j] = 1/eigen_val[j];
  413. // Now, eigen_val, eigen_vec are the eigen values and vectors of var
  414. for(j=0; j<*nFactors; j++)
  415. for(k=0; k<*nFactors; k++) temp[C_MAT(j,k,*nFactors)] = eigen_vec[C_MAT(j,k,*nFactors)] * eigen_val[k];
  416. for(j=0; j<*nFactors; j++)
  417. for(k=0; k<*nFactors; k++){
  418. var[C_MAT(j,k,*nFactors)] = 0;
  419. for(m=0; m<*nFactors; m++) var[C_MAT(j,k,*nFactors)] += temp[C_MAT(j,m,*nFactors)] * eigen_vec[C_MAT(k,m,*nFactors)];
  420. }
  421. // Now, var is the variance-covariance matrix
  422. //
  423. // Compute the mean vector
  424. //
  425. // print_vector("sum_ov: ", sum_ov, *nFactors);
  426. // print_vector("Gwi: ", Gwi, *nFactors);
  427. for(j=0; j<*nFactors; j++) sum_ov[j] += Gwi[j];
  428. for(j=0; j<*nFactors; j++){
  429. mean[j] = 0;
  430. for(k=0; k<*nFactors; k++) mean[j] += var[C_MAT(j,k,*nFactors)] * sum_ov[k];
  431. }
  432. if(outputMeanVar){
  433. for(j=0; j<*nFactors; j++) posteriorMean[C_MAT(i,j,*nLevelsThisEff)] = mean[j];
  434. for(j=0; j<*nFactors; j++)
  435. for(k=0; k<*nFactors; k++) posteriorVar[C_3DA(i,j,k,*nLevelsThisEff,*nFactors)] = var[C_MAT(j,k,*nFactors)];
  436. }
  437. if(*debug >= 2 && nObs_for_i == 0){
  438. for(k=1; k<=*nFactors; k++){
  439. CHK_SAME_NUMBER("mean[k] != fittedEff[k]", mean[R_VEC(k)], priorMean[R_MAT(thisIndex,k,*nLevelsThisEff)]);
  440. }
  441. if((*nPriorVar) == 1){
  442. for(j=0; j<*nFactors; j++)
  443. for(k=0; k<*nFactors; k++){
  444. if(j==k){ CHK_SAME_NUMBER("var != var_eff", var[C_MAT(j,k,*nFactors)], priorVar[0]);}
  445. else{ CHK_SAME_NUMBER("var != var_eff", var[C_MAT(j,k,*nFactors)], 0);}
  446. }
  447. }else{
  448. for(j=0; j<*nFactors; j++)
  449. for(k=0; k<*nFactors; k++){
  450. CHK_SAME_NUMBER("var != var_eff", var[C_MAT(j,k,*nFactors)], priorVar[C_3DA(i,j,k,*nLevelsThisEff,*nFactors)]);
  451. }
  452. }
  453. }
  454. //
  455. // Generate the random vector
  456. //
  457. // reuse the space allocated for Gwi
  458. rnd = Gwi;
  459. for(j=0; j<*nFactors; j++) eigen_val[j] = sqrt(eigen_val[j]);
  460. for(j=0; j<*nFactors; j++)
  461. for(k=0; k<*nFactors; k++) temp[C_MAT(j,k,*nFactors)] = eigen_vec[C_MAT(j,k,*nFactors)] * eigen_val[k];
  462. for(j=0; j<*nFactors; j++) rnd[j] = norm_rand();
  463. for(j=0; j<*nFactors; j++){
  464. sample[C_MAT(i,j,*nLevelsThisEff)] = mean[j];
  465. for(k=0; k<*nFactors; k++) sample[C_MAT(i,j,*nLevelsThisEff)] += temp[C_MAT(j,k,*nFactors)] * rnd[k];
  466. }
  467. }
  468. }
  469. PutRNGstate();
  470. Free(sum_ov); Free(sum_vv); Free(vj); Free(Gwi);
  471. Free(mean); Free(var); Free(temp);
  472. if(lwork > 0) Free(work);
  473. }
  474. void gaussianPosterior_3WayInteraction(
  475. // OUTPUT
  476. double* sample, /* nLevelsThisEff x nFactors */
  477. double* posteriorMean, /* nLevelsThisEff x nFactors */
  478. double* posteriorVar, /* nLevelsThisEff x nFactors x nFactors */
  479. // INPUT
  480. const int* option /*1: output sample, 2: output mean & var, 3: output sample & Mean & Var*/,
  481. const int* thisEffIndex /* nObs x 1 */,
  482. const int* otherEffIndex /* nObs x 1 */,
  483. const int* thirdEffIndex /* nObs x 1 */,
  484. const double* obs /* nObs x 1 */,
  485. const double* priorMean /* nLevelsThisEff x nFactors */,
  486. const double* otherEff /* nLevelsOtherEff x nFactors */,
  487. const double* thirdEff /* nLevelsThirdEff x nFactors */,
  488. const double* obsVar /* nObsVar x 1 */,
  489. const double* priorVar /* nPriorVar x 1 */,
  490. const int* nObs, const int* nLevelsThisEff, const int* nLevelsOtherEff, const int* nLevelsThirdEff,
  491. const int* nFactors, const int* nObsVar /* 1 or nObs */,
  492. const int *nPriorVar /* 1 or nLevelsThisEff*nFactors*nFactors */,
  493. const int* obsIndex, const int* oiStart, const int* oiNum,
  494. // OTHER
  495. const int* debug
  496. ){
  497. double *sum_vv /*nFactors x nFactors*/, *sum_ov /*nFactors x 1*/, o, *vj /*nFactors x 1*/, *Gwi /*nFactors x 1*/,
  498. *work, size, *mean, *var, *temp, *rnd;
  499. int i,j,k,m, thisIndex, otherIndex, outputSample, outputMeanVar, oIndex, lwork=-1, info, symCheck;
  500. char jobz = 'V', uplo = 'L';
  501. symCheck = (*debug) - 2;
  502. if(*option == 1){
  503. outputSample = 1; outputMeanVar = 0;
  504. }else if(*option == 2){
  505. outputSample = 0; outputMeanVar = 1;
  506. }else if(*option == 3){
  507. outputSample = 1; outputMeanVar = 1;
  508. }else error("Unknown option: %d", *option);
  509. vj = (double*)Calloc(*nFactors, double);
  510. Gwi = (double*)Calloc(*nFactors, double);
  511. sum_ov = (double*)Calloc(*nFactors, double);
  512. sum_vv = (double*)Calloc((*nFactors)*(*nFactors), double);
  513. mean = (double*)Calloc(*nFactors, double);
  514. var = (double*)Calloc((*nFactors)*(*nFactors), double);
  515. temp = (double*)Calloc((*nFactors)*(*nFactors), double);
  516. if(outputSample) GetRNGstate();
  517. for(i=0; i<*nLevelsThisEff; i++){
  518. thisIndex = i+1;
  519. for(j=0; j<*nFactors; j++) sum_ov[j] = 0;
  520. for(j=0; j<(*nFactors)*(*nFactors); j++) sum_vv[j] = 0;
  521. for(j=0; j<oiNum[i]; j++){
  522. oIndex = obsIndex[R_VEC(oiStart[i]+j)];
  523. otherIndex = otherEffIndex[R_VEC(oIndex)];
  524. if(*debug > 0) CHK_R_INDEX(oIndex, *nObs);
  525. if(*debug > 0) CHK_R_INDEX(otherIndex, *nLevelsOtherEff);
  526. if(*debug > 1) if(thisEffIndex[R_VEC(oIndex)] != i+1) error("error in obsIndex, oiStart, oiNum\n");
  527. o = obs[R_VEC(oIndex)];
  528. if((*nLevelsThirdEff) > 0){
  529. int thirdIndex = thirdEffIndex[R_VEC(oIndex)];
  530. if(*debug > 0) CHK_R_INDEX(thirdIndex, *nLevelsThirdEff);
  531. for(k=1; k<=*nFactors; k++)
  532. vj[R_VEC(k)] = otherEff[R_MAT(otherIndex,k,*nLevelsOtherEff)] *
  533. thirdEff[R_MAT(thirdIndex,k,*nLevelsThirdEff)];
  534. }else{
  535. for(k=1; k<=*nFactors; k++) vj[R_VEC(k)] = otherEff[R_MAT(otherIndex,k,*nLevelsOtherEff)];
  536. }
  537. double var_y_thisObs = 0;
  538. if((*nObsVar) == 1) var_y_thisObs = obsVar[0];
  539. else if((*nObsVar) == (*nObs)) var_y_thisObs = obsVar[R_VEC(oIndex)];
  540. else error("nVar_y = %d, nObs = %d", *nObsVar, *nObs);
  541. for(k=0; k<*nFactors; k++) sum_ov[k] += (o * vj[k]) / var_y_thisObs;
  542. for(k=0; k<*nFactors; k++)
  543. for(m=0; m<*nFactors; m++) sum_vv[C_MAT(k,m,*nFactors)] += (vj[k] * vj[m]) / var_y_thisObs;
  544. }
  545. for(k=1; k<=*nFactors; k++) Gwi[R_VEC(k)] = priorMean[R_MAT(thisIndex,k,*nLevelsThisEff)];
  546. if((*nPriorVar) == 1){
  547. for(k=0; k<*nFactors; k++) sum_vv[C_MAT(k,k,*nFactors)] += (1/priorVar[0]);
  548. for(k=0; k<*nFactors; k++) Gwi[k] /= priorVar[0];
  549. }else if((*nPriorVar) == (*nFactors)){
  550. for(k=0; k<*nFactors; k++) sum_vv[C_MAT(k,k,*nFactors)] += (1/priorVar[k]);
  551. for(k=0; k<*nFactors; k++) Gwi[k] /= priorVar[k];
  552. }else if((*nPriorVar) == (*nLevelsThisEff)*(*nFactors)*(*nFactors)){
  553. for(k=0; k<*nFactors; k++)
  554. for(m=0; m<*nFactors; m++) temp[C_MAT(k,m,*nFactors)] = priorVar[C_3DA(i,k,m,*nLevelsThisEff,*nFactors)];
  555. sym_inv_byCholesky(temp, nFactors, &symCheck);
  556. // Now, temp is var_u[i]^-1
  557. for(k=0; k<*nFactors; k++)
  558. for(m=0; m<*nFactors; m++) sum_vv[C_MAT(k,m,*nFactors)] += temp[C_MAT(k,m,*nFactors)];
  559. // reuse the space of vj
  560. for(k=0; k<*nFactors; k++) vj[k] = Gwi[k];
  561. for(k=0; k<*nFactors; k++){
  562. Gwi[k] = 0;
  563. for(m=0; m<*nFactors; m++) Gwi[k] += temp[C_MAT(k,m,*nFactors)] * vj[m];
  564. }
  565. }else error("nVar_eff = %d, nThisEff = %d", *nPriorVar, *nLevelsThisEff);
  566. // Now, sum_vv = var^-1
  567. // Gwi = var_u[i]^-1 G wi
  568. if((*nFactors) == 1){
  569. var[0] = 1/sum_vv[0];
  570. mean[0] = var[0] * (sum_ov[0] + Gwi[0]);
  571. if(outputSample){
  572. sample[i] = rnorm(mean[0], sqrt(var[0]));
  573. }
  574. if(outputMeanVar){
  575. posteriorMean[i] = mean[0];
  576. posteriorVar[i] = var[0];
  577. }
  578. }else{
  579. double *eigen_val, *eigen_vec;
  580. eigen_val = vj;
  581. eigen_vec = sum_vv;
  582. if(*debug > 2) CHK_SYMMETRIC(eigen_vec, *nFactors);
  583. //
  584. // Compute the variance-covariance matrix
  585. //
  586. // Allocate workspace for eigen value decomposition (only allocate once)
  587. if(lwork == -1){
  588. F77_NAME(dsyev)(&jobz, &uplo, nFactors, eigen_vec, nFactors, eigen_val, &size, &lwork, &info);
  589. if(info != 0) error("error in dsyev(...)");
  590. lwork = (int)size;
  591. work = (double*)Calloc(lwork, double);
  592. }
  593. F77_NAME(dsyev)(&jobz, &uplo, nFactors, eigen_vec, nFactors, eigen_val, work, &lwork, &info);
  594. if(info != 0) error("error in dsyev(...)");
  595. for(j=0; j<*nFactors; j++) eigen_val[j] = 1/eigen_val[j];
  596. // Now, eigen_val, eigen_vec are the eigen values and vectors of var
  597. for(j=0; j<*nFactors; j++)
  598. for(k=0; k<*nFactors; k++) temp[C_MAT(j,k,*nFactors)] = eigen_vec[C_MAT(j,k,*nFactors)] * eigen_val[k];
  599. for(j=0; j<*nFactors; j++)
  600. for(k=0; k<*nFactors; k++){
  601. var[C_MAT(j,k,*nFactors)] = 0;
  602. for(m=0; m<*nFactors; m++) var[C_MAT(j,k,*nFactors)] += temp[C_MAT(j,m,*nFactors)] * eigen_vec[C_MAT(k,m,*nFactors)];
  603. }
  604. // Now, var is the variance-covariance matrix
  605. //
  606. // Compute the mean vector
  607. //
  608. for(j=0; j<*nFactors; j++) sum_ov[j] += Gwi[j];
  609. for(j=0; j<*nFactors; j++){
  610. mean[j] = 0;
  611. for(k=0; k<*nFactors; k++) mean[j] += var[C_MAT(j,k,*nFactors)] * sum_ov[k];
  612. }
  613. if(outputMeanVar){
  614. for(j=0; j<*nFactors; j++) posteriorMean[C_MAT(i,j,*nLevelsThisEff)] = mean[j];
  615. for(j=0; j<*nFactors; j++)
  616. for(k=0; k<*nFactors; k++) posteriorVar[C_3DA(i,j,k,*nLevelsThisEff,*nFactors)] = var[C_MAT(j,k,*nFactors)];
  617. }
  618. if(*debug >= 2 && oiNum[i] == 0){
  619. // printf("i = %d\n",i);
  620. // print_vector(" mean: ", mean, *nFactors);
  621. // print_matrix(" var: ", var, *nFactors, *nFactors);
  622. // print_vector("prior_var: ", priorVar, *nPriorVar);
  623. for(k=1; k<=*nFactors; k++){
  624. CHK_SAME_NUMBER("mean[k] != fittedEff[k]", mean[R_VEC(k)], priorMean[R_MAT(thisIndex,k,*nLevelsThisEff)]);
  625. }
  626. if((*nPriorVar) == 1){
  627. for(j=0; j<*nFactors; j++)
  628. for(k=0; k<*nFactors; k++){
  629. if(j==k){ CHK_SAME_NUMBER("var != var_eff", var[C_MAT(j,k,*nFactors)], priorVar[0]);}
  630. else{ CHK_SAME_NUMBER("var != var_eff", var[C_MAT(j,k,*nFactors)], 0);}
  631. }
  632. }else if((*nPriorVar) == (*nFactors)){
  633. for(j=0; j<*nFactors; j++)
  634. for(k=0; k<*nFactors; k++){
  635. if(j==k){ CHK_SAME_NUMBER("var != var_eff", var[C_MAT(j,k,*nFactors)], priorVar[k]);}
  636. else{ CHK_SAME_NUMBER("var != var_eff", var[C_MAT(j,k,*nFactors)], 0);}
  637. }
  638. }else{
  639. for(j=0; j<*nFactors; j++)
  640. for(k=0; k<*nFactors; k++){
  641. CHK_SAME_NUMBER("var != var_eff", var[C_MAT(j,k,*nFactors)], priorVar[C_3DA(i,j,k,*nLevelsThisEff,*nFactors)]);
  642. }
  643. }
  644. }
  645. //
  646. // Generate the random vector
  647. //
  648. if(outputSample){
  649. // reuse the space allocated for Gwi
  650. rnd = Gwi;
  651. for(j=0; j<*nFactors; j++) eigen_val[j] = sqrt(eigen_val[j]);
  652. for(j=0; j<*nFactors; j++)
  653. for(k=0; k<*nFactors; k++) temp[C_MAT(j,k,*nFactors)] = eigen_vec[C_MAT(j,k,*nFactors)] * eigen_val[k];
  654. for(j=0; j<*nFactors; j++) rnd[j] = norm_rand();
  655. for(j=0; j<*nFactors; j++){
  656. sample[C_MAT(i,j,*nLevelsThisEff)] = mean[j];
  657. for(k=0; k<*nFactors; k++) sample[C_MAT(i,j,*nLevelsThisEff)] += temp[C_MAT(j,k,*nFactors)] * rnd[k];
  658. }
  659. }
  660. }
  661. }
  662. if(outputSample) PutRNGstate();
  663. Free(sum_ov);
  664. Free(sum_vv);
  665. Free(vj);
  666. Free(Gwi);
  667. Free(mean);
  668. Free(var);
  669. Free(temp);
  670. if(lwork > 0) Free(work);
  671. }
  672. void gaussianPosterior_SelfPlusOneInteraction(
  673. // IN/OUT
  674. double* sample /* the current sample: nLevelsThisEff x nFactors */,
  675. // OUTPUT
  676. double* posteriorMean, /* nLevelsThisEff x nFactors */
  677. double* posteriorVar, /* nLevelsThisEff x nFactors x nFactors */
  678. // INPUT
  679. const int* option /*1: output sample, 2: output mean & var, 3: output sample & Mean & Var*/,
  680. const int* fromIndex /* nObs x 1 */,
  681. const int* toIndex /* nObs x 1 */,
  682. const int* thirdEffIndex /* nObs x 1 */,
  683. const double* obs /* nObs x 1 */,
  684. const double* priorMean /* nLevelsThisEff x nFactors */,
  685. const double* obsVar /* nObsVar x 1 */,
  686. const double* priorVar /* nPriorVar x 1 */,
  687. const double* thirdEff /* nLevelsThirdEff x nFactors */,
  688. const int* nObs, const int* nLevelsThisEff, const int* nLevelsThirdEff, const int* nFactors,
  689. const int* nObsVar /* 1 or nObs */,
  690. const int *nPriorVar /* 1 or nLevelsThisEff*nFactors*nFactors */,
  691. const int* from_obsIndex, const int* from_oiStart, const int* from_oiNum,
  692. const int* to_obsIndex, const int* to_oiStart, const int* to_oiNum,
  693. // OTHER
  694. const int* debug
  695. ){
  696. double *sum_vv /*nFactors x nFactors*/, *sum_ov /*nFactors x 1*/, o, *vj /*nFactors x 1*/, *Gwi /*nFactors x 1*/,
  697. *work, size, *mean, *var, *temp, *rnd;
  698. int i,j,k,m, thisIndex, otherIndex, outputMeanVar, oIndex, lwork=-1, info, symCheck, role;
  699. char jobz = 'V', uplo = 'L';
  700. symCheck = (*debug) - 2;
  701. if(*option == 1){
  702. outputMeanVar = 0;
  703. }else if(*option == 2){
  704. outputMeanVar = 1;
  705. }else if(*option == 3){
  706. outputMeanVar = 1;
  707. }else error("Unknown option: %d", *option);
  708. vj = (double*)Calloc(*nFactors, double);
  709. Gwi = (double*)Calloc(*nFactors, double);
  710. sum_ov = (double*)Calloc(*nFactors, double);
  711. sum_vv = (double*)Calloc((*nFactors)*(*nFactors), double);
  712. mean = (double*)Calloc(*nFactors, double);
  713. var = (double*)Calloc((*nFactors)*(*nFactors), double);
  714. temp = (double*)Calloc((*nFactors)*(*nFactors), double);
  715. GetRNGstate();
  716. for(i=0; i<*nLevelsThisEff; i++){
  717. thisIndex = i+1;
  718. for(j=0; j<*nFactors; j++) sum_ov[j] = 0;
  719. for(j=0; j<(*nFactors)*(*nFactors); j++) sum_vv[j] = 0;
  720. int nObs_for_i = 0;
  721. // begin: compute sum_ov and sum_vv
  722. for(role=0; role<2; role++){
  723. int *obsIndex = NULL, *oiNum = NULL, *oiStart=NULL, *thisEffIndex=NULL, *otherEffIndex=NULL;
  724. if(role == 0){
  725. // user i is an author
  726. obsIndex = (int*)to_obsIndex; oiNum = (int*)to_oiNum; oiStart = (int*)to_oiStart;
  727. thisEffIndex = (int*)toIndex; otherEffIndex = (int*)fromIndex;
  728. }else if(role == 1){
  729. // user i is an voter
  730. obsIndex = (int*)from_obsIndex; oiNum = (int*)from_oiNum; oiStart = (int*)from_oiStart;
  731. thisEffIndex = (int*)fromIndex; otherEffIndex = (int*)toIndex;
  732. }else DIE_HERE;
  733. for(j=0; j<oiNum[i]; j++){
  734. nObs_for_i++;
  735. oIndex = obsIndex[R_VEC(oiStart[i]+j)];
  736. otherIndex = otherEffIndex[R_VEC(oIndex)];
  737. if(otherIndex == i+1) error("self votes are not allowed");
  738. if(*debug > 0) CHK_R_INDEX(oIndex, *nObs);
  739. if(*debug > 0) CHK_R_INDEX(otherIndex, *nLevelsThisEff);
  740. if(*debug > 1) if(thisEffIndex[R_VEC(oIndex)] != i+1) error("error in obsIndex, oiStart, oiNum\n");
  741. o = obs[R_VEC(oIndex)];
  742. if((*nLevelsThirdEff) > 0){
  743. int thirdIndex = thirdEffIndex[R_VEC(oIndex)];
  744. if(*debug > 0) CHK_R_INDEX(thirdIndex, *nLevelsThirdEff);
  745. for(k=1; k<=*nFactors; k++)
  746. vj[R_VEC(k)] = sample[R_MAT(otherIndex,k,*nLevelsThisEff)] *
  747. thirdEff[R_MAT(thirdIndex,k,*nLevelsThirdEff)];
  748. }else{
  749. for(k=1; k<=*nFactors; k++) vj[R_VEC(k)] = sample[R_MAT(otherIndex,k,*nLevelsThisEff)];
  750. }
  751. double var_y_thisObs = 0;
  752. if((*nObsVar) == 1) var_y_thisObs = obsVar[0];
  753. else if((*nObsVar) == (*nObs)) var_y_thisObs = obsVar[R_VEC(oIndex)];
  754. else error("nVar_y = %d, nObs = %d", *nObsVar, *nObs);
  755. for(k=0; k<*nFactors; k++) sum_ov[k] += (o * vj[k]) / var_y_thisObs;
  756. for(k=0; k<*nFactors; k++)
  757. for(m=0; m<*nFactors; m++) sum_vv[C_MAT(k,m,*nFactors)] += (vj[k] * vj[m]) / var_y_thisObs;
  758. }
  759. }
  760. // end: compute sum_ov and sum_vv
  761. for(k=1; k<=*nFactors; k++) Gwi[R_VEC(k)] = priorMean[R_MAT(thisIndex,k,*nLevelsThisEff)];
  762. if((*nPriorVar) == 1){
  763. for(k=0; k<*nFactors; k++) sum_vv[C_MAT(k,k,*nFactors)] += (1/priorVar[0]);
  764. for(k=0; k<*nFactors; k++) Gwi[k] /= priorVar[0];
  765. }else if((*nPriorVar) == (*nFactors)){
  766. for(k=0; k<*nFactors; k++) sum_vv[C_MAT(k,k,*nFactors)] += (1/priorVar[k]);
  767. for(k=0; k<*nFactors; k++) Gwi[k] /= priorVar[k];
  768. }else if((*nPriorVar) == (*nLevelsThisEff)*(*nFactors)*(*nFactors)){
  769. for(k=0; k<*nFactors; k++)
  770. for(m=0; m<*nFactors; m++) temp[C_MAT(k,m,*nFactors)] = priorVar[C_3DA(i,k,m,*nLevelsThisEff,*nFactors)];
  771. sym_inv_byCholesky(temp, nFactors, &symCheck);
  772. // Now, temp is var_u[i]^-1
  773. for(k=0; k<*nFactors; k++)
  774. for(m=0; m<*nFactors; m++) sum_vv[C_MAT(k,m,*nFactors)] += temp[C_MAT(k,m,*nFactors)];
  775. // reuse the space of vj
  776. for(k=0; k<*nFactors; k++) vj[k] = Gwi[k];
  777. for(k=0; k<*nFactors; k++){
  778. Gwi[k] = 0;
  779. for(m=0; m<*nFactors; m++) Gwi[k] += temp[C_MAT(k,m,*nFactors)] * vj[m];
  780. }
  781. }else error("nVar_eff = %d, nThisEff = %d", *nPriorVar, *nLevelsThisEff);
  782. // Now, sum_vv = var^-1
  783. // Gwi = var_u[i]^-1 G wi
  784. if((*nFactors) == 1){
  785. var[0] = 1/sum_vv[0];
  786. mean[0] = var[0] * (sum_ov[0] + Gwi[0]);
  787. sample[i] = rnorm(mean[0], sqrt(var[0]));
  788. if(outputMeanVar){
  789. posteriorMean[i] = mean[0];
  790. posteriorVar[i] = var[0];
  791. }
  792. }else{
  793. double *eigen_val, *eigen_vec;
  794. eigen_val = vj;
  795. eigen_vec = sum_vv;
  796. if(*debug > 2) CHK_SYMMETRIC(eigen_vec, *nFactors);
  797. //
  798. // Compute the variance-covariance matrix
  799. //
  800. // Allocate workspace for eigen value decomposition (only allocate once)
  801. if(lwork == -1){
  802. F77_NAME(dsyev)(&jobz, &uplo, nFactors, eigen_vec, nFactors, eigen_val, &size, &lwork, &info);
  803. if(info != 0) error("error in dsyev(...)");
  804. lwork = (int)size;
  805. work = (double*)Calloc(lwork, double);
  806. }
  807. F77_NAME(dsyev)(&jobz, &uplo, nFactors, eigen_vec, nFactors, eigen_val, work, &lwork, &info);
  808. if(info != 0) error("error in dsyev(...)");
  809. for(j=0; j<*nFactors; j++) eigen_val[j] = 1/eigen_val[j];
  810. // Now, eigen_val, eigen_vec are the eigen values and vectors of var
  811. for(j=0; j<*nFactors; j++)
  812. for(k=0; k<*nFactors; k++) temp[C_MAT(j,k,*nFactors)] = eigen_vec[C_MAT(j,k,*nFactors)] * eigen_val[k];
  813. for(j=0; j<*nFactors; j++)
  814. for(k=0; k<*nFactors; k++){
  815. var[C_MAT(j,k,*nFactors)] = 0;
  816. for(m=0; m<*nFactors; m++) var[C_MAT(j,k,*nFactors)] += temp[C_MAT(j,m,*nFactors)] * eigen_vec[C_MAT(k,m,*nFactors)];
  817. }
  818. // Now, var is the variance-covariance matrix
  819. //
  820. // Compute the mean vector
  821. //
  822. for(j=0; j<*nFactors; j++) sum_ov[j] += Gwi[j];
  823. for(j=0; j<*nFactors; j++){
  824. mean[j] = 0;
  825. for(k=0; k<*nFactors; k++) mean[j] += var[C_MAT(j,k,*nFactors)] * sum_ov[k];
  826. }
  827. if(outputMeanVar){
  828. for(j=0; j<*nFactors; j++) posteriorMean[C_MAT(i,j,*nLevelsThisEff)] = mean[j];
  829. for(j=0; j<*nFactors; j++)
  830. for(k=0; k<*nFactors; k++) posteriorVar[C_3DA(i,j,k,*nLevelsThisEff,*nFactors)] = var[C_MAT(j,k,*nFactors)];
  831. }
  832. if(*debug >= 2 && nObs_for_i == 0){
  833. for(k=1; k<=*nFactors; k++){
  834. CHK_SAME_NUMBER("mean[k] != fittedEff[k]", mean[R_VEC(k)], priorMean[R_MAT(thisIndex,k,*nLevelsThisEff)]);
  835. }
  836. if((*nPriorVar) == 1){
  837. for(j=0; j<*nFactors; j++)
  838. for(k=0; k<*nFactors; k++){
  839. if(j==k){ CHK_SAME_NUMBER("var != var_eff", var[C_MAT(j,k,*nFactors)], priorVar[0]);}
  840. else{ CHK_SAME_NUMBER("var != var_eff", var[C_MAT(j,k,*nFactors)], 0);}
  841. }
  842. }else if((*nPriorVar) == (*nFactors)){
  843. for(j=0; j<*nFactors; j++)
  844. for(k=0; k<*nFactors; k++){
  845. if(j==k){ CHK_SAME_NUMBER("var != var_eff", var[C_MAT(j,k,*nFactors)], priorVar[k]);}
  846. else{ CHK_SAME_NUMBER("var != var_eff", var[C_MAT(j,k,*nFactors)], 0);}
  847. }
  848. }else{
  849. for(j=0; j<*nFactors; j++)
  850. for(k=0; k<*nFactors; k++){
  851. CHK_SAME_NUMBER("var != var_eff", var[C_MAT(j,k,*nFactors)], priorVar[C_3DA(i,j,k,*nLevelsThisEff,*nFactors)]);
  852. }
  853. }
  854. }
  855. //
  856. // Generate the random vector
  857. //
  858. // reuse the space allocated for Gwi
  859. rnd = Gwi;
  860. for(j=0; j<*nFactors; j++) eigen_val[j] = sqrt(eigen_val[j]);
  861. for(j=0; j<*nFactors; j++)
  862. for(k=0; k<*nFactors; k++) temp[C_MAT(j,k,*nFactors)] = eigen_vec[C_MAT(j,k,*nFactors)] * eigen_val[k];
  863. for(j=0; j<*nFactors; j++) rnd[j] = norm_rand();
  864. for(j=0; j<*nFactors; j++){
  865. sample[C_MAT(i,j,*nLevelsThisEff)] = mean[j];
  866. for(k=0; k<*nFactors; k++) sample[C_MAT(i,j,*nLevelsThisEff)] += temp[C_MAT(j,k,*nFactors)] * rnd[k];
  867. }
  868. }
  869. }
  870. PutRNGstate();
  871. Free(sum_ov); Free(sum_vv); Free(vj); Free(Gwi);
  872. Free(mean); Free(var); Free(temp);
  873. if(lwork > 0) Free(work);
  874. }
  875. /**
  876. * contextSample can be set the same as contextPosteriorMean
  877. * globalSample can be set the same as globalPosteriorMean
  878. * If so, the output will be the sample only.
  879. */
  880. void gaussianPosterior_mainEffect_2Levels(
  881. // OUTPUT
  882. double* contextSample /* nLevelsThisEff x nContexts */,
  883. double* globalSample /* nLevelsThisEff x 1 */,
  884. double* contextPosteriorMean /* nLevelsThisEff x nContexts: This is the posterior given the globalSample */,
  885. double* contextPosteriorVar /* nLevelsThisEff x nContexts: This is the posterior given the globalSample */,
  886. double* globalPosteriorMean /* nLevelsThisEff x 1 */,
  887. double* globalPosteriorVar /* nLevelsThisEff x 1 */,
  888. //INPUT
  889. const int* thisEffIndex /* nObs x 1 */,
  890. const int* context /* nObs x 1 */,
  891. const double* obs /* nObs x 1 */,
  892. const double* q /* nContext x 1 */,
  893. const double* contextOffset, /* nLevelsThisEff x nContexts */
  894. const double* obsVar /* nObsVar x 1 */,
  895. const double* contextPriorVar /* see nContextPriorVar */,
  896. const double* globalPriorVar /* see nGlobalPriorVar */,
  897. const int* numObs, const int* numLevelsThisEff, const int* numContexts,
  898. const int* numObsVar /* 1 or nObs */,
  899. const int* numContextPriorVar /* nContexts or nLevelsThisEff*nContexts */,
  900. const int* numGlobalPriorVar /* 1 or nLevelsThisEff */,
  901. const int* numContextOffset /* 0 or nLevelsThisEff or nLevelsThisEff*nContexts */,
  902. // OTHER
  903. const int* debug, const int* verbose
  904. ){
  905. const int nObs = (*numObs), nItems = (*numLevelsThisEff), nCategories = (*numContexts),
  906. nObsVar = (*numObsVar), nContextPriorVar = (*numContextPriorVar), nGlobalPriorVar = (*numGlobalPriorVar),
  907. nCatOffset = (*numContextOffset);
  908. const int *itemIndex = thisEffIndex, *categoryIndex=context;
  909. double *b_mean=contextPosteriorMean, *b_var=contextPosteriorVar,
  910. *a_mean=globalPosteriorMean, *a_var=globalPosteriorVar;
  911. const double *b_offset=contextOffset, *var_obs=obsVar, *var_b=contextPriorVar, *var_a=globalPriorVar;
  912. // Model:
  913. // obs[n] ~ N(mean=b[i,k], var=var_obs[n])
  914. // b[i,k] ~ N(mean=b_offset[i,k] + q[k]*a[i], var=var_b[i,k])
  915. // a[i] ~ N(mean=0, var=var_a[i])
  916. if(nObsVar != 1 && nObsVar != nObs) error("nObsVar != 1 && nObsVar != nObs");
  917. if(nContextPriorVar != nCategories && nContextPriorVar != nItems*nCategories) error("nContextPriorVar != nCategories && nContextPriorVar != nItem*nCategories");
  918. if(nGlobalPriorVar != 1 && nGlobalPriorVar != nItems) error("nContextPriorVar != nCategories && nContextPriorVar != nItem*nCategories");
  919. // Compute sufficient statistics
  920. // b_mean[i,k] = sum_j { o_{ijk}/var_obs_{ijk} } = C_ik
  921. // b_var[i,k] = sum_j { 1/var_obs_{ijk} } = F_ik
  922. for(int n=0; n < nItems*nCategories; n++){ b_mean[n] = 0; b_var[n] = 0; }
  923. for(int j=0; j<nObs; j++){
  924. int i = itemIndex[j] - 1; CHK_C_INDEX(i,nItems);
  925. int k = categoryIndex[j] - 1; CHK_C_INDEX(k,nCategories);
  926. int ik = C_MAT(i,k,nItems);
  927. double var = (nObsVar==1 ? var_obs[0] : var_obs[j]);
  928. double o = obs[j];
  929. if(nCatOffset == nItems) o -= b_offset[i];
  930. else if(nCatOffset == nItems*nCategories) o -= b_offset[ik];
  931. else if(nCatOffset != 0) error("nCatOffset = %d", nCatOffset);
  932. b_mean[ik] += o / var;
  933. b_var[ik] += 1 / var;
  934. }
  935. GetRNGstate();
  936. // Compute E[a[i] | obs] and Var[a[i] | obs]
  937. for(int i=0; i<nItems; i++){
  938. double sum_for_mean = 0; // sum_k E[a_i | obs_ik]/Var[a_i | obs_ik]
  939. double sum_for_var = 0; // sum_k (1/Var[a_i | obs_ik] - 1/var_a)
  940. for(int k=0; k<nCategories; k++){
  941. double var_b_this = (nContextPriorVar==nCategories ? var_b[k] : var_b[C_MAT(i,k,nItems)]);
  942. double F = b_var[C_MAT(i,k,nItems)];
  943. if(F == 0) continue;
  944. double C = b_mean[C_MAT(i,k,nItems)];
  945. if(var_b_this > 0){
  946. double A = (1/var_b_this) + F;
  947. // E[a_i | obs_ik]/Var[a_i | obs_ik] = (C * q[k]) / (A * var_b[k])
  948. // (1/Var[a_i | obs_ik] - 1/var_a) = (q[k]^2 / var_b[k]) * (1 - 1/(A * var_b[k]))
  949. sum_for_mean += (C * q[k]) / (A * var_b_this);
  950. sum_for_var += (q[k]*q[k] / var_b_this) * (1 - 1/(A * var_b_this));
  951. }else if(var_b_this == 0){
  952. STOP("not yet support prior var = 0");
  953. }else STOP("var_b_this < 0");
  954. }
  955. if((*verbose) >= 100) printf(" i=%d: sum.for.a.mean=%f, sum.for.a.var=%f\n", i+1, sum_for_mean, sum_for_var);
  956. // Compute E[a[i] | obs] and Var[a[i] | obs]
  957. double var_a_this = (nGlobalPriorVar==1 ? var_a[0] : var_a[i]);
  958. a_var[i] = 1/( (1/var_a_this) + sum_for_var );
  959. a_mean[i] = a_var[i] * sum_for_mean;
  960. // draw for the globalSample
  961. globalSample[i] = rnorm(a_mean[i], sqrt(a_var[i]));
  962. }
  963. // Compute E[b[i,k] | a, obs] and Var[b[i,k] | a, obs]
  964. for(int i=0; i<nItems; i++){ for(int k=0; k<nCategories; k++){
  965. int ik = C_MAT(i,k,nItems);
  966. double var_b_this = (nContextPriorVar==nCategories ? var_b[k] : var_b[C_MAT(i,k,nItems)]);
  967. double A = 1 / ( (1/var_b_this) + b_var[ik] );
  968. double D = (A * q[k]) / var_b_this;
  969. b_mean[ik] = D * globalSample[i] + A * b_mean[ik];
  970. b_var[ik] = A;
  971. if(nCatOffset == nItems) b_mean[ik] += b_offset[i];
  972. else if(nCatOffset == nItems*nCategories) b_mean[ik] += b_offset[ik];
  973. else if(nCatOffset != 0) error("nCatOffset = %d", nCatOffset);
  974. contextSample[ik] = rnorm(b_mean[ik], sqrt(b_var[ik]));
  975. }}
  976. PutRNGstate();
  977. }