Good afternoon: I have 30 years of population data on guanacos, and a matrix simulation model; I want to estimate the optimal values of 12 of the model's parameters in R using optim, by minimizing the residual sums of squares (Sum(obs-pred)^2). I created a function with the model. The model is working fine, for if I invoke the function with fixed parameter values I get the exected results. When I call optim with a sewt of initial parameters and the function, I get the following error message: "the argument a13 is absent, with no value by omission"; also: Message of lost warning: In if (SSQ == 0) { : the condition has a length > 1 and only the first element will be used Called from: top level (freely translated from Spanish).
Please find below the R code in three sections: (1) first with the function "guafit" declaration, (2) with a standalone run of the model invoking the "guafit", and (3) the call of "optim" with its starting parameter values.
Thank you, Jorge Rabinovich
# Section (1):
# Clean all
rm(list=ls())
#####################################################################
####################### Function "guafit" ##########################
#####################################################################
guafit <- function(SSQ,a13,a21,a32,a33,ad1,ad2,ad3,ad4,bd1,bd2,bd3,bd4) {
# Create the field population (a 30-years time series)
# ====================================================
tfield <- c(12334,10670,19078,11219,11771,12323,13027,14094,14604,17775,20774,16410,17626,21445,21111,20777,28978,27809,28935,38841,38363,32273,43128,58597,52456,33125,61334,60488,44773,56973)
# Assign values to the vector of the initial population
# =====================================================
G <- matrix(c(0,0,0),ncol=3, nrow=1)
G[1]= 1542
G[2]= 740
G[3]= 3885
# Load the matrices with their initial values for all 30 time units (years)
# =========================================================================
if (SSQ == 0) {
a<-array(0,dim=c(3,3,30))
for(i in 1:29) {
a[1,3,i]= a13
a[2,1,i]= a21
a[3,2,i]= a32
a[3,3,i]= a33
}
}
# Initialize some variables
# ==========================
tmod<-array(1,dim=c(1,30)); tmod <- as.numeric(tmod)
densprop<-array(1,dim=c(1,30)); densprop <- as.numeric(densprop)
FdeltaFe<-array(1,dim=c(1,30)); FdeltaFe <- as.numeric(FdeltaFe)
FdeltaSc<-array(1,dim=c(1,30)); FdeltaSc <- as.numeric(FdeltaSc)
FdeltaSj<-array(1,dim=c(1,30)); FdeltaSj <- as.numeric(FdeltaSj)
FdeltaSa<-array(1,dim=c(1,30)); FdeltaSa <- as.numeric(FdeltaSa)
# N0 is the initial population vector
# It is multiplied by 2 to represewnt both sexes
# ===============================================
# Transfer guanacos (G) as a vector with the three age classes
N0 <- G
tmod[1] <- (N0[1]+N0[2]+N0[3]) * 2
# Declaration of the initial simulation conditions
# ================================================
# ng is the number of female individuals per age class (dim 3x30)
# tmod is the total (both sexes) population (sum of the three age classes * 2)
ng <- matrix( 0, nrow= 3, ncol=30)
ng[,1] <- N0
# We assume a constant carrying capacity (K= 60000 individuals)
carcap= 60000
# Start simulation for 30 years
for(i in 1:29) {
#Set up the density-dependent coefficients
densprop[i] <- tmod[i] / carcap
# Calculate the density-dependent factors
FdeltaFe[i]= 1/(1+exp((densprop[i]-ad1)*bd1))
FdeltaSc[i]= 1/(1+exp((densprop[i]-ad2)*bd2))
FdeltaSj[i]= 1/(1+exp((densprop[i]-ad3)*bd3))
FdeltaSa[i]= 1/(1+exp((densprop[i]-ad4)*bd4))
# Apply the density-dependent factors to each coefficient in its own age class
a[1,3,i]= a[1,3,i] * FdeltaFe[i]
a[2,1,i]= a[2,1,i] * FdeltaSc[i]
a[3,2,i]= a[3,2,i] * FdeltaSj[i]
a[3,3,i]= a[3,3,i] * FdeltaSa[i]
# Project the total population with the matrix operation
ng[,i+1] <- a[,,i]%*%ng[,i]
tmod[i+1] <- (ng[1,i+1] + ng[2,i+1] + ng[3,i+1]) * 2
# End of the 30-years simulation loop
}
# Calculate the residual sum of squares (SSQ)
SSQ = sum((tmod - tfield)^2)
return(list(outm=tmod, outc=tfield, elSSQ=SSQ, matrices=a, losgua=G, losguaxe=ng))
# End of function guafit
}
#################################################################################
# Section (2):
# Initialize conditions and parameters before calling function guafit
SSQ <- 0
# Initialize the 8 density-dependent coefficients (2 coefficients per age class)
# ==============================================================================
ad1= 1.195680167
ad2= 1.127219245
ad3= 1.113739384
ad4= 1.320456815
bd1= 10.21559509
bd2= 9.80201883
bd3= 9.760834107
bd4= 10.59390027
# Assign initial values to the transition matrix coefficients
# ============================================================
a21= 0.6
a32=0.8
a33=0.9
a13=0.37
# Initialization of conditions is finished, we can call function guafit
# As a test, we call function guafit only once to check for results
myresults <- guafit(SSQ,a13,a21,a32,a33,ad1, ad2, ad3, ad4, bd1, bd2, bd3, bd4)
# We save the results of interest of function guafit with new variables
restmod <- myresults$outm
tfield <- myresults$outc
SSQvalue <- myresults$elSSQ
lasmatrices <- myresults$matrices
reslosgua <- myresults$losgua
reslosguaxe <- myresults$losguaxe
SSQvalue
# Graph the results
axisx <- c(1982:2011)
plot(axisx,tfield)
lines(axisx,restmod)
#################################################################################
# Section (3):
# I try the optim function
# First creating the initial parameter values variable to pass as an argument
startparam <- c(SSQ, a13,a21,a32,a33,ad1, ad2, ad3, ad4, bd1, bd2, bd3, bd4)
optim(startparam, guafit)
# and I got error message mentioned above.
# I also tried calling as:
optim(par=startparam, fn=guafit)
# and I got the same error message
# I also tried calling optim but passing the values directly as a list of values:
startparam <- c(SSQ=0, a13=0.37, a21=0.6, a32=0.8, a33=0.9, ad1=1.1, ad2=1.1, ad3=1.1, ad4=1.1, bd1=10, bd2=10, bd3=10, bd4=10)
optim(startparam, guafit)
optim(par=startparam, fn=guafit)
# and I got the same error message
a13appears to be a constant, but it looks like you are trying to estimate it. Maybe remove your constants from youroptimstatement. - Mark Miller