00001 #include "GradFunc.h"
00002 #include "NumUtil.h"
00003 #include <iostream>
00004
00005
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)
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
00031
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
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
00103 SensitivityMatrix = CalcPartialDerivs(Objective, Model, varfactor);
00104 }
00105
00106 void ModelAnalysis::CalcSVD()
00107 {
00108 if (!haveSVD)
00109 {
00110 CalcSensitivityMatrix();
00111
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
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
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
00178
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
00196 }
00197 }
00198 return temp2;
00199 }
00200
00201 gplib::rvec ModelAnalysis::GetSingularValues()
00202 {
00203 CalcSVD();
00204 return s;
00205 }