首页 > 解决方案 > R 在 Rcpp 中使用 stats::optimize,简单示例无法编译

问题描述

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

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

这返回

$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.

标签: rrcpp

解决方案


您的问题之一是您假设成为您提交到编译下的函数可以Rcpp::sourceCpp()在其导出名称下调用。

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

为了证明,这是您的代码的“工作但无用”版本。如果我们也f()从 R 传递,一切都是可调用的。

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/stackoverflow/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

推荐阅读