ADMB Documentation  11.1.1015
 All Classes Files Functions Variables Typedefs Friends Defines
dmultinom.cpp
Go to the documentation of this file.
00001 #include "statsLib.h"
00002 
00015 dvariable dmultinom(const dvector& x, const dvar_vector& p)
00016 {
00017   if(x.indexmin() != p.indexmin() || x.indexmax() != p.indexmax())
00018   {
00019     cerr << "Index bounds do not macth in"
00020     " dmultinom(const dvector& x, const dvar_vector& p)\n";
00021     ad_exit(1);
00022   }
00023 
00024   double n=sum(x);
00025   return -gammln(n+1.)+sum(gammln(x+1.))-x*log(p/sum(p));
00026 }
00027 
00028 double neff(const dvector& obs, const dvar_vector& pred)
00029 {
00030   dvector resid=value(obs-pred);
00031   dvector var=value(elem_prod(1.-pred,pred));
00032   return sum(var)/norm2(resid);
00033 }
00034 
00035 dvariable dmultinom(const dmatrix o, const dvar_matrix& p,dvar_matrix& nu,double& tau2,const double minp)
00036 { // returns the negative loglikelihood
00037   /*
00038      uses Martell dmvlogistic code for grouping age classes
00039      with observed proportions < minp
00040      NB minp must be greater than 0, otherwise algorithm returns
00041      an error if one of the observed proportions is zero.
00042      tau2 returns the median absolute standardized residual
00043 
00044   FIX ME SM I'm getting an array out of Bounds error in here for gear3
00045     has to do with the if statement (if minp >1.-4) because Ncount is only
00046     1.  I've commented the if statement out for now.
00047   */
00048   RETURN_ARRAYS_INCREMENT();
00049   int i,j,k,n;
00050   int a = o.colmin();
00051   int A=o.colmax();
00052   int t=o.rowmin();
00053   int T=o.rowmax();
00054   dvector tmptau(1,A*T);  // vector of residuals
00055     int Ncount=1;
00056     dvariable Nsamp;           // multinomial sample size
00057   //FIXME NB Make proc_err into a switch in the control file
00058   //add this likelihood description to the documentation.
00059     dvariable proc_err=0.009;   // allow for process error in the pred.age freq...fixed value based on HCAM assessments
00060   nu.initialize();
00061   dvariable nloglike=0.;
00062     //ofstream ofs("check.tmp");
00063 
00064   for(i=t; i<=T; i++)
00065   {
00066     //cout<<"Ok to here 1"<<endl;
00067     Nsamp=sum(o(i))/(1.+proc_err*sum(o(i)));
00068     n=0;
00069     dvector oo = o(i)/sum(o(i));
00070     dvar_vector pp = p(i)/sum(p(i));
00071 
00072     //count # of observations greater than minp (2% is a reasonable number)
00073     for(j=a;j<=A;j++)
00074       if(oo(j) > minp)n++;
00075 
00076     ivector iiage(1,n);
00077     dvector o1(1,n); o1.initialize();
00078     dvar_vector p1(1,n); p1.initialize();
00079     k=1;
00080     for(j=a;j<=A;j++)
00081     {
00082       if(oo(j)<=minp)
00083       {
00084         o1(k)+=oo(j);
00085         p1(k)+=pp(j);
00086       }
00087       else
00088       {
00089         o1(k)+=oo(j);
00090         p1(k)+=pp(j);
00091         if(k<=n)iiage(k)=j;   //ivector for the grouped residuals
00092         if(k<n) k++;
00093       }
00094     }
00095     /*
00096     //assign residuals to nu based on iiage index
00097     dvar_vector t1 = elem_div(o1-p1,sqrt(elem_prod(p1,1.-p1)/Nsamp));
00098     for(j=1;j<=n;j++)
00099     {
00100       nu(i)(iiage(j))=t1(j);
00101       tmptau(Ncount++)=sqrt(square(value(t1(j))));
00102     }
00103     */
00104 
00105     //CHANGED Later addition from Viv to prevent crashes if
00106     //min(p1) is very small.
00107     //if(min(p1)>1e-4)
00108     {
00109       dvar_vector t1 = elem_div(o1-p1,sqrt(elem_prod(p1,1.-p1)/Nsamp));
00110       for(j=1;j<=n;j++)
00111       {
00112         nu(i)(iiage(j))=t1(j);
00113         tmptau(Ncount++)=sqrt(square(value(t1(j))));
00114       }
00115     }
00116     //end of addition.
00117     // negative log Mulitinomial with constant is:
00118     // r = -1.*(gammln(Nsamp+1)+sum(Nsamp*o1(log(p1))-gammln(Nsamp+1)));
00119     // TODO add calculation for effective sample size.
00120     /*
00121       TODO Neff = sum(elem_prod(p1,1.-p1))/sum(square(o1-p1));
00122       for each year.  Plot the Nsamp vs Neff and look for a 1:1 slope.
00123     */
00124 
00125     nloglike+=sum(-1.*elem_prod(Nsamp*o1,log(p1))+
00126           elem_prod(Nsamp*o1,log(o1)));
00127     //cout<<"Ok to here 2"<<endl;
00128   }
00129 
00130   dvector w=sort(tmptau(1,Ncount-1));
00131   //cout<<"All good "<<Ncount<<endl;
00132   tau2=w(int(Ncount/2.)); //median absolute residual (expected value of 0.67ish)
00133 
00134   RETURN_ARRAYS_DECREMENT();
00135   return(nloglike);
00136 }
00137 
00138