#include <iostream>
template <class Type>
Type f(Type x){return Type(2)/(Type(1) + exp(-Type(2) * x)) - Type(1);}
template <class Type>
Type square(Type x){return x*x;}
template<class Type>
Type objective_function<Type>::operator() ()
{
for(int i=0;i<nlogN;i++)
for(int j=0;j<U.cols();j++)
logN(i,j)=U(i,j);
for(int i=0;i<nlogF;i++)
for(int j=0;j<U.cols();j++)
logF(i,j)=U(i+nlogN,j);
int timeSteps=logF.dim[1];
int stateDimF=logF.dim[0];
int stateDimN=logN.dim[0];
for(int i=0; i<stateDimF; ++i){
for(int j=0; j<stateDimF; ++j){
if(i!=j){fcor(i,j)=rho;}else{fcor(i,j)=1.0;}
}
fsd(i)=sdLogFsta(CppAD::Integer(keyVarF(0,i)));
}
for(int i=0; i<stateDimF; ++i){
for(int j=0; j<stateDimF; ++j){
fvar(i,j)=fsd(i)*fsd(j)*fcor(i,j);
}
}
Type ans=0;
for(int i=1;i<timeSteps;i++){
ans+=neg_log_densityF(logF.col(i)-logF.col(i-1));
logF.col(i) = logF.col(i-1) + neg_log_densityF.simulate();
}
}
for(int i=0;i<timeSteps;i++){
ssb(i)=0.0;
for(int j=0; j<stateDimN; ++j){
ssb(i)+=exp(logN(j,i))*exp(-exp(logF((keyLogFsta(0,j)),i))*propF(i,j)-natMor(i,j)*propM(i,j))*propMat(i,j)*stockMeanWeight(i,j);
}
logssb(i)=log(ssb(i));
}
for(int i=0; i<stateDimN; ++i){
for(int j=0; j<stateDimN; ++j){
if(i!=j){nvar(i,j)=0.0;}else{nvar(i,j)=varLogN(CppAD::Integer(keyVarLogN(0,i)));}
}
}
vector<Type> predN(stateDimN);
for(int i=1;i<timeSteps;i++){
if(stockRecruitmentModelCode==0){
predN(0)=logN(0,i-1);
}else{
if(stockRecruitmentModelCode==1){
predN(0)=rec_loga+log(ssb(i-1))-exp(rec_logb)*ssb(i-1);
}else{
if(stockRecruitmentModelCode==2){
predN(0)=rec_loga+log(ssb(i-1))-log(1.0+exp(rec_logb)*ssb(i-1));
}else{
error("SR model code not recognized");
}
}
}
for(int j=1; j<stateDimN; ++j){
predN(j)=logN(j-1,i-1)-exp(logF((keyLogFsta(0,j-1)),i-1))-natMor(i-1,j-1);
}
if(maxAgePlusGroup==1){
predN(stateDimN-1)=log(exp(logN(stateDimN-2,i-1)-exp(logF((keyLogFsta(0,stateDimN-2)),i-1))-natMor(i-1,stateDimN-2))+
exp(logN(stateDimN-1,i-1)-exp(logF((keyLogFsta(0,stateDimN-1)),i-1))-natMor(i-1,stateDimN-1)));
}
ans+=neg_log_densityN(logN.col(i)-predN);
logN.col(i) = predN + neg_log_densityN.simulate();
}
}
int f, ft, a, y;
int minYear=CppAD::Integer((obs(0,0)));
Type predObs=0, zz, var;
for(int i=0;i<nobs;i++){
y=CppAD::Integer(obs(i,0))-minYear;
f=CppAD::Integer(obs(i,1));
ft=CppAD::Integer(fleetTypes(f-1));
a=CppAD::Integer(obs(i,2))-minAge;
zz=exp(logF((keyLogFsta(0,a)),y))+natMor(y,a);
if(ft==0){
predObs=logN(a,y)-log(zz)+log(1-exp(-zz));
if((keyLogFsta(f-1,a))>(-1)){
predObs+=logF((keyLogFsta(0,a)),y);
}
}else{
if(ft==1){
}else{
if(ft==2){
predObs=logN(a,y)-zz*sampleTimes(f-1);
if(CppAD::Integer(keyQpow(f-1,a))>(-1)){
predObs*=exp(logQpow(CppAD::Integer(keyQpow(f-1,a))));
}
if(CppAD::Integer(keyLogFpar(f-1,a))>(-1)){
predObs+=logFpar(CppAD::Integer(keyLogFpar(f-1,a)));
}
}else{
if(ft==3){
}else{
if(ft==4){
}
}
}
}
}
var=varLogObs(CppAD::Integer(keyVarObs(f-1,a)));
ans+=-
dnorm(log(obs(i,3)),predObs,sqrt(var),
true);
obs(i,3) = exp(
rnorm(predObs, sqrt(var)) ) ;
}
}
}
return ans;
}