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
00045
00046 DataCovarInv = DataCovar;
00047 ModelCovarInv = ModelCovar;
00048 CalcPartialDerivs();
00049 CalcGradient();
00050 F.assign(Iparams);
00051 axpy_prod(ModelCovar,trans(PartialDerivs),CMGT,true);
00052 cout << "ModelCovar: " << ModelCovar << endl;
00053 cout << "PartialDerivs: " << PartialDerivs << endl;
00054 axpy_prod(DataCovarInv,CurrentMisfit,CDMisfit,true);
00055 axpy_prod(CMGT,CDMisfit,gamma,true);
00056 cout << "Gamma: " << gamma << endl;
00057
00058
00059 axpy_prod(F,gamma,phi);
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);
00078 muenum = -inner_prod(prod(gamma,ModelCovarInv),phi);
00079 mudenom = inner_prod(prod(phi,ModelCovarInv),phi) + inner_prod(prod(b,DataCovarInv),b);
00080
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
00106
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
00124 double yTs = inner_prod(deltagamma,deltamodel);
00125 cout << "yTs: " << yTs << endl;
00126 if (yTs > 0)
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
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
00143 cout << "F after second: " << F << endl;
00144 }
00145 else
00146 {
00147 cout << "yTs: " << yTs << " Reset Hessian ! " << endl;
00148 ublas::identity_matrix<double> Iparams(nparams);
00149 F.assign(Iparams);
00150 }
00151
00152 axpy_prod(F,gamma,phi,true);
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 }