00001 #include <iostream>
00002 #include <cmath>
00003 #include "TRandom.h"
00004 #include "TDecompChol.h"
00005 #include "RootUtil/CorrGauss.h"
00006
00007 using namespace std;
00008
00009 CorrGauss::CorrGauss():
00010 randgen(0),
00011 V(0),
00012 C(0),
00013 randseed(65539)
00014 {}
00015
00016 CorrGauss::CorrGauss(TMatrixD &covar):
00017 randgen(0),
00018 C(0),
00019 randseed(65539)
00020 {
00021 V = new TMatrixD(covar);
00022 }
00023
00024 CorrGauss::CorrGauss(Int_t nrows, Int_t ncols, const double* data):
00025 randgen(0),
00026 C(0),
00027 randseed(65539)
00028 {
00029 V = new TMatrixD(nrows,ncols,data);
00030 }
00031
00032 CorrGauss::~CorrGauss()
00033 {
00034
00035 if(randgen){
00036 delete randgen;
00037 }
00038 randgen=0;
00039 if(V){
00040 delete V;
00041 }
00042 V=0;
00043 if(C){
00044 delete C;
00045 }
00046 C=0;
00047
00048 }
00049
00050
00051 void CorrGauss::SetCovarMatrix(TMatrixD &covar)
00052 {
00053
00054 if(V){
00055 delete V;
00056 }
00057 V = new TMatrixD(covar);
00058 if(C){
00059 delete C;
00060 }
00061 C=0;
00062 }
00063
00064 void CorrGauss::SetCovarMatrix(Int_t nrows, Int_t ncols, const double* data)
00065 {
00066
00067 if(V){
00068 delete V;
00069 }
00070 V = new TMatrixD(nrows,ncols,data);
00071 if(C){
00072 delete C;
00073 }
00074 C=0;
00075 }
00076
00077 void CorrGauss::DoCholesky(int method)
00078 {
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 if(C){
00101 delete C;
00102 }
00103 C=0;
00104
00105 if(V==0){
00106 cerr<<"You have not input the covariance matrix"<<endl;
00107 cerr<<"You must provide a covariance matrix before attempting to decompose it"<<endl;
00108 return;
00109 }
00110 if(V->GetNrows()!=V->GetNcols()){
00111 cerr<<"Nrows!=NCols"<<endl;
00112 cerr<<"Covariance matrix must be square"<<endl;
00113 return;
00114 }
00115
00116 int NPAR = V->GetNrows();
00117 if(NPAR<1){
00118 cerr<<"Nrows==0"<<endl;
00119 cerr<<"Covariance matrix must have some rows"<<endl;
00120 return;
00121 }
00122
00123 if(method>3||method<1) method=1;
00124
00125 if(method==1){
00126 TDecompChol *tdc=new TDecompChol(*V);
00127 bool worked=tdc->Decompose();
00128 if(!worked){
00129 cerr<<"Root can not Decompose this covariance matrix"<<endl;
00130 return;
00131 }
00132 TMatrixD *tcheck = new TMatrixD(tdc->GetU());
00133 C=new TMatrixD(tcheck->T());
00134 if(tcheck){
00135 delete tcheck;
00136 }
00137 tcheck=0;
00138 if(tdc){
00139 delete tdc;
00140 }
00141 tdc=0;
00142 }
00143 else if(method==2||method==3){
00144 C=new TMatrixD(V->GetNrows(),V->GetNcols());
00145 for(int i=0;i<NPAR;i++){
00146 double denom=(*V)(0,0);
00147 if(denom<=0){
00148 cerr<<"Can not do Cholesky since v[0][0]="<<denom<<endl;
00149 return;
00150 }
00151 (*C)(i,0)=(*V)(i,0)/sqrt(denom);
00152 for(int j=1;j<NPAR;j++){
00153 if(j<i){
00154 double s=0.;
00155 for(int k=0;k<=j-1;k++){
00156 s+=(*C)(i,k)*(*C)(j,k);
00157 }
00158 if((*C)(j,j)!=0){
00159 (*C)(i,j)=((*V)(i,j)-s)/(*C)(j,j);
00160 }
00161 else{
00162 (*C)(i,j)=0.;
00163 }
00164 }
00165 if(i==j){
00166 double s=0.;
00167 for(int k=0;k<=i-1;k++){
00168 s+=(*C)(i,k)*(*C)(i,k);
00169 }
00170 if((*V)(i,i)-s>=0){
00171 (*C)(j,j)=sqrt((*V)(i,i)-s);
00172 }
00173 else{
00174 (*C)(j,j)=0;
00175 }
00176 }
00177 if(j>i){
00178 (*C)(i,j)=0.;
00179 }
00180 }
00181 }
00182
00183 for(int i=0;i<NPAR;i++){
00184 for(int j=0;j<NPAR;j++){
00185 double s=0.;
00186 for(int k=0;k<NPAR;k++){
00187 s+=(*C)(i,k)*(*C)(j,k);
00188 }
00189 if(fabs(s-(*V)(i,j))>0.000001){
00190 cout<<"Does not check! "<<s<<" v["<<i<<"]["<<j<<"]="<<(*V)(i,j)<<endl;
00191 }
00192 }
00193 }
00194 }
00195
00196 if(method==3){
00197 TDecompChol *tdc=new TDecompChol(*V);
00198 bool worked=tdc->Decompose();
00199 if(!worked){
00200 cerr<<"Root can not Decompose this covariance matrix"<<endl;
00201 return;
00202 }
00203 TMatrixD *tcheck = new TMatrixD(tdc->GetU());
00204 TMatrixD *check=new TMatrixD(tcheck->T());
00205
00206 if(tdc){
00207 delete tdc;
00208 }
00209 tdc=0;
00210 bool match=true;
00211 for(int i=0;i<C->GetNrows();i++){
00212 for(int j=0;j<C->GetNrows();j++){
00213 if(fabs((*C)(i,j)-(*check)(i,j))>1e-11){
00214 match=false;
00215 cerr<<"Matrices are not the same!"<<endl;
00216 cerr<<"C["<<i<<","<<j<<"]="<<(*C)(i,j)
00217 <<" check["<<i<<","<<j<<"]="<<(*check)(i,j)
00218 <<"Diff "<<(*C)(i,j)-(*check)(i,j)<<endl;
00219 }
00220 }
00221 }
00222 if(match){
00223 cout<<"The methods match"<<endl;
00224 }
00225 if(tcheck){
00226 delete tcheck;
00227 }
00228 tcheck=0;
00229 if(check){
00230 delete check;
00231 }
00232 check=0;
00233
00234 }
00235
00236 }
00237
00238 TMatrixD *CorrGauss::GetCovarMat() const
00239 {
00240
00241
00242 if(V){
00243 return V;
00244 }
00245 cerr<<"No covariance matrix"<<endl;
00246 return 0;
00247 }
00248
00249 double CorrGauss::GetCovarElement(int rindx, int cindx) const
00250 {
00251
00252
00253 if(V){
00254 if(rindx>=V->GetNrows()||cindx>=V->GetNcols()){
00255 cerr<<"Wrong indices, asking for ("<<rindx<<","<<cindx<<")"<<endl;
00256 cerr<<"From a "<<V->GetNrows()<<"x"<<V->GetNcols()<<" matrix"<<endl;
00257 return -999.;
00258 }
00259 return (*V)(rindx,cindx);
00260 }
00261 cerr<<"No covariance matrix"<<endl;
00262 return -999.;
00263
00264
00265 }
00266
00267 TMatrixD *CorrGauss::GetDecompMat()
00268 {
00269
00270
00271
00272
00273 if(C){
00274 return C;
00275 }
00276 DoCholesky();
00277 if(C){
00278 return C;
00279 }
00280 cerr<<"No decomposed matrix"<<endl;
00281 return 0;
00282 }
00283
00284
00285 double CorrGauss::GetDecompElement(int rindx, int cindx)
00286 {
00287
00288
00289
00290
00291
00292 if(!C){
00293 DoCholesky();
00294 }
00295 if(C){
00296 if(rindx>=C->GetNrows()||cindx>=C->GetNcols()){
00297 cerr<<"Wrong indices, asking for ("<<rindx<<","<<cindx<<")"<<endl;
00298 cerr<<"From a "<<C->GetNrows()<<"x"<<C->GetNcols()<<" matrix"<<endl;
00299 return -999.;
00300 }
00301 return (*C)(rindx,cindx);
00302 }
00303 cerr<<"No covariance matrix"<<endl;
00304 return -999.;
00305 }
00306
00307 void CorrGauss::GetRandomParSet(vector<double> &pars,bool correlated)
00308 {
00309
00310
00311
00312
00313
00314
00315
00316 pars.clear();
00317 vector<double> uncorr;
00318 if(!randgen){
00319 randgen = new TRandom(randseed);
00320 }
00321 for(int i=0;i<C->GetNrows();i++){
00322
00323 if(correlated){
00324 uncorr.push_back(randgen->Gaus(0,1));
00325 }
00326 else{
00327 pars.push_back(randgen->Gaus(0,sqrt((*V)(i,i))));
00328 }
00329 }
00330
00331 if(!correlated){
00332 return;
00333 }
00334
00335
00336
00337
00338 for(int j=0;j<C->GetNrows();j++){
00339 double row=0.;
00340 for(int k=0;k<C->GetNcols();k++){
00341 row+=(*C)(j,k)*uncorr[k];
00342 }
00343
00344 pars.push_back(row);
00345 }
00346 }