R在Rcpp中使用stats::optimize,简单的例子编译失败

R use stats::optimize in Rcpp, simple example fails to compile

我想在 Rcpp 中使用 R stats::optimize 函数,因为我找不到 Rcpp 的等效函数。下面的代码是我尝试基于优化帮助中的示例的一个简单示例,但失败了。 这是 R 函数和结果

f <- function (x) (x - .33)^2
xmin <- optimize(f, c(0, 1), tol = 0.0001)
xmin

这个returns

$minimum
[1] 0.333

$objective
[1] 0

这是获取它时失败的 Rcpp 代码。

    #include <Rcpp.h>
    const double tolerance = 1e-0;

   // [[Rcpp::export]]
    Rcpp::NumericVector f(Rcpp::NumericVector x) {
      return pow(x-0.33, 2);
    }
    
    Rcpp::List fTg_opt(const double optmin, const double optmax) {
      Rcpp::Environment base("package:stats");
      Rcpp::Function optimize_r = base["optimize"];    
      Rcpp::NumericVector interval = {optmin,optmax};
      return optimize_r(f, interval, tolerance);
    }

Rstudio 控制台出现以下错误信息。

> Rcpp::sourceCpp("R/cpp/testopt.cpp")
In file included from testopt.cpp:1:
In file included from /Library/Frameworks/R.framework/Versions/4.1/Resources/library/Rcpp/include/Rcpp.h:27:
In file included from /Library/Frameworks/R.framework/Versions/4.1/Resources/library/Rcpp/include/RcppCommon.h:157:
In file included from /Library/Frameworks/R.framework/Versions/4.1/Resources/library/Rcpp/include/Rcpp/traits/traits.h:45:
/Library/Frameworks/R.framework/Versions/4.1/Resources/library/Rcpp/include/Rcpp/traits/is_convertible.h:35:10: error: function cannot return function type 'Rcpp::Vector<14> (Rcpp::Vector<14>)'
                static T MakeT() ;
                       ^
/Library/Frameworks/R.framework/Versions/4.1/Resources/library/Rcpp/include/Rcpp/internal/wrap.h:770:75: note: in instantiation of template class 'Rcpp::traits::is_convertible<Rcpp::Vector<14> (Rcpp::Vector<14>), SEXPREC *>' requested here
            return wrap_dispatch_unknown(object, typename ::Rcpp::traits::is_convertible<T,SEXP>::type());
                                                                          ^
/Library/Frameworks/R.framework/Versions/4.1/Resources/library/Rcpp/include/Rcpp/internal/wrap.h:787:20: note: in instantiation of function template specialization 'Rcpp::internal::wrap_dispatch_eigen<Rcpp::Vector<14> (Rcpp::Vector<14>)>' requested here
            return wrap_dispatch_eigen(object, typename traits::is_eigen_base<T>::type());
                   ^
/Library/Frameworks/R.framework/Versions/4.1/Resources/library/Rcpp/include/Rcpp/internal/wrap.h:807:20: note: in instantiation of function template specialization 'Rcpp::internal::wrap_dispatch_unknown_importable<Rcpp::Vector<14> (Rcpp::Vector<14>)>' requested here
            return wrap_dispatch_unknown_importable(object, typename ::Rcpp::traits::is_importer<T>::type());
                   ^
/Library/Frameworks/R.framework/Versions/4.1/Resources/library/Rcpp/include/Rcpp/internal/wrap_end.h:30:25: note: in instantiation of function template specialization 'Rcpp::internal::wrap_dispatch<Rcpp::Vector<14> (Rcpp::Vector<14>)>' requested here
          return internal::wrap_dispatch( object, typename ::Rcpp::traits::wrap_type_traits<T>::wrap_category() ) ;
                           ^
