adcomp
adcomp copied to clipboard
MakeADFun() throws error when all values of a vector are fixed with map= argument
Hello,
I'm trying to use the map argument to MakeADFun to fix the values of an entire parameter vector. When I fix the entire vector using NA values, I get an error Error in retape(set.defaults = TRUE) : PARAMETER COMPONENT NOT A VECTOR!. It works as described if only some of the elements of the vector are set to NA.
Thanks, Jeff
Description:
TMB::MakeADFun(..., map = <>) argument throws the following error when an entire parameter vector is fixed to NA using the map argument to MakeADFun:
> map_arg3 <- list(x = factor(1:5))
> map_arg3$x[] <- NA
> obj3 <- MakeADFun(data = data, parameters = par, dll = dll,
+ map = map_arg3)
Error in retape(set.defaults = TRUE) : PARAMETER COMPONENT NOT A VECTOR!
Reproducible Steps:
Below is an R script reproducing the issue. I found this while trying fix the values for an entire random effect while debugging convergence issues with a model.
library(TMB)
code <- '
#include <TMB.hpp>
template<class Type>
Type objective_function<Type>::operator() ()
{
PARAMETER_VECTOR(x);
PARAMETER_VECTOR(y);
Type val(0.0);
val -= dnorm(x, 0, 1, true).sum();
val -= dnorm(y, 0, 1, true).sum();
return val;
}
'
f <- tempfile(fileext = ".cpp")
writeLines(code, f)
TMB::compile(f)
dyn.load(TMB::dynlib(tools::file_path_sans_ext(f)))
dll <- basename(tools::file_path_sans_ext(f))
data <- list()
par <- list(x = numeric(5), y = numeric(5))
obj1 <- MakeADFun(data = data, parameters = par, dll = dll)
obj1$fn()
obj1$gr()
## Fix x[2:5] -- works fine
map_arg2 <- list(x = factor(1:5))
map_arg2$x[2:5] <- NA
obj2 <- MakeADFun(data = data, parameters = par, dll = dll,
map = map_arg2)
## Fix x[1:5] -- throws error:
## "Error in retape(set.defaults = TRUE) : PARAMETER COMPONENT NOT A VECTOR!"
map_arg3 <- list(x = factor(1:5))
map_arg3$x[] <- NA
obj3 <- MakeADFun(data = data, parameters = par, dll = dll,
map = map_arg3)
Current Output:
Here's the full console output, culminating in the error message noted above:
> library(TMB)
>
> code <- '
+ #include <TMB.hpp>
+ template<class Type>
+ Type objective_function<Type>::operator() ()
+ {
+ PARAMETER_VECTOR(x);
+ PARAMETER_VECTOR(y);
+ Type val(0.0);
+ val -= dnorm(x, 0, 1, true).sum();
+ val -= dnorm(y, 0, 1, true).sum();
+ return val;
+ }
+ '
>
> f <- tempfile(fileext = ".cpp")
> writeLines(code, f)
> TMB::compile(f)
...
[1] 0
> dyn.load(TMB::dynlib(tools::file_path_sans_ext(f)))
> dll <- basename(tools::file_path_sans_ext(f))
>
> data <- list()
> par <- list(x = numeric(5), y = numeric(5))
> obj1 <- MakeADFun(data = data, parameters = par, dll = dll)
>
> obj1$fn()
[1] 9.189385
> obj1$gr()
outer mgc: 0
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 0 0 0 0 0 0 0 0 0 0
>
> ## Fix x[2:5] -- works fine
> map_arg2 <- list(x = factor(1:5))
> map_arg2$x[2:5] <- NA
>
> obj2 <- MakeADFun(data = data, parameters = par, dll = dll,
+ map = map_arg2)
>
> ## Fix x[1:5] -- throws error:
> ## "Error in retape(set.defaults = TRUE) : PARAMETER COMPONENT NOT A VECTOR!"
> map_arg3 <- list(x = factor(1:5))
> map_arg3$x[] <- NA
> obj3 <- MakeADFun(data = data, parameters = par, dll = dll,
+ map = map_arg3)
Error in retape(set.defaults = TRUE) : PARAMETER COMPONENT NOT A VECTOR!
Expected Output:
This line would compile and fix the values for parameter vector x.
map_arg3 <- list(x = factor(1:5))
map_arg3$x[] <- NA
obj3 <- MakeADFun(data = data, parameters = par, dll = dll,
map = map_arg3)
TMB Version:
TMB_1.7.18
R Version:
4.0.2
Operating System:
macOS Catalina 10.15.6
This is not the right way to use maps because the factor levels are kept constant (fix by e.g. x=factor(x)). The documentation ?MakeADFun should probably be improved by saying something like:
nlevels(map$p) is the resulting number of parameters after the map has been applied.
In addition one could expect a better error message...
Thanks very much for clarifying the usage. Confirming adding in map$x = droplevels(map$x) results in works as expected:
library(TMB)
code <- '
#include <TMB.hpp>
template<class Type>
Type objective_function<Type>::operator() ()
{
PARAMETER_VECTOR(x);
PARAMETER_VECTOR(y);
Type val(0.0);
val -= dnorm(x, 0, 1, true).sum();
val -= dnorm(y, 0, 1, true).sum();
return val;
}
'
f <- tempfile(fileext = ".cpp")
writeLines(code, f)
TMB::compile(f)
dyn.load(TMB::dynlib(tools::file_path_sans_ext(f)))
dll <- basename(tools::file_path_sans_ext(f))
par <- list(x = numeric(5), y = numeric(5))
data <- list()
map_arg <- list(x = factor(1:5))
map_arg$x[] <- NA
map_arg$x <- droplevels(map_arg$x)
obj <- MakeADFun(data = data, parameters = par, dll = dll,
map = map_arg)
Thanks, Jeff