Rcpp和main/optim.c – 在通过`nmmin()`传递变量后如何翻译`void *ex`?

huangapple go评论107阅读模式
英文:

Rcpp & main/optim.c - How to translate `void *ex` after passing the variable through `nmmin()`?

问题

抱歉,你的要求是只返回翻译好的代码部分,我将为你提取代码部分并进行翻译。请注意,以下是代码的翻译部分:

  1. #include <RcppCommon.h>
  2. typedef struct {
  3. double *xi;
  4. int xil;
  5. int zrows;
  6. int zcols;
  7. double *zdata;
  8. double *denom;
  9. int denoml;
  10. } Ething;
  11. #include <Rcpp.h>
  12. // 帮助函数在这里:
  13. // ...
  14. // 定义 optimfn 函数:
  15. typedef double optimfn(int n, double *par, void *ex);
  16. double elnlikeB(int n, double *par, void *ex) {
  17. Rcpp::Rcout << "entering elnlikeB\n";
  18. Rcpp::Rcout << "The value of ex: " << ex << "\n";
  19. Ething *et = (Ething *) ex;
  20. Rcpp::Rcout << "The value of et : " << et << "\n";
  21. Rcpp::Rcout << "making z\n";
  22. int zrows = et->zrows;
  23. int zcols = et->zcols;
  24. double *z = et->zdata;
  25. Rcpp::NumericMatrix Zprobsmat;
  26. int count = 0;
  27. for (int x = 0; x < zcols; x++) {
  28. for (int y = 0; y < zrows; y++) {
  29. Zprobsmat(y, x) = z[count]; // 行,列
  30. count = count + 1;
  31. }
  32. }
  33. Rcpp::Rcout << "The value of zprob : " << Zprobsmat << "\n";
  34. // 其他部分的翻译省略...
  35. }
  36. optimfn elnlikeB;
  37. // 更多帮助函数
  38. extern "C" {
  39. void nmmin(int n, double *xin, double *x, double *Fmin, optimfn fn,
  40. int *fail, double abstol, double intol, void *ex,
  41. double alpha, double beta, double gamma, int trace,
  42. int *fncount, int maxit);
  43. }
  44. // [[Rcpp::export]]
  45. Rcpp::List optim_test(Rcpp::List eout) {
  46. Rcpp::Rcout << "starting\n";
  47. // 其他部分的翻译省略...
  48. }

这是你提供的代码的翻译版本。请注意,这只是代码的一部分,其中包括函数和结构的定义以及部分函数实现。如果需要完整的代码翻译,请提供完整的代码。

英文:

Main question: How to format a complex struct in Rcpp that will be accepted by optim.c? and how will this struct be modified when returned to the defined optimfn function?

Background: I'm writing an EM algorithm in Rcpp that will be used in a beta mixture model. I am trying to use a simple nelder mead numerical optimization approach through the R API (nmmin), however I am having a hard time passing the variable list through. I'm very very new to C++/Rcpp.

Information:

eout countains:

  • zprobs: a matrix (double[45203x5]). (the number of col and rows will vary).
  • parmlist: a list which contains lists avec, mvec, and svec (each list of 5 doubles). (the length will vary).
  • xi: a list of doubles of length 45203. (the length will vary).
  • denom: a list of doubles of length 45203. (the length will vary).

To pass my variables through to nmmin, I've tried to convert it to a struct format by first converting the NumericMatrix and NumericVector into double *var, (but I then learned these are not real (edit: that these do not hold vectors)), followed by creating an object with my defined struct with these items. The current method is able to compile, but I am not sure what *ex looks like when it enters the enlikeB function. I also tried to convert the Rcpp::List items to std::vectors, in case these were possible to pass through.