/Library/Frameworks/R.framework/Versions/4.1/Resources/library/Rcpp/include/Rcpp/grow.h:44:26: note: in instantiation of function template specialization 'Rcpp::wrap<Rcpp::Vector<14> (Rcpp::Vector<14>)>' requested here
            return grow( wrap(head), tail ) ;
                         ^
/Library/Frameworks/R.framework/Versions/4.1/Resources/library/Rcpp/include/Rcpp/grow.h:65:26: note: in instantiation of function template specialization 'Rcpp::internal::grow__dispatch<Rcpp::Vector<14> (Rcpp::Vector<14>)>' requested here
        return internal::grow__dispatch(typename traits::is_named<T>::type(), head, y);
                         ^
/Library/Frameworks/R.framework/Versions/4.1/Resources/library/Rcpp/include/Rcpp/generated/grow__pairlist.h:45:9: note: in instantiation of function template specialization 'Rcpp::grow<Rcpp::Vector<14> (Rcpp::Vector<14>)>' requested here
        return grow( t1, grow( t2, grow( t3, R_NilValue ) ) ) ;
               ^
/Library/Frameworks/R.framework/Versions/4.1/Resources/library/Rcpp/include/Rcpp/generated/Function__operator.h:45:20: note: in instantiation of function template specialization 'Rcpp::pairlist<Rcpp::Vector<14> (Rcpp::Vector<14>), Rcpp::Vector<14>, double>' requested here
            return invoke(pairlist(t1, t2, t3), R_GlobalEnv);
                          ^
testopt.cpp:13:20: note: in instantiation of function template specialization 'Rcpp::Function_Impl<PreserveStorage>::operator()<Rcpp::Vector<14> (Rcpp::Vector<14>), Rcpp::Vector<14>, double>' requested here
  return optimize_r(f, interval, tolerance);
                   ^
1 error generated.
make: *** [testopt.o] Error 1
clang++ -mmacosx-version-min=10.13 -std=gnu++14 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG   -I"/Library/Frameworks/R.framework/Versions/4.1/Resources/library/Rcpp/include" -I"/Users/gcn/Documents/workspace/ISIMIPData/R/cpp" -I/usr/local/include   -fPIC  -Wall -g -O2  -c testopt.cpp -o testopt.o
Error in Rcpp::sourceCpp("R/cpp/testopt.cpp") : 
  Error 1 occurred building shared library.

这里的一个问题是您假设在 Rcpp::sourceCpp() 下提交给编译的函数可以在其导出名称下调用。

不是。尝试 Rcpp::sourceCpp(..., verbose=TRUE),即添加该参数,以查看 真正 调用的是什么。那些你可以传递的(使用 SEXP 参数和结果,但它们很笨重)。

为了证明,这是您的代码的 'working but useless' 版本。如果我们也从 R 传递 f(),一切都是可调用的。

士气:界面仍然是 SEXP .Call("name", SEXP a, SEXP b, ...),即使 Rcpp 隐藏了它。没有免费的午餐 (TM)。但正如我的评论所暗示的,有一些优化包可以与 Rcpp 一起使用。

代码

#include <Rcpp.h>

// [[Rcpp::export]]
Rcpp::List fTg_opt(Rcpp::Function f, const double optmin, const double optmax) {
    Rcpp::Environment base("package:stats");
    Rcpp::Function optimize_r = base["optimize"];
    Rcpp::NumericVector interval = {optmin,optmax};
    Rcpp::List res = optimize_r(f, interval);
    return res;
}

/*** R
f <- function (x) (x - .33)^2
xmin <- optimize(f, c(0, 1), tol = 0.0001)
xmin

fTg_opt(f, 0, 1)
*/

输出

> Rcpp::sourceCpp("~/git/Whosebug/68674076/question.cpp")

> f <- function (x) (x - .33)^2

> xmin <- optimize(f, c(0, 1), tol = 0.0001)

> xmin
$minimum
[1] 0.33

$objective
[1] 0


> fTg_opt(f, 0, 1)
$minimum
[1] 0.33

$objective
[1] 0