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

glmm2.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 #undef DEBUG
00060 
00061 #define EPSILON  SESSION.epsilon
00062    //#define act_numtrait numtrait // Temporary fix
00063 
00064  extern void getlambda(double **lambda, const int n);
00065 
00066  void GLMM::Vec2Var(const double *x)
00067    ///////////////////////////////////////////////////////////////////////
00068    // put variance components into a double vector
00069    // user is totally responsible to have an appropriate size for vector x
00070    ///////////////////////////////////////////////////////////////////////
00071  {
00072    int i,k,t1,t2,ped_done;
00073    ped_done=0;
00074    doubleMatrix *var;
00075  #ifdef DO_CHOL
00076    doubleMatrix L;
00077  #endif
00078    for (k=0,i=0; i<numterm; i++) {
00079      if (term[i].classi() == 'R' || (!ped_done && term[i].classi() == 'P')) {
00080        if(var_link[i]==i){
00081          int nt=nt_vec[i];
00082 #ifdef DO_CHOL
00083          L.resize(numtrait,numtrait);
00084          L.assign(0.0);
00085          var=&L;
00086 #else
00087          var = term[i].prior->var_matrix();
00088 #endif
00089          for (t1=0; t1<nt; t1++) {
00090            for (t2=t1; t2<nt; t2++,k++) {
00091              (*var)[t1][t2] = x[k];
00092 #ifndef DO_CHOL
00093              if ( t2>t1 ) (*var)[t2][t1] = x[k];
00094 #endif
00095            }
00096          }
00097 #ifdef DO_CHOL
00098          var= term[i].prior->var_matrix();
00099          *var=L.transpose()*L;
00100 #endif
00101        }
00102        else{
00103          int ii=var_link[i];
00104          var= term[i].prior->var_matrix();
00105          doubleMatrix *var2;
00106          var2=term[ii].prior->var_matrix();
00107          *var=*var2;
00108        }
00109      }       
00110        //if(corrmap[i]) corrvar[i][i]=*var;
00111    }
00112    /*
00113      if(ncorr) {
00114      for(int ict=0;ict<numterm;ict++) {
00115      if(corrmap[ict]) {
00116      for(int jct=(ict+1);jct<numterm;jct++) {
00117      if(corrmap[jct]) {
00118      for (t1=0; t1<numtrait; t1++) for (t2=0; t2<numtrait; t2++,k++) {
00119      corrvar[ict][jct].me[t1][t2]=x[k];
00120      }
00121      corrvar[jct][ict]=corrvar[ict][jct];
00122      }
00123      }
00124      }
00125      }
00126      }
00127    */
00128    if(link_function){
00129      for(t1=0;t1<res_nvc;t1++) varcomp[t1]=x[k++];
00130    }
00131    else{
00132      for (t1=0; t1<numtrait; t1++) {
00133        for (t2=t1; t2<numtrait; t2++,k++) {
00134         residual_var[t1][t2] = x[k];
00135         if ( t2>t1 ) residual_var[t2][t1] = x[k];
00136        }
00137      }
00138    }
00139  }
00140 
00141 
00142  Vector<double> * GLMM::glim(int iterations,double **ke, int nr, int nc, double *mean)
00143  {
00144    int iter,i,j,k;
00145    doubleMatrix kvk;
00146    Vector<double> kpm,wrkvec;
00147    double old_like,new_like,*krow,*m,*tmpsol,kpd;
00148    double *kp,*sol;
00149    Vector<double> old_sol;
00150    Vector<double> *retval;
00151    if(!link_function) {
00152      blup("ysmp1");
00153      if(ke)
00154        {
00155          tmpsol=new double [hmmesize];
00156          krow=new double [hmmesize];
00157        }
00158      if(ke)
00159        {
00160         kpm.resize(nr);
00161         kvk.resize(nr,nr);
00162         if(mean) memcpy(kpm.begin(),mean,sizeof(double)*nr);
00163         for(i=0;i<nr;i++){
00164           for(j=0;j<nc;j++)  kpm[i]-=ke[i][j]*blupsol[j];
00165           memset(krow,'\0',sizeof(double)*hmmesize);
00166           memcpy(krow,ke[i],sizeof(double)*nc);
00167           hmmec.solve(tmpsol,krow,"ysmp");
00168           for (k=0; k<nr; k++) {
00169             kp = ke[k]; sol = tmpsol;
00170             for (kpd=0.0,j=0; j<nc; j++) kpd += *kp++ * *sol++;
00171             kvk[k][i] = kpd;
00172           }
00173         }
00174         kvk.ginv1();
00175         kpm=kvk*kpm;
00176         memset(krow,'\0',sizeof(double)*hmmesize);
00177         for(i=0;i<nr;i++) {
00178           for(j=0;j<nc;j++) { 
00179             krow[j]+=ke[i][j]*kpm[i];
00180           }
00181         }
00182         hmmec.solve(tmpsol,krow,"ysmp");
00183         for(i=0;i<hmmesize;i++) blupsol[i]+=tmpsol[i];
00184         
00185         delete [] krow;
00186         delete [] tmpsol;       
00187        }
00188 
00189 
00190 
00191      return(&blupsol);
00192    }
00193    for(iter=0;iter< iterations;iter++) {
00194      setup_mme(&rellrhs); 
00195 #ifdef DEBUG
00196      doubleMatrix LHS;
00197      LHS=mmec()->dense();
00198      std::cout << "\nRHS\n"<<rellrhs.subvec()<<"\n";
00199      std::cout << "\nLHS\n"<<LHS <<"\n";
00200 #endif
00201      blup("ysmp1");
00202 
00203      if(ke && iter==0)
00204        {
00205          tmpsol=new double [hmmesize];
00206          krow=new double [hmmesize];
00207        }
00208      if(ke)
00209        {
00210          kpm.resize(nr);
00211          kvk.resize(nr,nr);
00212          if(mean) memcpy(kpm.begin(),mean,sizeof(double)*nr);
00213          for(i=0;i<nr;i++){
00214            for(j=0;j<nc;j++)  kpm[i]-=ke[i][j]*blupsol[j];
00215            memset(krow,'\0',sizeof(double)*hmmesize);
00216            memcpy(krow,ke[i],sizeof(double)*nc);
00217            hmmec.solve(tmpsol,krow,"ysmp");
00218            for (k=0; k<nr; k++) {
00219              kp = ke[k]; sol = tmpsol;
00220              kpd=0.0;
00221              for (j=0; j<nc; j++) kpd += ke[k][j] * tmpsol[j];
00222              kvk[k][i] = kpd;
00223            }
00224          }
00225          kvk.ginv1();
00226          kpm=kvk*kpm;
00227          memset(krow,'\0',sizeof(double)*hmmesize);
00228          for(i=0;i<nr;i++) {
00229            for(j=0;j<nc;j++) {
00230              krow[j]+=ke[i][j]*kpm[i];
00231            }
00232          }
00233          hmmec.solve(tmpsol,krow,"ysmp");
00234          for(i=0;i<hmmesize;i++) blupsol[i]+=tmpsol[i]; 
00235        }
00236      
00237    }  
00238    
00239    
00240    retval=&blupsol;
00241    if(ke)
00242      {
00243        delete [] krow;
00244        delete [] tmpsol;
00245      }
00246    return retval;
00247  }
00248   
00249 
00250  double GLMM::contrast(const double **kpme, const unsigned nr,
00251                       const unsigned nc,const double *M,const int prt_flag,double **result)
00252  {
00253    ////////////////////////////////////////////////////
00254    // H0:  K'*b = M
00255    // trailing zeros in K' can be omitted
00256    // REMINDER: blupsol & rellrhs remain intact
00257    //
00258    // meanp must be declared as double meanp[nr][4]
00259    /////////////////////////////////////////////////////
00260 
00261 
00262    if(!link_function){
00263      return(Model::contrast(kpme,nr,nc,M, prt_flag,result));
00264    }
00265    int do_varcomp=Info.num_rows();
00266    int Print_Flag=1;
00267    if(Print_Level < 0 || !prt_flag) Print_Flag=0;
00268 
00269    if (!kpme) {
00270      warning("GLMM::contrast(kp): kp is null, thus it is ignored");
00271      return 0.0;
00272    }
00273    if (!get_blupsol()) throw exception("GLMM::contrast(): bad model");
00274 
00275    if (nc > hmmesize) throw exception("GLMM::contrast(): size not conformable");
00276    int est=1;
00277    doubleMatrix kvk(nr,nr);
00278    doubleMatrix kvkori(nr,nr);
00279    doubleMatrix kv(nr,hmmesize);
00280    doubleMatrix kGk(nr,nr);
00281    doubleMatrix kRk(nr,nr);
00282    Vector<double> kpdiff(nr);
00283    Vector<double> kpb_m(nr);
00284    Vector<double> xy(hmmesize);
00285    Vector<double> tmpsol(hmmesize);
00286    double *sol, kpd;
00287    double log_LR;
00288    log_LR=2.*like_val;
00289    const double *kp;
00290    unsigned i,j,k;
00291    int t1,t2,ii,*ainv_ia,*ainv_ja,ainv_nrow;
00292    int ipos,jpos,je,jj,jaddr;
00293    double *ainv_a;
00294    if(LR==2) glim(10,(double **)kpme,nr,nc,(double *)M);//Lagrange Multiplier uses KVK under Ho
00295 
00296    for (i=0; i<nr; i++) {
00297      if (nc < hmmesize) {
00298        memset(xy.begin(),'\0',sizeof(double)*hmmesize);
00299        memcpy(xy.begin(),kpme[i],sizeof(double)*nc);
00300        hmmec.solve(tmpsol,xy,"ysmp");
00301      }
00302      else {
00303        hmmec.solve(tmpsol.begin(),kpme[i],"ysmp");
00304      }
00305      hmmec.mv(tmpsol,xy);
00306      memcpy(kv[i],tmpsol.begin(),sizeof(double)*hmmesize);
00307      kp = kpme[i]; 
00308      sol = xy.begin();
00309      for (kpd=0.0,j=0; j<nc; j++) {
00310        kpd = std::max(kpd,fabs(kpme[i][j] - xy[j]));
00311        kp++;
00312        sol++;
00313      }
00314      for (j=nc; j<hmmesize; j++) {
00315        kpd = std::max(kpd,fabs(xy[j]));
00316        sol++;
00317      }
00318      kpdiff[i] = kpd;
00319      for (k=0; k<nr; k++) {
00320        kp = kpme[k]; sol = tmpsol.begin();
00321        for (kpd=0.0,j=0; j<nc; j++) kpd += kpme[k][j] * tmpsol[j];
00322        kvk[k][i] = kpd;
00323      }
00324    }
00325    for(k=1;k<nr;k++) for(i=0;i<k;i++) kvk[k][i]=kvk[i][k];
00326    kvkori=kvk;
00327    kvk = kvkori;
00328    kvk.ginv1(&k);
00329    if (k < nr) {
00330      warning("GLMM::contrast(K'): K'V{-1}K is singular. Possible reason:\n"
00331             " (1) K is non-estimable, and (2) K isn't of full column rank");
00332      //return 0.0;
00333    }
00334    // Get Lambda's for vc calculations
00335    int nvc=TotalNvc();
00336    unsigned startaddr,nlevels,iaddr,t;
00337    Vector<double> Lambda(nvc);
00338    double addj=0.;
00339    doubleMatrix *smat;
00340    int k_vc,i_vc;
00341    doubleMatrix wmat(numtrait,numtrait);
00342    doubleMatrix rmat(numtrait,numtrait);
00343    for(k_vc=0,i_vc=0;do_varcomp && i_vc<numterm;i_vc++) {
00344      if(term[i_vc].classi() == 'P' || term[i_vc].classi() == 'R'){
00345        startaddr=term[i_vc].startaddr()+1;
00346        int nt=nt_vec[i_vc];
00347        for(t1=0;t1<nt;t1++) for(t2=t1;t2<nt;t2++,k_vc++) {
00348         
00349         rmat=*(term[i_vc].prior->var_matrix());
00350         rmat.ginv1();
00351         wmat=SinMat[k_vc];
00352         kGk.assign(0.0);
00353         kRk.assign(0.0);
00354         if(term[i_vc].classi() == 'R') {
00355           nlevels=term[i_vc].nlevel();
00356           for(ii=1;ii<=nlevels;ii++) {
00357             iaddr=startaddr+(ii-1)*numtrait;
00358             kGk+=kv.submat(0,iaddr-1,nr,nt)*wmat
00359               *(kv.submat(0,iaddr-1,nr,nt)).transpose();
00360             if(t1==0 && t2==0) kRk+=kv.submat(0,iaddr-1,nr,nt)*rmat
00361                                  *(kv.submat(0,iaddr-1,nr,nt)).transpose();
00362           }
00363         }
00364         if(term[i_vc].classi() == 'P') {
00365           ainv();
00366           ainv_ia=hainv.ia();
00367           ainv_ja=hainv.ja();
00368           ainv_a=hainv.a();
00369           ainv_nrow=hainv.num_rows();
00370           for(ii=1;ii<=ainv_nrow;ii++) {
00371             ipos=ii;
00372             iaddr=startaddr+(ipos-1)*nt;
00373             je=ainv_ia[ii+1];
00374             for(jj=ainv_ia[ii];jj<je;jj++) {
00375               jpos=ainv_ja[jj];
00376               double offdiag;
00377               offdiag=2.;
00378               if(ipos==jpos) offdiag=1.;
00379               jaddr=startaddr+(jpos-1)*nt;
00380               kGk+=ainv_a[jj]*offdiag*
00381                 kv.submat(0,iaddr-1,nr,nt)*wmat
00382                 *(kv.submat(0,iaddr-1,nr,nt)).transpose();
00383               if(t1==0 && t2==0)  kRk+=kv.submat(0,iaddr-1,nr,nt)*rmat
00384                                     *(kv.submat(0,iaddr-1,nr,nt)).transpose();
00385             }
00386           }
00387         }
00388         Lambda[k_vc]=(kvk*kGk).trace();
00389         if(t1 == 0 && t2 == 0)  addj+=(kvk*kRk).trace();
00390        }
00391      }
00392    }
00393 
00394    //   ****
00395    // Build Residual SSs and CP
00396    //   ****
00397    unsigned kvc;
00398 
00399    if(link_function){
00400 
00401      for(kvc=0;do_varcomp && kvc<res_nvc;kvc++,k_vc++){
00402        wmat.assign(0.0);
00403        rmat.assign(0.0);
00404        for(ii=0;ii<numrec;ii++) {
00405         wmat+=observation[ii].H.transpose()*observation[ii].Resid_Sin_Mat[kvc]*
00406           observation[ii].H*observation[ii].weight;
00407         rmat+=observation[ii].rve*observation[ii].weight;
00408         //
00409         // At this point I am not sure if it is better to adjust
00410         // for prediction errors or leave it alone.
00411         // For "most" of the cases I typically run accross it is
00412         // probably not much of an issue.
00413         //
00414         
00415        }
00416        Lambda[k_vc]=(static_cast<double>(nr) - addj)*(wmat*rmat.inv()).trace();
00417 
00418      }
00419 
00420 
00421    }
00422    else{
00423      rmat.assign(0.0);
00424      for(ii=0;ii<numrec;ii++) {
00425        rmat+=observation[ii].rve*observation[ii].weight;
00426      }
00427      for(t1=0;t1<numtrait;t1++) for(t2=t1;t2<numtrait;t2++,k_vc++) {
00428        wmat.assign(0.0);
00429        for(ii=0;ii<numrec;ii++) {
00430         wmat+=SinMat[k_vc]*observation[ii].weight;
00431         
00432        }
00433        Lambda[k_vc]=(static_cast<double>(nr) - addj)*(wmat*rmat.inv()).trace();
00434      }
00435    }
00436 
00437    if(LR==2) glim();
00438    double dfe;
00439 
00440 
00441    // K'b-M
00442    for (i=0; i<nr; i++) kpb_m[i] = blupsol.inner_product(kpme[i]);
00443    if (M) for (i=0; i<nr; i++) kpb_m[i] -= M[i];
00444    double quq;
00445    if(LR!=1) {
00446      quq = kvk.quadratic(kpb_m,kpb_m);       // (K'b-m)'(K'(X'V-1X)-K)-1(K'b-m)
00447    }
00448    else{
00449      //    tmpsol=blupsol-((kvk*kpb_m)*kv); //tmpsol now contains the restricted solutions
00450      {
00451        //double *blupve;
00452        //blupve=blupsol.ve;
00453        //blupsol.ve=tmpsol.ve;
00454        glim(10,(double **)kpme,nr,nc,(double *)M);
00455        residual();
00456        quq= -like_val;
00457        //blupsol.ve=blupve;
00458        glim();
00459        residual();
00460        quq+=like_val;
00461        quq*=2.;
00462      }
00463    }
00464    double ssm,sse;
00465    unsigned rank_x;
00466    int degen = 0;
00467    int errcode = 0;
00468    double f_stat=0.0, prob=0.0,vart=0.0;
00469    double sigma_e = residual_var[0][0];
00470    int not_chisq = Info.num_rows();
00471    if(Asym) not_chisq=0;
00472 
00473    if(not_chisq) vart=Info.ginv0().quadratic(Lambda,Lambda);
00474    if (!not_chisq || vart <= EPSILON ) {
00475      f_stat = quq;
00476 
00477      prob = ChiSquare_cdf(f_stat,static_cast<double>(nr),0.0,errcode);
00478      f_stat /= static_cast<double>(nr);
00479      dfe=2000.;
00480    }
00481    else {
00482 
00483      dfe=(2.0*nr*nr)/vart;
00484      if(dfe < 1.) dfe=1.;
00485      if(dfe > 2000.) {
00486        dfe=2000.;
00487      }
00488      f_stat = (quq)/nr;
00489      // if(f_stat > 1000.) f_stat=1000.;
00490      prob = F_cdf(f_stat,static_cast<double>(nr),static_cast<double>(dfe),0.0,errcode);
00491 
00492      //   in univariate cases only: the estimated variance of estimator K'B
00493    }
00494    std::string raw_data_code;
00495    double p_value,var,tcal=0.0;
00496    int W = SESSION.output_precision;
00497    std::cout.precision(W);
00498    if(Print_Level < 0) Print_Flag=0;
00499    if (Print_Flag) {
00500      std::cout << "\n            RESULTS FROM CONTRAST(S)\n";
00501      std::cout << " ----------------------------------------------------------\n";
00502      std::cout << "  Contrast MME_addr    K_coef   Raw_data_code\n";
00503      std::cout << "  ---------------------------------------------\n";
00504    }
00505    for (i=0; i<nr; i++) {
00506      if (Print_Flag) {
00507        kp = kpme[i];
00508        for (j=0; j<nc; j++) {
00509         if (kp[j] == 0.0) continue;
00510         trait_effect_level(j,raw_data_code);
00511         std::cout << std::setw(4) << i+1 <<std::setw(11) << j+1 << std::setw(13) << kp[j]
00512              << "   " << raw_data_code << "\n";
00513        }
00514      }
00515      kpd = kpdiff[i];
00516      if (result) {
00517        result[i][0] = kpb_m[i];
00518        result[i][3] = kpd;
00519      }
00520      var = kvkori[i][i];
00521      if (var <= 0.0) throw exception("GLMM::contrast(): you have probably found a bug!");
00522      var = std::sqrt(var);
00523      //    std::cout << var << "                              \n";
00524      //    std::cout << kpb_m[i] << "      xxxxxx              \n";
00525      tcal = fabs(kpb_m[i]/var);
00526      //  std::cout << tcal << "  "<< dfe << "                               \n";
00527      p_value = 2.0*(1.0-t_cdf(tcal,static_cast<double>(dfe),0.0));
00528 
00529      if (result) {
00530        result[i][1] = var;
00531        result[i][2] = p_value;
00532      }
00533      if (!Print_Flag) continue;
00534      if (kpd > 1.0e-5) {
00535        est = 0;
00536        std::cout << "            **** NON-ESTIMABLE ****\n\n";
00537      }
00538      else {
00539        if (kpd > 1.0e-10) {
00540         std::cout << " ***WARNING***: it may or mayn't be estimable\n";
00541         std::cout << "       max(k'*ginv(mme)*mme - k') = " << kpd << "\n";
00542        }
00543        std::cout << "          estimated value (K'b-M) = " << kpb_m[i]
00544            << " +- " << var << "\n";
00545        std::cout << "             Prob(|t| > " << tcal << ") = "
00546            <<  p_value << " (p_value)\n";
00547        if(nr == 1 && not_chisq)
00548         std::cout << "             " << dfe << " (Error degrees of freedom)\n";
00549        if (i != nr-1) std::cout << "\n";
00550      }
00551    }
00552    if (Print_Flag || Print_Summary) {
00553      std::cout << " ----------------------------------------------------------\n";
00554      if ((nr > 1 || Print_Summary) && est) {
00555        std::cout << "   joint hypothesis test H: K'b = M\n";
00556        std::cout << "   Prob(F > " <<  f_stat << ") = "
00557            <<  1.0-prob << " (p_value)\n";
00558        if(not_chisq) std::cout << "  " << dfe << " (Error degrees of freedom)\n";
00559      }
00560 
00561    }
00562    if(Return_Stat) return f_stat;
00563    return 1.0-prob;   // p_value
00564  }
00565 
00566 
00567 
00568 
00569  //
00570  //
00571  //
00572 
00573  double GLMM::contrast(const Vector<double>& Kp,const double m)
00574  {
00575    ///////////////////////////////////////////
00576    // trailing zeros in K' can be omitted
00577    ///////////////////////////////////////////
00578         
00579    double retval, **kpme = new double *[1];
00580    kpme[0] = Kp.begin();
00581    unsigned nc = Kp.size();
00582    double* M = (double *)NULL;
00583    if (m != 0.0) {
00584      M = new double [1];
00585      M[0] = m;
00586    }
00587    retval = contrast((const double **)kpme,1,nc,M);
00588    delete [] kpme;
00589    if (M) delete [] M;
00590    return retval;
00591  }
00592 
00593  double GLMM::contrast(const doubleMatrix& Kp)
00594  {
00595    ///////////////////////////////////////////
00596    // trailing zeros in K' can be omitted
00597    ///////////////////////////////////////////
00598         
00599    return contrast((const double **)Kp.begin(), Kp.num_rows(), Kp.num_cols());
00600  }
00601 
00602  double GLMM::contrast(const doubleMatrix& Kp,const Vector<double>& M)
00603  {
00604    ///////////////////////////////////////////
00605    // trailing zeros in K' can be omitted 
00606    ///////////////////////////////////////////
00607         
00608 
00609    double retval = 0.0;
00610    int nr = Kp.num_rows();
00611    unsigned nc = Kp.num_cols();
00612    if (M.size() != nr ) throw exception(" GLMM::contrast: size is incomformable");
00613    Vector<double> fullsize_M(hmmesize);
00614    Matrix<double>fullsize_Kp(nr,hmmesize);
00615    for (unsigned i=0; i<nr; i++) {
00616      memcpy(fullsize_Kp[i],Kp[i], sizeof(double)*nc);
00617      }
00618      memcpy(fullsize_M.begin(),M.begin(), sizeof(double)*nc);
00619      retval=GLMM::contrast((const double **)fullsize_Kp.begin(),nr,hmmesize,fullsize_M.begin());
00620      return retval;
00621  }
00622 
00623  double GLMM::contrast(const std::string &termname,const doubleMatrix& Kp, const Vector<double>& M)
00624  {
00625    if (!(Kp.begin())) {
00626      warning("GLMM::contrast(kp): kp is null, thus it is ignored");
00627      return 0.0;
00628    }
00629 
00630    double retval = 0.0;
00631    if (!get_blupsol()) throw exception("GLMM::contrastranspose(): bad model");
00632 
00633    int k = term.index(termname,factor_struct);
00634    if (k < 0) {
00635      warning("GLMM::contrast(): no such term in the model");
00636      return retval;
00637    }
00638 
00639    unsigned nr = Kp.num_rows();
00640    unsigned nc = Kp.num_cols();
00641    if (M.size() != nr) {
00642      warning("GLMM::contrast(): unconformable size");
00643      return retval;
00644    }
00645    unsigned i,startaddr;
00646    int nt=nt_vec[k];
00647    if (nc <= term[k].nlevel()*nt) {
00648      startaddr = term[k].startaddr();
00649      Vector<double> fullsize_M(hmmesize);
00650      Matrix<double>fullsize_Kp(nr,hmmesize);
00651      for (i=0; i<nr; i++) {
00652        memcpy(&(fullsize_Kp[i][startaddr]),Kp[i], sizeof(double)*nc);
00653      }
00654      memcpy(&(fullsize_M[startaddr]),M.begin(), sizeof(double)*nc);
00655      retval=contrast((const double **)fullsize_Kp.begin(),nr,hmmesize,fullsize_M.begin());
00656    }
00657    else {
00658      warning("GLMM::contrast(%s,Kp): too many columns in Kp",termname.c_str());
00659    }
00660    return retval;
00661  }
00662 
00663  double GLMM::restricted_log_likelihood(int solve)
00664  {
00665    ////////////////////////////////////////////////////////////////////
00666    // it returns restricted log likelihood under this model with data D
00667    //  Important Notice:
00668    //  because  restricted_log_likelihood will be called sequentially
00669    //  under the same MME structure.
00670    //  hmmec is kept after restricted_log_likelihood(D) call.
00671    //  Call release_mme() to release hmmec from memory
00672    ////////////////////////////////////////////////////////////////////
00673                 
00674    if(!link_function) {
00675                 
00676      return(Model::restricted_log_likelihood());
00677    }
00678    int Need_PEV_orig=Need_PEV;
00679    Need_PEV=0;
00680    Need_Residual=1;
00681    setup_mme(&rellrhs);
00682    double rellhood = 0.0;
00683 
00684    SESSION.warning = 0;
00685    if(solve){
00686      hmmec.solve(blupsol,rellrhs,"ysmp1");
00687      //     Need_Residual=1;
00688      setup_mme(&rellrhs);
00689    }
00690    hmmec.factor();
00691    //hmmec.display_order();
00692    //rellhood=0.0;
00693    rellhood = hmmec.info_vec[0];
00694    //   SESSION.warning = 1;
00695    // std::cout << "\n relhood " << rellhood << " rank " <<hmmec.info_vec[1];
00696    SESSION.warning = 0;
00697 
00698 
00699    if(Use_Like)rellhood +=yry+like_adj;
00700    //std::cout << "\n yry " << yry << " like_adj " << like_adj;
00701    if(!Use_Like)rellhood += yry - blupsol.inner_product(rellrhs);
00702    unsigned i;
00703    int done_ped;
00704    done_ped=0;
00705    // for (i=0; i<npattern; i++) rellhood += double(kvec[i])*lnr0vec[i];
00706    for (i=0; i<numterm; i++) {
00707      if (term[i].classi() == 'R'){
00708        rellhood += lng0vec[i]*term[i].nlevel();
00709        //std::cout << "\n[" << i << "] n "<<term[i].nlevel() << " log|D|" << lng0vec[i];
00710      }
00711      else if (term[i].classi() =='P' && !done_ped) {
00712        // ainv();
00713        done_ped=1;
00714        //       build_CorrVar();
00715        rellhood += lng0vec[i]*double(popsize-numgroup);
00716        //       std::cout << "\n[" << i << "] n "<< (popsize-numgroup)<< " log|G|" << lng0vec[i] ;
00717        rellhood -= ldet*double(nt_vec[i]);
00718        //        std::cout << "|A| " << -double(nt_vec[i])*ldet <<"\n";;
00719      }
00720    }
00721    Need_PEV=Need_PEV_orig;
00722    return (-0.5*rellhood);
00723  }
00724 
00725 
00726 
00727 
00728  double GLMM::log_likelihood(int solve)
00729  {
00730    ////////////////////////////////////////////////////////////////////
00731    // it returns restricted log likelihood under this model with data D
00732    //  Important Notice:
00733    //  because  restricted_log_likelihood will be called sequentially
00734    //  under the same MME structure.
00735    //  hmmec is kept after restricted_log_likelihood(D) call.
00736    //  Call release_mme() to release hmmec from memory
00737    // Still need -.5ln|D^{-1}+Z'H'R^{-1}HZ|
00738    ////////////////////////////////////////////////////////////////////
00739 
00740    if(!link_function) {
00741 
00742      return(Model::restricted_log_likelihood());
00743    }
00744 
00745    Need_Residual=1;
00746    setup_mme(&rellrhs);
00747    double rellhood = 0.0;
00748 
00749    SESSION.warning = 0;
00750    if(solve){
00751      hmmec.solve(blupsol,rellrhs,"ysmp1");
00752      Need_Residual=1;
00753      setup_mme(&rellrhs);
00754    }
00755    //   hmmec.factor();
00756    //hmmec.display_order();
00757    rellhood=0.0;
00758    //rellhood = hmmec.info_vec[0];
00759    //   SESSION.warning = 1;
00760    //       std::cout << "\n relhood " << rellhood << " rank " <<hmmec.info_vec[1];
00761    SESSION.warning = 0;
00762 
00763 
00764    if(Use_Like)rellhood +=yry+like_adj;
00765    //std::cout << "\n yry " << yry << " like_adj " << like_adj;
00766    if(!Use_Like)rellhood += yry - blupsol.inner_product(rellrhs);
00767    unsigned i;
00768    int done_ped;
00769    done_ped=0;
00770    // for (i=0; i<npattern; i++) rellhood += double(kvec[i])*lnr0vec[i];
00771    for (i=0; i<numterm; i++) {
00772      if (term[i].classi() == 'R'){
00773        rellhood += lng0vec[i]*term[i].nlevel();
00774             //std::cout << "\n[" << i << "] n "<<term[i].nlevel() << " log|D|" << lng0vec[i];
00775      }
00776      else if (term[i].classi() =='P' && !done_ped) {
00777        done_ped=1;
00778        //build_CorrVar();
00779        rellhood += lng0vec[i]*double(popsize-numgroup);
00780             //std::cout << "\n[" << i << "] n "<< (popsize-numgroup)<< " log|G|" << CorrVar.logdet() << " CorrVar " << CorrVar;
00781        rellhood -= hainv.logdet()*double(act_numtrait);
00782            //std::cout << "|A| " << -double(act_numtrait)*hainv.logdet() <<"\n";;
00783      }
00784    }
00785    return (-0.5*rellhood);
00786  }
00787 
00788  #ifdef GLMM_QUAD
00789  extern int ysmp_solve(int n,int *iiv,int *jjv,double *aav,int *p,int *ip,int nsp,
00790                       double *rsp,const double *b, double *z,double tol,int& irank,
00791                       double& lgdet,int path1,int path2);
00792 
00793  double GLMM::quad(double *x, double *y, double *xsol, double *ysol,  int path){
00794    ////
00795    //
00796    // calculates x`Cy
00797    // path = 3 return x`Cy,  Du`y in ysol, and ux in xsol
00798    // path = 1 return Du`y in ysol
00799    // path = 2 given Du`y in ysol, return x`Cy and ux in xsol
00800    //
00801    ///
00802                 
00803    double xCy,ldet;
00804    int path1,path2,ir;
00805    xCy=0;
00806    if(!hmmec.perm) hmmec.factorization();
00807    path1=0;
00808    if(path & 1){
00809      path2=13;
00810      ysmp_solve(hmmec.dim,hmmec.iiv,hmmec.jjv,hmmec.aav,
00811                hmmec.perm,hmmec.iperm,hmmec.nsp,hmmec.rsp,y,ysol,
00812                EPSILON,ir,ldet,path1,path2);
00813    }
00814    if(path & 2){
00815      path2=23;
00816      ysmp_solve(hmmec.dim,hmmec.iiv,hmmec.jjv,hmmec.aav,
00817                hmmec.perm,hmmec.iperm,hmmec.nsp,hmmec.rsp,x,xsol,
00818                EPSILON,ir,ldet,path1,path2);
00819      for(int i=0;i< hmmec.dim;i++) xCy += xsol[i]*ysol[i];
00820    }
00821    return(xCy);
00822 
00823  }
00824  #endif
00825 
00826   ////////////////////////////////////////////////////////////
00827   //KP function
00828   //March 1998, University of Nebraska
00829   //Copyright (C) 1998 Roger Collins
00830   /////////////////////////////////////////////////////////////
00831 
00832  doubleMatrix *KP( Data *D,doubleMatrix &SKM_ans,const std::string &lpl,const std::string &censor){
00833 
00834    // 0=censored 1=uncensored;
00835    doubleMatrix ret,*retpt;
00836    doubleMatrix SKM;
00837    int ny;
00838    ny=D->num_rows();
00839    doubleMatrix lpl_mat;
00840    lpl_mat.resize(ny,2);
00841    int lpl_col;
00842    if(-1 ==(lpl_col=D->field_index(lpl))) {
00843      warning("KP: Can't find lpl %s \n",lpl.c_str());
00844      return(NULL);
00845    }
00846    for(int i=0;i<ny;i++){
00847      lpl_mat[i][0]=D->datasheet[lpl_col][i].double_val();
00848    }
00849    int status_col;
00850    if(-1 ==(status_col=D->field_index(censor))) {
00851      warning("KP: Can't find status %s \n",censor.c_str());
00852      return(NULL);
00853    };
00854    for(int i=0;i<ny;i++){
00855      lpl_mat[i][1]=D->datasheet[status_col][i].double_val();
00856      // std::cout << i << " " << lpl_mat[i][0] << " " << lpl_mat[i][1] << endl;
00857    }
00858    lpl_mat.sortby(Matrix<double>::COLUMN,0);
00859    // std::cout << "\n  Input doubleMatrix col 1 = time  col 2: 0=censored 1=uncensored " << lpl_mat;
00860    int j;
00861    float numdead;
00862    float numcensored;
00863    float lagdead;
00864    float lagcensored;
00865    doubleMatrix skm_dead;
00866    skm_dead.resize(ny,3);
00867    j=0;
00868    lagdead=0.;
00869    lagcensored=0.;
00870    for(int i=0;i<ny;i++){
00871      if(i < ny-1 && lpl_mat[i][0] == lpl_mat[i+1][0]){
00872        if(lpl_mat[i][1]==1){
00873         lagdead++;
00874        }
00875        if(lpl_mat[i][1]==0){
00876         lagcensored++;
00877        }
00878      }
00879      else{
00880        if(lpl_mat[i][1]==1){
00881         numdead=1.+lagdead;
00882         numcensored=lagcensored;
00883         lagdead=0.;
00884         lagcensored=0.;
00885         skm_dead[j][0]=lpl_mat[i][0];
00886         skm_dead[j][1]=numdead;
00887         skm_dead[j][2]=numcensored;
00888         j++;
00889        }
00890        if(lpl_mat[i][1]==0.){
00891         numdead=lagdead;
00892         numcensored=1.+lagcensored;
00893         lagdead=0.;
00894         lagcensored=0.;
00895         skm_dead[j][0]=lpl_mat[i][0];
00896         skm_dead[j][1]=numdead;
00897         skm_dead[j][2]=numcensored;
00898         j++;
00899        }
00900      }
00901    }
00902    //std::cout << "\n SKM dead vector = " << skm_dead;
00903    skm_dead=skm_dead.submat(0,0,j,3);
00904    //std::cout << "\n SKM dead vector = " << skm_dead;
00905 
00906 
00907    //doubleMatrix SKM;
00908    SKM.resize(j+1,3);
00909    float tot_alive;
00910    tot_alive=ny;
00911    int k;
00912    k=0;
00913    for(int i=0;i<j+1;i++){
00914      if(i == 0){
00915        SKM[k][0]=0.;
00916        SKM[k][1]=1.;
00917        k++;
00918      }
00919      if(i > 0 && skm_dead[i-1][1] != 0.){
00920        SKM[k][0]=skm_dead[i-1][0];
00921        SKM[k][1]=SKM[k-1][1]*(1.-(skm_dead[i-1][1]/tot_alive));
00922        SKM[k-1][2]=SKM[k][1]/SKM[k-1][1];
00923        SKM[k-1][2]/=SKM[k][0]-SKM[k-1][0];
00924        tot_alive=tot_alive-(skm_dead[i-1][1]+skm_dead[i-1][2]);
00925        k++;
00926      }
00927      if(i > 0 && skm_dead[i-1][1] == 0.){
00928        tot_alive=tot_alive-(skm_dead[i-1][1]+skm_dead[i-1][2]);
00929      }
00930    }
00931    SKM[k-1][2]=SKM[k-2][2];
00932    //for(int ii=0;ii<k;ii++) cout << SKM[ii][0] << " " << SKM[ii][1] << " " << SKM[ii][2] <<endl;
00933    SKM_ans=SKM.submat(0,0,k,3);
00934    return(&SKM_ans);
00935 
00936 
00937  }
00938 
00939 
00940 
00941 
00942  void GLMM::add_G_Sand(void)
00943  {
00944    for (int t=0; t<numterm; t++) {
00945      if (term[t].classi() == 'P') {
00946        add_AgSand(t);
00947      }
00948      else if (term[t].classi() == 'R') {
00949        add_IgSand(t);
00950      }
00951    }
00952  }
00953 
00954  void GLMM::add_IgSand(int t)
00955  {
00956    unsigned k,i,ii,jj;
00957    int t1,t2;
00958    double **v = (double **)NULL;
00959    doubleMatrix *tmp = term[t].prior->var_matrix();
00960    if (!tmp) throw exception("Model::add_Ig():  you probably forgot to use M.variance(...)\n"
00961           "  to set variance for each random effect");
00962    v = tmp->begin();
00963    Matrix<double> rv(numtrait,numtrait);
00964    for (t1=0; t1<numtrait; t1++) {
00965      for(t2=0; t2<numtrait; t2++) rv[t1][t2]=v[t1][t2];
00966    }
00967    ginverse1(rv.begin(),numtrait,lng0vec[t],1,EPSILON);
00968 
00969    unsigned na = term[t].nlevel();
00970    unsigned startaddr = term[t].start + 1;
00971    for (k=0; k<na; k++) {
00972      i = startaddr + k*numtrait;
00973      for (t1=0; t1<numtrait; t1++) {
00974        ii = i + t1;
00975        for (t2=0; t2<numtrait; t2++) {
00976         jj = i + t2;
00977         if (jj>=ii) hSand.insert(ii,jj,rv[t1][t2]);
00978        }
00979      }
00980    }
00981  }
00982 
00983 
00984 
00985  void GLMM::add_Ag(int t,int ct)
00986  {
00987    unsigned t1, t2, k, i, j, ii, jj, iii, jjj;
00988    double dii,val,value;
00989    double **var = (double **)NULL;
00990    var = corrvar[t][ct].begin();
00991    Matrix<double> rvarg(numtrait,numtrait);
00992    for (i=0; i<numtrait;i++) for (j=0; j<numtrait; j++) rvarg[i][j]= var[i][j];
00993    ginverse1(rvarg.begin(),numtrait,lng0vec[t],1,EPSILON);
00994 
00995    Matrix<double> lambda(3,3);
00996    getlambda(lambda.begin(),3);
00997    unsigned startaddr = term[t].start + 1;
00998    unsigned startaddrct = term[ct].start + 1;
00999    unsigned asd[3];
01000    Individual *I;
01001    if(startaddr > startaddrct){
01002      jjj=startaddr;
01003      startaddr =startaddrct;
01004      startaddrct=jjj;
01005    }
01006    for (k=0; k<popsize; k++) {
01007      I = pop->member(k);
01008      asd[0] = I->id(); asd[1] = I->father_id(); asd[2] = I->mother_id();
01009      dii = 4.0/(2.0 - I->father_inbcoef() - I->mother_inbcoef());
01010 
01011      for (i=0; i<3; i++) {
01012        if (asd[i] != 0) {
01013         ii = startaddr + (asd[i]-1)*numtrait;
01014         for (j=0; j<3; j++) {
01015           if (asd[j] != 0) {
01016             jj = startaddrct + (asd[j]-1)*numtrait;
01017             val = lambda[i][j]* dii;
01018             for (t1=0; t1<numtrait; t1++) {
01019               iii = ii + t1;
01020               for (t2=0; t2<numtrait; t2++) {
01021                 jjj = jj + t2;
01022                 if (jjj>=iii) {
01023                   value = val*rvarg[t1][t2];
01024                   hmmec.insert(iii,jjj,value);
01025                 }
01026               }
01027             }
01028           }
01029         }
01030        }
01031      }
01032    }
01033  }
01034 
01035 
01036  void GLMM::add_AgSand(int t)
01037  {
01038    unsigned t1, t2, k, i, j, ii, jj, iii, jjj;
01039    double dii,val,value;
01040    double **var = (double **)NULL;
01041    doubleMatrix *tmp = term[t].prior->var_matrix();
01042    if (!tmp) throw exception("Model::add_Ag():  you probably forgot to use M.variance(...)\n"
01043           "  to set variance for each random effect");
01044    var = tmp->begin();
01045    Matrix<double> rvarg(numtrait,numtrait);
01046    for (i=0; i<numtrait;i++) for (j=0; j<numtrait; j++) rvarg[i][j]= var[i][j];
01047    ginverse1(rvarg.begin(),numtrait,lng0vec[t],1,EPSILON);
01048 
01049    Matrix<double> lambda(3,3);
01050    getlambda(lambda.begin(),3);
01051    unsigned startaddr = term[t].start + 1;
01052    unsigned asd[3];
01053    Individual *I;
01054 
01055    for (k=0; k<popsize; k++) {
01056      I = pop->member(k);
01057      asd[0] = I->id(); asd[1] = I->father_id(); asd[2] = I->mother_id();
01058      dii = 4.0/(2.0 - I->father_inbcoef() - I->mother_inbcoef());
01059 
01060      for (i=0; i<3; i++) {
01061        if (asd[i] != 0) {
01062         ii = startaddr + (asd[i]-1)*numtrait;
01063         for (j=0; j<3; j++) {
01064           if (asd[j] != 0) {
01065             jj = startaddr + (asd[j]-1)*numtrait;
01066             val = lambda[i][j]* dii;
01067             for (t1=0; t1<numtrait; t1++) {
01068               iii = ii + t1;
01069               for (t2=0; t2<numtrait; t2++) {
01070                 jjj = jj + t2;
01071                 if (jjj>=iii) {
01072                   value = val*rvarg[t1][t2];
01073                   hSand.insert(iii,jjj,value);
01074                 }
01075               }
01076             }
01077           }
01078         }
01079        }
01080      }
01081    }
01082  }
01083 
01084  doubleMatrix operator*(Vector<double> &a,Vector<double> &b)
01085  {
01086    int row,col;
01087    row=a.size();
01088    col=b.size();
01089    doubleMatrix temp(row,col);
01090    for(int i=0;i<row;i++) {
01091      for(int j=0;j<col;j++) {
01092        temp[i][j]=a[i]*b[j];
01093      }
01094    }
01095    return temp;
01096  }
01097 
01098  void GLMM::covariance_old(const std::string &termname,const std::string &termname2,const doubleMatrix& v)
01099    // **********************************************************************
01100    // * covariance is the method to get variance components for each random
01101    // * effect.
01102    // *********************************************************************
01103  {
01104    if (!factor_struct) throw exception("Model::variance(args): no equation(s) in the model");
01105 
01106    int k = term.index(termname,factor_struct);
01107    int k2 = term.index(termname2,factor_struct);
01108    if(k2<k) {
01109      int kt=k;
01110      k=k2;
01111      k2=kt;
01112    }
01113    if ( k < 0) {
01114      warning("GLMM::covariance(): %s: not in the model",termname.c_str());
01115      type = bad_model;
01116      return;
01117    }
01118    if ( k2< 0) {
01119      warning("GLMM::covariance(): %s: not in the model",termname2.c_str());
01120      type = bad_model;
01121      return;
01122    }
01123    if (term[k].classi() != 'P')   {
01124      warning("GLMM::covariance(): %s: no associated Pedigree",termname.c_str());
01125      type = bad_model;
01126      return;
01127    }          // factor classi will override
01128    if (term[k2].classi() != 'P')  {
01129      warning("GLMM::covariance(): %s: no associated Pedigree",termname2.c_str());
01130      type = bad_model;
01131      return;
01132    }                  // factor classi will override
01133    if(!corrmap[k]) {
01134      corrmap[k]=1;
01135      ncorr++;
01136    }
01137    if(!corrmap[k2]) {
01138      corrmap[k2]=1;
01139      ncorr++;
01140    }
01141    if (v.num_rows() == v.num_cols() && v.num_rows() == numtrait) {
01142        corrvar[k][k2]=v;
01143    }
01144    else {
01145      warning("Model::variance(): invalid variance matrix size");
01146      type = bad_model;
01147    }
01148  }
01149 
01150 
01151  void GLMM::build_CorrVar(void) {
01152    CorrVar.resize(act_numtrait,act_numtrait);
01153    int ipos,jpos,i,j;
01154    doubleMatrix *var;
01155    Matrix<int> posmat(numterm,act_numtrait);
01156    for(i=0,ipos=0;i<numterm;i++) {
01157     if(term[i].classi() == 'P' && corrmap[i]==0) {
01158       corrmap[i]=1;
01159       ncorr++;
01160     }
01161      if(corrmap[i]) {
01162        for(int t=0;t<numtrait;t++) {
01163         posmat[i][t]=ipos++;
01164        }
01165      }
01166    }
01167    for(i=0;i<numterm;i++) {
01168      if(corrmap[i]) {
01169        var = term[i].prior->var_matrix();
01170        for(int t1=0;t1<numtrait;t1++) {
01171         for(int t2=0;t2<numtrait;t2++) {
01172           CorrVar[posmat[i][t1]][posmat[i][t2]]=(*var)[t1][t2];
01173         }
01174        }
01175        for(j=(i+1);j<numterm;j++) {
01176         if(corrmap[j]) {
01177           var = &corrvar[i][j];
01178           for(int t1=0;t1<numtrait;t1++) {
01179             for(int t2=0;t2<numtrait;t2++) {
01180               CorrVar[posmat[i][t1]][posmat[j][t2]]=(*var)[t1][t2];
01181               CorrVar[posmat[j][t2]][posmat[i][t1]]=(*var)[t1][t2];
01182             }
01183           }
01184         }
01185        }
01186      }
01187    }
01188  }
01189 
01190  void GLMM::add_G_1_old(void)
01191  {
01192    int done_ped=0;
01193     for (int t=0; t<numterm; t++) {
01194        if (term[t].classi() == 'P' && !done_ped) {
01195         done_ped=1;
01196         Model::add_Ag(t);
01197        }
01198        else if (term[t].classi() == 'R') {
01199           Model::add_Ig(t);
01200        }
01201     }
01202  }
01203 
01204 
01205  void GLMM::add_Ag_old(int t)
01206  {
01207     unsigned t1, t2, k, i, j, ii, jj, iii, jjj,icnt;
01208     double dii,val,value;
01209     double **var = (double **)NULL;
01210     Vector<int> tmap;
01211     build_CorrVar();
01212     tmap.resize(act_numtrait);
01213     icnt=0;
01214     for(i=t;i<numterm;i++){
01215       if(term[i].classi()=='P') {
01216         for(j=0;j<numtrait;j++,icnt++){
01217           tmap[icnt]=i;
01218         }
01219       }
01220     }
01221     //    std::cout <<tmap;
01222     doubleMatrix *tmp = &CorrVar;
01223     if (!tmp) throw exception("Model::add_Ag():  you probably forgot to use M.variance(...)\n"
01224              "  to set variance for each random effect");
01225     var = tmp->begin();
01226     Matrix<double> rvarg(act_numtrait,act_numtrait);
01227     for (i=0; i<act_numtrait;i++) for (j=0; j<act_numtrait; j++) rvarg[i][j]= var[i][j];
01228 
01229     ginverse1(rvarg.begin(),act_numtrait,lng0vec[t],1,EPSILON);
01230 
01231 
01232     double f1,f2;
01233     Matrix<double> lambda(3,3);
01234     getlambda(lambda.begin(),3);
01235     unsigned startaddr = term[t].start + 1;
01236     unsigned asd[3];
01237     Individual *I;
01238     unsigned nanim=popsize-numgroup;
01239     for (k=0; k<nanim; k++) {
01240        I = pop->member(k);
01241        asd[0] = I->id(); asd[1] = I->father_id(); asd[2] = I->mother_id();
01242        f1= I->father_inbcoef() ;
01243        f2= I->mother_inbcoef();
01244        if(asd[1]> nanim) f1=-1.;
01245        if(asd[2]> nanim) f2=-1.;
01246        dii = 4.0/(2.0 -f1-f2);
01247 
01248        for (i=0; i<3; i++) {
01249           if (asd[i] != 0) {
01250              ii = startaddr + (asd[i]-1)*act_numtrait;
01251              for (j=0; j<3; j++) {
01252                 if (asd[j] != 0) {
01253                    jj = startaddr + (asd[j]-1)*act_numtrait;
01254                    val = lambda[i][j]* dii;
01255                    for (t1=0; t1<act_numtrait; t1++) {
01256                       iii = ii + t1;
01257                       for (t2=0; t2<act_numtrait; t2++) {
01258                          jjj = jj + t2;
01259                          if (jjj>=iii) {
01260                             value = val*rvarg[t1][t2];
01261                             //if(term[tmap[t1]].trait[t1%numtrait] && term[tmap[t2]].trait[t2%numtrait])
01262                               hmmec.insert(iii,jjj,value);
01263                          }
01264                       }
01265                    }
01266                 }
01267              }
01268           }
01269        }
01270     }
01271  }
01272 
01273 
01274 
01275  void
01276  bound_pd (double *varnew, int numtrait, doubleMatrix & P)
01277  {
01278    int i, j, k, t1, t2;
01279    doubleMatrix varbound (numtrait, numtrait);
01280    Vector<double> eig, flg;
01281    flg.resize (numtrait);
01282    for (k = 0, i = 0; i < numtrait; i++)
01283      for (j = i; j < numtrait; j++, k++)
01284        {
01285         varbound[i][j] = varnew[k];
01286         varbound[j][i] = varnew[k];
01287        }
01288    P = varbound;
01289 
01290    eig = P.eigen ();
01291 
01292    for (t1 = 0; t1 < numtrait; t1++)
01293      {
01294        flg[t1] = 0;
01295        if (eig[t1] < 1.e-3)
01296         {
01297           eig[t1] = .99e-3;
01298           flg[t1] = 1;
01299         }
01300        if (eig[t1] > 1.e10)
01301         {
01302           eig[t1] = 1.01e10;
01303           flg[t1] = 0;
01304         }
01305      }
01306    varbound = P * diag(eig) * P.transpose();
01307    for (t1 = 0; t1 < numtrait; t1++)
01308      {
01309        if (flg[t1])
01310         {
01311           for (t2 = 0; t2 < numtrait; t2++)
01312             {
01313               P[t1][t2] = 0;
01314             }
01315         }
01316      }
01317 
01318    for (k = 0, t1 = 0; t1 < numtrait; t1++)
01319      for (t2 = t1; t2 < numtrait; t2++, k++)
01320        {
01321         varnew[k] = varbound[t1][t2];
01322 
01323        }
01324  }
01325 
01326  void GLMM::info(std::ostream& stream)
01327  {
01328     if (type == bad_model) {
01329        warning("Model::info(stream): model is too bad");
01330        return;
01331     }
01332     stream.precision(SESSION.output_precision);
01333     stream <<"\n             some extra information in the model\n";
01334     stream << " --------------------------------------------------------\n";
01335     if (dfreml_called) {
01336        stream << "optimizor used in dfreml = " << dfreml_method <<"\n";
01337        stream <<"# of function evaluations used in dfreml = "
01338               << nfunk_in_dfreml<<"\n";
01339        stream << "maximum log restricted likelihood in dfreml = "
01340               <<  reml_value <<"\n";
01341     }
01342     else {
01343        ;
01344     }
01345     if(aireml_called){
01346       stream << "AI REML ";
01347       if(aireml_called < 0) stream << "failed to converge\n";
01348       else stream << "converged\n";
01349       stream << "maximum log restricted likelihood = "
01350               <<  restricted_log_likelihood(0) <<"\n";
01351     }
01352     const ModelTerm *T;
01353     int i,done_ped,nt;
01354     doubleMatrix *var;
01355     done_ped=0;
01356     for (i=0; i<numterm; i++) {
01357        T = &(term(i));
01358        if (T->classi() == 'R' || (T->classi() == 'P' && !done_ped)) {
01359         nt=nt_vec[i];
01360         var=T->prior->var_matrix();
01361         //if(T->classi() == 'P') {
01362         //  nt=act_numtrait;
01363         //  done_ped=1;
01364         //  build_CorrVar();
01365         //  var=&CorrVar;
01366         //}
01367           stream << " variance for "
01368                  << factor_struct[T->factorindx[0]].name() << " = \n"
01369                  << (*var);
01370        }
01371     }
01372     stream << " residual variance =\n" << residual_var;
01373 
01374     if (data_prepared) {
01375        stream << "\n";
01376        stream << " MME dimension   : " << hmmesize << "\n";
01377        stream << " non-zeros in MME: " << hmmec.nz() << "\n\n";
01378 
01379        stream << "       basic statistics for dependent variables\n";
01380        stream << "  -----------------------------------------------------\n";
01381        stream << "      trait-name         n          mean         std\n";
01382        unsigned n;
01383        for (i=0; i<numtrait; i++) {
01384         // std::cout <<"\n i= " << i << "\n";
01385           n = trait_struct[i]->nlevel();
01386           stream << " " << std::setw(16) << trait_struct[i]->name()
01387                  << " " << std::setw(10) << n
01388                  << " " << std::setw(12) << trait_struct[i]->mean();
01389           if (n==1) {
01390              stream << " " << std::setw(12) << "." << "\n";
01391           }
01392           else {
01393              stream<< " " << std::setw(12) << trait_struct[i]->std() << "\n";
01394           }
01395        }
01396     }
01397     stream << " --------------------------------------------------------\n";
01398  }
01399 
01400 
01401 
01402  void GLMM::save(const std::string &fname, const int io_mode)
01403  {
01404     if (type == bad_model) {
01405        warning("Model::save(): model is too bad, nothing is saved");
01406        return;
01407     }
01408     if((numterm+ntermGdist) == 0) return;
01409     if (blupsol.size() != hmmesize + ntermGdist*popsize) return;
01410     if (!data) {
01411        warning("Model::save(): no data has been fitted");
01412        return;
01413     }
01414     std::ofstream ofs;
01415     ofs.open(fname.c_str(),(OpenModeType)io_mode);
01416     if (!ofs) throw exception("Model::save(): cann't open or already exit");
01417     ofs.setf(std::ios::unitbuf | std::ios::showpoint);
01418     ofs.precision(SESSION.output_precision);
01419     int W = SESSION.output_precision + 6;        // 6 = +.e+00
01420     char S = ' ';                               // one blank space
01421 
01422     if (!data->in_memory()) data->input_datasheet();
01423     this->info(ofs);
01424 
01425     double *ve = blupsol.begin();
01426 
01427     char* tempstr;
01428     int nord, *tempval;
01429     unsigned *tempuns;
01430     unsigned i,j,t,k,ii,kk,jj,nlevel,total_numterm;
01431     char CL;
01432 
01433     ofs << "\n            BLUP (BLUE, Posterior_Mean) \n";
01434     ofs << "    ----------------------------------------------- \n\n";
01435     total_numterm = numterm+ntermGdist;
01436     for (i=0; i<total_numterm; i++) {
01437        ofs << S << std::setw(W)<< "Term";
01438        for (t=0; t<numtrait; t++) {
01439           ofs << S << std::setw(W-2) << "Trait" << S << std::setw(2) << t+1;
01440        }
01441        ofs <<"\n";
01442 
01443        ofs << S << std::setw(W) << factor_struct[term[i].factorindx[0]].name();
01444        for (t=1; t<term[i].order(); t++) {
01445           ofs << "*" << factor_struct[term[i].factorindx[t]].name();
01446        }
01447        for (t=0; t<numtrait; t++) ofs <<S <<std::setw(W)<<trait_struct[t]->name();
01448        ofs << "\n";
01449        nlevel = term[i].nlevel();
01450        k = term[i].startaddr();
01451        nord = term[i].order();
01452        if (nord == 1) {      // single_factor_term
01453           kk = factor_struct[term[i].factorindx[0]].index();
01454           CL = data->datasheet[kk].classi();
01455           switch(CL) {
01456              case 'F':
01457                 for (j=0; j<nlevel; j++) {
01458                    tempval = (int *)(idlist[kk]->find(j+1));
01459                    ofs << S << std::setw(W) << *tempval;
01460                    for (t=0; t<numtrait; t++,k++) {
01461                       ofs << S << std::setw(W);
01462                       if (term[i].trait[t]) {
01463                          ofs << ve[k];
01464                       }
01465                       else {
01466                          ofs << S;
01467                       }
01468                    }
01469                    k+=(nt_vec[base_effect[i]]-numtrait);
01470                    ofs << "\n";
01471                 }
01472                 break;
01473              case 'U':
01474                 for (j=0; j<nlevel; j++) {
01475                    tempstr = (char *)(idlist[kk]->find(j+1));
01476                    ofs << S << std::setw(W) << tempstr;
01477                    for (t=0; t<numtrait; t++,k++) {
01478                       ofs << S << std::setw(W);
01479                       if (term[i].trait[t]) {
01480                          ofs << ve[k];
01481                       }
01482                       else {
01483                          ofs << S;
01484                       }
01485                    }
01486                    ofs << "\n";
01487                 }
01488                 break;
01489              case 'P':
01490                 for (j=0; j<nlevel; j++) {
01491                    ofs << S;
01492                    if (pop->maxnamelen > 0) {
01493                       ofs << std::setw(W) << (char *)pop->hashtable.find(j+1);
01494                    }
01495                    else {
01496                       ofs << std::setw(W) << j+1;
01497                    }
01498                    for (t=0; t<numtrait; t++,k++) {
01499                       ofs << S;
01500                       if (term[i].trait[t]) {
01501                          ofs << std::setw(W) << ve[k];
01502                       }
01503                       else {
01504                          ofs << std::setw(W) << S;
01505                       }
01506                    }
01507                   k+=(nt_vec[base_effect[i]]-numtrait);
01508                    ofs << "\n";
01509                 }
01510                 break;
01511              case 'C':
01512                 ofs << S << std::setw(W) << data->datasheet[kk].name();
01513                 for (t=0; t<numtrait; t++,k++) {
01514                    ofs << S << std::setw(W);
01515                    if (term[i].trait[t]) {
01516                       ofs << ve[k];
01517                    }
01518                    else {
01519                       ofs << S;
01520                    }
01521                 }
01522                 ofs << "\n";
01523                 break;
01524              case 'I':
01525                 ofs << S << std::setw(W) << "1";
01526                 for (t=0; t<numtrait; t++,k++) {
01527                    ofs << S << std::setw(W);
01528                    if (term[i].trait[t]) {
01529                       ofs << ve[k];
01530                    }
01531                    else {
01532                       ofs << S;
01533                    }
01534                 }
01535                 ofs << "\n";
01536                 break;
01537              default:
01538                 warning("Model.save(): unknown column type: %c",CL);
01539                 break;
01540           }
01541           if (i+1 < total_numterm) ofs << "\n";
01542        }
01543        else {     // there are interactions
01544           for (j=0; j<nlevel; j++) {
01545              tempuns = (unsigned *)(xact_htable[i].find(j+1));
01546              kk = factor_struct[term[i].factorindx[0]].index();
01547              CL = data->datasheet[kk].classi();
01548              jj = tempuns[0];
01549 
01550              if (CL == 'F') {
01551                 tempval = (int *)(idlist[kk]->find(jj));
01552                 ofs << S << std::setw(W) << *tempval;
01553              }
01554              else if (CL =='U') {
01555                 tempstr = (char *)(idlist[kk]->find(jj));
01556                 ofs << S << std::setw(W) << tempstr;
01557              }
01558              else if ( CL =='C') {
01559                 ofs << S << std::setw(W) << data->datasheet[kk].name();
01560              }
01561              else if (CL =='P') {
01562                 ofs << S << std::setw(W) << (char *)pop->hashtable.find(jj);
01563              }
01564              else if (CL =='I') {
01565                 ofs << S << std::setw(W) << "1";
01566              }
01567              else {
01568                 warning("Model::save(): unknown column type: %c",CL);
01569                 break;
01570              }
01571 
01572              for (ii=1; ii<nord; ii++) {
01573                 kk = factor_struct[term[i].factorindx[ii]].index();
01574                 CL = data->datasheet[kk].classi();
01575                 jj = tempuns[ii];
01576 
01577                 if (CL == 'F') {
01578                    tempval = (int *)(idlist[kk]->find(jj));
01579                    ofs << "*" << *tempval;
01580                 }
01581                 else if (CL =='U') {
01582                    tempstr = (char *)(idlist[kk]->find(jj));
01583                    ofs << "*" << tempstr;
01584                 }
01585                 else if (CL =='C' || CL =='I') {
01586                    ofs << "*" << data->datasheet[kk].name();
01587                 }
01588                 else if (CL =='P') {
01589                    ofs << "*" << (char *)pop->hashtable.find(jj);
01590                 }
01591                 else {
01592                   warning("Model::save(): unknown column type: %c",CL);
01593                 }
01594              }
01595              for (t=0; t<numtrait; t++,k++) {
01596                 ofs << S << std::setw(W);
01597                 if (term[i].trait[t]) ofs << ve[k];
01598                 else ofs << S;
01599              }
01600              //if(CL == 'P' || CL=='F') 
01601               k+=(nt_vec[base_effect[i]]-numtrait);
01602              ofs << "\n";
01603           }
01604           if (i+1 < total_numterm) ofs << "\n";
01605        }
01606     }
01607     ofs.close();
01608     if(!data_static) data->release_datasheet();
01609  }
01610 
01611  static int squeeze(unsigned len,int *ia,int *ja,double *a)
01612  /*******************************************************************
01613         squeeze out zeros from (ia,ja,a)        Tianlin Wang at UIUC
01614         ia(1...len),jjv(1..len),a(1..len)
01615         return the actural number of non-zeros in a
01616          "actually this moves the nonzeros to the begining"
01617  *******************************************************************/
01618  {
01619     unsigned lmar = 1;
01620     unsigned rmar = len;
01621     for (;;) {
01622        if (lmar >= rmar) {
01623           if (ia[lmar] == 0 && rmar == lmar) return(rmar-1);
01624           else return(rmar);
01625        }
01626        if ( ia[lmar] != 0) {
01627           lmar++;
01628        }
01629        else if (ia[rmar] == 0) {
01630           rmar--;
01631        }
01632        else {
01633           ia[lmar] = ia[rmar];
01634           ja[lmar] = ja[rmar];
01635           a[lmar]  = a[rmar];
01636           lmar++;
01637           rmar--;
01638        }
01639     }
01640  }
01641 
01642  static void hsort_ija(unsigned n,int *ia,int *ja,double *a)
01643  /******************************************************************
01644         this is a Heap sort, sorting (ia,ja) ascendingly
01645         ia(1...n), ja(1...n) ,a(1..n)
01646         where n is the actual number of non-zeros in A
01647  **********************************************************************/
01648  {
01649     unsigned iia, jja,i,j,l,ir;
01650     double aa;
01651     if (n == 1) return;
01652     l = (n >> 1)+1;             /* l = n/2+1; */
01653     ir=n;
01654     for (;;) {
01655        if (l > 1) {
01656           l = l-1;  iia = ia[l];  jja = ja[l];  aa = a[l];
01657 
01658        }
01659        else {
01660           iia = ia[ir];  jja = ja[ir];  aa = a[ir];
01661           ia[ir] = ia[1]; ja[ir] = ja[1];  a[ir] = a[1];
01662           ir--;
01663           if(ir == 1) {
01664              ia[1] = iia;  ja[1] = jja;  a[1] = aa;
01665              return;
01666           }
01667        }
01668        i=l;
01669        j=l+l;
01670        while ( j <= ir) {
01671           if (j < ir) {
01672              if (ia[j]<ia[j+1]  || (ia[j]==ia[j+1] && ja[j] < ja[j+1])) j++;
01673           }
01674           if (iia < ia[j] || (iia == ia[j] && jja < ja[j])) {
01675              ia[i] = ia[j];  ja[i] = ja[j];  a[i] = a[j];
01676              i=j;
01677              j=j+j;
01678           }
01679           else {
01680              j=ir+1;
01681           }
01682        }
01683        ia[i] = iia;  ja[i] = jja;  a[i] = aa;
01684     }
01685  }
01686 
01687  #ifdef DO_THREADS
01688  #include "pt.h"
01689 
01690  struct thread_arg {
01691    SparseMatrix *A,*Ainv;
01692    unsigned *rowdone,*order,hmmesize;
01693    int *ia,*ja,*lhs_ia,*lhs_ja;
01694    pthread_mutex_t *mdone_mutex;
01695  };
01696 
01697 
01698  int nextrow(int *lhs_ia,int *lhs_ja,unsigned *rowdone,pthread_mutex_t *mdone_mutex,int hmmesize, int i,unsigned *order,SparseMatrix *hInv,Vector<double> &InvCol) {
01699    int res;
01700 
01701    pt_mutex_lock(mdone_mutex,"mutex lck");     /* lock the mutex      */
01702    if(i) {
01703      for(int jj=lhs_ia[i];jj<lhs_ia[i+1];jj++) {
01704        // std::cout << i<< " " << jj << " "<< lhs_ja[jj] << "\n";
01705        hInv->insert(order[i-1],order[lhs_ja[jj]-1],InvCol[order[lhs_ja[jj]-1]-1]);
01706      }
01707    }
01708    *rowdone=(*rowdone)+1;
01709    res=*rowdone;                                 /* get & incr row cntr */
01710    pt_mutex_unlock(mdone_mutex,"mutex unlck"); /* unlock the mutex    */
01711    return(res<=hmmesize ? res : -1);                /* return -1 if done   */
01712 
01713  }
01714 
01715 
01716  pt_addr_t thread_code(pt_arg_t *t_arg)
01717  {
01718    thread_arg *arg=(thread_arg *)t_arg->data;
01719 
01720    //  std::cout << "thread_code " << arg <<  "\n";
01721    int n,p;                              /* n and p counters         */
01722    int m;                                /* row we're working on     */
01723    double sum;                           /* temporary var            */
01724    int *lhs_ia=arg->lhs_ia;
01725    int *lhs_ja=arg->lhs_ja;
01726    int *ia=arg->ia;
01727    int *ja=arg->ja;
01728    unsigned *rowdone=arg->rowdone;
01729    m=0;
01730    pthread_mutex_t *mdone_mutex=arg->mdone_mutex;
01731    unsigned *order=arg->order;
01732    SparseMatrix *hInv=arg->Ainv;
01733    SparseMatrix *hmmec=arg->A;
01734    unsigned hmmesize=arg->hmmesize;
01735    Vector<double> InvCol,wrkVec;
01736    wrkVec.resize(hmmesize);
01737    InvCol.resize(hmmesize);
01738 
01739 
01740    while ((m=nextrow(lhs_ia,lhs_ja,rowdone,mdone_mutex,hmmesize,m,order,hInv,InvCol))!=-1) {           /* m=row to do              */
01741      wrkVec(order[m-1])=1;
01742      hmmec->solvrow(InvCol.begin(),wrkVec.begin(),m);
01743      wrkVec(order[m-1])=0;
01744    }
01745    return(NULL);
01746  }
01747  #endif
01748 
01749 
01750  void GLMM::build_hInv()
01751  {
01752 
01753    unsigned row=0;
01754    Vector<double> InvCol,wrkVec;
01755    int *lhs_ia,*lhs_ja,*lhs_sh,nz;
01756    double *lhs_a;
01757    unsigned hsize=hmmesize;
01758    InvCol.resize(hmmesize);
01759    wrkVec.resize(hmmesize);
01760    hInv.resize(hmmesize,max_nz);
01761 #ifdef DEBUG
01762      doubleMatrix LHS;
01763      LHS=hmmec.dense();
01764      std::cout << "\nbuild_hInv LHS\n"<<LHS <<"\n";
01765  #endif
01766    if (!hmmec.factor_done) hmmec.factor();
01767    unsigned int *order=hmmec.order.begin();
01768 
01769  #ifdef DO_THREADS
01770    pthread_mutex_t mdone_mutex;
01771    pt_mutex_init(&mdone_mutex,"init mutex"); /* initialize the mutex */
01772 
01773    thread_arg mult_arg;
01774    mult_arg.mdone_mutex=&mdone_mutex;
01775    mult_arg.A=&hmmec;
01776    mult_arg.Ainv=&hInv;
01777    mult_arg.hmmesize=hmmesize;
01778    mult_arg.rowdone=&row;
01779    mult_arg.order=hmmec.order.begin();
01780  #endif
01781    int *ia   = hmmec.iiv-1;
01782    int *ja   = hmmec.jjv-1;
01783    double *a = hmmec.aav-1;
01784    unsigned nrow   = 0;         
01785    unsigned oldrow = 0;
01786    nz=squeeze(hmmec.hsize,ia,ja,a);
01787    for(int i=1;i<=nz;i++) {
01788      ia[i]=hmmec.inv_order[ia[i]-1];
01789      ja[i]=hmmec.inv_order[ja[i]-1];
01790      if(ja[i] < ia[i]) {
01791        int itmp=ia[i];
01792        ia[i]=ja[i];
01793        ja[i]=itmp;
01794      }
01795    }
01796    hsort_ija(nz,ia,ja,a);
01797    for (int k=1; k<=nz ; k++) {
01798      if (ia[k] != oldrow) {
01799        nrow++;
01800        ia[nrow] = k;
01801        oldrow = ia[k];    
01802      }
01803    }
01804    ia[hmmec.dim+1] = nz+1;
01805 
01806    lhs_ia=hmmec.ia();
01807    lhs_ja=hmmec.ja();
01808    lhs_a=hmmec.a();
01809  #ifdef DO_THREADS
01810    mult_arg.ia=ia;
01811    mult_arg.ja=ja;
01812    mult_arg.lhs_ja=lhs_ja;
01813    mult_arg.lhs_ia=lhs_ia;
01814    int NTHREADS;
01815    char *MP_NUM;
01816    NTHREADS=1;
01817    MP_NUM=getenv("MP_NUM_THREADS");
01818    if(MP_NUM) NTHREADS=atol(MP_NUM);
01819    if(NTHREADS >1) {
01820      NTHREADS--;
01821      std::cout << "Nthreads "<< NTHREADS << "\n";
01822      //thread_code(&mult_arg[0]);
01823      //  std::cout << &mult_arg << "\n";
01824  //TW    pt_fork(NTHREADS,thread_code,(pt_addr_t) &mult_arg,NULL); /* run code in parallel */
01825     
01826     
01827  //TW    pt_mutex_destroy(&mdone_mutex,"del mutex");
01828      //  hInv.close();
01829    }
01830    else{
01831  #endif
01832      Vector<double> solwrk,temp_rhswrk;
01833      Vector<unsigned int> temp_col,temp_row; 
01834      int m,jj;
01835 #pragma omp parallel private(jj,m,wrkVec,solwrk,temp_rhswrk,InvCol,temp_col,temp_row)
01836      {
01837 #pragma omp critical
01838        {
01839        wrkVec.resize(hmmesize);
01840        InvCol.resize(hmmesize); 
01841        solwrk.resize(hmmesize);
01842        temp_rhswrk.resize(hmmesize);
01843        temp_row.resize(hmmesize);
01844        temp_col.resize(hmmesize);
01845        }
01846 #pragma omp for schedule(dynamic,50) nowait
01847        for(m=1;m<=hmmesize;m++) {
01848          wrkVec(order[m-1])=1;
01849          hmmec.solvrow(InvCol.begin(),wrkVec.begin(),m,solwrk,temp_rhswrk,temp_row.begin(),temp_col.begin());
01850          wrkVec(order[m-1])=0;
01851          {
01852            for(jj=lhs_ia[m];jj<lhs_ia[m+1];jj++) {
01853              //      hInv.insert(order[m-1],order[lhs_ja[jj]-1],InvCol[order[lhs_ja[jj]-1]-1]);
01854              //      hInv.insert(order[m-1],order[lhs_ja[jj]-1],solwrk[order[lhs_ja[jj]-1]-1]);
01855              hInv.insert(order[m-1],order[lhs_ja[jj]-1],InvCol[lhs_ja[jj]-1]);
01856            }
01857          }
01858        }
01859      }
01860  #ifdef DO_THREADS
01861      pt_mutex_destroy(&mdone_mutex,"del mutex");
01862    }
01863  #endif
01864  }
01865 
01866 doubleMatrix GLMM::getVarEstimates(const std::string &termname)
01867 {
01868   // Authors: Liviu R. Totir and Rohan L. Fernando (March, 2004) 
01869   // Contributors: 
01870   doubleMatrix* retval = 0;
01871   if (type == bad_model) {
01872     warning("Model::info(stream): model is too bad");
01873     return *retval;
01874   }
01875   int k = term.index(termname,factor_struct);
01876   if (k < 0) throw exception("GLMM::getVarEstimates: no such term in the model");
01877   const ModelTerm *T;
01878   T = &(term(k));
01879   if (T->classi() == 'R' || (T->classi() == 'P')) {
01880     retval=T->prior->var_matrix();
01881   }
01882   return *retval;
01883 }
01884 
01885 } ///////// end of namespace matvec
01886 
01887 

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