Where I am currently:

  1. #include &lt;RcppCommon.h&gt;
  2. typedef struct{
  3. double *xi;
  4. int xil;
  5. int zrows;
  6. int zcols;
  7. double *zdata;
  8. double *denom;
  9. int denoml;
  10. }Ething;
  11. #include &lt;Rcpp.h&gt;
  12. //HELPER FUNCTIONS HERE:
  13. //
  14. // Defining the optimfn function:
  15. typedef double optimfn(int n, double *par, void *ex);
  16. double elnlikeB(int n, double *par, void *ex) {
  17. Rcpp::Rcout &lt;&lt; &quot;entering elnlikeB\n&quot;;
  18. Rcpp::Rcout &lt;&lt; &quot;The value of ex: &quot; &lt;&lt; ex &lt;&lt; &quot;\n&quot;;
  19. Ething *et = (Ething *) ex;
  20. Rcpp::Rcout &lt;&lt; &quot;The value of et : &quot; &lt;&lt; et &lt;&lt; &quot;\n&quot;;
  21. Rcpp::Rcout &lt;&lt; &quot;making z\n&quot;;
  22. int zrows = et -&gt;zrows;
  23. int zcols = et -&gt;zcols;
  24. double *z = et -&gt;zdata;
  25. Rcpp::NumericMatrix Zprobsmat;
  26. int count = 0;
  27. for(int x = 0; x &lt; zcols; x++) {
  28. for(int y = 0; y &lt; zrows; y++) {
  29. Zprobsmat(y, x) = z[count]; //row, column
  30. count = count +1;
  31. }
  32. }
  33. Rcpp::Rcout &lt;&lt; &quot;The value of zprob : &quot; &lt;&lt; Zprobsmat &lt;&lt; &quot;\n&quot;;
  34. Rcpp::Rcout &lt;&lt; &quot;making xi\n&quot;;
  35. int xil = et -&gt; xil;
  36. double *xid = et -&gt; xi;
  37. Rcpp::NumericVector xi;
  38. for(int nn = 0; nn &lt; xil; nn++){
  39. xi[nn] = xid[nn];
  40. }
  41. Rcpp::Rcout &lt;&lt; &quot;The value of xi : &quot; &lt;&lt; xi &lt;&lt; &quot;\n&quot;;
  42. Rcpp::Rcout &lt;&lt; &quot;making denom\n&quot;;
  43. int denoml = et -&gt;denoml;
  44. double *denomd = et -&gt; denom;
  45. Rcpp::NumericVector denom;
  46. for(int nn = 0; nn &lt; denoml; nn++){
  47. denom[nn] = denomd[nn];
  48. }
  49. Rcpp::Rcout &lt;&lt; &quot;The value of denom: &quot; &lt;&lt; denom &lt;&lt; &quot;\n&quot;;
  50. Rcpp::Rcout &lt;&lt; &quot;making myguess\n&quot;;
  51. Rcpp::NumericVector myguess;
  52. for(int nn = 0; nn &lt; n; nn++){
  53. myguess[nn] = par[nn];
  54. }
  55. Rcpp::Rcout &lt;&lt; &quot;The value of myguess: &quot; &lt;&lt; myguess &lt;&lt; &quot;\n&quot;;
  56. //This section works is the vectors and matrix are correct//
  57. Rcpp::Rcout &lt;&lt; &quot;calculating\n&quot;;
  58. int nnew = xi.size();
  59. int nmixt = Zprobsmat.ncol();
  60. int gsize = myguess.size();
  61. Rcpp::NumericVector avec(nmixt);
  62. avec[Rcpp::Range(0, (nmixt - 2))] = invmlogitc(myguess[Rcpp::Range(0, (nmixt - 2))]);
  63. avec[(nmixt-1)] = (1 - rcpp_sum(avec));
  64. Rcpp::NumericVector mvec(nmixt);
  65. Rcpp::NumericVector svec(nmixt);
  66. mvec = mutransform(myguess[Rcpp::Range((nmixt-1), (((nmixt-1)*2)))]);
  67. svec = stransform(myguess[Rcpp::Range((((nmixt-1)*2)+1), (gsize-1))]);
  68. Rcpp::NumericMatrix loglikemat( nnew, nmixt );
  69. Rcpp::NumericMatrix lnfr( nnew, nmixt );
  70. double sum = 0;
  71. for(int i = 0; i &lt; nmixt; i++){
  72. double a = log(avec[i]);
  73. double m = mvec[i];
  74. double s = svec[i];
  75. Rcpp::NumericVector ab = alphabetacalc(m, s);
  76. for( int z = 0; z &lt; nnew; z++){
  77. lnfr(z,i) = (R::dbeta( xi[z], ab[0], ab[1], true));
  78. double left = (Zprobsmat(z,i)/denom[z]);
  79. double right = (a + lnfr(z,i));
  80. loglikemat(z, i) = (left*right);
  81. sum += loglikemat(z, i);
  82. }
  83. }
  84. sum = (-sum);
  85. Rprintf(&quot;sum: %d \n&quot;, sum);
  86. return(sum);
  87. }
  88. optimfn elnlikeB;
  89. //More helpers
  90. extern &quot;C&quot; {
  91. void nmmin(int n, double *xin, double *x, double *Fmin, optimfn fn,
  92. int *fail, double abstol, double intol, void *ex,
  93. double alpha, double beta, double gamma, int trace,
  94. int *fncount, int maxit);
  95. }
  96. // [[Rcpp::export]]
  97. Rcpp::List optim_test(Rcpp::List eout){
  98. Rcpp::Rcout &lt;&lt; &quot;starting\n&quot;;
  99. Rcpp::Rcout &lt;&lt; &quot;making avec, mvec, svec\n&quot;;
  100. Rcpp::List parmlist = eout[&quot;parm.list&quot;];
  101. Rcpp::NumericVector avec = parmlist[&quot;avec&quot;];
  102. Rcpp::NumericVector mvec = parmlist[&quot;mvec&quot;];
  103. Rcpp::NumericVector svec = parmlist[&quot;svec&quot;];
  104. Rcpp::Rcout &lt;&lt; &quot;making zprob and xi \n&quot;;
  105. Rcpp::NumericMatrix Zprobsmat = eout[&quot;zprob&quot;];
  106. Rcpp::NumericVector xi = eout[&quot;xi&quot;];
  107. int xil = xi.size();
  108. Rcpp::NumericVector denom = eout[&quot;denom&quot;];
  109. int denoml = denom.size();
  110. double nmixt = avec.size();
  111. Rcpp::NumericVector mas = mlogitc(avec, nmixt);
  112. Rcpp::Rcout &lt;&lt; &quot;making guess\n&quot;;
  113. int gl = ((nmixt-1) + nmixt + nmixt);
  114. Rcpp::NumericVector guess(gl);
  115. guess[Rcpp::Range(0, (nmixt-2))] = mas;
  116. guess[Rcpp::Range((nmixt-1), ((nmixt-1)*2))] = min(mvec);
  117. guess[Rcpp::Range((((nmixt-1)*2)+1), (gl-1))] = sin(svec);
  118. Rcpp::Rcout &lt;&lt; &quot;making zdata\n&quot;;
  119. int tl = (xil*nmixt);
  120. Rcpp::NumericVector zdata(tl);
  121. int count = 0;
  122. for(int x = 0; x &lt; nmixt; x++) {
  123. for(int y = 0; y &lt; xil; y++) {
  124. zdata[count] = Zprobsmat(y, x); //row, column
  125. count = count +1;
  126. }
  127. }
  128. int zrows = xil;
  129. int zcols = nmixt;
  130. Rcpp::Rcout &lt;&lt; &quot;making et\n&quot;;
  131. Rcpp::List et = Rcpp::List::create(Rcpp::Named(&quot;xi&quot;) = xi, Rcpp::Named(&quot;xil&quot;) = xil,
  132. Rcpp::Named(&quot;zrows&quot;) = zrows,
  133. Rcpp::Named(&quot;zcols&quot;) = zcols,
  134. Rcpp::Named(&quot;zdata&quot;) = zdata, Rcpp::Named(&quot;denom&quot;) = denom,
  135. Rcpp::Named(&quot;denoml&quot;) =denoml);
  136. Rcpp::Rcout &lt;&lt; &quot;making guess vec\n&quot;;
  137. double vec[gl];
  138. for(int nn = 0; nn &lt; gl; nn++){
  139. vec[nn] = guess[nn];
  140. }
  141. double opar[gl];
  142. double Fmin = 0.0;
  143. int fail = 0;
  144. double abstol = 1.0e-8;
  145. double intol = 1.0e-8;
  146. double alpha = 1.0;
  147. double beta = 0.5;
  148. double gamma = 2.0;
  149. int trace =0;
  150. int fncount = 0;
  151. int maxit = 500;
  152. Rcpp::Rcout &lt;&lt; &quot;Attempting nmmin\n&quot;;
  153. nmmin(gl, vec, opar, &amp;Fmin,
  154. elnlikeB, &amp;fail, abstol, intol, &amp;et, alpha, beta,
  155. gamma, trace, &amp;fncount, maxit);
  156. Rcpp::List res = Rcpp::List::create(Rcpp::_[&quot;Fmin&quot;] = Fmin, Rcpp::_[&quot;fail&quot;]=fail);
  157. return(res);`
  158. }

答案1

得分: 0

解决了!

不再使用 typedef struct,我定义了一个类:

  1. class Ething {
  2. public:
  3. double *xi;
  4. int xil;
  5. int zrows;
  6. int zcols;
  7. double *zdata;
  8. double *denom;
  9. int denoml;
  10. Ething(double *xi, int xil, int zrows, int zcols, double *zdata, double *denom, int denoml) : xi(xi), xil(xil), zrows(zrows), zcols(zcols), zdata(zdata), denom(denom), denoml(denoml) {}
  11. };

在将我的数据转换为正确格式后,我能够将 void *ex 对象设置为:

  1. Ething et(xid, xil, zrows, zcols, zdata, denomd, denoml);

这允许您在创建对象时绕过内存/大小设置,并以易于解释的方式传递对象。完整代码将在几个月后在 GitHub 上提供,位于 mgaynor1/nQuack 下。

英文:

Solved!

Instead of typedef struct, I defined a class:

  1. class Ething {
  2. public:
  3. double *xi;
  4. int xil;
  5. int zrows;
  6. int zcols;
  7. double *zdata;
  8. double *denom;
  9. int denoml;
  10. Ething(double *xi, int xil, int zrows, int zcols, double *zdata, double *denom, int denoml) : xi(xi), xil(xil), zrows(zrows), zcols(zcols), zdata(zdata), denom(denom), denoml(denoml) {}
  11. };

After converting my data into the correct format, I was able to make the void *ex object equal to:

  1. Ething et(xid, xil, zrows, zcols, zdata, denomd, denoml);

This allows you to surpass setting the memory/size when creating the object and passes the object as formatted in an easy-to-interpret manner. The full code will be available on github under mgaynor1/nQuack in a few months.

huangapple
  • 本文由 发表于 2023年6月29日 01:00:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/76575299.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定