CVariableMetric.cpp

Go to the documentation of this file.
00001 #include "CVariableMetric.h"
00002 #include <gsl/gsl_math.h>
00003 #include <iostream>
00004 
00005 
00006 using namespace std;
00007 
00008 CVariableMetric::CVariableMetric(const unsigned int ndatapoints, const unsigned int nmodel)  : CGeneralLinInversion(ndatapoints,nmodel)
00009 {
00010         gamma.resize(nparams,false);
00011         oldgamma.resize(nparams,false);
00012         oldmodel.resize(nparams,false);
00013         phi.resize(nparams,false);
00014         PartialDerivs.resize(ndata,nparams,false);
00015         DataCovarInv.resize(ndata,ndata);
00016         ModelCovarInv.resize(nparams,nparams);
00017         InversionResult.resize(ndata,false);
00018         CMu.resize(nparams,false);
00019         deltagamma.resize(nparams,false);
00020         deltamodel.resize(nparams,false);
00021         deltamodelF.resize(nparams,false);
00022         CMGT.resize(nparams,ndata);
00023         CDinvG.resize(ndata,nparams);
00024         CDMisfit.resize(ndata,true);
00025         b.resize(ndata,true);
00026         F.resize(nparams,nparams,false);
00027         Hinv.resize(nparams,nparams,false);
00028         deltaF.resize(nparams,nparams,false);
00029         currentstepsize = 5.;
00030         Wolfe2Factor = 0.1;
00031         FirstIteration = true;
00032         currentiteration = 0;
00033 }
00034 
00035 CVariableMetric::~CVariableMetric()
00036 {
00037 }
00038 
00039 void CVariableMetric::Prepare()
00040 {
00041         currentiteration = 0;
00042         ublas::identity_matrix<double> Iparams(nparams);
00043         CurrentModel = StartModel;
00044         //InvertMatrix(DataCovar,DataCovarInv);
00045         //InvertMatrix(ModelCovar,ModelCovarInv);
00046         DataCovarInv = DataCovar;
00047         ModelCovarInv = ModelCovar;
00048         CalcPartialDerivs();
00049         CalcGradient();
00050         F.assign(Iparams);
00051         axpy_prod(ModelCovar,trans(PartialDerivs),CMGT,true); // CMGT = Cm * G^T
00052         cout << "ModelCovar: " << ModelCovar << endl;
00053         cout << "PartialDerivs: " << PartialDerivs << endl;
00054         axpy_prod(DataCovarInv,CurrentMisfit,CDMisfit,true);  //CDMisfit = Cd * misfit
00055         axpy_prod(CMGT,CDMisfit,gamma,true); //gamma = CMGT * CDMisfit
00056         cout << "Gamma: " << gamma << endl;
00057         //gamma = Gradient;
00058         //cout << "Gradient: " << Gradient << endl;
00059         axpy_prod(F,gamma,phi); //phi = F * gamma
00060         phi *= -1.;
00061         cout << "F: " << F << endl;
00062 }
00063 
00064 void CVariableMetric::DoIteration()
00065 {
00066         double NewRMS = 1e90;
00067         const unsigned int maxsearch = 20;
00068         unsigned int searchiterations = 0;
00069         double Fdenominator;
00070         double usedstepsize = currentstepsize;
00071         double mudenom,muenum, mu;
00072         double newgradsearchprodukt;
00073         
00074         oldgamma = gamma;
00075         oldmodel = CurrentModel;
00076         
00077         axpy_prod(PartialDerivs,phi,b,true); // b = part * phi
00078         muenum = -inner_prod(prod(gamma,ModelCovarInv),phi);
00079         mudenom = inner_prod(prod(phi,ModelCovarInv),phi) + inner_prod(prod(b,DataCovarInv),b);
00080         //mu = muenum/mudenom;
00081         mu = 1.;
00082         const double gradsearchprodukt =  inner_prod(gamma,phi);
00083         const double searchangle = acos(gradsearchprodukt/(norm_2(gamma)*norm_2(phi))) *180./M_PI;
00084         const double Wolfe2 = gradsearchprodukt * Wolfe2Factor;
00085         cout << endl << "Iteration : " << currentiteration << endl;
00086         cout << "CMGT: " << CMGT << endl;
00087         cout << "CurrentMisfit: " << CurrentMisfit<< endl;
00088         cout << "CDMisfit: " << CDMisfit << endl;
00089         cout << "Gamma: " << gamma << endl;
00090         cout << "Phi: " << phi << endl;
00091         cout << "Angle: " << searchangle <<  endl;
00092         cout << "CurrentModel: " << CurrentModel << endl;
00093         do
00094         {
00095                 cout << "Orig Stepsize: " << mu << endl; 
00096                 mu = LineSearch->SearchStepsize(mu,CurrentRMS,phi,CurrentModel,InputData,gamma);
00097                 cout << "New Stepsize: " << mu << endl;
00098                 CurrentModel = oldmodel + mu * phi;
00099                 CalcPartialDerivs();
00100                 CalcGradient();
00101                 axpy_prod(ModelCovar,trans(PartialDerivs),CMGT,true);
00102                 axpy_prod(DataCovarInv,CurrentMisfit,CDMisfit,true);
00103                 axpy_prod(CMGT,CDMisfit,gamma,true);
00104                 cout << "Gamma: " << gamma << endl;
00105                 //gamma = Gradient;
00106                 //cout << "Gradient: " << Gradient << endl;
00107                 newgradsearchprodukt = inner_prod(gamma,phi);
00108                 
00109                 cout << "NewGradSearchProdukt: " << newgradsearchprodukt << " ";
00110                 cout << "Wolfe2: " << Wolfe2 << endl;
00111                 cout << "CurrentModel: " << CurrentModel << endl;
00112                 cout << "CurrentMisfit: " << CurrentMisfit<< endl;      
00113                 mu *= 10.;
00114         }
00115         while (newgradsearchprodukt *1.001 < Wolfe2);
00116         
00117         cout << "New Mu: " << mu << endl; 
00118         
00119         deltamodel = CurrentModel - oldmodel;
00120         deltagamma = gamma - oldgamma;
00121         gplib::rvec v = prod(F,deltagamma);
00122         gplib::rvec u = deltamodel - v;
00123         //Update of Hessian using the BFGS formula after Nocedal 1992 p. 17
00124         double yTs = inner_prod(deltagamma,deltamodel);
00125         cout << "yTs: " << yTs << endl;
00126         if (yTs > 0) // we can update the Hessian using the BFGS formula
00127         {
00128                 cout << "F before: " << F << endl;
00129                 cout << "DeltaModel: " << deltamodel << endl;
00130                 axpy_prod(F,deltamodel,deltamodelF,true);
00131                 cout << "DeltaModelF: " << deltamodelF << endl;
00132                 Fdenominator = inner_prod(deltamodelF,deltamodel);
00133                 deltaF = -outer_prod(deltamodelF,deltamodelF)/Fdenominator;
00134                 cout << "Delta F: " << deltaF << endl;
00135                 //axpy_prod(deltaF,ModelCovarInv,F,false);
00136                 cout << "F after first: " << F << endl;
00137                 cout << "DeltaGamma: " << deltagamma << endl;
00138                 cout << "dgammaTdgamma: " << outer_prod(deltagamma,deltagamma) << endl;
00139                 cout << "dgamma*dgamma: " << inner_prod(deltagamma,deltamodel) << endl;
00140                 cout << "DeltaF: " << outer_prod(deltagamma,deltagamma)/inner_prod(deltagamma,deltamodel) << endl;
00141                 F += outer_prod(u,u)/inner_prod(u,deltagamma); 
00142                 //F += outer_prod(deltagamma,deltagamma)/inner_prod(deltagamma,deltamodel); //needs to incorporate Covariance !!
00143                 cout << "F after second: " << F << endl;
00144         }
00145         else // reset hessian to identity matrix
00146         {
00147                 cout << "yTs: " << yTs << " Reset Hessian ! " << endl; 
00148                 ublas::identity_matrix<double> Iparams(nparams);
00149                 F.assign(Iparams);
00150         }
00151         //InvertMatrix(F,Hinv);
00152         axpy_prod(F,gamma,phi,true); //changed F for Hinv to use inverse of Hessian !!!
00153         phi *= -1.;
00154         cout << "|gamma| : " << norm_2(gamma) << endl;
00155         cout << "Abort: " << epsilon * (1. + CurrentRMS) << endl;
00156         if (norm_2(gamma) < epsilon * (1. + CurrentRMS))
00157                 throw ConvergenceException();
00158                 
00159         cout  << endl << endl;
00160         ++currentiteration;
00161         FirstIteration = false;
00162 }

Generated on Tue Aug 4 16:04:06 2009 for GPLIB++ by  doxygen 1.5.8