Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

glmm1.cpp

Go to the documentation of this file.
00001 
00002 //****************************************************
00003 // GLMM class July 2000, University of Nebraska 2000 Stephen D. Kachman
00004 //****************************************************
00005 //  April, 1993, University of Illinois
00006 // Copyright (C) 1993, 1994 Tianlin Wang
00007 /* Copyright (C) 1994-2003 Matvec Development Team. 
00008 
00009   This program is free software; you can redistribute it and/or
00010   modify it under the terms of the GNU Library General Public
00011   License as published by the Free Software Foundation; either
00012   version 2 of the License, or (at your option) any later version.
00013   
00014   This program is distributed in the hope that it will be useful,
00015   but WITHOUT ANY WARRANTY; without even the implied warranty of
00016   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017   Library General Public License for more details.
00018     
00019   You should have received a copy of the GNU Library General Public
00020   License along with this library; if not, write to the Free
00021   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00022   MA 02111-1307, USA 
00023 */
00024 
00025 #include <iostream>
00026 #include <iomanip>
00027 #include <sstream>
00028 
00029 #include "session.h"
00030 #include "util.h"
00031 #include "doublematrix.h"
00032 #include "model.h"
00033 #include "population.h"
00034 #include "statdist.h"
00035 #include "glmm.h"
00036 
00037 namespace matvec {
00038 #undef DO_THREADS
00039 #ifdef SKIP_THREADS
00040 #undef  DO_THREADS
00041 #endif
00042 
00043 #undef DO_PMAT
00044 #define DO_LOG
00045 #undef DO_CHOL
00046 
00047 #ifdef DO_CHOL
00048 #undef DO_PMAT
00049 #undef DO_LOG
00050 #endif
00051 
00052 #ifdef DO_LOG
00053 #undef DO_PMAT
00054 #undef DO_CHOL
00055 #endif
00056 
00057 #define DO_HINV
00058 
00059 
00060 
00061 #define EPSILON  SESSION.epsilon
00062    //#define act_numtrait numtrait // Temporary fix
00063 
00064  doubleMatrix *P_Mat=NULL;
00065  ;
00066  ;
00067  ;
00068 
00069  extern void getlambda(double **lambda, const int n);
00070  
00071  void normal_loginClasses(matvec::Observe &observe);
00072 
00073 
00074  Observe& GLMM::new_obs()
00075  {
00076    unsigned i,j;
00077    if(observation) release_obs();
00078    observation=new Observe [numrec+1] ;
00079    observation[numrec].rec=-1;
00080    observation[numrec].numtrait=numtrait;
00081    observation[numrec].param=param;
00082    observation[numrec].data=data;
00083    observation[numrec].resid_var=&residual_var;
00084    if(link_function) {
00085      observation[numrec].nvc=res_nvc;
00086      observation[numrec].varcomp=&varcomp;
00087      (*link_function)(observation[numrec]);
00088      if(res_nvc)observation[numrec].Adj_Cov.identity(res_nvc,res_nvc);
00089    }
00090    for(i=0;i<numrec;i++) {
00091      observation[i].rec=i;
00092      observation[i].need_data=1;
00093      observation[i].pattern.reserve(numtrait);
00094      observation[i].numtrait=numtrait;
00095      observation[i].residual.resize(numtrait);
00096      observation[i].estimate.resize(numtrait);
00097      if(Initial.begin()) observation[i].estimate=Initial;
00098      observation[i].y.resize(numtrait);
00099      observation[i].Resid_Var.identity(numtrait);
00100      observation[i].H.identity(numtrait);
00101      observation[i].Hinv.identity(numtrait);
00102      observation[i].pev.resize(numtrait,numtrait);
00103      observation[i].weight=1;
00104      observation[i].pev_current=0;
00105      observation[i].rve.resize(numtrait,numtrait);
00106      //    observation[i].rve_sand.zeros(numtrait,numtrait);
00107      observation[i].rpy.resize(numtrait);
00108      observation[i].nvc=res_nvc;
00109      observation[i].data=data;
00110      observation[i].param=param;
00111 
00112      observation[i].resid_var=&residual_var;
00113      if(res_nvc) {
00114        observation[i].Resid_Sin_Mat=new doubleMatrix [res_nvc];
00115        observation[i].varcomp=&varcomp;
00116      }
00117      for(j=0;j<res_nvc;j++) {
00118        observation[i].Resid_Sin_Mat[j].resize(numtrait,numtrait);
00119      }
00120 
00121    }
00122    return *observation;
00123  }
00124 
00125 
00126 
00127 
00128  void GLMM::release_obs(void){
00129    unsigned i,j;
00130 
00131    if(observation) {
00132      delete [] observation;
00133      observation=(Observe *)NULL;
00134    }
00135  }
00136 
00137  void GLMM::residual(int get_pev)
00138  {
00139    unsigned i,j,k,l,rec,t1,t2,ii,jj;
00140    double xval;
00141    //GLMMModelTerm *localterm;
00142    UniformDist U;
00143 
00144    double *k_new_vec;
00145    k_new_vec=new double [hmmesize];
00146    double *k_new_vec2;
00147    k_new_vec2=new double [hmmesize];
00148    double *svec;
00149    svec=new double [hmmesize];
00150    double *xtmp;
00151    xtmp=new double [hmmesize];
00152    double *ytmp;
00153    ytmp=new double [hmmesize];
00154    double *koff,*koff2;
00155    koff=k_new_vec-1;
00156    koff2=k_new_vec2-1;
00157    double *soff;
00158    soff=svec-1;
00159    like_val=0;
00160    doubleMatrix var;
00161    int startaddr,nlevels,iaddr,*ainv_ia,*ainv_ja,ipos,ainv_nrow;
00162    int ped_cnt=0;
00163    int je,jpos,jaddr;
00164    double *ainv_a;
00165 
00166  #ifdef DO_HINV
00167    if(Need_PEV)
00168      build_hInv();
00169  #endif
00170      like_adj=0;
00171    for(i=0;i<numterm;i++){
00172      if(term[i].classi() == 'P' || term[i].classi() == 'R'){
00173        unsigned nanim=popsize-numgroup;
00174        startaddr=term[i].startaddr()+1;
00175        var=*term[i].prior->var_matrix();
00176        var.ginv1();
00177        int nt=nt_vec[i];
00178        if(term[i].classi() == 'R') {
00179         nlevels=term[i].nlevel();
00180         for(ii=1;ii<=nlevels;ii++) {
00181           iaddr=startaddr+(ii-1)*nt;
00182           like_val+=
00183             -.5*var.quadratic(blupsol.subvec(iaddr-1,nt),
00184                                 blupsol.subvec(iaddr-1,nt));
00185           if(Use_Like)like_adj+=
00186                         var.quadratic(blupsol.subvec(iaddr-1,nt),
00187                                 blupsol.subvec(iaddr-1,nt));
00188         }
00189        }
00190        if(term[i].classi() == 'P') {;
00191                                     //  build_CorrVar();
00192         doubleMatrix Varinv=term[i].prior->var_matrix()->ginv0();
00193         //      corrmap[i]=1;
00194         //      if(!ncorr) ncorr=1;
00195         //      ped_cnt++;
00196         double mult_corr;
00197         unsigned startaddr2;
00198         int jcorr=i;
00199         //for(int jcorr=i;jcorr<=i;jcorr++) 
00200           {
00201             //if(corrmap[jcorr]) 
00202             {
00203             mult_corr=1.;
00204             //if(jcorr!=i && corrmap[jcorr]) {
00205             // mult_corr=2.;
00206             // var=corrvar[i][jcorr];
00207             //}
00208             startaddr2=term[jcorr].startaddr()+1;
00209             ainv();
00210             ainv_ia=hainv.ia();
00211             ainv_ja=hainv.ja();
00212             ainv_a=hainv.a();
00213             ainv_nrow=hainv.num_rows();
00214         
00215             for(ii=1;ii<=ainv_nrow;ii++) {
00216               ipos=ii;
00217               iaddr=startaddr+(ipos-1)*nt;
00218               je=ainv_ia[ii+1];
00219               for(jj=ainv_ia[ii];jj<je;jj++) {
00220                 jpos=ainv_ja[jj];
00221                 double offdiag;
00222                 offdiag=2.;
00223                 if(ipos==jpos) offdiag=1.;
00224                 jaddr=startaddr2+(jpos-1)*nt;
00225                 like_val+=-.5*ainv_a[jj]*offdiag*
00226                   mult_corr*Varinv.quadratic(blupsol.subvec(jaddr-1,nt),
00227                                                 blupsol.subvec(iaddr-1,nt));
00228                 if(i==jcorr &&Use_Like){
00229                 like_adj+=ainv_a[jj]*offdiag*
00230                   mult_corr*Varinv.quadratic(blupsol.subvec(jaddr-1,nt),
00231                                                 blupsol.subvec(iaddr-1,nt));
00232                 }
00233               }
00234             }
00235           }
00236         }
00237        }
00238      }
00239    }
00240 
00241    if(!link_function) inverse_residual_var();
00242    if(!observation) new_obs();
00243    // for gcc-3.2 replaced 
00244    // std::istrstream modelfile(modelstr, modelpcount);
00245    // with 
00246    std::istringstream modelfile(modelstringstr);
00247    // std::cout << "numrec = " << numrec << "\n";
00248    // std::cout << "numobs = " << numobs << "\n";
00249 
00250 
00251    double pselect,scalvar;
00252    int numrem,numneed,numsel;
00253    int selected;
00254    numneed=numrec;
00255    numrem=numrec;
00256    numsel=0;
00257    if(AI_sample && AI_sample < numrec) numneed=AI_sample;
00258    scalvar=static_cast<double>(numrem)/static_cast<double>(numneed);
00259 
00260 
00261    for(rec=0;rec<numrec;rec++) {
00262 
00263      selected=0;
00264      pselect=static_cast<double>(numneed)/static_cast<double>(numrem);
00265      if(U.sample() <= pselect) selected=1;
00266      numrem--;
00267      numsel+=selected;
00268      numneed-=selected;
00269 
00270      input_pos_val(modelfile);
00271      observation[rec].pattern = pattern[pos_term[numterm]];
00272      //std::cout << "\n rec " << rec << " " << pos_term[numterm] << " " << pattern[pos_term[numterm]];
00273 
00274      if(get_pev) observation[rec].pev.resize(numtrait,numtrait);
00275      for(t1=0;t1< numtrait;t1++) {
00276        memset(k_new_vec,'\0',sizeof(double)*hmmesize);
00277        //      observation[rec].residual.ve[t1]=trait_vec[t1];
00278        if(Update_estimate)
00279         observation[rec].estimate[t1]=0;
00280        if(weightname.size())
00281         observation[rec].weight = xval_term[numterm];
00282        for(i=0;i<numterm;i++) {
00283         //      localterm=(GLMMModelTerm *)&term[i];
00284         ii=term[i].addr[t1];
00285         if(ii){
00286           xval=xval_term[i];
00287         
00288           //  observation[rec].residual[t1]-=xval*(blupsol(ii));
00289         
00290           if(Update_estimate)
00291             observation[rec].estimate[t1]+=xval*(blupsol(ii));
00292           koff[ii]=xval;
00293         }
00294  #ifdef DO_HINV
00295         if(get_pev) {
00296           for(t2=0;t2<numtrait;t2++) {
00297             for(j=0;j<numterm;j++) {
00298               int jj=term[j].addr[t2];
00299               if(jj){
00300                 (observation[rec].pev)[t1][t2] += xval_term[i]*xval_term[j]*hInv.getaij(ii,jj);
00301               }
00302             }
00303           }
00304           observation[rec].pev_current=1;
00305         }
00306  #endif
00307         
00308        }
00309  #ifndef DO_HINV
00310        if(get_pev ) {
00311         if(selected) {
00312           hmmec.solve(svec,k_new_vec,"ysmp");
00313           //quad(k_new_vec2,k_new_vec,xtmp,ytmp,1);
00314           for(t2=0;t2<numtrait;t2++) {
00315             memset(k_new_vec2,'\0',sizeof(double)*hmmesize);
00316         
00317             for(i=0;i<numterm;i++) {
00318               ii=term[i].addr[t2];
00319               if(ii){
00320                 koff2[ii]=xval_term[i];
00321                 (observation[rec].pev)[t1][t2] += xval_term[i]*soff[ii];
00322               }
00323             }
00324             //observation[rec].pev.me[t1][t2]=quad(k_new_vec2,k_new_vec,xtmp,ytmp,2);
00325           }
00326           observation[rec].pev_current=1;
00327         }
00328         else{
00329           observation[rec].pev_current=0;
00330         }
00331        }
00332  #endif
00333 
00334      }
00335      if(link_function){
00336        link_function(observation[rec]);
00337        like_val+=observation[rec].like_val*observation[rec].weight;
00338        if(get_pev &&
00339           observation[rec].pev_current)
00340         observation[rec].pev=
00341           observation[rec].H*
00342           observation[rec].pev*observation[rec].H.transpose();
00343      }
00344      else{
00345        observation[rec].Resid_Var.assign(0.0);
00346        for(t1=0;t1<numtrait;t1++) {
00347         if(observation[rec].pattern[t1] != '0') {
00348           for(t2=0;t2<numtrait;t2++) {
00349             if(observation[rec].pattern[t2] != '0') {
00350               observation[rec].Resid_Var[t1][t2]=residual_var[t1][t2];
00351               observation[rec].rve[t1][t2]=rve[pos_term[numterm]][t1][t2];
00352             }
00353           }
00354         }
00355        }
00356 
00357        for(t1=0;t1<numtrait;t1++) {
00358         observation[rec].rpy[t1]=0.;
00359         for(t2=0;t2<numtrait;t2++) {
00360           observation[rec].rpy[t1]+=
00361             observation[rec].rve[t1][t2]*trait_vec[t2];
00362         }
00363        }
00364      }
00365    }
00366    delete [] ytmp;
00367    delete [] xtmp;
00368    delete [] svec;
00369    delete [] k_new_vec2;
00370    delete [] k_new_vec;
00371    //  modelfile.close();
00372    Need_Residual=0;
00373  }
00374 
00375 
00376 
00377  void GLMM::new_SinMat(void)
00378  {
00379 
00380    int i;
00381    int nvc;
00382    nvc=TotalNvc();
00383    if(SinMat) release_SinMat();
00384    SinMat = new doubleMatrix [nvc];
00385    for(i=0;i<nvc;i++) {
00386      
00387      SinMat[i].resize(numtrait,numtrait);
00388    }
00389  }
00390 
00391 
00392 
00393  void GLMM::release_SinMat(void)
00394  {
00395    if(SinMat) {
00396      int i,nvc;
00397      nvc=TotalNvc();
00398 
00399      for(i=0;i<nvc;i++) SinMat[i].resize(0,0);
00400      delete [] SinMat;
00401      SinMat=NULL;
00402    }
00403 
00404  }
00405 
00406  void GLMM::Build_SinMat()
00407  {
00408    int i,k,t1,t2,raneff;
00409 #ifdef DO_CHOL
00410    doubleMatrix L;
00411 #endif
00412 #ifdef DO_LOG
00413    doubleMatrix P,L;
00414    Vector<double> D;
00415 #endif
00416    if(!SinMat)new_SinMat();
00417    if(!varinv)varinv = new doubleMatrix [numterm];
00418    if(!Var)Var = new doubleMatrix [numterm];
00419    int done_ped=0;
00420    doubleMatrix var,part;
00421    part.resize(numtrait,numtrait);
00422    kvec.resize(numterm);
00423    int kk=0;
00424    for(k=0,i=0,raneff=0;i<numterm;i++) {
00425      if((term[i].classi() == 'P'&& !done_ped) || term[i].classi() == 'R'){
00426        int nt=nt_vec[i];
00427        kvec[i]=k;
00428        if(var_link[i]!=i) {
00429          kvec[i]=kvec[var_link[i]];
00430        }
00431        else{
00432          raneff++;
00433          kk+=(nt*(nt+1))/2;
00434        }
00435        k=kvec[i];
00436        Var[i]=*term[var_link[i]].prior->var_matrix();
00437        
00438        
00439 #ifdef DO_CHOL
00440        L=Var[i];
00441        L.chol();
00442        L=L.transpose();
00443 #endif
00444 #ifdef DO_LOG
00445        P=Var[i];
00446        D=P.eigen();
00447        double dmax=D.max();
00448        if(dmax < 1) dmax=1;
00449        double dmin=10.*dmax*SESSION.epsilon;
00450        for(int ii=0;ii<nt;ii++) {
00451          if(D[ii] < dmin) D[ii]=.5*dmin;
00452        }
00453        D=log(D);
00454 #endif
00455        var=Var[i].ginv0();
00456        varinv[i]=var;
00457 #ifdef DO_PMAT
00458        var*=P_Mat[raneff]*P_Mat[raneff].transpose();
00459 #endif
00460        for(t1=0;t1<nt;t1++) for(t2=t1;t2<nt;t2++,k++) {
00461            part.resize(nt,nt);
00462            //   std::cout << "PART\n";
00463            part[t1][t2]=1.;
00464            part[t2][t1]=1.;
00465 #ifdef DO_CHOL
00466            part[t1][t2]=0.;
00467            part[t2][t1]=0.;
00468            for(int j=0;j<nt;j++) {
00469              part[t2][j]+=L[t1][j];
00470              if(j != t2) part[j][t2]+=L[t1][j];
00471            }
00472 #endif
00473 #ifdef DO_LOG
00474            part[t1][t2]=0.;
00475            part[t2][t1]=0.;
00476            //std::cout << "DO LOG\n";
00477            double D_avg,D_delt;
00478            D_avg=.5*(D[t1]+D[t2]);
00479            D_delt=.5*(D[t1]-D[t2]);
00480            if(fabs(D_delt) > 1.e-8) {
00481              
00482              // Sinh(x)=(e^x-e^{-x})/2
00483              part[t1][t2]=std::exp(D_avg)*sinh(D_delt)/(D_delt);
00484              part[t2][t1]=std::exp(D_avg)*sinh(D_delt)/(D_delt);
00485            }
00486            else{
00487              part[t1][t2]=std::exp(D_avg);
00488              part[t2][t1]=std::exp(D_avg);
00489            }
00490          
00491            /**/
00492            if(D[t1]<-11 && D[t2]<-11) {
00493              part[t2][t1]=0;
00494              part[t1][t2]=0;
00495            }
00496            /**/  
00497          
00498        
00499    
00500          //std::cout << "part" << part;
00501          part=P*part*P.transpose();
00502          //      if(std::exp(D[t1]) <= dmin || std::exp(D[t2]) <= dmin)  part.assign(0.0);
00503 #endif
00504          SinMat[k]=var*part*var.transpose();
00505          //std::cout << "SinMat" << SinMat[k];
00506        }
00507        
00508      }
00509      
00510    }
00511    k=kk;
00512    if(!link_function) {
00513      var=residual_var.ginv0();
00514      var*=P_Mat[raneff]*P_Mat[raneff].transpose();
00515      for(t1=0;t1<numtrait;t1++) for(t2=t1;t2<numtrait;t2++,k++) {
00516        part.assign(0.0);
00517        part[t1][t2]=1.;
00518        part[t2][t1]=1.;
00519        SinMat[k]=var*part*var.transpose();
00520      }
00521    }
00522  }
00523 
00524 
00525 
00526  #define STRTEND(start,length) (start,start+length-1)   
00527 
00528 
00529  void GLMM::SSQCP(void)
00530  {
00531    int i,k,j,t1,t2,ii,jj,a_i,a_j,je,ipos,jpos,startaddr,iaddr,jaddr;
00532    int t_1,t_2,t;
00533    int *ainv_ia,*ainv_ja,ainv_nrow,nvc;
00534    //  GLMMModelTerm *localterm;
00535    UniformDist U;
00536    unsigned nlevels;
00537    double *ainv_a,xval;
00538    doubleMatrix *smat,wmat,*var_pt;
00539    wmat.resize(numtrait,numtrait);
00540    Vector<double> wvec;
00541    wvec.resize(numtrait);
00542    doubleMatrix vc_mat;
00543    Vector<double> k_new_vec,*svec,wrhs,wsol;
00544    k_new_vec.resize(numtrait);
00545    double *kvecx,*kvecy,*svecx,*svecy;
00546    kvecx=new double [hmmesize];
00547    kvecy=new double [hmmesize];
00548    svecx=new double [hmmesize];
00549    svecy=new double [hmmesize];
00550    wrhs.resize(hmmesize);
00551    wsol.resize(hmmesize);
00552    svec=new Vector<double> [act_numtrait];
00553    for(t1=0;t1<numtrait;t1++) {
00554      svec[t1].resize(hmmesize);
00555    }
00556    k_new_vec.resize(hmmesize);
00557    Need_PEV=1;
00558    glim(1);
00559    Need_PEV=0;
00560    //residual(res_nvc);
00561    //setup_mme(&rellrhs);
00562    //blup("ysmp1");
00563    nvc=TotalNvc();
00564    vc_mat.resize(nvc,numtrait);
00565    Build_SinMat();
00566    Info.resize(nvc,nvc);
00567    Score.resize(nvc);
00568    // Bulild SSs and CP for Random Effects;
00569    like_adj=0;
00570    int done_ped=0;
00571    int kk;
00572    for(kk=0,i=0;i<numterm;i++) {
00573      doubleMatrix tmpvar;
00574      if((term[i].classi() == 'P' && !done_ped) || term[i].classi() == 'R'){
00575        int nt;
00576        nt=nt_vec[i];
00577        kvec[i]=kk;
00578        if(var_link[i]!=i) {
00579          kvec[i]=kvec[var_link[i]];
00580        }
00581        else{
00582          kk+=(nt*(nt+1))/2;
00583        }
00584        k=kvec[i];
00585        var_pt=term[var_link[i]].prior->var_matrix();
00586        doubleMatrix Varinv;
00587        Varinv=*var_pt;
00588        Varinv.ginv1();
00589        startaddr=term[i].startaddr()+1;
00590        for(t1=0;t1<nt;t1++) for(t2=t1;t2<nt;t2++,k++) {
00591          int t1_i,t2_i;
00592          t1_i=trait_map[i][t1];
00593          t2_i=trait_map[i][t2];
00594          
00595          if(term[t1_i].trait[t1%numtrait] && term[t2_i].trait[t2%numtrait]) {
00596            smat= &SinMat[k];
00597            if(term[i].classi() == 'R') {
00598              nlevels=term[i].nlevel();
00599              double pselect,scalvar;
00600              int numrem,numneed,numsel;
00601              int selected;
00602              numneed=nlevels;
00603              numrem=nlevels;
00604              numsel=0;
00605              if(AI_sample && AI_sample < nlevels) numneed=AI_sample;
00606              scalvar=static_cast<double>(numrem)/static_cast<double>(numneed);
00607              for(ii=1;ii<=nlevels;ii++) {
00608                selected=0;
00609                pselect=static_cast<double>(numneed)/static_cast<double>(numrem);
00610                if(U.sample() <= pselect) selected=1;
00611                numrem--;
00612                numsel+=selected;
00613                numneed-=selected;
00614                iaddr=startaddr+(ii-1)*nt;
00615                for(t=0;t<nt;t++) {
00616 #ifndef DO_HINV
00617                  if(selected) {
00618                    k_new_vec.assign(0.0);
00619                    k_new_vec(iaddr+t)=1.;
00620                    hmmec.solve(svec[t],k_new_vec,"ysmp");
00621                  }
00622 #endif
00623                  //Mem_zero(kvecx,hmmesize*sizeof(double));
00624                  //kvecx[iaddr+t-1]=1.;
00625                  //quad(kvecy,kvecx,svecy,svec[t].ve,1);
00626                }
00627                if(t1==0 && t2==0 && Use_Like) like_adj+=Varinv.quadratic(
00628                                                                          blupsol.subvec(iaddr-1,nt),
00629                                                                          blupsol.subvec(iaddr-1,nt));
00630                Score[k]+=
00631                  smat->quadratic(
00632                                  blupsol.subvec(iaddr-1,nt),
00633                                  blupsol.subvec(iaddr-1,nt));
00634                wmat.resize(nt,nt);
00635                for(t_1=0;t_1<nt;t_1++) {
00636                  for(t_2=0;t_2<nt;t_2++) {
00637 #ifdef DO_HINV
00638                    wmat[t_2][t_1]= -hInv.getaij(iaddr+t_1,iaddr+t_2);
00639 #else
00640                    if(selected){
00641                      wmat[t_2][t_1]= -scalvar*svec[t_1][iaddr+t_2-1];
00642                    }
00643                    else{
00644                      wmat[t_2][t_1]=0;
00645                    }
00646 #endif
00647                  }
00648                }
00649                wmat+=*(term[i].prior->var_matrix());
00650                Score[k]-=
00651                  ((*smat)*wmat).trace();
00652                
00653              }
00654            }
00655            if(term[i].classi() == 'P') {
00656              //   Score[k]-=((*smat)*CorrVar).trace();
00657              
00658              unsigned nanim=popsize-numgroup;
00659              
00660              double pselect,scalvar;
00661              unsigned numrem,numneed,numsel;
00662              int selected;
00663              numneed=popsize;
00664              numrem=popsize;
00665              numsel=0;
00666              unsigned *sel_vec;
00667              sel_vec=new unsigned [popsize+1];
00668              if(AI_sample && AI_sample < popsize) numneed=AI_sample;
00669              scalvar=static_cast<double>(numrem)/static_cast<double>(numneed);
00670              for(ii=1;ii<=popsize;ii++) {
00671                selected=0;
00672                if(U.sample() <= static_cast<double>(numneed)/static_cast<double>(numrem)) selected=1;
00673                sel_vec[ii]=selected;
00674                numrem--;
00675                numsel+=selected;
00676                numneed-=selected;
00677              }
00678              ainv();
00679              ainv_ia=hainv.ia();
00680              ainv_ja=hainv.ja();
00681              ainv_a=hainv.a();
00682              ainv_nrow=hainv.num_rows();
00683              for(ii=1;ii<=popsize;ii++) {
00684                
00685                
00686                iaddr=startaddr+(ii-1)*numtrait;
00687                ipos=ii;
00688                iaddr=startaddr+(ipos-1)*nt;
00689                for(t=0;t<nt;t++) {
00690 #ifndef DO_HINV
00691                  if(sel_vec[ii]) {
00692                    k_new_vec.assign(0.0);
00693                    k_new_vec(iaddr+t)=1.;
00694                    hmmec.solve(svec[t],k_new_vec,"ysmp");
00695                  }
00696 #endif
00697                  //Mem_zero(kvecx,hmmesize*sizeof(double));
00698                  //kvecx[iaddr+t-1]=1.;
00699                  //quad(kvecy,kvecx,svecy,svec[t].ve,1);
00700                }
00701                je=ainv_ia[ii+1];
00702                for(jj=ainv_ia[ii];jj<je;jj++) {
00703                  jpos=ainv_ja[jj];
00704                  double offdiag;
00705                  offdiag=2.;
00706                  if(ipos==jpos) offdiag=1.;
00707                  jaddr=startaddr+(jpos-1)*nt;
00708                  if(t1==0 && t2==0 && Use_Like) like_adj+=ainv_a[jj]*offdiag*
00709                                                   Varinv.quadratic(
00710                                                                    blupsol.subvec(jaddr-1,nt),
00711                                                                    blupsol.subvec(iaddr-1,nt));
00712                  
00713                  Score[k]+=ainv_a[jj]*offdiag*
00714                    smat->quadratic(
00715                                    blupsol.subvec(jaddr-1,nt),
00716                                    blupsol.subvec(iaddr-1,nt));
00717                  //     std::cout << "\nScore " << Score[k] << " k " << k << " jj " << jj << " iaddr " << iaddr << " jaddr " << jaddr;
00718                  wmat.resize(nt,nt);
00719                  for(t_1=0;t_1<nt;t_1++) for(t_2=0;t_2<nt;t_2++) {
00720                    //  Mem_zero(kvecy,hmmesize*sizeof(double));
00721                    //  kvecy[jaddr+t_2-1]=-1.;
00722                    //  wmat.me[t_2][t_1]=quad(kvecy,kvecx,svecx,svec[t_1].ve,2);
00723 #ifdef DO_HINV
00724                    wmat[t_2][t_1]= -hInv.getaij(iaddr+t_1,jaddr+t_2);
00725                    //std::cout << "\n wmat " << wmat[t_2][t_1] << "t_2" << t_2 << "t_1" << t_1 << " iaddr " << iaddr << " jaddr " << jaddr;
00726 #else
00727                    if(sel_vec[ii] ){// && sel_vec[jpos]) {
00728                      wmat[t_2][t_1]= -scalvar*svec[t_1][jaddr+t_2-1];
00729                    }
00730                    else{
00731                      //             std::cout << ii << " " << jpos << " " << sel_vec[ii] << " " << sel_vec[jpos] << "\n";
00732                    }
00733 #endif
00734                  }
00735                  //     wmat+=CorrVar;
00736                  //std::cout << "\nScore " << Score[k] << " k " << k;
00737                  Score[k]-=ainv_a[jj]*offdiag*
00738                    ((*smat)*wmat).trace();
00739                  //std::cout << "\nScore " << Score[k] << " k " << k  << " jj " <<jj << " ainv  " <<ainv_a[jj] << " offdiag "<< offdiag<< " wmat " <<  wmat<< " smat " <<  *smat << "prod" <<((*smat)*wmat) ;
00740                }
00741                //       std::cout << "\nScore " << Score[k] << " k " << k;
00742                if(ii<=nanim )Score[k]-=((*smat)*(Var[i])).trace();
00743                //std::cout << "\nScore " << Score[k] << " k " << k;
00744              }
00745              delete [] sel_vec;
00746            }
00747          }
00748        }
00749      }
00750    }
00751 
00752    //   ****
00753    // Build Residual SSs and CP
00754    //   ****
00755    k=kk;
00756    unsigned kvc;
00757    if(link_function){
00758      double scalvar=1.;
00759      if(AI_sample && AI_sample < numrec) scalvar=static_cast<double>(numrec)/static_cast<double>(AI_sample);    
00760      
00761      for(kvc=0;kvc<res_nvc;kvc++,k++){
00762        
00763        for(ii=0;ii<numrec;ii++) {
00764          smat=&(observation[ii].Resid_Sin_Mat[kvc]);
00765          Score[k]+=
00766            smat->quadratic(observation[ii].residual,observation[ii].residual)*
00767            observation[ii].weight;
00768          wmat=observation[ii].Resid_Var/observation[ii].weight;
00769 
00770          if(PEV_Scale){
00771            //      std::cout << "\nBefore " << Score[k]<< " " << wmat << observation[ii].pev;    
00772            
00773            wmat-=observation[ii].pev;
00774          }
00775          
00776          //
00777          // At this point I am not sure if it is better to adjust
00778          // for prediction errors or leave it alone.
00779          // For most of the cases I typically run accross it is
00780          // probably not much of an issue.
00781          //             
00782          Score[k]-=
00783            observation[ii].weight*
00784            ((*smat)*wmat).trace();
00785          
00786 
00787          //      std::cout << "\nAfter " << Score[k]<< " " << wmat;        
00788          //         if(k == 0) std::cout << "  ii " << Score[k];
00789        }
00790      }
00791      
00792      //std::cout << "\n";
00793    }
00794    else{
00795      for(t1=0;t1<numtrait;t1++) for(t2=t1;t2<numtrait;t2++,k++) {
00796        smat = &SinMat[k];
00797        for(ii=0;ii<numrec;ii++) {
00798          Score[k]+=
00799            observation[ii].weight*
00800            smat->quadratic(observation[ii].residual,observation[ii].residual);
00801          
00802          wmat=observation[ii].Resid_Var/observation[ii].weight-observation[ii].pev;
00803          Score[k]-=
00804            observation[ii].weight*
00805            ((*smat)*wmat).trace();
00806          
00807        }
00808      }
00809      
00810      
00811    }
00812    // for gcc-3.2 replaced 
00813    // std::istrstream modelfile(modelstr, modelpcount);
00814    // with 
00815    std::istringstream modelfile(modelstringstr);  
00816    FRHS.resize(nvc,hmmesize);
00817    FSol.resize(nvc,hmmesize);
00818    Fmat.resize(nvc,numtrait);
00819 
00820    int rec,Fmatrow;
00821    Fmatrow=numtrait;
00822    for(rec=0;rec<numrec;rec++) {
00823      if(link_function) {
00824        Fmatrow=observation[rec].H.num_rows();
00825        Fmat.resize(nvc,Fmatrow);
00826      }
00827      Fmat.assign(0.0);
00828      input_pos_val(modelfile);
00829      done_ped=0;
00830      for(kk=0,i=0;i<numterm;i++) {
00831        if((term[i].classi() == 'P' && !done_ped) || term[i].classi() == 'R'){
00832          int nt;
00833          nt=nt_vec[i];
00834          if(var_link[i]==i) {
00835            kk+=(nt*(nt+1))/2;
00836          }
00837          k=kvec[i];
00838          int i_link=var_link[i];
00839          //     if(term[i].classi() == 'P') {
00840          //       done_ped=1;
00841          //       nt=act_numtrait;
00842          //     }
00843          
00844         doubleMatrix H,one;
00845         H=observation[rec].H;
00846         //H=H.kron(one.ones(1,nt/numtrait));
00847         
00848         for(t1=0;t1<nt;t1++)
00849           for(t2=t1;t2<nt;t2++,k++){
00850             wvec.resize(numtrait);
00851             int t1_i,t2_i,t1_a,t2_a;
00852             t1_i=trait_map[i][t1];
00853             t2_i=trait_map[i][t2];
00854             t1_a=t1%numtrait;
00855             t2_a=t2%numtrait;
00856               int jt;ii=0;
00857               Vector<double> uscaled;
00858               uscaled.resize(nt);
00859               for(jt=0;(jt<nt) && (ii<=0);jt++)
00860                 {
00861                   int t3_i;
00862                   t3_i=i;
00863                   t3_i=trait_map[i][jt];
00864                   ii=term[t3_i].addr[jt%numtrait]-jt%numtrait;
00865                 }
00866               uscaled = Var[i] * SinMat[k] * blupsol.subvec(ii-1, nt);
00867               //std::cout << "\nuscaled "<<uscaled<< "Var" << Var[i] <<"SinMat " << SinMat[k] << "u" << blupsol.subvec(ii-1, nt);
00868               int t3;
00869               for(t3=0;t3<nt;t3++) {
00870                 int t3_i;
00871                 t3_i=trait_map[i][t3];
00872                 ii=term[t3_i].addr[t3%numtrait];
00873                 if(ii) {
00874                   int ioff=ii-t3;
00875                   uscaled=Var[i]*SinMat[k]*blupsol.subvec(ioff-1,nt);
00876                   xval=xval_term[t3_i];
00877                   wvec[t3%numtrait] += xval*uscaled[t3];
00878                 }
00879               }
00880               if(link_function) wvec=H*wvec;
00881               for(int iii=0;iii<Fmatrow;iii++) Fmat[k][iii]+=wvec[iii];
00882               //memcpy(Fmat[k],wvec.begin(),sizeof(double)*Fmatrow);
00883               //}
00884           }
00885        }
00886      }
00887      k=kk;
00888 
00889      if(link_function) {
00890 
00891        for(kvc=0;kvc<res_nvc;kvc++,k++) {
00892         
00893         wvec=//observation[rec].Hinv*
00894           observation[rec].Resid_Var*
00895             observation[rec].Resid_Sin_Mat[kvc]*
00896               observation[rec].residual;
00897         
00898         memcpy(Fmat[k],wvec.begin(),sizeof(double)*Fmatrow);
00899        }
00900 
00901      }
00902      else{
00903        for(t1=0;t1<numtrait;t1++) for(t2=t1;t2<numtrait;t2++,k++){
00904         
00905         wvec=observation[rec].Resid_Var*SinMat[k]*observation[rec].residual;
00906         
00907         memcpy(Fmat[k],wvec.begin(),sizeof(double)*Fmatrow);
00908        }
00909 
00910      }
00911      doubleMatrix vinv;
00912      if(observation[rec].Resid_Var.empty()) {
00913        vinv=observation[rec].rve;
00914      }
00915      else {
00916        vinv=observation[rec].Resid_Var;
00917        vinv.ginv1();
00918      }
00919      //std::cout << "Info B"<< Info << "vinv" << vinv << "Fmat"<<Fmat;
00920      Info+=Fmat*vinv*Fmat.transpose()*
00921        observation[rec].weight;
00922      //std::cout << "Info A"<< Info;
00923      //    if(Info[20][20] < -1.e-6) {
00924      //      std::cout << "Wow!\n";
00925      //    }
00926 
00927      vc_mat=observation[rec].weight*Fmat*vinv*observation[rec].H;
00928 
00929 
00930      for(t1=0;t1<numtrait;t1++) {
00931        for(i=0;i<numterm;i++) {
00932         // localterm=(GLMMModelTerm *)&term[i];
00933         ii=term[i].addr[t1];
00934         if(ii) {
00935           ii--;
00936           xval=xval_term[i];
00937           for(j=0;j<nvc;j++){
00938             FRHS[j][ii]+=vc_mat[j][t1]*xval;
00939             //    if(fabs(vc_mat[j][t1]*xval) > 1.e4){
00940             //  std::cout << "Wow2 " ;
00941             //}
00942           }
00943         }
00944        }
00945      }
00946    }
00947    for(k=0;k<nvc;k++) {
00948      hmmec.solve(FSol[k],FRHS[k],"ysmp");
00949    }
00950    Info-=
00951      FRHS*FSol.transpose();
00952    Info*=.5;
00953    Score*=.5;
00954    // modelfile.close();
00955 
00956    delete [] svec;
00957    delete [] svecy;
00958    delete [] svecx;
00959    delete [] kvecy;
00960    delete[] kvecx;
00961 
00962  }
00963 
00964 
00965 
00966  SparseMatrix& GLMM::ainv(void)
00967  {
00968    if(!Need_Ainv) return(hainv);
00969    Need_Ainv=0;
00970    //TW  int do_west;
00971    //TW Vector<double> West;
00972    //TW  do_west=pop->do_west;
00973    //TW  West=pop->West;
00974    unsigned nanim=popsize-numgroup;
00975    hainv.resize(popsize,4*popsize);
00976    double dii,val;
00977 
00978    Matrix<double> lambda(3,3);
00979    getlambda(lambda.begin(),3);
00980    unsigned asd[3];
00981    int  ii,jj,j;
00982    Individual *I;
00983    double f1,f2;
00984    ldet=0.;
00985    for (int k=0; k<nanim; k++) {
00986      I = pop->member(k);
00987      asd[0] = I->id(); asd[1] = I->father_id(); asd[2] = I->mother_id();
00988      dii = 4.0/(2.0 - I->father_inbcoef() - I->mother_inbcoef());;
00989      f1= I->father_inbcoef() ;
00990      f2= I->mother_inbcoef();
00991      if(asd[1]> nanim) f1=-1.;
00992      if(asd[2]> nanim) f2=-1.;
00993      dii = 4.0/(2.0 -f1-f2);
00994      ldet+=std::log(dii);
00995      for (int i=0; i<3; i++) {
00996        if (asd[i] != 0) {
00997         ii = asd[i];
00998         for (j=0; j<3; j++) {
00999           if (asd[j] != 0) {
01000             jj = asd[j];
01001             val = lambda[i][j]* dii;
01002             // std::cout << "\n ii " << ii << " jj " << jj << " val " << val << " dii " << dii;
01003             if(ii <= jj ) hainv.insert(ii,jj,val);
01004           }
01005         }
01006        }
01007      }
01008    }
01009    ldet=-2.*ldet;
01010    //std::cout << "ldet " << ldet << "\n";
01011    //std::cout << hainv.dense();
01012    hainv.logdet();
01013    hainv.close();
01014 
01015    return(hainv);
01016  }
01017 doubleMatrix GLMM::AI_REML(int numiter,double tol,double info_scale)
01018 {
01019   int Converged,Need_Like;
01020   aireml_called=-1;
01021   Converged=0;
01022   Need_Like=1;
01023   Vector<double> varold,varnew;
01024   int Update_estimate_AI;
01025   int nvc,iteration,numran,k,t1,t2,raneff,kidx,kend;
01026   Update_estimate=1;
01027   // info_scale=1.1;
01028   glim(num_glmm);
01029   //  glim(5)->display();
01030   Update_estimate=1;
01031   nvc=TotalNvc();
01032   doubleMatrix varbound;
01033   varbound.resize(numtrait,numtrait);
01034   Vector<double> eig,flg,fix;
01035   eig.resize(numtrait);
01036   flg.resize(numtrait);
01037   fix.resize(nvc);
01038   varold.resize(nvc);
01039   varnew.resize(nvc);
01040   numran=Var2Vec(varold.begin()); //Have Numran return Number af random
01041   // effects plus one for P if it exists
01042   
01043   doubleMatrix Adj_Cov;
01044   if(numran) P_Mat = new doubleMatrix [numran];
01045   doubleMatrix Ip,Info_orig;
01046   double log_like_old,log_like_new;
01047   if(Need_Like){ 
01048     log_like_old=restricted_log_likelihood(0);
01049     std::cout << "\nOriginal  Residual Log Likelihood:" << std::setprecision(SESSION.output_precision) << log_like_old <<"\n\n";
01050     Need_Like=0;
01051   }
01052   for(k=0;k<numran;k++) P_Mat[k].identity(nt_vec2[k]);
01053   //if(Print_Level == 0) std::cout << "Initial Estimates " << varold;
01054   long subit;
01055   for(iteration=0;(iteration<numiter) && !Converged;iteration++){
01056     
01057     Update_estimate=1;
01058     //log_like_old=restricted_log_likelihood(1);
01059     //std::cout << "\nOld Residual Log Likelihood:" << log_like_old <<"\n";
01060     SSQCP();
01061     if(Need_Like) {
01062       //glim(2);
01063       log_like_old=restricted_log_likelihood(0);
01064       Need_Like=0;
01065     }
01066     if(Print_Level > 0)  std::cout << "\n Old Residual Log Likelihood:" << std::setprecision(SESSION.output_precision)<< log_like_old <<"\n";
01067     Var2Vec(varold.begin());
01068     subit=0;
01069     
01070     info_scale=0.;
01071     Info_orig=Info;
01072     do{
01073       Info=Info_orig;
01074       //      std::cout << "\nOrig Info" << Info_orig;
01075     if(info_scale ){
01076       double info_mult=std::exp(info_scale);
01077       //std::cout << "\n Info Mult " << info_mult;
01078       for(k=0;k<nvc;k++) Info[k][k]*=info_mult;
01079     }
01080     //std::cout <<"\n Fix " << fix;
01081     for(k=0;k<nvc;k++) {
01082       if(Info[k][k] < EPSILON || fix[k]) {
01083         for(int k2=0;k2<nvc;k2++) {
01084           Info[k][k2]=0;
01085           Info[k2][k]=0;
01086         }
01087         Info[k][k]=10.*EPSILON;
01088         //fix[k]=1;
01089       }
01090     }
01091 #ifdef DO_CHOL_NOT
01092     //varbound=Info;
01093     //    std::cout << "Eigen" << varbound.eigen();
01094     /*
01095     for(k=0;k<nvc;k++) {
01096     if(fix[k] ) {
01097     Score[k]=0;
01098     for(int k2=0;k2<nvc;k2++) {
01099           Info[k2][k]=0;
01100           Info[k][k2]=0;
01101         }
01102         Info[k][k]=1.e-10
01103       }
01104     }
01105     */
01106     //    Info_orig=Info;
01107     //std::cout << "Score " << Score;
01108     //std::cout << "Info " << Info;
01109     //    std::cout << "ascov 1" << Info_orig.ginv1();
01110     //    std::cout << "ascov 0" << Info_orig.ginv0();
01111     /*Info_orig=Info;*/
01112 #endif
01113     //    std::cout << "Score " << Score;
01114     //    std::cout << "Info " << Info;
01115     Vector<double> Delt;
01116     Delt=Info.ginv0()*Score;
01117     varnew=varold+Delt;
01118     //std::cout << "\nVar " << varnew << varold << Delt;
01119     //    if(Print_Level >= 0) {
01120     //  std::cout << " New Estimates before Adjustment" << varnew;
01121     //}
01122 #ifdef DO_LOG
01123     doubleMatrix P,L,D;
01124     
01125     Adj_Cov.identity(nvc);
01126     int offset=nvc-res_nvc;
01127     for(k=0;k<res_nvc;k++)
01128       for(int k2=0;k2<res_nvc;k2++)
01129         Adj_Cov[offset+k][offset+k2]=observation[numrec].Adj_Cov[k][k2];
01130     
01131 
01132     Vector<double> d;   
01133     int nt;
01134     for(k=0,raneff=0;raneff<numran;raneff++) {
01135       nt=nt_vec2[raneff];
01136       varbound.resize(nt,nt);
01137       for(kidx=k,t1=0;t1<nt;t1++) for(t2=t1;t2<nt;t2++,kidx++) {
01138         varbound[t1][t2]=varold[kidx];
01139         varbound[t2][t1]=varold[kidx];
01140       }
01141       //      std::cout << "varbound "<< varbound;
01142       P=varbound;
01143       //std::cout << "\nP " << P;
01144       d=P.eigen();
01145       D.resize(nt,nt);
01146       for(t1=0;t1<nt;t1++){
01147        d[t1]=std::log(d[t1]);
01148        D[t1][t1]=d[t1];
01149       }
01150           
01151 
01152       doubleMatrix part;
01153       
01154       for(kidx=k,t1=0;t1<nt;t1++) for(t2=t1;t2<nt;t2++,kidx++) {
01155         part.resize(nt,nt);
01156         double D_avg,D_delt;
01157         D_avg=.5*(d[t1]+d[t2]);
01158         D_delt=.5*(d[t1]-d[t2]);
01159         if(fabs(D_delt) > 1.e-8) {
01160           
01161           //std::cout << "how did I get here!!!\n";
01162           part[t1][t2]=std::exp(D_avg)*(sinh(D_delt))/(D_delt);
01163           part[t2][t1]=std::exp(D_avg)*(sinh(D_delt))/(D_delt);
01164         }
01165         else{
01166           part[t1][t2]=std::exp(D_avg);
01167           part[t2][t1]=std::exp(D_avg);
01168         }
01169         //std::cout << "part\n" << part <<"d\n"<< d;
01170         part=P*part*P.transpose();
01171         if(d[t1] <= -9. && d[t2] <= -9.)  part.assign(0.0);
01172         int kkidx,tt1,tt2;
01173         for( kkidx=k,tt1=0;tt1<nt;tt1++) for(tt2=tt1;tt2<nt;tt2++,kkidx++) {
01174           //      std::cout <<"\n" << kkidx << " " << kidx << " " << tt1 << " " << tt2 << " " << nt << " " << raneff << " " << k <<"\n",
01175           Adj_Cov[kkidx][kidx]=part[tt1][tt2];
01176         }
01177       }
01178       
01179       /*
01180       double dmax=0.;
01181       for(kidx=k,t1=0;t1<nt;t1++) {
01182         for(t2=t1;t2<nt;t2++,kidx++) {
01183           if(fabs(Delt[kidx])> dmax) dmax=fabs(Delt[kidx]);
01184         }
01185       }
01186 
01187       
01188 #define      MAXCHG 1.
01189             if(dmax > MAXCHG){
01190         std::cout << "\ndmax " << dmax <<"\n";
01191         for(kidx=k,t1=0;t1<nt;t1++) {
01192           for(t2=t1;t2<nt;t2++,kidx++) {
01193           Delt[kidx]/=dmax/MAXCHG;
01194           }
01195         }
01196       }
01197       */
01198       //std::cout << "D" << D << "P" << P;
01199       for(kidx=k,t1=0;t1<nt;t1++) {
01200         for(t2=t1;t2<nt;t2++,kidx++) {
01201         D[t1][t2]+=Delt[kidx];
01202         D[t2][t1]=D[t1][t2];
01203         }
01204       }
01205       
01206       //std::cout << "D new" << D;
01207 
01208       D=P*D*P.transpose();
01209       doubleMatrix Q;
01210       doubleMatrix DE;
01211       Q=D;
01212       d=Q.eigen();
01213       //std::cout << " d " << d << " Q " << Q << " D" << D;
01214       double dmax=d.max();
01215       //if(dmax < -8.) std::cerr << "\nD\n" << D << "\nP\n" << P<< "\n";
01216       if(dmax > 15.) dmax=15.;//
01217       if(dmax < 0.) dmax=0;
01218       double dmin=std::log(10.*SESSION.epsilon)+dmax;
01219       for(t1=0;t1<nt;t1++) {
01220         if(d[t1] < dmin) d[t1]=dmin+std::log(.5);
01221         if(d[t1] > dmax) d[t1]=15;
01222       }
01223       DE.resize(nt,nt);
01224       for(t1=0;t1<nt;t1++)DE[t1][t1]=std::exp(d[t1]);
01225       D=Q*DE*Q.transpose();
01226       Q=D;
01227       d=Q.eigen(); 
01228       //std::cout << " d exp " << d << " Q " << Q;
01229       varbound=D;//P*D*P.t();
01230       //std::cout << " d " << d;
01231       //   std::cout << " New Estimates before Adjustment" << varbound;
01232       for(t1=0;t1<nt;t1++) {
01233         //      varbound[t1][t1]+=1.0e-4;
01234         if(varbound[t1][t1] <  std::exp(-11.)) {
01235           for(t2=0;t2<nt;t2++){
01236             varbound[t1][t2]=0.;
01237             varbound[t2][t1]=0.;
01238           }
01239           varbound[t1][t1]=std::exp(-11.5);
01240         }
01241       }
01242       //std::cout << "varbound   new" << varbound;
01243       for(t1=0;t1<nt;t1++) for(t2=t1;t2<nt;t2++,k++) {
01244         varnew[k]=varbound[t1][t2];
01245       }
01246     }
01247     
01248 #endif
01249 
01250     
01251     //   ****
01252     //    If the variance covariance matrix is not pd make it slighty pd
01253     //   ****
01254     //Print_Level=2;
01255 #ifdef DO_CHOL_2
01256     int nt;
01257     for(k=0,raneff=0;raneff<numran;raneff++) {
01258       nt=nt_vec2[raneff];
01259       flg.zeros(nt);
01260       
01261       for(t1=0;t1<nt;t1++) for(t2=t1;t2<nt;t2++,k++) {
01262         if(t1==t2 && varnew[k]<1.e-8 && !fix[k]) {
01263           Score[k]=0;;
01264           varnew[k]=1.e-4;
01265           flg[t1]=1;
01266           fix[k]=1;
01267         }
01268         else if(flg[t1] && t1!=t2) {
01269           Score[k]=0.;
01270           varnew[k]=0.;
01271           fix[k]=1;
01272         }
01273        }
01274      }
01275         
01276     //    for(k=0;k<nvc;k++) {
01277     //      if(fix[k]){
01278     //       for(int k2=0;k2<nvc;k2++) {
01279     //        Info[k][k2]=0;
01280     //        Info[k2][k]=0;
01281     //       }
01282     //       Info[k][k]=1.e-4;
01283     //      }
01284     //    }
01285     // varnew=varold+Info.ginv0()*Score;
01286 #endif
01287 
01288 #ifdef DO_PMAT   
01289     int nt;
01290     for(k=0,raneff=0;raneff<numran;raneff++) {
01291       nt=nt_vec2[raneff];
01292       varbound.resize(nt,nt);
01293       eig.resize(nt);
01294       flg.resize(nt);
01295       for(kidx=k,t1=0;t1<nt;t1++) for(t2=t1;t2<nt;t2++,kidx++) {
01296         varbound[t1][t2]=varnew[kidx];
01297         varbound[t2][t1]=varnew[kidx];
01298       }
01299 
01300       for(t1=0;t1<nt;t1++){
01301         if(varbound[t1][t1] < 1.e-8){
01302           for(t2=0;t2<nt;t2++) {
01303             varbound[t1][t2]=0;
01304             varbound[t2][t1]=0;
01305           }
01306         }
01307        }
01308         
01309        //           P_Mat[raneff]=P_Mat[raneff]*P_Mat[raneff].transpose()*varbound*P_Mat[raneff]*P_Mat[raneff].transpose();
01310         
01311         
01312        P_Mat[raneff]=varbound;
01313         
01314        eig=P_Mat[raneff].eigen();
01315        if(Print_Level > 1) {
01316          //     std::cout << "varbound" << varbound << "\n";
01317          //     std::cout << "Eigen Values " << eig << "\n";
01318          //     std::cout << "P_Mat" << P_Mat[raneff] << "\n";
01319       }
01320             
01321       for(t1=0;t1<nt;t1++){
01322         flg[t1]=0;
01323         if(eig[t1]<1.e-8){
01324           eig[t1]=.99e-3;
01325           flg[t1]=1;
01326         }
01327         if(eig[t1]>1.e10){
01328           eig[t1]=1.01e10;
01329           flg[t1]=0;
01330         }
01331       }
01332       if(Print_Level > 1) {
01333         //      std::cout << "Adjusted Eigen Values " << eig << "\n";
01334        }
01335        varbound=P_Mat[raneff]*eig.diag()*P_Mat[raneff].transpose();
01336        for(t1=0;t1<nt;t1++){
01337         if(flg[t1]){
01338           for(t2=0;t2<nt;t2++) {
01339             P_Mat[raneff][t1][t2]=0;
01340           }
01341         }
01342       }
01343             
01344       for(t1=0;t1<nt;t1++) for(t2=t1;t2<nt;t2++,k++) {
01345         varnew[k]=varbound[t1][t2];
01346               
01347       }
01348       eig=varbound.eigen();
01349       if(Print_Level > 1) {
01350         //      std::cout << " Eigen Values bounded Matrix " << eig << "\n";
01351       }
01352          
01353     }
01354 #endif /* DO_PMAT */
01355     Vec2Var(varnew.begin());
01356     //std::cout << "Varnew " <<varnew;
01357     glim(num_glmm); 
01358     log_like_new=restricted_log_likelihood(0);
01359     std::cout << " Iteration " << (iteration+1) <<"."<< subit << " Res Log Like "<< std::setprecision(SESSION.output_precision)<< log_like_new << " Change " << std::setprecision(SESSION.output_precision)<<(log_like_new-log_like_old) << "\n";
01360     info_scale+=1.5*ranf();
01361   }while(tol && log_like_new-log_like_old < -tol && subit++<= 10);
01362     if(subit == 0 && std::abs(log_like_new-log_like_old) < std::max(tol,EPSILON) ) Converged=1;
01363     if(Converged) aireml_called=1;
01364     log_like_old=log_like_new;
01365     info_scale-=.75;
01366     varold=varnew;
01367 
01368     //    if(iteration%3 == 2) {
01369     //      Update_estimate=1; 
01370     //      glim(2);
01371     //      Update_estimate=1;
01372     //    }
01373 
01374     //        Print_Level=2;
01375     
01376     if(Print_Level > 0) {
01377       std::cout << " Iteration " << iteration << "  Subit " << subit << "\n";
01378       std::cout << " Residual log likelihood " 
01379                 << std::setprecision(SESSION.output_precision)
01380            << log_like_new << "\n";
01381       std::cout << " New Estimates \n" << varnew;
01382       if(Print_Level > 1) {
01383         std::cout << " Score \n" << Score;
01384         std::cout << " Info     \n" << Info;
01385         std::cout << " Asy Cov \n" << Info.ginv0();
01386       }
01387     }  
01388 
01389 
01390      Vec2Var(varnew.begin());
01391      varold=varnew;
01392    }
01393    if(Print_Level >= 0) {
01394      if(Converged){
01395        std::cout << "\n Iteration " << iteration  << " Converged\n";
01396      }
01397      else{
01398        std::cout << "\n Iteration " << iteration  << "  Subit " << subit << " Failed to Converge\n";
01399      }
01400      std::cout << " Final Estimates \n" << varnew;
01401      std::cout << " Last Change \n" << Info.ginv0()*Score;
01402      Info=Info_orig;
01403      if(info_scale) std::cout << " Unscaled Last Change \n" << Info.ginv0()*Score;
01404      std::cout << " Residual log likelihood "
01405                << std::setprecision(SESSION.output_precision)
01406          << restricted_log_likelihood(0) << "\n" ;
01407      Info=Info_orig;
01408      //  std::cout << "    Adj Matrix " << Adj_Cov;
01409      std::cout << " Asy Covariance Matrix\n" <<
01410  #ifdef DO_LOG
01411        Adj_Cov*
01412  #endif
01413        Info.ginv0()
01414  #ifdef DO_LOG
01415      *Adj_Cov.transpose()
01416  #endif
01417        ;
01418    }
01419    Update_estimate=1;
01420    //glim();
01421    //  for(k=0;k<numran;k++) P_Mat[k].resize(0,0);
01422    if(P_Mat)delete [] P_Mat;
01423    P_Mat=NULL;
01424    varest=varnew;
01425    doubleMatrix ans;
01426    ans = hadjoin(varest,
01427  #ifdef DO_LOG
01428      Adj_Cov*
01429  #endif
01430                  Info.ginv0()
01431  #ifdef DO_LOG
01432      *Adj_Cov.transpose()
01433  #endif
01434    );
01435    return ans;
01436  }
01437 
01438 
01439  SparseMatrix* GLMM::setup_mme(Vector<double>* rhs)
01440  {
01441    /////////////////////////////////////////////////
01442    // build up MME: hmmec, the coefficient matrix,
01443    //               rellrhs, right-hand-side
01444    ///////////////////////////////////////////////////
01445 
01446    if(link_function == NULL) {
01447      return Model::setup_mme( rhs);
01448    }
01449 
01450 
01451    if (type == bad_model) {
01452      warning("GLMM::setup_mme(): bad model");
01453      return 0;
01454    }
01455    if (!data_prepared) {
01456      if (!prepare_data()) {
01457        type = bad_model;
01458        return 0;
01459      }
01460    }
01461    if (hmmesize==0) return &hmmec;
01462 
01463    if (type == mixed_model) {
01464       ;
01465    }
01466    else if (type == fixed_model) {
01467       ;
01468    }
01469    else {
01470      warning("Model::setup_mme(): inappropriate model");
01471      return 0;
01472    }
01473    if(res_nvc) {
01474      varcomp.reserve(res_nvc);
01475    }
01476 
01477    if(!observation)new_obs();
01478    if(hmmec.nz() != 0 && Need_Residual) {
01479      residual(res_nvc*Need_PEV);
01480    }
01481    //hmmec.release();
01482    //hmmec.resize(0,0);
01483    //std::cout << "\n hmmesize " << hmmesize << " max_nz " << max_nz << "\n";
01484    hmmec.resize(hmmesize,max_nz);
01485    if(Sand_Calc) hSand.resize(hmmesize,max_nz);
01486    Vector<double> localrhs;
01487    Vector<double> *rhsvec = &localrhs;
01488    if (rhs) rhsvec = rhs;
01489 
01490    rhsvec->resize(hmmesize);
01491    setup_ww(rhsvec);
01492    Model::add_G_1();
01493    if(Sand_Calc) {
01494      add_G_Sand();
01495      hSand.close();
01496    }
01497  #ifdef OLD_SPARSE
01498    non_zero = hmmec.close();
01499  #else
01500    non_zero=hmmec.nz();
01501  #endif
01502    //std::cout << "\nNon Zero  " << non_zero << "\n";
01503    Need_Residual=1;
01504    return &hmmec;
01505  }
01506 
01507  int GLMM::equation(const std::string &modelspecs){
01508 
01509   
01510    int retval;
01511    retval=Model::equation(modelspecs);
01512 
01513 
01514    return(retval);
01515  }
01516 
01517 
01518  void GLMM::setup_ww(Vector<double>* rhsvec)
01519  {
01520    if(!link_function) {
01521      Model::setup_ww(rhsvec);
01522      return;
01523    }
01524    //  std::cout << " setup_ww ";
01525    unsigned i,j,ii,jj,t1,t2,rec;
01526    double vy,xval,val,otherval;;
01527    memset(rhsvec->begin(),'\0', sizeof(double)*hmmesize);
01528    double *rhstmp = rhsvec->begin() -1;
01529    // for gcc-3.2 replaced 
01530    // std::istrstream modelfile(modelstr, modelpcount);
01531    // with 
01532    std::istringstream modelfile(modelstringstr);  
01533    if (!modelfile) throw exception(" GLMM::setup_ww(): cannot open binary file");
01534    double **vep;
01535    Matrix<double> ve(numtrait,numtrait);
01536    Vector<double> scale_res(numtrait);
01537    doubleMatrix ves(numtrait,numtrait);
01538    for (yry=0, rec=0; rec<numrec; rec++) {
01539      input_pos_val(modelfile);
01540      observation[rec].pattern=pattern[pos_term[numterm]];
01541      if (ntermGdist) {
01542        trait_vec[0] -= pop->popmember[rec_indid[rec]-1]->xbzu();
01543      }
01544      if(observation[rec].need_data) {
01545        memcpy(observation[rec].y.begin(),trait_vec,sizeof(double)*numtrait);
01546        observation[rec].need_data=0;
01547      }
01548      (*link_function)(observation[rec]);
01549      if(Sand_Calc) {
01550        scale_res=observation[rec].rpy-observation[rec].rve*observation[rec].estimate;
01551        ves=scale_res*scale_res;
01552      }
01553      vep = rve[pos_term[numterm]].begin();
01554      val = xval_term[numterm];        // val = weight  variable
01555      if(Use_Like) yry -= 2.*observation[rec].like_val*val;
01556      if(!Use_Like) yry+=observation[rec].Resid_Var.logdet()*val;
01557      for (t1=0; t1<numtrait; t1++) {
01558        if(!Use_Like) yry+=observation[rec].y[t1]*observation[rec].rpy[t1]*val;
01559        for (t2=0; t2<numtrait; t2++)
01560         ve[t1][t2] = val*observation[rec].rve[t1][t2];
01561 
01562      }
01563      for (t1=0; t1<numtrait; t1++) {
01564        vy = val*observation[rec].rpy[t1];
01565 
01566        for (i=0; i<numterm; i++) {
01567         ii = term[i].addr[t1];
01568         if (ii) {
01569           xval = xval_term[i];
01570           for (t2=t1; t2<numtrait; t2++) {
01571             otherval = xval* ve[t1][t2];
01572             jj = term[i].addr[t2];
01573             if (jj) {
01574               hmmec.insert(ii,jj,otherval*xval);
01575               if(Sand_Calc) hSand.insert(ii,jj, xval* (ves[t1][t2])*xval);
01576             }
01577           }
01578           for (t2=0; t2<numtrait; t2++) {
01579             otherval = xval * ve[t1][t2];
01580             for (j=i+1; j<numterm; j++) {
01581               jj = term[j].addr[t2];
01582               if (jj) {
01583                 hmmec.insert(ii,jj,otherval*xval_term[j]);
01584                 if(Sand_Calc) hSand.insert(ii,jj, xval* (ves[t1][t2])*xval_term[j]);
01585               }
01586             }
01587           }
01588           //std::cout << "\nBuilding "<< rec <<" trait " << t1  << " pos " << ii << '\n' << vy <<"\nrpy" << observation[rec].rpy << "\nrve" <<observation[rec].rve<<'\n' <<ve;
01589           rhstmp[ii] += vy*xval_term[i];
01590         }
01591        }
01592      }
01593    }
01594 
01595    //  modelfile.close();
01596  }
01597 
01598 
01599  unsigned GLMM::TotalNvc(void) const
01600  {
01601    ////////////////////////////////////////////////////
01602    //  total number of distinct variance components
01603    /////////////////////////////////////////////////////
01604         
01605    unsigned nvc,i,np;
01606    if(link_function) {
01607      nvc=res_nvc;
01608    }
01609    else{
01610      nvc = (numtrait*(numtrait + 1))/2; //
01611    }
01612    np=0;
01613    for (i=0; i<numterm; i++) {
01614 
01615      if (term(i).classi() == 'R' || term(i).classi() =='P') {
01616        if(var_link[i]==i) nvc += nt_vec[i]*(nt_vec[i] + 1)/2;
01617      }
01618    }
01619    if(np) {
01620      nvc +=(np)*(np-1)*numtrait*numtrait/2;
01621      //ncorr=np;
01622    }
01623 
01624    return nvc;
01625  }
01626 
01627  int GLMM::Var2Vec(double *x)
01628    /*******************************************************************
01629        * put variance components into a double vector
01630        * user is totally responsible to have an appropriate size for vector x
01631        * and matrix residual_var
01632        *********************************************************************/
01633  {
01634    int i,k,t1,t2,numran,ped_done,nt;
01635    doubleMatrix *var;
01636  #ifdef DO_CHOL
01637    doubleMatrix L;
01638  #endif
01639    numran=0;
01640    ped_done=0;
01641    if(nrandom) {
01642      nrandom=0;
01643    }
01644    if(nt_vec2) {
01645      delete [] nt_vec2;
01646    }
01647    nt_vec2=new int [numterm+1];
01648    for (k=0,i=0; i<numterm; i++) {
01649      if ((term[i].classi() == 'R' ||  (!ped_done && term[i].classi() == 'P'))&&(var_link[i]==i)) {
01650        numran++;
01651        nt=nt_vec[i];
01652        nt_vec2[nrandom++]=nt;
01653        var = term[i].prior->var_matrix();
01654        if(term[i].classi()=='R') {
01655  #ifdef DO_CHOL
01656         L=*var;
01657         L.chol();
01658         L=L.transpose();
01659         var=&L;
01660  #endif
01661         for (t1=0; t1<nt; t1++) for (t2=t1; t2<nt; t2++) {
01662           x[k++] = (*var)[t1][t2];
01663         }
01664        }
01665        if(term[i].classi()=='P'){
01666  #ifdef DO_CHOL
01667          //     build_CorrVar();
01668         L=var;
01669         L.chol();
01670         L=L.transpose();
01671         var=&L;
01672         for (t1=0; t1<nt; t1++) for (t2=t1; t2<nt; t2++) {
01673           x[k++] = (*var)[t1][t2];
01674         }
01675  #else
01676         //      for(int ii=i;ii<numterm;ii++) {
01677         //        for(t1=0;t1<numtrait;t1++){
01678         //          if(corrmap[ii]) {
01679         //            var=term[ii].prior->var_matrix();
01680         //            for(int jcorr=ii;jcorr<numterm;jcorr++) {
01681         //              if(corrmap[jcorr]) {
01682         //                int imult=1;
01683         //                if(ii != jcorr) {
01684         //                  var=&corrvar[ii][jcorr];
01685         //                  imult=0;
01686         //                }
01687         //                for (t2=imult*t1; t2<numtrait; t2++) {
01688         //                  x[k++] = (*var)[t1][t2];
01689         //                }
01690         //              }
01691         //            }
01692         //          }
01693         //        }
01694         //      }
01695 
01696         for (t1=0; t1<nt; t1++) for (t2=t1; t2<nt; t2++) {
01697           x[k++] = (*var)[t1][t2];
01698         }
01699  #endif
01700        }
01701      }
01702    }
01703    /*  if(ncorr) {
01704        for(int ict=0;ict<numterm;ict++) {
01705        if(corrmap[ict]) {
01706        for(int jct=(ict+1);jct<numterm;jct++) {
01707        if(corrmap[jct]) {
01708        for (t1=0; t1<numtrait; t1++) for (t2=t1; t2<numtrait; t2++) {
01709        x[k++] = corrvar[ict][jct].me[t1][t2];
01710        }
01711        }
01712        }
01713        }
01714        }
01715        }*/
01716    if(link_function) {
01717      for(t1=0;t1<res_nvc;t1++) x[k++]=varcomp[t1];
01718    }
01719    else{
01720      numran++;
01721      nt_vec2[nrandom++]=numtrait;
01722      for (t1=0; t1<numtrait; t1++) {
01723        for (t2=t1; t2<numtrait; t2++) x[k++] = residual_var[t1][t2];
01724      }
01725    }
01726    return(numran);
01727    }
01728 
01729 // This is a function that I am adding to make the normal_log link function
01730 // work from C++. (March 2, 2004; RLF)
01731 void GLMM::normalLog(void){
01732         int n_nvc= (ntrait()*(ntrait()+1))/2;
01733         link(&normal_loginClasses,n_nvc);
01734         num_glmm=1;
01735         Like_LR(1);
01736 }
01737         
01738 
01739 // I am moving the following stuff from the link.cc file that is in the interface directory to make the normal_log link function
01740 // work from C++. (March 2, 2004; RLF)
01741 
01742 #define twopi 6.283195307179587
01743 #define invsqrt2pi .3989422804014326779399461 
01744 #define BOUND(est,L,U) (est=(est > U ? U:(est < L ? L:est) ));
01745 #define BOUND_FLG(est,L,U,flg) (flg=0,(if (est < L || est > U )flg=1),est=(est > U ? U:(est < L ? L:est) ));
01746 #define UPPER_BOUND(est,U) (est=(est > U ? U:est ));
01747 #define LOWER_BOUND(est,L) (est=(est < L ? L:est ));
01748         
01749 void normal_loginClasses(matvec::Observe &observe) {
01750         int numtrait=observe.numtrait;
01751         
01752         doubleMatrix H,variance;
01753         doubleMatrix Alog;
01754         doubleMatrix P,R;
01755         Vector<double> D;
01756         // double final=0;
01757         //if(observe.param) final=*((double *) observe.param[0]);
01758         int k,t1,t2;
01759         if(observe.rec < 0) {
01760                 if(observe.nvc) { 
01761                         if(observe.nvc != (numtrait*(numtrait+1))/2) {
01762                                 throw matvec::exception("Error: Should be normal(,%d)");
01763                                 return;
01764                         } 
01765                         
01766                         
01767                         //cout <<  variance << observe.resid_var[0];
01768                         *observe.resid_var=observe.resid_var[0];
01769                         Alog=(observe.resid_var[0]).mat_log();
01770                         for(k=0,t1=0;t1<numtrait;t1++) 
01771                                 for(t2=t1;t2<numtrait;t2++,k++) 
01772                                         observe.varcomp[0][k]=Alog[t1][t2];
01773                 }
01774                 return;
01775         }
01776         Vector<double> mean,y;
01777         Alog.resize(numtrait,numtrait);
01778         
01779         Vector<doubleMatrix> part(observe.nvc);
01780         for(k=0;k<observe.nvc;k++) part[k].resize(numtrait,numtrait);
01781         if(observe.nvc) {
01782                 
01783         for(k=0,t1=0;t1<numtrait;t1++) 
01784                         for(t2=t1;t2<numtrait;t2++,k++) {
01785                                 Alog[t1][t2]=observe.varcomp[0][k];
01786                                 Alog[t2][t1]=observe.varcomp[0][k];
01787                         }
01788                                 variance=Alog.mat_exp();
01789                 //cout << variance;
01790                 Alog=variance.mat_log();
01791                 
01792                 for(k=0,t1=0;t1<numtrait;t1++) 
01793                         for(t2=t1;t2<numtrait;t2++,k++) 
01794                                 observe.varcomp[0][k]=Alog[t1][t2];
01795                 *observe.resid_var=variance;
01796                 variance.mat_exp_der(part);
01797                 doubleMatrix Atmp;
01798                 /*
01799                  for(int ii=0,t1=0;t1 <numtrait;t1++)  
01800                  for(t2=t1;t2<numtrait;t2++,ii++) {
01801                          Atmp=Alog;
01802                          Atmp[t1][t2]+=.0001;
01803                          Atmp[t2][t1]=Atmp[t1][t2];
01804                          Atmp=(Atmp.mat_exp()-Alog.mat_exp())/.0001;
01805                          cout << ii << part[ii]<< endl;
01806                          cout << ii << Atmp << endl;
01807                  }
01808                  */
01809                 
01810         }
01811         else{
01812                 variance=observe.resid_var[0];
01813         }
01814         //cout << "\n Variance " << variance << *observe.resid_var;
01815         doubleMatrix Miss;
01816         Miss.resize(numtrait,numtrait);
01817         //cout << "\n Pattern" ;
01818         for(t1=0;t1<numtrait;t1++) {
01819                 //cout <<' ' <<observe.pattern[t1];
01820                 if(observe.pattern[t1]=='1') Miss[t1][t1]=1;
01821         }
01822         //Miss.identity();
01823         
01824         //static double mean,H,variance,scale,y;
01825         y=observe.y;
01826         y=Miss*y;
01827         //cout << "\n y\n" << y;
01828         // if(observe.estimate[0] < -5.) observe.estimate[0]=-5.;
01829         //  if(observe.estimate[0] > 5.) observe.estimate[0]=5.;
01830         mean=Miss*observe.estimate;
01831         
01832         variance=*observe.resid_var;
01833         variance=Miss*variance*Miss;
01834         //cout << "\n Variance \n" << variance; 
01835         observe.Resid_Var=variance;
01836         variance=variance.ginv1();
01837         //cout << "\n Variance inv \n" << variance; 
01838         observe.like_val=.5*(variance.logdet()-variance.quadratic((y-mean),(y-mean))) ;
01839         
01840         
01841         observe.H=Miss;
01842         H=observe.H;
01843         //observe.Hinv[0][0]=1./H;
01844         observe.rve=H.transpose()*variance*H;
01845         
01846         observe.rpy=H.transpose()*variance*y;
01847         //cout <<"\n rve rpy "<<observe.rve << " " << observe.rpy<< " H "<< H << "pattern" << observe.pattern <<" y"<<  y <<" var" << variance;
01848         observe.residual=y-mean;
01849         if(observe.nvc) {
01850                 for(k=0,t1=0;t1<numtrait;t1++)
01851                         for(t2=t1;t2<numtrait;t2++,k++) {
01852                                 
01853                                 observe.Resid_Sin_Mat[k]=variance*Miss*part[k]*Miss*variance;
01854                                 //      cout << k << " " << part[k] << observe.Resid_Sin_Mat[k] << endl;
01855                         }
01856                                 
01857         }
01858 }
01859 
01860         
01861 
01862 
01863 
01864  } ///////// end of namespace matvec
01865 
01866 

Generated on Thu Jun 16 17:13:42 2005 for Matvec by doxygen1.2.16