You need to enable JavaScript to run this app. Rcpp中调用stats::constrOptim传入自定义函数出现编译报错
优惠活动
大模型
产品
解决方案
定价
更多

Rcpp中调用stats::constrOptim传入自定义函数出现编译报错

错误原因

你遇到的编译错误核心是类型不匹配:R的stats::constrOptim接收的目标函数必须是R可识别的Function类型对象,你直接传入C原生函数指针subject_function,Rcpp的类型转换系统没有对应规则把C函数指针转换为R可识别的函数对象,因此触发了类型转换阶段的报错,也就是你看到的is_convertible.h中的"function returning a function"错误。你传入R原生函数时,取到的本身就是Rcpp::Function类型实例,类型匹配因此不会报错。

可行解决方法

方案1:最小改动适配(推荐)

你已经通过// [[Rcpp::export]]将subject_function导出为R可调用的函数,只需要在调用constrOptim前,从R环境中获取该导出函数的Rcpp::Function实例即可,同时可以直接提取返回结果中的par对象返回,修改后的C++代码如下:

// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::depends(RcppProgress)]]
#define RCPP_ARMADILLO_RETURN_VEC_AS_VECTOR
#include <RcppArmadillo.h>
#include <string>
#include <progress.hpp>
using namespace arma;

// [[Rcpp::export]]
double subject_function(const vec &weights,
                        const mat &predictions,
                        const vec &truth)
{
    vec pred = predictions * weights;
    vec loss_vec = arma::pow(pred - truth, 2);
    return arma::mean(loss_vec);
}

// [[Rcpp::export]]
arma::vec constr_optim_rcpp(const vec &weights,
                       const mat &predictions,
                       const vec &truth,
                       const mat &ui,
                       const vec &ci)
{
    Rcpp::Environment stats_pkg = Rcpp::Environment::namespace_env("stats");
    Rcpp::Function constrOptim = stats_pkg["constrOptim"];
    // 核心修改:获取已导出到R环境的损失函数实例
    Rcpp::Environment global_env = Rcpp::Environment::global_env();
    Rcpp::Function subject_fun = global_env["subject_function"];
    
    // 调用优化函数,直接提取par返回
    Rcpp::List optim_res = constrOptim(
        weights,
        subject_fun,
        R_NilValue,
        Rcpp::Named("ui", ui),
        Rcpp::Named("ci", ci),
        Rcpp::Named("method", "Nelder-Mead"),
        Rcpp::Named("predictions", predictions),
        Rcpp::Named("truth", truth)
    );
    return Rcpp::as<arma::vec>(optim_res["par"]);
}

R端调用示例:

Rcpp::sourceCpp("development/batch_reprex.cpp")

A <- matrix(1:6, ncol = 2)
weights <- c(0.5, 0.5)
truth <- c(3, 3, 3)

# 构造约束
positivity <- diag(ncol(A))
convexity <- rep(1, ncol(A))
constr_left <- rbind(convexity, positivity)
constr_right <- c(1, rep(0, ncol(A)))

# 直接调用封装函数即可拿到par结果
constr_optim_rcpp(weights, A, truth, constr_left, constr_right - 1e-12)

注:如果你的代码是写在R包内而非全局环境,只需要将获取函数的环境从global_env替换为你包的命名空间即可,比如Rcpp::Environment::namespace_env("你的包名")。

方案2:纯C++层面优化(性能更高)

如果对性能要求较高,不想在迭代过程中反复进行R和C的交互,可以直接使用C的约束优化库ensmallen,它原生支持Armadillo数据结构,可以完全在C++层面完成约束优化,不需要调用R的constrOptim,性能提升非常明显。

内容的提问来源于stack exchange,提问作者BerriJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.18 09:06:00