Skip to content
This repository has been archived by the owner on Jul 29, 2020. It is now read-only.

Commit

Permalink
added example of overload fn to track REPORT
Browse files Browse the repository at this point in the history
  • Loading branch information
James-Thorson committed May 8, 2018
1 parent 3215142 commit f12eff5
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 0 deletions.
61 changes: 61 additions & 0 deletions TMB examples/Track report objects/Track_report.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@

setwd( "C:/Users/James.Thorson/Desktop/Project_git/2018_FSH556/TMB examples/Track report objects/" )

library(TMB)
library(RandomFields)
library(Matrix)

###################
# Equal distance 2D autoregressive
###################

Dim = c("n_x"=10, "n_y"=10)
loc_xy = expand.grid("x"=1:Dim['n_x'], "y"=1:Dim['n_y'])
Scale = 5
Sigma2 = (0.5) ^ 2
beta0 = 3
prob_missing = 0.2

# Simulate spatial process
RMmodel = RMexp(var=Sigma2, scale=Scale)
epsilon_xy = array(RFsimulate(model=RMmodel, x=loc_xy[,'x'], y=loc_xy[,'y'])@data[,1], dim=Dim)
image( z=epsilon_xy )

# SImulate counts
c_xy = array(NA, dim=dim(epsilon_xy))
for(x in 1:nrow(c_xy)){
for(y in 1:ncol(c_xy)){
c_xy[x,y] = rpois(1, exp(beta0 + epsilon_xy[x,y]) )
if( rbinom(n=1, size=1, prob=prob_missing)==1) c_xy[x,y] = NA
}}
true_abundance = sum( exp(beta0 + epsilon_xy) )

# Generate sparse matrices for precision matrix of 2D AR1 process
M0 = as( ifelse(as.matrix(dist(loc_xy,diag=TRUE,upper=TRUE))==0,1,0), "dgTMatrix" )
M1 = as( ifelse(as.matrix(dist(loc_xy,diag=TRUE,upper=TRUE))==1,1,0), "dgTMatrix" )
M2 = as( ifelse(as.matrix(dist(loc_xy,diag=TRUE,upper=TRUE))==sqrt(2),1,0), "dgTMatrix" )

# Compile
Params = list( "beta0"=0, "ln_sigma2"=0, "logit_rho"=0, "epsilon_xy"=array(rnorm(prod(dim(loc_xy)))-100,dim=dim(epsilon_xy)) )
compile( "autoregressive_grid.cpp" )
dyn.load( dynlib("autoregressive_grid") )

# Build object
Data = list("c_xy"=c_xy, "M0"=M0, "M1"=M1, "M2"=M2 )
Obj = MakeADFun( data=Data, parameters=Params, random="epsilon_xy", DLL="autoregressive_grid" )

# Overload marginal log-likelihood function
Obj$fn_orig = Obj$fn
Obj$fn = function( par ){
MargNLL = Obj$fn_orig( par )
Report = Obj$report()
Total_Abundance = rbind(Total_Abundance, c(nrow(Total_Abundance)+1, Report$Total_Abundance) )
colnames(Total_Abundance) = c("Function_call","Total_Abundance")
assign( "Total_Abundance", Total_Abundance, pos=.GlobalEnv )
return( MargNLL )
}

# Optimize
Total_Abundance = data.frame()
Opt = TMBhelper::Optimize( obj=Obj, fn=Obj$fn_trace, newtonsteps=1 )

61 changes: 61 additions & 0 deletions TMB examples/Track report objects/autoregressive_grid.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@

#include <TMB.hpp>
// Function for detecting NAs
template<class Type>
bool isNA(Type x){
return R_IsNA(asDouble(x));
}

// Space time
template<class Type>
Type objective_function<Type>::operator() ()
{
// Data
DATA_MATRIX( c_xy );

// Sparse matrices for forming the AR precision matrix (Version #4 below)
// Q = M0*(1+rho^2)^2 + M1*(1+rho^2)*(-rho) + M2*rho^2
DATA_SPARSE_MATRIX(M0);
DATA_SPARSE_MATRIX(M1);
DATA_SPARSE_MATRIX(M2);

// Parameters
PARAMETER( beta0 );
PARAMETER( ln_sigma2 );
PARAMETER( logit_rho );

// Random effects
PARAMETER_ARRAY( epsilon_xy );

// Objective funcction
int n_x = c_xy.col(0).size();
int n_y = c_xy.row(0).size();
vector<Type> jnll_comp(2);
jnll_comp.setZero();
Type sigma2 = exp(ln_sigma2);
Type rho = 1 / (1 + exp(-logit_rho));

//// Calculate using built-in TMB functions
using namespace density;
Eigen::SparseMatrix<Type> Q_zz = ( M0*pow(1+pow(rho,2),2) + M1*(1+pow(rho,2))*(-rho) + M2*pow(rho,2) ) / sigma2;
jnll_comp(1) += GMRF(Q_zz)( epsilon_xy );

// Probability of data conditional on random effects
Type Total_Abundance = 0;
for( int x=0; x<n_x; x++){
for( int y=0; y<n_y; y++){
if( !isNA(c_xy(x,y)) ) jnll_comp(0) -= dpois( c_xy(x,y), exp(beta0 + epsilon_xy(x,y)), true );
Total_Abundance += exp(beta0 + epsilon_xy(x,y));
}}

// Reporting
Type jnll = jnll_comp.sum();
REPORT( jnll_comp );
REPORT( jnll );
REPORT( sigma2 );
REPORT( rho );
REPORT( Total_Abundance );
ADREPORT( Total_Abundance );

return jnll;
}

0 comments on commit f12eff5

Please sign in to comment.