26 #define TMB_CATCH catch(std::bad_alloc& excpt) 31 #ifndef TMB_ERROR_BAD_ALLOC 32 #define TMB_ERROR_BAD_ALLOC \ 33 Rf_error("Caught exception '%s' in function '%s'\n", \ 40 #ifndef TMB_ERROR_BAD_THREAD_ALLOC 41 #define TMB_ERROR_BAD_THREAD_ALLOC \ 42 Rf_error("Caught exception '%s' in function '%s'\n", \ 53 extern "C" void finalizeDoubleFun(SEXP x);
54 extern "C" void finalizeADFun(SEXP x);
55 extern "C" void finalizeparallelADFun(SEXP x);
56 extern "C" SEXP FreeADFunObject(SEXP f) CSKIP ({
57 SEXP tag = R_ExternalPtrTag(f);
58 if (tag == Rf_install(
"DoubleFun")) {
61 else if (tag == Rf_install(
"ADFun")) {
64 else if (tag == Rf_install(
"parallelADFun")) {
65 finalizeparallelADFun(f);
68 Rf_error(
"Unknown external ptr type");
70 R_ClearExternalPtr(f);
74 struct memory_manager_struct {
79 void RegisterCFinalizer(SEXP list);
81 void CallCFinalizer(SEXP x);
84 memory_manager_struct();
87 void memory_manager_struct::RegisterCFinalizer(SEXP x) {
91 void memory_manager_struct::CallCFinalizer(SEXP x){
95 void memory_manager_struct::clear(){
96 std::set<SEXP>::iterator it;
97 while (alive.size() > 0) {
98 FreeADFunObject(*alive.begin());
101 memory_manager_struct::memory_manager_struct(){
105 TMB_EXTERN memory_manager_struct memory_manager;
118 SEXP ptrList(SEXP x);
123 PROTECT(ans=Rf_allocVector(VECSXP,1));
124 PROTECT(names=Rf_allocVector(STRSXP,1));
125 SET_VECTOR_ELT(ans,0,x);
126 SET_STRING_ELT(names,0,Rf_mkChar(
"ptr"));
127 Rf_setAttrib(ans,R_NamesSymbol,names);
128 memory_manager.RegisterCFinalizer(x);
136 #include <R_ext/Rdynload.h> 137 void LIB_UNLOAD(DllInfo *dll)
139 if(memory_manager.counter>0)Rprintf(
"Warning: %d external pointers will be removed\n",memory_manager.counter);
140 memory_manager.clear();
141 for(
int i=0;i<1000;i++){
142 if(memory_manager.counter>0){
144 R_RunExitFinalizers();
147 if(memory_manager.counter>0)Rf_error(
"Failed to clean. Please manually clean up before unloading\n");
153 TMB_EXTERN
bool _openmp CSKIP( =
true; )
155 TMB_EXTERN
bool _openmp CSKIP( =
false; )
159 template<class ADFunPointer>
160 void optimizeTape(ADFunPointer pf){
170 if(config.trace.
optimize)std::cout <<
"Optimizing tape... ";
172 if(config.trace.
optimize)std::cout <<
"Done\n";
177 if(config.trace.
optimize)std::cout <<
"Optimizing tape... ";
179 if(config.trace.
optimize)std::cout <<
"Done\n";
208 #define TMB_OBJECTIVE_PTR \ 213 #define PARAMETER_MATRIX(name) \ 214 tmbutils::matrix<Type> name(TMB_OBJECTIVE_PTR -> fillShape( \ 215 asMatrix<Type> ( TMB_OBJECTIVE_PTR -> getShape( #name, &Rf_isMatrix) ), \ 220 #define PARAMETER_VECTOR(name) \ 221 vector<Type> name(TMB_OBJECTIVE_PTR -> fillShape( \ 222 asVector<Type>(TMB_OBJECTIVE_PTR -> getShape(#name, &Rf_isReal )), \ 227 #define PARAMETER(name) \ 228 Type name(TMB_OBJECTIVE_PTR -> fillShape( \ 229 asVector<Type>(TMB_OBJECTIVE_PTR -> getShape(#name,&isNumericScalar)), \ 236 #define DATA_VECTOR(name) \ 238 if (!Rf_isNull(getListElement(TMB_OBJECTIVE_PTR -> parameters,#name))){ \ 239 name = TMB_OBJECTIVE_PTR -> fillShape(asVector<Type>( \ 240 TMB_OBJECTIVE_PTR -> getShape(#name, &Rf_isReal )), #name); \ 242 name = asVector<Type>(getListElement( \ 243 TMB_OBJECTIVE_PTR -> data,#name,&Rf_isReal )); \ 248 #define DATA_MATRIX(name) \ 249 matrix<Type> name(asMatrix<Type>( \ 250 getListElement(TMB_OBJECTIVE_PTR -> data, #name, &Rf_isMatrix))); 254 #define DATA_SCALAR(name) \ 255 Type name(asVector<Type>(getListElement(TMB_OBJECTIVE_PTR -> data, \ 256 #name,&isNumericScalar))[0]); 260 #define DATA_INTEGER(name) int name(CppAD::Integer(asVector<Type>( \ 261 getListElement(TMB_OBJECTIVE_PTR -> data, \ 262 #name, &isNumericScalar))[0])); 281 #define DATA_FACTOR(name) vector<int> name(asVector<int>( \ 282 getListElement(TMB_OBJECTIVE_PTR -> data, #name, &Rf_isReal ))); 287 #define DATA_IVECTOR(name) vector<int> name(asVector<int>( \ 288 getListElement(TMB_OBJECTIVE_PTR -> data, #name, &Rf_isReal ))); 292 #define NLEVELS(name) \ 293 LENGTH(Rf_getAttrib(getListElement(TMB_OBJECTIVE_PTR -> data, #name), \ 294 Rf_install("levels"))) 299 #define DATA_SPARSE_MATRIX(name) \ 300 Eigen::SparseMatrix<Type> name(tmbutils::asSparseMatrix<Type>( \ 301 getListElement(TMB_OBJECTIVE_PTR -> data, \ 302 #name, &isValidSparseMatrix))); 313 #define REPORT(name) \ 314 if( isDouble<Type>::value && \ 315 TMB_OBJECTIVE_PTR -> current_parallel_region<0 ) \ 317 SEXP _TMB_temporary_sexp_; \ 318 PROTECT( _TMB_temporary_sexp_ = asSEXP(name) ); \ 319 Rf_defineVar(Rf_install(#name), \ 320 _TMB_temporary_sexp_, TMB_OBJECTIVE_PTR -> report); \ 330 if(isDouble<Type>::value && TMB_OBJECTIVE_PTR -> do_simulate) 342 #define ADREPORT(name) \ 343 TMB_OBJECTIVE_PTR -> reportvector.push(name, #name); 345 #define PARALLEL_REGION \ 346 if( TMB_OBJECTIVE_PTR -> parallel_region() ) 352 #define DATA_ARRAY(name) \ 353 tmbutils::array<Type> name; \ 354 if (!Rf_isNull(getListElement(TMB_OBJECTIVE_PTR -> parameters,#name))){ \ 355 name = TMB_OBJECTIVE_PTR -> fillShape(tmbutils::asArray<Type>( \ 356 TMB_OBJECTIVE_PTR -> getShape(#name, &Rf_isArray)), #name); \ 358 name = tmbutils::asArray<Type>(getListElement( \ 359 TMB_OBJECTIVE_PTR -> data, #name, &Rf_isArray)); \ 364 #define PARAMETER_ARRAY(name) \ 365 tmbutils::array<Type> name(TMB_OBJECTIVE_PTR -> fillShape( \ 366 tmbutils::asArray<Type>(TMB_OBJECTIVE_PTR -> getShape( \ 367 #name, &Rf_isArray)), #name)); 371 #define DATA_IMATRIX(name) \ 372 matrix<int> name(asMatrix<int>( \ 373 getListElement(TMB_OBJECTIVE_PTR -> data,#name, &Rf_isMatrix))); 377 #define DATA_IARRAY(name) \ 378 tmbutils::array<int> name(tmbutils::asArray<int>( \ 379 getListElement(TMB_OBJECTIVE_PTR -> data, #name, &Rf_isArray))); 394 #define DATA_STRING(name) \ 396 CHAR(STRING_ELT(getListElement(TMB_OBJECTIVE_PTR -> data, #name), 0)); 433 #define DATA_STRUCT(name, struct) \ 434 struct<Type> name(getListElement(TMB_OBJECTIVE_PTR -> data, #name)); 440 template<
class VT,
class Type =
typename VT::Scalar>
458 if (init_one) VT::fill(Type(1.0));
459 cdf_lower = obs; cdf_lower.setZero();
460 cdf_upper = obs; cdf_upper.setZero();
465 int n = (*this).size();
466 if(p.size() >= n ) VT::operator=(p.segment(0, n));
467 if(p.size() >= 2*n) cdf_lower = p.segment(n, n);
468 if(p.size() >= 3*n) cdf_upper = p.segment(2 * n, n);
469 if(!Rf_isNull(ord_)) {
470 this->ord = asVector<int>(ord_);
472 for (
int i=0; i<p.size(); i++) {
473 osa_flag |= CppAD::Variable(p[i]);
480 ans.
cdf_lower = cdf_lower.segment(pos, n);
481 ans.
cdf_upper = cdf_upper.segment(pos, n);
482 if (ord.size() != 0) {
483 ans.
ord = ord.segment(pos, n);
490 int n = this->size();
492 if (ord.size() == 0) {
493 for (
int i=0; i<n; i++)
496 if (ord.size() != n) Rf_error(
"Unexpected 'ord.size() != n'");
497 std::vector<std::pair<int, int> > y(n);
498 for (
int i=0; i<n; i++) {
502 std::sort(y.begin(), y.end());
503 for (
int i=0; i<n; i++) {
504 ans[i] = y[i].second;
518 #define DATA_ARRAY_INDICATOR(name, obs) \ 519 data_indicator<tmbutils::array<Type> > name(obs, true); \ 520 if (!Rf_isNull(getListElement(TMB_OBJECTIVE_PTR -> parameters,#name))){ \ 521 name.fill( TMB_OBJECTIVE_PTR -> fillShape(asVector<Type>( \ 522 TMB_OBJECTIVE_PTR -> getShape(#name, &Rf_isReal )), \ 525 TMB_OBJECTIVE_PTR -> getShape(#name, &Rf_isReal ), \ 526 Rf_install("ord")) ); \ 534 #define DATA_VECTOR_INDICATOR(name, obs) \ 535 data_indicator<tmbutils::vector<Type> > name(obs, true); \ 536 if (!Rf_isNull(getListElement(TMB_OBJECTIVE_PTR -> parameters,#name))){ \ 537 name.fill( TMB_OBJECTIVE_PTR -> fillShape(asVector<Type>( \ 538 TMB_OBJECTIVE_PTR -> getShape(#name, &Rf_isReal )), \ 541 TMB_OBJECTIVE_PTR -> getShape(#name, &Rf_isReal ), \ 542 Rf_install("ord")) ); \ 550 matrix<int> HessianSparsityPattern(ADFun<Type> *pf){
553 for(
int i = 0; i < n; i++)
555 for(
int j = 0; j < n; j++)
556 Px[ i * n + j ] =
false;
557 Px[ i * n + i ] =
true;
559 pf->ForSparseJac(n, Px);
561 vector<int> tmp = (pf->RevSparseHes(n,Py)).
template cast<int>();
569 template <class Type>
571 std::vector<const char*> names;
572 std::vector<vector<int> > namedim;
573 std::vector<Type> result;
582 dim << x.rows(), x.cols();
588 template<
class Other>
595 template<
class Vector_Matrix_Or_Array>
596 void push(Vector_Matrix_Or_Array x,
const char* name) {
597 names.push_back(name);
598 namedim.push_back(getDim(x));
599 Eigen::Array<Type, Eigen::Dynamic, Eigen::Dynamic> xa(x);
600 result.insert(result.end(), xa.data(), xa.data() + x.size());
603 void push(Type x,
const char* name){
615 int n = result.size();
617 PROTECT( nam = Rf_allocVector(STRSXP, n) );
619 for(
size_t i = 0; i < names.size(); i++) {
620 int namelength = namedim[i].prod();
621 for(
int j = 0; j < namelength; j++) {
622 SET_STRING_ELT(nam, k, Rf_mkChar(names[i]) );
633 PROTECT( ans =
asSEXP(VVI(namedim)) );
634 PROTECT( nam = Rf_allocVector(STRSXP, names.size()) );
635 for(
size_t i = 0; i < names.size(); i++) {
636 SET_STRING_ELT(nam, i, Rf_mkChar(names[i]));
638 Rf_setAttrib(ans, R_NamesSymbol, nam);
642 EIGEN_DEFAULT_DENSE_INDEX_TYPE size(){
return result.size();}
646 void GetRNGstate(
void);
647 void PutRNGstate(
void);
651 template <
class Type>
652 class objective_function
663 report_stack<Type> reportvector;
668 void pushParname(
const char* x){
669 parnames.conservativeResize(parnames.size()+1);
670 parnames[parnames.size()-1]=x;
688 bool parallel_ignore_statements;
689 int current_parallel_region;
690 int selected_parallel_region;
691 int max_parallel_regions;
694 bool parallel_region(){
696 if(config.
autopar || current_parallel_region<0 || selected_parallel_region<0)
return true;
697 ans = (selected_parallel_region==current_parallel_region) && (!parallel_ignore_statements);
698 current_parallel_region++;
699 if(max_parallel_regions>0)current_parallel_region=current_parallel_region % max_parallel_regions;
703 int count_parallel_regions(){
704 current_parallel_region=0;
705 selected_parallel_region=0;
706 parallel_ignore_statements=
true;
709 if(max_parallel_regions>0)
return max_parallel_regions;
711 return current_parallel_region;
713 void set_parallel_region(
int i){
714 current_parallel_region=0;
715 selected_parallel_region=i;
716 parallel_ignore_statements=
false;
720 void set_simulate(
bool do_simulate_) {
721 do_simulate = do_simulate_;
734 objective_function(SEXP data, SEXP parameters, SEXP report) :
735 data(data), parameters(parameters), report(report), index(0)
739 theta.resize(nparms(parameters));
740 int length_parlist = Rf_length(parameters);
741 for(
int i = 0, counter = 0; i < length_parlist; i++) {
743 SEXP x = VECTOR_ELT(parameters, i);
744 int nx = Rf_length(x);
745 double* px = REAL(x);
746 for(
int j = 0; j < nx; j++) {
747 theta[counter++] = Type( px[j] );
750 thetanames.resize(theta.size());
751 for(
int i=0;i<thetanames.size();i++)thetanames[i]=
"";
752 current_parallel_region=-1;
753 selected_parallel_region=-1;
754 max_parallel_regions=-1;
756 max_parallel_regions = config.
nthreads;
772 SEXP env = ENCLOS(this->report);
773 this->data = Rf_findVar(Rf_install(
"data"), env);
782 PROTECT(res=Rf_allocVector(REALSXP,n));
783 PROTECT(nam=Rf_allocVector(STRSXP,n));
784 for(
int i=0;i<n;i++){
786 REAL(res)[i]=value(theta[i]);
787 SET_STRING_ELT(nam,i,Rf_mkChar(thetanames[i]));
789 Rf_setAttrib(res,R_NamesSymbol,nam);
797 int n=parnames.size();
799 PROTECT(nam=Rf_allocVector(STRSXP,n));
800 for(
int i=0;i<n;i++){
801 SET_STRING_ELT(nam,i,Rf_mkChar(parnames[i]));
818 double value(
double x){
return x;}
819 double value(AD<double> x){
return CppAD::Value(x);}
820 double value(AD<AD<double> > x){
return CppAD::Value(CppAD::Value(x));}
821 double value(AD<AD<AD<double> > > x){
return CppAD::Value(CppAD::Value(CppAD::Value(x)));}
822 #ifdef TMBAD_FRAMEWORK 831 for(
int i=0;i<Rf_length(obj);i++){
832 if(!Rf_isReal(VECTOR_ELT(obj,i)))Rf_error(
"PARAMETER COMPONENT NOT A VECTOR!");
833 count+=Rf_length(VECTOR_ELT(obj,i));
843 for(
int i=0;i<x.size();i++){
844 thetanames[index]=nam;
845 if(reversefill)theta[index++]=x[i];
else x[i]=theta[index++];
851 for(
int j=0;j<x.cols();j++){
852 for(
int i=0;i<x.rows();i++){
853 thetanames[index]=nam;
854 if(reversefill)theta[index++]=x(i,j);
else x(i,j)=theta[index++];
858 template<
class ArrayType>
859 void fill(ArrayType &x,
const char *nam)
862 for(
int i=0;i<x.size();i++){
863 thetanames[index]=nam;
864 if(reversefill)theta[index++]=x[i];
else x[i]=theta[index++];
869 template<
class ArrayType>
870 void fillmap(ArrayType &x,
const char *nam)
873 SEXP elm=getListElement(parameters,nam);
874 int* map=INTEGER(Rf_getAttrib(elm,Rf_install(
"map")));
875 int nlevels=INTEGER(Rf_getAttrib(elm,Rf_install(
"nlevels")))[0];
876 for(
int i=0;i<x.size();i++){
878 thetanames[index+map[i]]=nam;
879 if(reversefill)theta[index+map[i]]=x(i);
else x(i)=theta[index+map[i]];
885 SEXP getShape(
const char *nam, RObjectTester expectedtype=NULL){
886 SEXP elm=getListElement(parameters,nam);
887 SEXP shape=Rf_getAttrib(elm,Rf_install(
"shape"));
889 if(shape==R_NilValue)ans=elm;
else ans=shape;
890 RObjectTestExpectedType(ans, expectedtype, nam);
893 template<
class ArrayType>
895 ArrayType fillShape(ArrayType x,
const char *nam){
896 SEXP elm=getListElement(parameters,nam);
897 SEXP shape=Rf_getAttrib(elm,Rf_install(
"shape"));
898 if(shape==R_NilValue)
fill(x,nam);
903 void fill(Type &x,
char const *nam)
906 thetanames[index]=nam;
907 if(reversefill)theta[index++]=x;
else x=theta[index++];
912 Type evalUserTemplate(){
913 Type ans=this->operator()();
918 if(index != theta.size()){
920 ans += ( this->reportvector() * TMB_epsilon_ ).
sum();
959 objective_function<Type>* obj;
964 obj->max_parallel_regions=config.
nthreads;
967 inline void operator+=(Type x){
968 if(obj->parallel_region())result+=x;
970 inline void operator-=(Type x){
971 if(obj->parallel_region())result-=x;
981 #ifdef TMBAD_FRAMEWORK 982 template<
class ADFunType>
983 SEXP EvalADFunObjectTemplate(SEXP f, SEXP theta, SEXP control)
985 if(!Rf_isNewList(control))Rf_error(
"'control' must be a list");
987 pf=(ADFunType*)R_ExternalPtrAddr(f);
988 int data_changed = getListInteger(control,
"data_changed", 0);
992 int set_tail = getListInteger(control,
"set_tail", 0) - 1;
993 if (set_tail == -1) {
996 std::vector<TMBad::Index> r(1, set_tail);
999 PROTECT(theta=Rf_coerceVector(theta,REALSXP));
1002 if(LENGTH(theta)!=n)Rf_error(
"Wrong parameter length.");
1004 int rangecomponent = getListInteger(control,
"rangecomponent", 1) - 1;
1005 if(!((0<=rangecomponent)&(rangecomponent<=m-1)))
1006 Rf_error(
"Wrong range component.");
1007 int order = getListInteger(control,
"order");
1008 if((order!=0) & (order!=1) & (order!=2) & (order!=3))
1009 Rf_error(
"order can be 0, 1, 2 or 3");
1013 PROTECT(hessiancols=getListElement(control,
"hessiancols"));
1014 int ncols=Rf_length(hessiancols);
1016 PROTECT(hessianrows=getListElement(control,
"hessianrows"));
1017 int nrows=Rf_length(hessianrows);
1018 if((nrows>0)&(nrows!=ncols))Rf_error(
"hessianrows and hessianrows must have same length");
1023 for(
int i=0;i<ncols;i++){
1024 cols[i]=INTEGER(hessiancols)[i]-1;
1026 if(nrows>0)rows[i]=INTEGER(hessianrows)[i]-1;
1029 std::vector<double> x(REAL(theta), REAL(theta) + LENGTH(theta));
1031 SEXP res=R_NilValue;
1032 SEXP rangeweight=getListElement(control,
"rangeweight");
1033 if(rangeweight!=R_NilValue){
1034 if(LENGTH(rangeweight)!=m)Rf_error(
"rangeweight must have length equal to range dimension");
1035 std::vector<double> w(REAL(rangeweight),
1036 REAL(rangeweight) + LENGTH(rangeweight));
1043 Rf_error(
"Not implemented for TMBad");
1052 std::vector<double> ans = pf->operator()(x);
1053 PROTECT(res=
asSEXP(ans));
1055 SEXP rangenames=Rf_getAttrib(f,Rf_install(
"range.names"));
1056 if(LENGTH(res)==LENGTH(rangenames)){
1057 Rf_setAttrib(res,R_NamesSymbol,rangenames);
1061 std::vector<double> jvec;
1062 SEXP keepx = getListElement(control,
"keepx");
1063 if (keepx != R_NilValue && LENGTH(keepx) > 0) {
1064 SEXP keepy = getListElement(control,
"keepy");
1065 std::vector<bool> keep_x(pf->Domain(),
false);
1066 std::vector<bool> keep_y(pf->Range(),
false);
1067 for (
int i=0; i<LENGTH(keepx); i++) {
1068 keep_x[INTEGER(keepx)[i] - 1] =
true;
1070 for (
int i=0; i<LENGTH(keepy); i++) {
1071 keep_y[INTEGER(keepy)[i] - 1] =
true;
1075 jvec = pf->Jacobian(x, keep_x, keep_y);
1077 jvec = pf->Jacobian(x);
1082 for (
int i=0; i<m; i++) {
1083 for (
int j=0; j<n; j++) {
1084 jac(i, j) = jvec[k];
1088 PROTECT( res =
asSEXP(jac) );
1110 #ifdef CPPAD_FRAMEWORK 1145 template<
class ADFunType>
1146 SEXP EvalADFunObjectTemplate(SEXP f, SEXP theta, SEXP control)
1148 if(!Rf_isNewList(control))Rf_error(
"'control' must be a list");
1150 pf=(ADFunType*)R_ExternalPtrAddr(f);
1151 PROTECT(theta=Rf_coerceVector(theta,REALSXP));
1154 if(LENGTH(theta)!=n)Rf_error(
"Wrong parameter length.");
1156 int doforward = getListInteger(control,
"doforward", 1);
1158 int rangecomponent = getListInteger(control,
"rangecomponent", 1) - 1;
1159 if(!((0<=rangecomponent)&(rangecomponent<=m-1)))
1160 Rf_error(
"Wrong range component.");
1161 int order = getListInteger(control,
"order");
1162 if((order!=0) & (order!=1) & (order!=2) & (order!=3))
1163 Rf_error(
"order can be 0, 1, 2 or 3");
1164 int sparsitypattern = getListInteger(control,
"sparsitypattern");
1165 int dumpstack = getListInteger(control,
"dumpstack");
1167 PROTECT(hessiancols=getListElement(control,
"hessiancols"));
1168 int ncols=Rf_length(hessiancols);
1170 PROTECT(hessianrows=getListElement(control,
"hessianrows"));
1171 int nrows=Rf_length(hessianrows);
1172 if((nrows>0)&(nrows!=ncols))Rf_error(
"hessianrows and hessianrows must have same length");
1177 for(
int i=0;i<ncols;i++){
1178 cols[i]=INTEGER(hessiancols)[i]-1;
1180 if(nrows>0)rows[i]=INTEGER(hessianrows)[i]-1;
1184 SEXP res=R_NilValue;
1185 SEXP rangeweight=getListElement(control,
"rangeweight");
1186 if(rangeweight!=R_NilValue){
1187 if(LENGTH(rangeweight)!=m)Rf_error(
"rangeweight must have length equal to range dimension");
1188 if(doforward)pf->Forward(0,x);
1189 res=
asSEXP(pf->Reverse(1,asVector<double>(rangeweight)));
1196 if((nrows!=1) | (ncols!=1))Rf_error(
"For 3rd order derivatives a single hessian coordinate must be specified.");
1197 pf->ForTwo(x,rows,cols);
1201 if(dumpstack)CppAD::traceforward0sweep(1);
1202 PROTECT(res=
asSEXP(pf->Forward(0,x)));
1203 if(dumpstack)CppAD::traceforward0sweep(0);
1204 SEXP rangenames=Rf_getAttrib(f,Rf_install(
"range.names"));
1205 if(LENGTH(res)==LENGTH(rangenames)){
1206 Rf_setAttrib(res,R_NamesSymbol,rangenames);
1210 if(doforward)pf->Forward(0,x);
1215 for(
int i=0; i<m; i++) {
1216 v[i] = 1.0; u = pf->Reverse(1,v);
1220 PROTECT( res =
asSEXP(jac) );
1225 if(sparsitypattern){
1226 PROTECT(res=
asSEXP(HessianSparsityPattern(pf)));
1228 PROTECT(res=
asSEXP(
asMatrix(pf->Hessian(x,rangecomponent),n,n)));
1235 else PROTECT(res=
asSEXP(
asMatrix(pf->ForTwo(x,rows,cols),m,ncols)));
1243 template <
class ADFunType>
1244 void finalize(SEXP x)
1246 ADFunType* ptr=(ADFunType*)R_ExternalPtrAddr(x);
1247 if(ptr!=NULL)
delete ptr;
1248 memory_manager.CallCFinalizer(x);
1251 #ifdef TMBAD_FRAMEWORK 1254 SEXP report, SEXP control,
int parallel_region=-1,
1255 SEXP &info=R_NilValue)
1259 int returnReport = (control!=R_NilValue) && getListInteger(control,
"report");
1261 objective_function< ad > F(data,parameters,report);
1262 F.set_parallel_region(parallel_region);
1267 adfun* pf =
new adfun();
1268 pf->glob.ad_start();
1270 for (
int i=0; i<F.theta.size(); i++) F.theta(i).Independent();
1273 y[0] = F.evalUserTemplate();
1275 for (
int i=0; i<y.size(); i++) y[i].Dependent();
1279 for (
int i=0; i<F.reportvector.size(); i++) F.reportvector.result[i].Dependent();
1280 info=F.reportvector.reportnames();
1287 #ifdef CPPAD_FRAMEWORK 1289 ADFun<double>* MakeADFunObject_(SEXP data, SEXP parameters,
1290 SEXP report, SEXP control,
int parallel_region=-1,
1291 SEXP &info=R_NilValue)
1293 int returnReport = getListInteger(control,
"report");
1295 objective_function< AD<double> > F(data,parameters,report);
1296 F.set_parallel_region(parallel_region);
1301 Independent(F.theta);
1302 ADFun< double >* pf;
1305 y[0]=F.evalUserTemplate();
1306 pf =
new ADFun< double >(F.theta,y);
1309 pf =
new ADFun< double >(F.theta,F.reportvector());
1310 info=F.reportvector.reportnames();
1319 #ifdef TMBAD_FRAMEWORK 1321 void finalizeADFun(SEXP x)
1323 finalize<TMBad::ADFun<TMBad::ad_aug> > (x);
1325 void finalizeparallelADFun(SEXP x)
1327 finalize<parallelADFun<double> > (x);
1331 #ifdef CPPAD_FRAMEWORK 1333 void finalizeADFun(SEXP x)
1335 finalize<ADFun<double> > (x);
1337 void finalizeparallelADFun(SEXP x)
1339 finalize<parallelADFun<double> > (x);
1345 #ifdef TMBAD_FRAMEWORK 1347 SEXP MakeADFunObject(SEXP data, SEXP parameters,
1348 SEXP report, SEXP control)
1355 if(!Rf_isNewList(data))Rf_error(
"'data' must be a list");
1356 if(!Rf_isNewList(parameters))Rf_error(
"'parameters' must be a list");
1357 if(!Rf_isEnvironment(report))Rf_error(
"'report' must be an environment");
1358 if(!Rf_isNewList(control))Rf_error(
"'control' must be a list");
1359 int returnReport = getListInteger(control,
"report");
1362 SEXP par,res=NULL,info;
1363 objective_function< double > F(data,parameters,report);
1365 int n=F.count_parallel_regions();
1367 F.count_parallel_regions();
1369 if(returnReport && F.reportvector.size()==0){
1373 PROTECT(par=F.defaultpar());
1374 PROTECT(info=R_NilValue);
1376 if(_openmp && !returnReport){
1379 std::cout << n <<
" regions found.\n";
1383 const char* bad_thread_alloc = NULL;
1384 #pragma omp parallel for num_threads(config.nthreads) if (config.tape.parallel && n>1) 1385 for(
int i = 0; i < n; i++) {
1388 pfvec[i] = MakeADFunObject_(data, parameters, report, control, i, info);
1389 if (config.
optimize.instantly) pfvec[i]->optimize();
1392 if (pfvec[i] != NULL)
delete pfvec[i];
1393 bad_thread_alloc = excpt.what();
1396 if (bad_thread_alloc) {
1397 TMB_ERROR_BAD_THREAD_ALLOC;
1402 parallelADFun<double>* ppf=
new parallelADFun<double>(pfvec);
1404 PROTECT(res=R_MakeExternalPtr((
void*) ppf,Rf_install(
"parallelADFun"),R_NilValue));
1411 pf = MakeADFunObject_(data, parameters, report, control, -1, info);
1412 if (config.
optimize.instantly) pf->optimize();
1415 if (pf != NULL)
delete pf;
1416 TMB_ERROR_BAD_ALLOC;
1419 PROTECT(res=R_MakeExternalPtr((
void*) pf,Rf_install(
"ADFun"),R_NilValue));
1420 Rf_setAttrib(res,Rf_install(
"range.names"),info);
1425 Rf_setAttrib(res,Rf_install(
"par"),par);
1426 PROTECT(ans=ptrList(res));
1433 #ifdef CPPAD_FRAMEWORK 1435 SEXP MakeADFunObject(SEXP data, SEXP parameters,
1436 SEXP report, SEXP control)
1438 ADFun<double>* pf = NULL;
1440 if(!Rf_isNewList(data))Rf_error(
"'data' must be a list");
1441 if(!Rf_isNewList(parameters))Rf_error(
"'parameters' must be a list");
1442 if(!Rf_isEnvironment(report))Rf_error(
"'report' must be an environment");
1443 if(!Rf_isNewList(control))Rf_error(
"'control' must be a list");
1444 int returnReport = getListInteger(control,
"report");
1447 SEXP par,res=NULL,info;
1448 objective_function< double > F(data,parameters,report);
1450 int n=F.count_parallel_regions();
1452 F.count_parallel_regions();
1454 if(returnReport && F.reportvector.size()==0){
1458 PROTECT(par=F.defaultpar());
1459 PROTECT(info=R_NilValue);
1461 if(_openmp && !returnReport){
1464 std::cout << n <<
" regions found.\n";
1468 const char* bad_thread_alloc = NULL;
1469 #pragma omp parallel for num_threads(config.nthreads) if (config.tape.parallel && n>1) 1470 for(
int i=0;i<n;i++){
1473 pfvec[i] = MakeADFunObject_(data, parameters, report, control, i, info);
1474 if (config.
optimize.instantly) pfvec[i]->optimize();
1477 if (pfvec[i] != NULL)
delete pfvec[i];
1478 bad_thread_alloc = excpt.what();
1481 if (bad_thread_alloc) {
1482 TMB_ERROR_BAD_THREAD_ALLOC;
1484 parallelADFun<double>* ppf=
new parallelADFun<double>(pfvec);
1486 PROTECT(res=R_MakeExternalPtr((
void*) ppf,Rf_install(
"parallelADFun"),R_NilValue));
1492 pf = MakeADFunObject_(data, parameters, report, control, -1, info);
1493 if (config.
optimize.instantly) pf->optimize();
1496 if (pf != NULL)
delete pf;
1497 TMB_ERROR_BAD_ALLOC;
1500 PROTECT(res=R_MakeExternalPtr((
void*) pf,Rf_install(
"ADFun"),R_NilValue));
1501 Rf_setAttrib(res,Rf_install(
"range.names"),info);
1506 Rf_setAttrib(res,Rf_install(
"par"),par);
1507 PROTECT(ans=ptrList(res));
1516 #ifdef TMBAD_FRAMEWORK 1517 inline int get_num_tapes(SEXP f) {
1520 SEXP tag = R_ExternalPtrTag(f);
1521 if (tag != Rf_install(
"parallelADFun"))
1524 ((parallelADFun<double>*) R_ExternalPtrAddr(f))->ntapes;
1529 Rf_error(
"Cannot transform '<pointer: (nil)>' (unloaded/reloaded DLL?)");
1533 std::string method =
1534 CHAR(STRING_ELT(getListElement(control,
"method"), 0));
1536 if (method ==
"copy") {
1540 if (method ==
"set_compiled") {
1543 i = omp_get_thread_num();
1545 typedef void(*fct_ptr1)(
double*);
1546 typedef void(*fct_ptr2)(
double*,
double*);
1547 pf->glob.forward_compiled =
1548 (fct_ptr1) R_ExternalPtrAddr(VECTOR_ELT(getListElement(control,
"forward_compiled"), i));
1549 pf->glob.reverse_compiled =
1550 (fct_ptr2) R_ExternalPtrAddr(VECTOR_ELT(getListElement(control,
"reverse_compiled"), i));
1553 SEXP random_order = getListElement(control,
"random_order");
1554 int nr = (Rf_isNull(random_order) ? 0 : LENGTH(random_order));
1555 std::vector<TMBad::Index> random;
1557 random = std::vector<TMBad::Index>(INTEGER(random_order),
1558 INTEGER(random_order) + nr);
1559 for (
size_t i=0; i<random.size(); i++)
1563 if (method ==
"remove_random_parameters") {
1564 std::vector<bool> mask(pf->Domain(),
true);
1565 for (
size_t i = 0; i<random.size(); i++)
1566 mask[random[i]] =
false;
1567 pf->glob.inv_index =
TMBad::subset(pf->glob.inv_index, mask);
1569 else if (method ==
"laplace") {
1570 SEXP config = getListElement(control,
"config");
1572 *pf = newton::Laplace_(*pf, random, cfg);
1574 else if (method ==
"marginal_gk") {
1575 TMBad::gk_config cfg;
1576 SEXP config = getListElement(control,
"config");
1577 if (!Rf_isNull(config)) {
1578 cfg.adaptive = getListInteger(config,
"adaptive", 0);
1579 cfg.debug = getListInteger(config,
"debug", 0);
1581 *pf = pf -> marginal_gk(random, cfg);
1583 else if (method ==
"marginal_sr") {
1584 SEXP config = getListElement(control,
"config");
1585 std::vector<TMBad::sr_grid> grids;
1586 SEXP grid = getListElement(config,
"grid");
1587 SEXP random2grid = getListElement(config,
"random2grid");
1588 for (
int i=0; i<LENGTH(grid); i++) {
1589 SEXP grid_i = VECTOR_ELT(grid, i);
1590 SEXP x = getListElement(grid_i,
"x");
1591 SEXP w = getListElement(grid_i,
"w");
1592 if (LENGTH(x) != LENGTH(w))
1593 Rf_error(
"Length of grid$x and grid$w must be equal");
1595 grid_sr.x = std::vector<double>(REAL(x), REAL(x) + LENGTH(x));
1596 grid_sr.w = std::vector<double>(REAL(w), REAL(w) + LENGTH(w));
1597 grids.push_back(grid_sr);
1599 std::vector<TMBad::Index> r2g(INTEGER(random2grid),
1600 INTEGER(random2grid) + LENGTH(random2grid));
1601 for (
size_t i=0; i<r2g.size(); i++)
1603 *pf = pf -> marginal_sr(random, grids, r2g,
true);
1605 else if (method ==
"parallelize")
1606 *pf = pf -> parallelize(2);
1607 else if (method ==
"compress") {
1608 int max_period_size = getListInteger(control,
"max_period_size", 1024);
1609 TMBad::compress(pf->glob, max_period_size);
1611 else if (method ==
"compress_and_compile") {
1612 #ifdef HAVE_COMPILE_HPP 1613 int max_period_size = getListInteger(control,
"max_period_size", 1024);
1614 TMBad::compress(pf->glob, max_period_size);
1616 TMBad::compile(pf->glob);
1618 Rf_error(
"TMBad::compile() is unavailable");
1621 else if (method ==
"accumulation_tree_split")
1622 pf->glob = accumulation_tree_split(pf->glob,
true);
1623 else if (method ==
"fuse_and_replay") {
1624 pf->glob.set_fuse(
true);
1626 pf->glob.set_fuse(
false);
1628 else if (method ==
"reorder_random") {
1631 else if (method ==
"reorder_sub_expressions") {
1634 else if (method ==
"reorder_depth_first") {
1637 else if (method ==
"reorder_temporaries") {
1640 else if (method ==
"parallel_accumulate") {
1643 else if (method ==
"optimize") {
1646 Rf_error(
"Method unknown: '%s'", method.c_str());
1650 TMB_ERROR_BAD_ALLOC;
1657 SEXP TransformADFunObject(SEXP f, SEXP control)
1660 Rf_error(
"Expected external pointer - got NULL");
1661 SEXP tag = R_ExternalPtrTag(f);
1662 if (tag != Rf_install(
"ADFun"))
1663 if (tag != Rf_install(
"parallelADFun"))
1664 Rf_error(
"Expected ADFun or parallelADFun pointer");
1667 if(tag == Rf_install(
"ADFun")) {
1668 adfun* pf = (adfun*) R_ExternalPtrAddr(f);
1669 TransformADFunObjectTemplate(pf, control);
1670 }
else if (tag == Rf_install(
"parallelADFun")) {
1674 parallelADFun<double>* ppf = (parallelADFun<double>*) R_ExternalPtrAddr(f);
1677 std::string method =
1678 CHAR(STRING_ELT(getListElement(control,
"method"), 0));
1679 if (method ==
"parallel_accumulate") {
1680 int num_threads = getListInteger(control,
"num_threads", 2);
1681 if (num_threads == 1) {
1685 if (get_num_tapes(f) > 1) {
1689 adfun* pf = (ppf->vecpf)[0];
1692 Rcout <<
"Autopar work split\n";
1693 for (
size_t i=0; i < vf.size(); i++) {
1694 Rcout <<
"Chunk " << i <<
": ";
1695 Rcout << (double) vf[i].glob.opstack.size() / pf->glob.opstack.size() <<
"\n";
1698 parallelADFun<double>* new_ppf =
new parallelADFun<double>(vf);
1700 R_SetExternalPtrAddr(f, new_ppf);
1704 #pragma omp parallel for num_threads(config.nthreads) 1706 for (
int i=0; i<ppf->ntapes; i++) {
1707 adfun* pf = (ppf->vecpf)[i];
1708 TransformADFunObjectTemplate(pf, control);
1712 if (ppf->ntapes == 1) {
1713 ppf->domain = (ppf->vecpf)[0]->Domain();
1714 ppf->range = (ppf->vecpf)[0]->Range();
1717 for (
int i=0; i<ppf->ntapes; i++) {
1718 if (ppf->domain != (ppf->vecpf)[i]->Domain())
1719 Rf_warning(
"Domain has changed in an invalid way");
1722 Rf_error(
"Unknown function pointer");
1728 #ifdef CPPAD_FRAMEWORK 1730 SEXP TransformADFunObject(SEXP f, SEXP control)
1732 int mustWork = getListInteger(control,
"mustWork", 1);
1734 Rf_error(
"Not supported for CPPAD_FRAMEWORK");
1741 #ifdef TMBAD_FRAMEWORK 1742 SEXP InfoADFunObject(SEXP f) {
1745 if (Rf_isNull(f)) Rf_error(
"Expected external pointer - got NULL");
1746 int num_tapes = get_num_tapes(f);
1748 Rf_error(
"'InfoADFunObject' is only available for tapes with one thread");
1751 pf = (adfun*) R_ExternalPtrAddr(f);
1753 pf = ( (parallelADFun<double>*) R_ExternalPtrAddr(f) ) -> vecpf[0];
1756 PROTECT(ans = Rf_allocVector(VECSXP, 6));
1757 PROTECT(names = Rf_allocVector(STRSXP, 6));
1759 #define GET_INFO(EXPR) \ 1760 SET_VECTOR_ELT(ans, i, asSEXP(EXPR)); \ 1761 SET_STRING_ELT(names, i, Rf_mkChar(#EXPR)); \ 1764 std::vector<bool> a = pf -> activeDomain();
1765 std::vector<int> ai(a.begin(), a.end());
1767 GET_INFO(activeDomain);
1768 int opstack_size = pf->glob.opstack.size();
1769 GET_INFO(opstack_size);
1770 int values_size = pf->glob.values.size();
1771 GET_INFO(values_size);
1772 int inputs_size = pf->glob.inputs.size();
1773 GET_INFO(inputs_size);
1774 int Domain = pf->Domain();
1776 int Range = pf->Range();
1780 Rf_setAttrib(ans,R_NamesSymbol,names);
1786 #ifdef CPPAD_FRAMEWORK 1787 SEXP InfoADFunObject(SEXP f)
1790 pf = (ADFun<double>*) R_ExternalPtrAddr(f);
1792 PROTECT(ans = Rf_allocVector(VECSXP, 12));
1793 PROTECT(names = Rf_allocVector(STRSXP, 12));
1795 #define GET_MORE_INFO(MEMBER) \ 1796 SET_VECTOR_ELT(ans, i, asSEXP(int(pf->MEMBER()))); \ 1797 SET_STRING_ELT(names, i, Rf_mkChar(#MEMBER)); \ 1799 GET_MORE_INFO(Domain);
1800 GET_MORE_INFO(Range);
1801 GET_MORE_INFO(size_op);
1802 GET_MORE_INFO(size_op_arg);
1803 GET_MORE_INFO(size_op_seq);
1804 GET_MORE_INFO(size_par);
1805 GET_MORE_INFO(size_order);
1806 GET_MORE_INFO(size_direction);
1807 GET_MORE_INFO(size_text);
1808 GET_MORE_INFO(size_var);
1809 GET_MORE_INFO(size_VecAD);
1810 GET_MORE_INFO(Memory);
1811 #undef GET_MORE_INFO 1812 Rf_setAttrib(ans,R_NamesSymbol,names);
1818 #ifdef CPPAD_FRAMEWORK 1820 SEXP optimizeADFunObject(SEXP f)
1822 SEXP tag=R_ExternalPtrTag(f);
1823 if(tag == Rf_install(
"ADFun")){
1825 pf=(ADFun<double>*)R_ExternalPtrAddr(f);
1828 if(tag == Rf_install(
"parallelADFun")){
1829 parallelADFun<double>* pf;
1830 pf=(parallelADFun<double>*)R_ExternalPtrAddr(f);
1838 SEXP getTag(SEXP f){
1839 return R_ExternalPtrTag(f);
1842 #ifdef TMBAD_FRAMEWORK 1843 SEXP EvalADFunObject(SEXP f, SEXP theta, SEXP control)
1848 if(Rf_isNull(f))Rf_error(
"Expected external pointer - got NULL");
1849 SEXP tag=R_ExternalPtrTag(f);
1850 if(tag == Rf_install(
"ADFun"))
1851 return EvalADFunObjectTemplate< adfun >(f,theta,control);
1852 if(tag == Rf_install(
"parallelADFun"))
1853 return EvalADFunObjectTemplate<parallelADFun<double> >(f,theta,control);
1854 Rf_error(
"NOT A KNOWN FUNCTION POINTER");
1857 TMB_ERROR_BAD_ALLOC;
1862 #ifdef CPPAD_FRAMEWORK 1863 SEXP EvalADFunObject(SEXP f, SEXP theta, SEXP control)
1866 if(Rf_isNull(f))Rf_error(
"Expected external pointer - got NULL");
1867 SEXP tag=R_ExternalPtrTag(f);
1868 if(tag == Rf_install(
"ADFun"))
1869 return EvalADFunObjectTemplate<ADFun<double> >(f,theta,control);
1870 if(tag == Rf_install(
"parallelADFun"))
1871 return EvalADFunObjectTemplate<parallelADFun<double> >(f,theta,control);
1872 Rf_error(
"NOT A KNOWN FUNCTION POINTER");
1875 TMB_ERROR_BAD_ALLOC;
1880 SEXP getSetGlobalPtr(SEXP ptr) {
1881 #ifdef TMBAD_FRAMEWORK 1882 SEXP global_ptr_tag = Rf_install(
"global_ptr");
1883 if (!Rf_isNull(ptr)) {
1884 SEXP tag = R_ExternalPtrTag(ptr);
1885 if (tag != global_ptr_tag) Rf_error(
"Invalid pointer type");
1886 TMBad::global_ptr = (
TMBad::global**) R_ExternalPtrAddr(ptr);
1888 SEXP res = R_MakeExternalPtr( (
void*) TMBad::global_ptr, global_ptr_tag, R_NilValue);
1895 SEXP tmbad_print(SEXP f, SEXP control) {
1896 #ifdef TMBAD_FRAMEWORK 1899 int num_tapes = get_num_tapes(f);
1902 pf = (adfun*) R_ExternalPtrAddr(f);
1904 int i = getListInteger(control,
"i", 0);
1905 pf = ( (parallelADFun<double>*) R_ExternalPtrAddr(f) ) -> vecpf[i];
1907 std::string method =
1908 CHAR(STRING_ELT(getListElement(control,
"method"), 0));
1909 if (method ==
"num_tapes") {
1910 return Rf_ScalarInteger(num_tapes);
1912 else if (method ==
"tape") {
1913 int depth = getListInteger(control,
"depth", 1);
1916 pf->glob.print(cfg);
1918 else if (method ==
"dot") {
1919 graph2dot(pf->glob,
true, Rcout);
1921 else if (method ==
"inv_index") {
1922 using TMBad::operator<<;
1923 Rcout << pf->glob.inv_index <<
"\n";
1925 else if (method ==
"dep_index") {
1926 using TMBad::operator<<;
1927 Rcout << pf->glob.dep_index <<
"\n";
1929 else if (method ==
"src") {
1930 TMBad::code_config cfg;
1932 cfg.asm_comments =
false;
1934 *cfg.cout <<
"#include <cmath>" << std::endl;
1936 <<
"template<class T>T sign(const T &x) { return (x > 0) - (x < 0); }" 1939 TMBad::compress(glob);
1940 write_forward(glob, cfg);
1941 write_reverse(glob, cfg);
1943 else if (method ==
"op") {
1944 int name = getListInteger(control,
"name", 0);
1945 int address = getListInteger(control,
"address", 0);
1946 int input_size = getListInteger(control,
"input_size", 0);
1947 int output_size = getListInteger(control,
"output_size", 0);
1948 size_t n = pf->glob.opstack.size();
1949 SEXP ans = PROTECT(Rf_allocVector(STRSXP, n));
1950 for (
size_t i=0; i<n; i++) {
1951 std::stringstream strm;
1952 if (address) strm << (
void*) pf->glob.opstack[i] <<
" ";
1953 if (name) strm << pf->glob.opstack[i]->op_name() <<
" ";
1954 if (input_size) strm << pf->glob.opstack[i]->input_size();
1955 if (output_size) strm << pf->glob.opstack[i]->output_size();
1956 const std::string& tmp = strm.str();
1957 SET_STRING_ELT(ans, i, Rf_mkChar(tmp.c_str()));
1963 Rf_error(
"Unknown method: %s", method.c_str());
1976 void finalizeDoubleFun(SEXP x)
1978 objective_function<double>* ptr=(objective_function<double>*)R_ExternalPtrAddr(x);
1979 if(ptr!=NULL)
delete ptr;
1980 memory_manager.CallCFinalizer(x);
1983 SEXP MakeDoubleFunObject(SEXP data, SEXP parameters, SEXP report, SEXP control)
1986 if(!Rf_isNewList(data))Rf_error(
"'data' must be a list");
1987 if(!Rf_isNewList(parameters))Rf_error(
"'parameters' must be a list");
1988 if(!Rf_isEnvironment(report))Rf_error(
"'report' must be an environment");
1991 objective_function<double>* pF = NULL;
1993 pF =
new objective_function<double>(data,parameters,report);
1996 if (pF != NULL)
delete pF;
1997 TMB_ERROR_BAD_ALLOC;
2002 PROTECT(res=R_MakeExternalPtr((
void*) pF,Rf_install(
"DoubleFun"),R_NilValue));
2003 PROTECT(ans=ptrList(res));
2009 SEXP EvalDoubleFunObject(SEXP f, SEXP theta, SEXP control)
2012 int do_simulate = getListInteger(control,
"do_simulate");
2013 int get_reportdims = getListInteger(control,
"get_reportdims");
2014 objective_function<double>* pf;
2015 pf = (objective_function<double>*) R_ExternalPtrAddr(f);
2017 PROTECT( theta=Rf_coerceVector(theta,REALSXP) );
2018 int n = pf->theta.size();
2019 if (LENGTH(theta)!=n) Rf_error(
"Wrong parameter length.");
2021 for(
int i=0;i<n;i++) x[i] = REAL(theta)[i];
2026 pf->parnames.resize(0);
2027 pf->reportvector.clear();
2030 if(do_simulate) pf->set_simulate(
true );
2031 PROTECT( res =
asSEXP( pf->operator()() ) );
2033 pf->set_simulate(
false );
2036 if(get_reportdims) {
2038 PROTECT( reportdims = pf -> reportvector.reportdims() );
2039 Rf_setAttrib( res, Rf_install(
"reportdims"), reportdims);
2046 TMB_ERROR_BAD_ALLOC;
2053 SEXP getParameterOrder(SEXP data, SEXP parameters, SEXP report, SEXP control)
2057 if(!Rf_isNewList(data))Rf_error(
"'data' must be a list");
2058 if(!Rf_isNewList(parameters))Rf_error(
"'parameters' must be a list");
2059 if(!Rf_isEnvironment(report))Rf_error(
"'report' must be an environment");
2060 objective_function<double> F(data,parameters,report);
2062 return F.parNames();
2065 TMB_ERROR_BAD_ALLOC;
2072 #ifdef TMBAD_FRAMEWORK 2077 SEXP f = getListElement(control,
"f");
2079 bool allocate_new_pf = ( f == R_NilValue );
2080 if ( ! allocate_new_pf ) {
2081 if (parallel_region == -1)
2082 pf = (adfun*) R_ExternalPtrAddr(f);
2084 pf = ((parallelADFun<double>*) R_ExternalPtrAddr(f))->vecpf[parallel_region];
2086 SEXP control_adfun = R_NilValue;
2087 pf = MakeADFunObject_(data, parameters, report, control_adfun, parallel_region);
2090 SEXP random = getListElement(control,
"random");
2091 if (random != R_NilValue) {
2092 int set_tail = INTEGER(random)[0] - 1;
2093 std::vector<TMBad::Index> r(1, set_tail);
2096 adfun* pgf =
new adfun (pf->JacFun());
2098 if (allocate_new_pf)
delete pf;
2103 #ifdef CPPAD_FRAMEWORK 2104 ADFun< double >* MakeADGradObject_(SEXP data, SEXP parameters, SEXP report, SEXP control,
int parallel_region=-1)
2107 objective_function< AD<AD<double> > > F(data,parameters,report);
2108 F.set_parallel_region(parallel_region);
2109 int n=F.theta.size();
2110 Independent(F.theta);
2112 y[0]=F.evalUserTemplate();
2113 ADFun<AD<double> > tmp(F.theta,y);
2116 for(
int i=0;i<n;i++)x[i]=CppAD::Value(F.theta[i]);
2120 ADFun< double >* pf =
new ADFun< double >(x,yy);
2127 #ifdef TMBAD_FRAMEWORK 2129 SEXP MakeADGradObject(SEXP data, SEXP parameters, SEXP report, SEXP control)
2136 if(!Rf_isNewList(data))Rf_error(
"'data' must be a list");
2137 if(!Rf_isNewList(parameters))Rf_error(
"'parameters' must be a list");
2138 if(!Rf_isEnvironment(report))Rf_error(
"'report' must be an environment");
2142 objective_function< double > F(data,parameters,report);
2144 SEXP f = getListElement(control,
"f");
2145 int n = get_num_tapes(f);
2147 n = F.count_parallel_regions();
2149 F.count_parallel_regions();
2151 PROTECT(par=F.defaultpar());
2156 std::cout << n <<
" regions found.\n";
2160 const char* bad_thread_alloc = NULL;
2161 #pragma omp parallel for num_threads(config.nthreads) if (config.tape.parallel && n>1) 2162 for(
int i=0;i<n;i++){
2165 pfvec[i] = MakeADGradObject_(data, parameters, report, control, i);
2166 if (config.
optimize.instantly) pfvec[i]->optimize();
2169 if (pfvec[i] != NULL)
delete pfvec[i];
2170 bad_thread_alloc = excpt.what();
2173 if (bad_thread_alloc) {
2174 TMB_ERROR_BAD_THREAD_ALLOC;
2176 parallelADFun<double>* ppf=
new parallelADFun<double>(pfvec);
2178 PROTECT(res=R_MakeExternalPtr((
void*) ppf,Rf_install(
"parallelADFun"),R_NilValue));
2185 pf = MakeADGradObject_(data, parameters, report, control, -1);
2186 if(config.
optimize.instantly)pf->optimize();
2189 if (pf != NULL)
delete pf;
2190 TMB_ERROR_BAD_ALLOC;
2193 PROTECT(res=R_MakeExternalPtr((
void*) pf,Rf_install(
"ADFun"),R_NilValue));
2198 Rf_setAttrib(res,Rf_install(
"par"),par);
2199 PROTECT(ans=ptrList(res));
2205 #ifdef CPPAD_FRAMEWORK 2207 SEXP MakeADGradObject(SEXP data, SEXP parameters, SEXP report, SEXP control)
2209 ADFun<double>* pf = NULL;
2211 if(!Rf_isNewList(data))Rf_error(
"'data' must be a list");
2212 if(!Rf_isNewList(parameters))Rf_error(
"'parameters' must be a list");
2213 if(!Rf_isEnvironment(report))Rf_error(
"'report' must be an environment");
2217 objective_function< double > F(data,parameters,report);
2219 int n=F.count_parallel_regions();
2221 F.count_parallel_regions();
2223 PROTECT(par=F.defaultpar());
2228 std::cout << n <<
" regions found.\n";
2232 const char* bad_thread_alloc = NULL;
2233 #pragma omp parallel for num_threads(config.nthreads) if (config.tape.parallel && n>1) 2234 for(
int i=0;i<n;i++){
2237 pfvec[i] = MakeADGradObject_(data, parameters, report, control, i);
2238 if (config.
optimize.instantly) pfvec[i]->optimize();
2241 if (pfvec[i] != NULL)
delete pfvec[i];
2242 bad_thread_alloc = excpt.what();
2245 if (bad_thread_alloc) {
2246 TMB_ERROR_BAD_THREAD_ALLOC;
2248 parallelADFun<double>* ppf=
new parallelADFun<double>(pfvec);
2250 PROTECT(res=R_MakeExternalPtr((
void*) ppf,Rf_install(
"parallelADFun"),R_NilValue));
2256 pf = MakeADGradObject_(data, parameters, report, control, -1);
2257 if(config.
optimize.instantly)pf->optimize();
2260 if (pf != NULL)
delete pf;
2261 TMB_ERROR_BAD_ALLOC;
2264 PROTECT(res=R_MakeExternalPtr((
void*) pf,Rf_install(
"ADFun"),R_NilValue));
2269 Rf_setAttrib(res,Rf_install(
"par"),par);
2270 PROTECT(ans=ptrList(res));
2284 #ifdef TMBAD_FRAMEWORK 2285 sphess_t< TMBad::ADFun< TMBad::ad_aug > > MakeADHessObject2_(SEXP data, SEXP parameters, SEXP report, SEXP control,
int parallel_region=-1)
2289 typedef sphess_t<adfun> sphess;
2290 SEXP gf = getListElement(control,
"gf");
2292 bool allocate_new_pgf = ( gf == R_NilValue );
2293 if ( ! allocate_new_pgf ) {
2294 if (parallel_region == -1)
2295 pgf = (adfun*) R_ExternalPtrAddr(gf);
2297 pgf = ((parallelADFun<double>*) R_ExternalPtrAddr(gf))->vecpf[parallel_region];
2299 SEXP control_adgrad = R_NilValue;
2300 pgf = MakeADGradObject_(data, parameters, report, control_adgrad, parallel_region);
2302 if (config.
optimize.instantly) pgf->optimize();
2303 int n = pgf->Domain();
2304 std::vector<bool> keepcol(n,
true);
2305 SEXP skip = getListElement(control,
"skip");
2306 for(
int i=0; i<LENGTH(skip); i++) {
2307 keepcol[ INTEGER(skip)[i] - 1 ] =
false;
2310 spjacfun_cfg.index_remap =
false;
2312 TMBad::Sparse<adfun> h = pgf->SpJacFun(keepcol, keepcol, spjacfun_cfg);
2313 if (allocate_new_pgf)
delete pgf;
2316 h.subset_inplace( h.row() <= h.col() );
2317 h.transpose_inplace();
2320 adfun* phf =
new adfun( h );
2324 sphess ans(phf, h_i.cast<
int>(), h_j.cast<
int>());
2335 #ifdef CPPAD_FRAMEWORK 2336 sphess MakeADHessObject2_(SEXP data, SEXP parameters, SEXP report, SEXP control,
int parallel_region=-1)
2339 if(!Rf_isNewList(data))Rf_error(
"'data' must be a list");
2340 if(!Rf_isNewList(parameters))Rf_error(
"'parameters' must be a list");
2341 if(!Rf_isEnvironment(report))Rf_error(
"'report' must be an environment");
2344 objective_function< AD<AD<AD<double> > > > F(data,parameters,report);
2345 F.set_parallel_region(parallel_region);
2346 int n = F.theta.size();
2347 SEXP skip = getListElement(control,
"skip");
2349 for(
int i=0; i<n; i++){
2352 for(
int i=0; i<LENGTH(skip); i++){
2353 keepcol[INTEGER(skip)[i]-1]=
false;
2355 #define KEEP_COL(col) (keepcol[col]) 2356 #define KEEP_ROW(row,col) ( KEEP_COL(row) && (row>=col) ) 2359 Independent(F.theta);
2361 y[0] = F.evalUserTemplate();
2362 ADFun<AD<AD<double> > > tape1(F.theta, y);
2366 for(
int i=0; i<n; i++) xx[i] = CppAD::Value(F.theta[i]);
2369 yy = tape1.Jacobian(xx);
2370 ADFun<AD<double > > tape2(xx,yy);
2371 if (config.
optimize.instantly) tape2.optimize();
2374 tape2.my_init(keepcol);
2377 for(
int i=0; i<int(tape2.colpattern.size()); i++){
2378 colisize = tape2.colpattern[i].size();
2380 for(
int j=0; j<colisize; j++){
2381 m += KEEP_ROW( tape2.colpattern[i][j] , i);
2391 for(
int i = 0; i < n; i++) v[i] = 0.0;
2393 for(
int i=0; i<n; i++) xxx[i]=CppAD::Value(CppAD::Value(F.theta[i]));
2395 CppAD::vector<int>* icol;
2398 tape2.Forward(0, xxx);
2400 for(
int i = 0; i < n; i++){
2402 tape2.myReverse(1, v, i , u );
2403 icol = &tape2.colpattern[i];
2404 for(
int j=0; j<int(icol->size()); j++){
2405 if(KEEP_ROW( icol->operator[](j), i )){
2406 rowindex[k] = icol->operator[](j);
2408 yyy[k] = u[icol->operator[](j)];
2414 ADFun< double >* ptape3 =
new ADFun< double >;
2415 ptape3->Dependent(xxx,yyy);
2416 sphess ans(ptape3, rowindex, colindex);
2422 template <
class ADFunType>
2424 SEXP
asSEXP(
const sphess_t<ADFunType> &H,
const char* tag)
2430 PROTECT( res = R_MakeExternalPtr((
void*) H.pf, Rf_install(tag), R_NilValue) );
2434 SEXP par_symbol = Rf_install(
"par");
2435 SEXP i_symbol = Rf_install(
"i");
2436 SEXP j_symbol = Rf_install(
"j");
2437 Rf_setAttrib(res, par_symbol, par);
2438 Rf_setAttrib(res, i_symbol,
asSEXP(H.i));
2439 Rf_setAttrib(res, j_symbol,
asSEXP(H.j));
2440 PROTECT(ans=ptrList(res));
2449 #ifdef TMBAD_FRAMEWORK 2451 SEXP MakeADHessObject2(SEXP data, SEXP parameters, SEXP report, SEXP control){
2454 typedef sphess_t<adfun> sphess;
2456 std::cout <<
"Count num parallel regions\n";
2457 objective_function< double > F(data,parameters,report);
2458 SEXP gf = getListElement(control,
"gf");
2459 int n = get_num_tapes(gf);
2461 n = F.count_parallel_regions();
2463 std::cout << n <<
" regions found.\n";
2467 const char* bad_thread_alloc = NULL;
2469 #pragma omp parallel for num_threads(config.nthreads) if (config.tape.parallel && n>1) 2470 for (
int i=0; i<n; i++) {
2473 Hvec[i] =
new sphess( MakeADHessObject2_(data, parameters, report, control, i) );
2477 if (Hvec[i] != NULL) {
2481 bad_thread_alloc = excpt.what();
2484 if (bad_thread_alloc) {
2485 TMB_ERROR_BAD_THREAD_ALLOC;
2487 parallelADFun<double>* tmp=
new parallelADFun<double>(Hvec);
2488 return asSEXP(tmp->convert(),
"parallelADFun");
2491 SEXP MakeADHessObject2(SEXP data, SEXP parameters, SEXP report, SEXP control){
2494 typedef sphess_t<adfun> sphess;
2498 pH =
new sphess( MakeADHessObject2_(data, parameters, report, control, -1) );
2500 ans =
asSEXP(*pH,
"ADFun");
2507 TMB_ERROR_BAD_ALLOC;
2515 #ifdef CPPAD_FRAMEWORK 2517 SEXP MakeADHessObject2(SEXP data, SEXP parameters, SEXP report, SEXP control){
2519 std::cout <<
"Count num parallel regions\n";
2520 objective_function< double > F(data,parameters,report);
2521 int n=F.count_parallel_regions();
2523 std::cout << n <<
" regions found.\n";
2529 const char* bad_thread_alloc = NULL;
2531 #pragma omp parallel for num_threads(config.nthreads) if (config.tape.parallel && n>1) 2532 for (
int i=0; i<n; i++) {
2535 Hvec[i] =
new sphess( MakeADHessObject2_(data, parameters, report, control, i) );
2536 optimizeTape( Hvec[i]->pf );
2539 if (Hvec[i] != NULL) {
2543 bad_thread_alloc = excpt.what();
2546 if (bad_thread_alloc) {
2547 TMB_ERROR_BAD_THREAD_ALLOC;
2549 parallelADFun<double>* tmp=
new parallelADFun<double>(Hvec);
2550 for(
int i=0; i<n; i++) {
2554 SEXP ans =
asSEXP(tmp->convert(),
"parallelADFun");
2558 SEXP MakeADHessObject2(SEXP data, SEXP parameters, SEXP report, SEXP control){
2562 pH =
new sphess( MakeADHessObject2_(data, parameters, report, control, -1) );
2563 optimizeTape( pH->pf );
2564 ans =
asSEXP(*pH,
"ADFun");
2571 TMB_ERROR_BAD_ALLOC;
2583 #ifdef TMBAD_FRAMEWORK 2584 SEXP usingAtomics(){
2586 PROTECT(ans = Rf_allocVector(INTSXP,1));
2587 INTEGER(ans)[0] = 1;
2593 #ifdef CPPAD_FRAMEWORK 2594 SEXP usingAtomics(){
2596 PROTECT(ans = Rf_allocVector(INTSXP,1));
2597 INTEGER(ans)[0] = atomic::atomicFunctionGenerated;
2603 SEXP getFramework() {
2606 #ifdef TMBAD_FRAMEWORK 2607 ans = Rf_mkString(
"TMBad");
2608 #elif defined(CPPAD_FRAMEWORK) 2609 ans = Rf_mkString(
"CppAD");
2611 ans = Rf_mkString(
"Unknown");
2615 SEXP openmp_sym = Rf_install(
"openmp");
2616 PROTECT(openmp_sym);
2620 openmp_res = Rf_ScalarLogical(1);
2622 openmp_res = Rf_ScalarLogical(0);
2624 PROTECT(openmp_res);
2626 Rf_setAttrib(ans, openmp_sym, openmp_res);
2629 #ifdef TMBAD_FRAMEWORK 2630 SEXP index_size_sym = Rf_install(
"sizeof(Index)");
2631 PROTECT(index_size_sym);
2632 SEXP index_size = Rf_ScalarInteger(
sizeof(TMBad::Index));
2633 PROTECT(index_size);
2634 Rf_setAttrib(ans, index_size_sym, index_size);
2644 void tmb_forward(SEXP f,
const Eigen::VectorXd &x, Eigen::VectorXd &y) {
2645 #ifdef CPPAD_FRAMEWORK 2646 SEXP tag=R_ExternalPtrTag(f);
2647 if(tag == Rf_install(
"ADFun")) {
2649 pf = (ADFun<double>*) R_ExternalPtrAddr(f);
2650 y = pf->Forward(0, x);
2652 if(tag == Rf_install(
"parallelADFun")) {
2653 parallelADFun<double>* pf;
2654 pf = (parallelADFun<double>*) R_ExternalPtrAddr(f);
2655 y = pf->Forward(0, x);
2657 Rf_error(
"Unknown function pointer");
2659 #ifdef TMBAD_FRAMEWORK 2662 SEXP tag=R_ExternalPtrTag(f);
2663 if(tag == Rf_install(
"ADFun")) {
2664 adfun* pf = (adfun*) R_ExternalPtrAddr(f);
2667 if(tag == Rf_install(
"parallelADFun")) {
2668 parallelADFun<double>* pf;
2669 pf = (parallelADFun<double>*) R_ExternalPtrAddr(f);
2672 Rf_error(
"Unknown function pointer");
2675 void tmb_reverse(SEXP f,
const Eigen::VectorXd &v, Eigen::VectorXd &y) {
2676 #ifdef CPPAD_FRAMEWORK 2677 SEXP tag=R_ExternalPtrTag(f);
2678 if(tag == Rf_install(
"ADFun")) {
2680 pf = (ADFun<double>*) R_ExternalPtrAddr(f);
2681 y = pf->Reverse(1, v);
2683 if(tag == Rf_install(
"parallelADFun")) {
2684 parallelADFun<double>* pf;
2685 pf = (parallelADFun<double>*) R_ExternalPtrAddr(f);
2686 y = pf->Reverse(1, v);
2688 Rf_error(
"Unknown function pointer");
2690 #ifdef TMBAD_FRAMEWORK 2693 SEXP tag=R_ExternalPtrTag(f);
2694 if(tag == Rf_install(
"ADFun")) {
2695 adfun* pf = (adfun*) R_ExternalPtrAddr(f);
2698 if(tag == Rf_install(
"parallelADFun")) {
2699 parallelADFun<double>* pf;
2700 pf = (parallelADFun<double>*) R_ExternalPtrAddr(f);
2703 Rf_error(
"Unknown function pointer");
2716 template class objective_function<double>;
2717 #ifdef CPPAD_FRAMEWORK 2718 template class objective_function<AD<double> >;
2719 template class objective_function<AD<AD<double> > >;
2720 template class objective_function<AD<AD<AD<double> > > >;
2722 #ifdef TMBAD_FRAMEWORK 2723 template class objective_function<TMBad::ad_aug>;
2728 SEXP MakeADFunObject(SEXP data, SEXP parameters, SEXP report, SEXP control);
2729 SEXP InfoADFunObject(SEXP f);
2730 SEXP tmbad_print(SEXP f, SEXP control);
2731 SEXP optimizeADFunObject(SEXP f);
2732 SEXP EvalADFunObject(SEXP f, SEXP theta, SEXP control);
2733 SEXP MakeDoubleFunObject(SEXP data, SEXP parameters, SEXP report, SEXP control);
2734 SEXP EvalDoubleFunObject(SEXP f, SEXP theta, SEXP control);
2735 SEXP getParameterOrder(SEXP data, SEXP parameters, SEXP report, SEXP control);
2736 SEXP MakeADGradObject(SEXP data, SEXP parameters, SEXP report, SEXP control);
2737 SEXP MakeADHessObject2(SEXP data, SEXP parameters, SEXP report, SEXP control);
2738 SEXP usingAtomics();
2739 SEXP getFramework();
2740 SEXP getSetGlobalPtr(SEXP ptr);
2741 SEXP TransformADFunObject(SEXP f, SEXP control);
2742 void tmb_forward(SEXP f,
const Eigen::VectorXd &x, Eigen::VectorXd &y);
2743 void tmb_reverse(SEXP f,
const Eigen::VectorXd &v, Eigen::VectorXd &y);
2753 #define xstringify(s) stringify(s) 2754 #define stringify(s) #s 2756 #define TMB_CALLDEFS \ 2757 {"MakeADFunObject", (DL_FUNC) &MakeADFunObject, 4}, \ 2758 {"FreeADFunObject", (DL_FUNC) &FreeADFunObject, 1}, \ 2759 {"InfoADFunObject", (DL_FUNC) &InfoADFunObject, 1}, \ 2760 {"tmbad_print", (DL_FUNC) &tmbad_print, 2}, \ 2761 {"EvalADFunObject", (DL_FUNC) &EvalADFunObject, 3}, \ 2762 {"TransformADFunObject",(DL_FUNC) &TransformADFunObject,2}, \ 2763 {"MakeDoubleFunObject", (DL_FUNC) &MakeDoubleFunObject, 4}, \ 2764 {"EvalDoubleFunObject", (DL_FUNC) &EvalDoubleFunObject, 3}, \ 2765 {"getParameterOrder", (DL_FUNC) &getParameterOrder, 4}, \ 2766 {"MakeADGradObject", (DL_FUNC) &MakeADGradObject, 4}, \ 2767 {"MakeADHessObject2", (DL_FUNC) &MakeADHessObject2, 4}, \ 2768 {"usingAtomics", (DL_FUNC) &usingAtomics, 0}, \ 2769 {"getFramework", (DL_FUNC) &getFramework, 0}, \ 2770 {"getSetGlobalPtr", (DL_FUNC) &getSetGlobalPtr, 1}, \ 2771 {"TMBconfig", (DL_FUNC) &TMBconfig, 2} 2774 #define TMB_CCALLABLES(PACKAGE) \ 2775 R_RegisterCCallable(PACKAGE, "tmb_forward", (DL_FUNC) &tmb_forward); \ 2776 R_RegisterCCallable(PACKAGE, "tmb_reverse", (DL_FUNC) &tmb_reverse); 2779 #include <R_ext/Rdynload.h> 2780 static R_CallMethodDef CallEntries[] = {
2789 {xstringify(LIB_UNLOAD), (DL_FUNC) &LIB_UNLOAD, 1},
2794 void TMB_LIB_INIT(DllInfo *dll){
2795 R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
2796 R_useDynamicSymbols(dll, (Rboolean)FALSE);
2801 TMB_CCALLABLES(&(xstringify(TMB_LIB_INIT)[7]));
VT cdf_upper
Logarithm of upper CDF
std::vector< T > subset(const std::vector< T > &x, const std::vector< bool > &y)
Vector subset by boolean mask.
Vector class used by TMB.
void reorder_temporaries(global &glob)
Re-order computational graph to make it more compressible.
data_indicator segment(int pos, int n)
Extract segment of indicator vector or array.
data_indicator()
Default CTOR.
void reorder_sub_expressions(global &glob)
Re-order computational graph to make it more compressible.
void reorder_depth_first(global &glob)
Depth-first reordering of computational graph.
Newton configuration parameters.
Automatic differentiation function object.
Configuration of print method.
Matrix class used by TMB.
bool osa_active()
Are we inside a oneStepPredict calculation?
void reorder(std::vector< Index > last)
Reorder computational graph to allow quick updates of selected inputs.
bool optimize
Trace tape optimization.
Utilities for OSA residuals.
Struct defining the main AD context.
Scalar Value() const
Return the underlying scalar value of this ad_aug.
data_indicator(VT obs, bool init_one=false)
Construct from observation vector.
bool autopar
Enable automatic parallization (if OpenMP is enabled) ?
vector< int > order()
Get order in which the one step conditionals will be requested by oneStepPredict. ...
#define PARAMETER_VECTOR(name)
Get parameter vector from R and declare it as vector<Type>
Configuration parameters for SpJacFun()
SEXP asSEXP(const matrix< Type > &a)
Convert TMB matrix, vector, scalar or int to R style.
bool sparse_hessian_compress
Reduce memory of sparse hessian even if reducing speed ?
void replay()
Replay this operation sequence to a new sequence.
VT cdf_lower
Logarithm of lower CDF
Type sum(Vector< Type > x)
Utilility class for sequential_reduction.
matrix< Type > asMatrix(const vector< Type > &x, int nr, int nc)
Vector <-> Matrix conversion (for row-major matrices)
std::vector< ADFun > parallel_accumulate(size_t num_threads)
Parallel split this operation sequence Split function f:R^n->R by its accumulation tree...
int nthreads
Number of OpenMP threads to use (if OpenMP is enabled)
Helper to manage parallel accumulation.
void optimize()
Tape optimizer.
vector< int > ord
Subset argument (zero-based) passed from oneStepPredict. See data_indicator::order().
bool parallel
Trace info from parallel for loops.
void fill(vector< Type > p, SEXP ord_)
Fill with parameter vector.
bool osa_flag
Flag to tell if OSA calculation is active. See data_indicator::osa_active().