I'm trying to use the stats::constrOptim function inside of Rcpp Code and I'm only interested in the par object of the returned list.
This is what it looks like in R.
Rcpp::sourceCpp("development/batch_reprex.cpp")
A <- matrix(1:6, ncol = 2)
weights <- c(0.5, 0.5)
pred <- A %*% weights
truth <- c(3, 3, 3)
# Optim constraints:
positivity <- diag(ncol(A))
convexity <- rep(1, ncol(A))
constr_left <- rbind(convexity, positivity)
constr_right <- c(1, rep(0, ncol(A)))
constrOptim(weights,
subject_function,
grad = NULL,
ui = constr_left,
ci = constr_right - 1e-12, # see https://stackoverflow.com/a/50474095
method = "Nelder-Mead",
predictions = A,
truth = truth
)$par
I just want to do this last call inside of an RCPP function. This is what my batch_reprex.cpp looks like:
// [[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]]
SEXP constr_optim_rcpp(const vec &weights,
const mat &predictions,
const vec &truth,
const mat &ui,
const vec &ci)
{
Rcpp::Environment pkg = Rcpp::Environment::namespace_env("stats");
Rcpp::Function f = pkg["constrOptim"];
return f(weights,
subject_function,
Rcpp::Named("grad", NULL),
Rcpp::Named("ui", ui),
Rcpp::Named("ci", ci),
Rcpp::Named("method", "Nelder-Mead"),
Rcpp::Named("predictions", predictions),
Rcpp::Named("truth", truth));
}
Running sourceCpp returns a lot of error messages including:
/usr/local/lib/R/site-library/Rcpp/include/Rcpp/traits/is_convertible.h:35:12: error: function returning a function
35 | static T MakeT() ;
| ^~~~~
Thank you so much in advance.
Edit:
I figured out that the problem has something todo with the fact that I'm passing the Rcpp subject_function to constrOptim. When I pass an R function, everything works fine:
// [[Rcpp::export]]
Rcpp::List constr_optim_rcpp(const vec &weights,
const mat &predictions,
const vec &truth,
const mat &ui,
const vec &ci)
{
Rcpp::Environment pkg_base = Rcpp::Environment::namespace_env("base");
Rcpp::Function f_sum = pkg_base["sum"];
Rcpp::Environment pkg = Rcpp::Environment::namespace_env("stats");
Rcpp::Function f = pkg["constrOptim"];
Rcpp::List res = Rcpp::List::create(f(weights,
f_sum,
R_NilValue,
ui,
ci,
Rcpp::Named("predictions", predictions),
Rcpp::Named("truth", truth)));
return res;
}