如何在 TMB .cpp 文件中找到 objective 函数所需的参数名称和数据?
How do you find out names of parameters and data required by a objective function in a TMB .cpp file?
来自 TMB tutorial,在 .cpp
文件中定义了 objective 函数,这样参数名称和模型数据结构的名称在 C++ 函数和调用函数之间共享来自 R。例如,tutorial.cpp
文件:
#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;
}
编译后 dyn.load
可以从 R 中调用此函数,但是,您需要知道数据向量的名称为 x
,并且有两个参数值 mu
和 sigma
。是否可以通过某种方式从 R 中检索这些所需对象的名称?
我不知道包中有执行此操作的函数,但下面的函数可能会帮助您;
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" 可以是 'parameter'、'data'、'report' 或 'sdreport',但默认情况下我将其作为参数。
添加:如果 class==TRUE 则对于参数和数据,class(矩阵、数组等)作为每个对象的名称给出。
感谢@Wave 提供的实用功能。如果 what
有多个参数,我只是稍微改进了它以检索列表中的所有类型。我的名字中还有一些剩余的空格,所以我也添加了一个 gsub
。
TMBsearch <- function(path, what = c('parameter', 'data', 'report', 'sdreport')) {
res <- lapply(what, function(what) {
# what <- match.arg(what)
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(...) -> might be handy to now whether array or vector or...
found <- gsub("[\(\)]", "", regmatches(textsub, gregexpr("\(.*?\)", textsub))) # get rid of the brackets
found_nospace <- gsub(" ", "", found) # get rid of the spaces if some left
return(found_nospace)
})
names(res) <- what
res
}
来自 TMB tutorial,在 .cpp
文件中定义了 objective 函数,这样参数名称和模型数据结构的名称在 C++ 函数和调用函数之间共享来自 R。例如,tutorial.cpp
文件:
#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;
}
编译后 dyn.load
可以从 R 中调用此函数,但是,您需要知道数据向量的名称为 x
,并且有两个参数值 mu
和 sigma
。是否可以通过某种方式从 R 中检索这些所需对象的名称?
我不知道包中有执行此操作的函数,但下面的函数可能会帮助您;
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" 可以是 'parameter'、'data'、'report' 或 'sdreport',但默认情况下我将其作为参数。
添加:如果 class==TRUE 则对于参数和数据,class(矩阵、数组等)作为每个对象的名称给出。
感谢@Wave 提供的实用功能。如果 what
有多个参数,我只是稍微改进了它以检索列表中的所有类型。我的名字中还有一些剩余的空格,所以我也添加了一个 gsub
。
TMBsearch <- function(path, what = c('parameter', 'data', 'report', 'sdreport')) {
res <- lapply(what, function(what) {
# what <- match.arg(what)
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(...) -> might be handy to now whether array or vector or...
found <- gsub("[\(\)]", "", regmatches(textsub, gregexpr("\(.*?\)", textsub))) # get rid of the brackets
found_nospace <- gsub(" ", "", found) # get rid of the spaces if some left
return(found_nospace)
})
names(res) <- what
res
}