GradFunc.cpp

Go to the documentation of this file.
00001 #include "GradFunc.h"
00002 #include "NumUtil.h"
00003 #include <iostream>
00004 
00005 //! Calculate the Gradient dO(m)/dm of the objective function Objective at the point given by Model, return as a real vector
00006 gplib::rvec CalcGradient(GeneralObjective &Objective, const gplib::rvec &Model)
00007   {
00008     const double delta = 0.001;
00009     const double poschange = 1. + delta;
00010     const double negchange = 1. - delta;
00011 
00012     const unsigned int nparams = Model.size();
00013     double CurrentRMS = Objective.CalcPerformance(Model);
00014 
00015     gplib::rvec posmodel(Model);
00016     gplib::rvec negmodel(Model);
00017     gplib::rvec Gradient(nparams);
00018     for (unsigned int i = 0; i < nparams; ++i)
00019       {
00020         if (i > 0) //revert the change of the last iteration
00021           {
00022             posmodel(i - 1) = Model(i - 1);
00023             negmodel(i - 1) = Model(i - 1);
00024           }
00025         posmodel(i) = Model(i) * poschange;
00026         negmodel(i) = Model(i) * negchange;
00027         double posrms = Objective.CalcPerformance(posmodel);
00028         double negrms = Objective.CalcPerformance(negmodel);
00029 
00030         //cout << "Pos Model: " << posmodel << " Data:" << posdata << endl;
00031         //cout << "Neg Model: " << negmodel << " Data:" << negdata << endl;
00032         double denominator = 1. / (2. * delta * Model(i));
00033         if (fcmp(denominator, 0.0, 1e-10) != 0)
00034           Gradient(i) = (posrms - negrms) * denominator;
00035         else
00036           Gradient(i) = 0.0;
00037       }
00038     return Gradient;
00039   }
00040 
00041 //! Calculate the matrix of partial derivatives (or sensitivity matrix) dD/dm, for objective function Objective at point Model
00042 gplib::rmat CalcPartialDerivs(GeneralObjective &Objective,
00043     const gplib::rvec &Model, const gplib::rvec varfactor)
00044   {
00045     unsigned int i, j;
00046 
00047     const double delta = 0.001;
00048     const double poschange = 1. + delta;
00049     const double negchange = 1. - delta;
00050     double denominator;
00051     const int nparams = Model.size();
00052     Objective.CalcPerformance(Model);
00053     const int ndata = Objective.GetSynthData().size();
00054     gplib::rvec posdata(Objective.GetSynthData());
00055     gplib::rvec negdata(Objective.GetSynthData());
00056     gplib::rvec posmodel(Model);
00057     gplib::rvec negmodel(Model);
00058     gplib::rmat PartialDerivs(ndata, nparams);
00059 
00060     for (i = 0; i < nparams; ++i)
00061       {
00062         if (i > 0)
00063           {
00064             posmodel(i - 1) = Model(i - 1);
00065             negmodel(i - 1) = Model(i - 1);
00066           }
00067         posmodel(i) = Model(i) * poschange;
00068         negmodel(i) = Model(i) * negchange;
00069         Objective.CalcPerformance(posmodel);
00070         posdata = Objective.GetSynthData();
00071         Objective.CalcPerformance(negmodel);
00072         negdata = Objective.GetSynthData();
00073         if (fcmp(Model(i), 0.0, 1e-8) != 0)
00074           denominator = 1. / (2. * delta * Model(i));
00075         else
00076           denominator = 0.0;
00077         for (j = 0; j < ndata; ++j)
00078           {
00079             PartialDerivs(j, i) = (posdata(j) - negdata(j)) * denominator
00080                 * varfactor(i);
00081           }
00082 
00083       }
00084     return PartialDerivs;
00085   }
00086 
00087 void ModelAnalysis::SetModel(const gplib::rvec &TheModel)
00088   {
00089     Model = TheModel;
00090     haveSVD = false;
00091     s.resize(Model.size());
00092     sinv.resize(Model.size(), Model.size());
00093     vt.resize(Model.size(), Model.size());
00094     vnull.resize(Model.size(), Model.size());
00095     varfactor.resize(Model.size());
00096     for (size_t i = 0; i < varfactor.size(); ++i)
00097       varfactor(i) = 1.0;
00098   }
00099 
00100 void ModelAnalysis::CalcSensitivityMatrix()
00101   {
00102     //SensitivityMatrix.resize(Objective.GetSynthData().size(),Model.size(),false);
00103     SensitivityMatrix = CalcPartialDerivs(Objective, Model, varfactor);
00104   }
00105 
00106 void ModelAnalysis::CalcSVD()
00107   {
00108     if (!haveSVD)
00109       {
00110         CalcSensitivityMatrix();
00111         //std::cout << "ModelAnalyis: " << SensitivityMatrix << std::endl;
00112         OldSensitivityMatrix = SensitivityMatrix;
00113       }
00114     else
00115       {
00116         SensitivityMatrix = OldSensitivityMatrix;
00117       }
00118     if (changedThreshold)
00119       {
00120         u.resize(SensitivityMatrix.size1(), Model.size());
00121         boost::numeric::bindings::lapack::gesvd(SensitivityMatrix, s, u, vt);
00122         ApplyThreshold();
00123 
00124       }
00125     haveSVD = true;
00126     changedThreshold = false;
00127   }
00128 
00129 void ModelAnalysis::ApplyThreshold()
00130   {
00131     const double maxeval = *max_element(s.begin(), s.end());
00132     std::cout << "Maximum Eval: " << maxeval << std::endl;
00133     const double AbsoluteThreshold = maxeval * SVDThreshold;
00134     std::cout << "Eval Threshold: " << AbsoluteThreshold << std::endl;
00135     for (int i = 0; i < s.size(); ++i)
00136       {
00137         column(sinv, i) *= 0.0;
00138         if (fcmp(s(i), AbsoluteThreshold, std::numeric_limits<double>::epsilon()) == -1
00139             || (fcmp(s(i), 0.0, std::numeric_limits<double>::epsilon()) == 0))
00140           {
00141             //std::cout << "Eval: " << s(i) << " set to zero !" << std::endl;
00142             column(vnull, i) = row(vt, i);
00143             column(u, i) *= 0.0;
00144             row(vt, i) *= 0.0;
00145             sinv(i, i) = 0.0;
00146           }
00147         else
00148           {
00149             column(vnull, i) *= 0.0;
00150             sinv(i, i) = 1. / s(i);
00151           }
00152       }
00153   }
00154 
00155 gplib::rmat ModelAnalysis::GetModelResolution()
00156   {
00157     CalcSVD();
00158     return prec_prod(trans(vt), vt);
00159   }
00160 gplib::rmat ModelAnalysis::GetDataResolution()
00161   {
00162     CalcSVD();
00163     return prec_prod(u, trans(u));
00164   }
00165 gplib::rmat ModelAnalysis::GetModelNullspace()
00166   {
00167     CalcSVD();
00168     return prec_prod(vnull, trans(vnull));
00169   }
00170 
00171 //! The calculation of the Model Covariance is based on Menke, p. 122 formula 7.37
00172 gplib::rmat ModelAnalysis::GetModelCovariance(const gplib::rmat &DataCovar)
00173   {
00174     CalcSVD();
00175     gplib::rmat temp1 = prec_prod(sinv, trans(u));
00176     SensitivityInv = prec_prod(trans(vt), temp1);
00177     //gplib::rmat temp2 = prec_prod(DataCovar,trans(SensitivityInv));
00178     //return prec_prod(SensitivityInv,temp2);
00179     return prec_prod(SensitivityInv, trans(SensitivityInv));
00180   }
00181 gplib::rmat ModelAnalysis::GetModelCorrelation(const gplib::rmat &DataCovar)
00182   {
00183     gplib::rmat temp1 = GetModelCovariance(DataCovar);
00184     gplib::rmat temp2 = temp1;
00185     for (size_t i = 0; i < temp1.size1(); ++i)
00186       for (size_t j = 0; j < temp1.size2(); ++j)
00187         {
00188           if (std::abs(temp1(i, i)) < 1e-38 || std::abs(temp1(j, j))
00189               < 1e-38)
00190             temp2(i, j) = 0.0;
00191           else
00192             {
00193               temp2(i, j) = temp1(i, j) / (sqrt(temp1(i, i))
00194                   * sqrt(temp1(j, j)));
00195               //std::cout << i << " " << j << " " << temp2(i,j) << " " << temp1(i,j) << " " << temp1(i,i) << " " << temp1(j,j) << std::endl;
00196             }
00197         }
00198     return temp2;
00199   }
00200 
00201 gplib::rvec ModelAnalysis::GetSingularValues()
00202   {
00203     CalcSVD();
00204     return s;
00205   }

Generated on Tue May 4 16:52:14 2010 for GPLIB++ by  doxygen 1.5.8