rtmb

How do you find out names of parameters and data required by a objective function in a TMB .cpp file?


From the TMB tutorial, one defines objective functions in a .cpp file, such that parameter names and names of model data structures are shared between the C++ function and what is called from R. For example, the tutorial.cpp file:

#include <TMB.hpp>                                // Links in the TMB libraries

template<class Type>
Type objective_function<Type>::operator() ()
{
  DATA_VECTOR(x);                                 // Data vector transmitted from R
  PARAMETER(mu);                                  // Parameter value transmitted from R
  PARAMETER(sigma);                               //                 

  Type f;                                         // Declare the "objective function" (neg. log. likelihood)
  f = -sum(dnorm(x,mu,sigma,true));               // Use R-style call to normal density

  return f;
}

After compilation and dyn.load one can call this function from R, however, you need to know that the data vector is named x, and that there are two parameter values mu and sigma. Is it possible to retrieve the names of these required objects some how from R?


Solution

  • I am not aware of a function in the package that does this, but the function below might help you out;

        TMBsearch = function(path,what='parameter',class=FALSE){
    
        if(!missing(what) | length(what)>1) stop("What should be of length one")
        if(!(what %in% c('parameter','data','report','sdreport')))  stop("What should be parameter, data, report or sdreport")
    
         text = paste0(paste0(readLines(path), collapse = "\n"), "\n") # read the text from the cpp file
         start = unlist(gregexpr(pattern =toupper(what),text)) # starting position
         end.poss = unlist(gregexpr(pattern =')',text)) # possible end positions
         end = rep(NA,length(start))
         for(i in 1:length(start)){end[i] = end.poss[(end.poss-start[i]) > 0][1]} # actual end position
         textsub = substring(text,first=start,last=end) # extract the full PARAMETER/DATA_x(...) 
         found = gsub("[\\(\\)]", "", regmatches(textsub, gregexpr("\\(.*?\\)", textsub))) # get rid of the brackets
    
         if(class & what %in% c('parameter','data')){
           dataclass=tolower(gsub("_", "",gsub(".*PARAMETER\\s*|\\(.*", "", textsub)))
           dataclass[dataclass=='']="single value"
           names(found)=datatype
         }
    
         return(found)
    }
    
    TMBsearch(path=paste0(filename,'.cpp'), what='parameter')
    

    "what" can either be 'parameter', 'data', 'report' or 'sdreport' but by default I made it parameter.

    ADDITION: if class==TRUE than for parameter and data the class (matrix, array, etc.) is given as the name of each object.