从std :: vector到adept :: avector

时间:2018-07-28 18:41:14

标签: c++ rcpp

我想在R的软件包中嵌入一些熟练的优化方法。请参见下面的最小示例。我需要将x(和b)的值传递给该函数。默认情况下,它们以Rcpp:NumericVector的形式出现,可以轻松转换为std :: vector或双精度数组,例如

std::vector<double> inx_std(inx.begin(),inx.end());
double* inx_d = inx_std.data();

但是,我在将其传递给avector时遇到了麻烦。 avector a = inx_d不起作用。我创建了一个for循环,并且一切正常,但是必须有一种更好的方法来实现。

下面的代码示例。

#include <Rcpp.h>
#include "adept_source.h"
#include <adept_arrays.h>                

using namespace Rcpp;
using namespace adept;


// [[Rcpp::export]]
NumericVector run(NumericVector inx, NumericVector inb) {
  int inxsize=inx.size();       // dim of gradient
  NumericVector out(inxsize);   // output vector

  //adept main 

  Stack stack;                    // Object to store differential statements
  aVector x(inxsize);             // Independent variables: active vector with inxsize elements
  aVector b(inxsize);             // Independent variables: active vector with inxsize elements
  for(int i=0; i<inxsize; i++) {  // Fill vector
    x[i]=inx(i);
    b[i]=inb(i);
  }

  stack.new_recording();          // Clear any existing differential statements

  //function to be differentiated 
  aReal J = sum(log(x)/log(b));   // Compute dependent variable: L3-norm in this case


  //adept main
  J.set_gradient(1.0);             // Seed the dependent variable
  stack.reverse();                 // Reverse-mode differentiation

  //return gradient from adept to R
  for(int i=0; i<inxsize; i++) {
    out[i]=x[i].get_gradient();
  }

  return out;
}

1 个答案:

答案 0 :(得分:2)

基于JHBonarius的有用评论和Dirk关于指针的提示,我创建了以下通过Rcpp在R中使用adept的最小示例:

#include <Rcpp.h>
#include <adept_source.h>
#include <adept_arrays.h>                

using namespace Rcpp;
using namespace adept;


// [[Rcpp::export]]
NumericVector run(NumericVector inx, NumericVector inb, double gamma) {
  int inxsize=inx.size();       // dim of gradient
  NumericVector out(inxsize);   // output vector

  //convert inputs to adept arrays
  adept::Vector inxV(inx.begin(), dimensions(inxsize) );  
  adept::Vector b(inb.begin(), dimensions(inxsize) );  

  //adept main 
  Stack stack;                    // Object to store differential statements
  adept::aVector x = inxV;

  stack.new_recording();          // Clear any existing differential statements

  //function to be differentiated
  aReal J = gamma*sum(log(x)/log(b));   // Compute dependent variable


  //adept main
  J.set_gradient(1.0);             // Seed the dependent variable
  stack.reverse();                 // Reverse-mode differentiation


  //return gradient from adept to R
  for(int i=0; i<inxsize; i++) {
    out[i]=x[i].get_gradient();
  }

  return out;
}

/*** R
run(1:3,rep(exp(1),3),1)
*/

解决方案的关键要素是:

(1)使用适当的构造函数创建adept :: Vector,并使用一个指向输入Rcpp :: Numericvector的指针,称为inx:

adept::Vector inxV(inx.begin(), dimensions(inxsize) )

(2)然后可以将感兴趣的向量(我们要为其计算偏导数)变成“活动”向量:

adept::aVector x = inxV;