GPLIB++
GradFunc.cpp
Go to the documentation of this file.
1 #include "GradFunc.h"
2 #include "NumUtil.h"
3 #include <iostream>
4 
5 //! Calculate the Gradient dO(m)/dm of the objective function Objective at the point given by Model, return as a real vector
6 gplib::rvec CalcGradient(GeneralObjective &Objective, const gplib::rvec &Model)
7  {
8  const double delta = 0.001;
9  const double poschange = 1. + delta;
10  const double negchange = 1. - delta;
11 
12  const unsigned int nparams = Model.size();
13  double CurrentRMS = Objective.CalcPerformance(Model);
14 
15  gplib::rvec posmodel(Model);
16  gplib::rvec negmodel(Model);
17  gplib::rvec Gradient(nparams);
18  for (unsigned int i = 0; i < nparams; ++i)
19  {
20  if (i > 0) //revert the change of the last iteration
21  {
22  posmodel(i - 1) = Model(i - 1);
23  negmodel(i - 1) = Model(i - 1);
24  }
25  posmodel(i) = Model(i) * poschange;
26  negmodel(i) = Model(i) * negchange;
27  double posrms = Objective.CalcPerformance(posmodel);
28  double negrms = Objective.CalcPerformance(negmodel);
29 
30  //cout << "Pos Model: " << posmodel << " Data:" << posdata << endl;
31  //cout << "Neg Model: " << negmodel << " Data:" << negdata << endl;
32  double denominator = 1. / (2. * delta * Model(i));
33  if (fcmp(denominator, 0.0, 1e-10) != 0)
34  Gradient(i) = (posrms - negrms) * denominator;
35  else
36  Gradient(i) = 0.0;
37  }
38  return Gradient;
39  }
40 
41 //! Calculate the matrix of partial derivatives (or sensitivity matrix) dD/dm, for objective function Objective at point Model
42 gplib::rmat CalcPartialDerivs(GeneralObjective &Objective,
43  const gplib::rvec &Model, const gplib::rvec varfactor)
44  {
45  unsigned int i, j;
46 
47  const double delta = 0.001;
48  const double poschange = 1. + delta;
49  const double negchange = 1. - delta;
50  double denominator;
51  const int nparams = Model.size();
52  Objective.CalcPerformance(Model);
53  const int ndata = Objective.GetSynthData().size();
54  gplib::rvec posdata(Objective.GetSynthData());
55  gplib::rvec negdata(Objective.GetSynthData());
56  gplib::rvec posmodel(Model);
57  gplib::rvec negmodel(Model);
58  gplib::rmat PartialDerivs(ndata, nparams);
59 
60  for (i = 0; i < nparams; ++i)
61  {
62  if (i > 0)
63  {
64  posmodel(i - 1) = Model(i - 1);
65  negmodel(i - 1) = Model(i - 1);
66  }
67  posmodel(i) = Model(i) * poschange;
68  negmodel(i) = Model(i) * negchange;
69  Objective.CalcPerformance(posmodel);
70  posdata = Objective.GetSynthData();
71  Objective.CalcPerformance(negmodel);
72  negdata = Objective.GetSynthData();
73  if (fcmp(Model(i), 0.0, 1e-8) != 0)
74  denominator = 1. / (2. * delta * Model(i));
75  else
76  denominator = 0.0;
77  for (j = 0; j < ndata; ++j)
78  {
79  PartialDerivs(j, i) = (posdata(j) - negdata(j)) * denominator
80  * varfactor(i);
81  }
82 
83  }
84  return PartialDerivs;
85  }
86 
87 void ModelAnalysis::SetModel(const gplib::rvec &TheModel)
88  {
89  Model = TheModel;
90  haveSVD = false;
91  s.resize(Model.size());
92  sinv.resize(Model.size(), Model.size());
93  vt.resize(Model.size(), Model.size());
94  vnull.resize(Model.size(), Model.size());
95  varfactor.resize(Model.size());
96  for (size_t i = 0; i < varfactor.size(); ++i)
97  varfactor(i) = 1.0;
98  }
99 
100 void ModelAnalysis::CalcSensitivityMatrix()
101  {
102  //SensitivityMatrix.resize(Objective.GetSynthData().size(),Model.size(),false);
103  SensitivityMatrix = CalcPartialDerivs(Objective, Model, varfactor);
104  }
105 
106 void ModelAnalysis::CalcSVD()
107  {
108  if (!haveSVD)
109  {
110  CalcSensitivityMatrix();
111  //std::cout << "ModelAnalyis: " << SensitivityMatrix << std::endl;
112  OldSensitivityMatrix = SensitivityMatrix;
113  }
114  else
115  {
116  SensitivityMatrix = OldSensitivityMatrix;
117  }
118  if (changedThreshold)
119  {
120  u.resize(SensitivityMatrix.size1(), Model.size());
121  boost::numeric::bindings::lapack::gesvd(SensitivityMatrix, s, u, vt);
122  ApplyThreshold();
123 
124  }
125  haveSVD = true;
126  changedThreshold = false;
127  }
128 
129 void ModelAnalysis::ApplyThreshold()
130  {
131  const double maxeval = *max_element(s.begin(), s.end());
132  std::cout << "Maximum Eval: " << maxeval << std::endl;
133  const double AbsoluteThreshold = maxeval * SVDThreshold;
134  std::cout << "Eval Threshold: " << AbsoluteThreshold << std::endl;
135  for (int i = 0; i < s.size(); ++i)
136  {
137  column(sinv, i) *= 0.0;
138  if (fcmp(s(i), AbsoluteThreshold, std::numeric_limits<double>::epsilon()) == -1
139  || (fcmp(s(i), 0.0, std::numeric_limits<double>::epsilon()) == 0))
140  {
141  //std::cout << "Eval: " << s(i) << " set to zero !" << std::endl;
142  column(vnull, i) = row(vt, i);
143  column(u, i) *= 0.0;
144  row(vt, i) *= 0.0;
145  sinv(i, i) = 0.0;
146  }
147  else
148  {
149  column(vnull, i) *= 0.0;
150  sinv(i, i) = 1. / s(i);
151  }
152  }
153  }
154 
156  {
157  CalcSVD();
158  return prec_prod(trans(vt), vt);
159  }
161  {
162  CalcSVD();
163  return prec_prod(u, trans(u));
164  }
166  {
167  CalcSVD();
168  return prec_prod(vnull, trans(vnull));
169  }
170 
171 //! The calculation of the Model Covariance is based on Menke, p. 122 formula 7.37
172 gplib::rmat ModelAnalysis::GetModelCovariance(const gplib::rmat &DataCovar)
173  {
174  CalcSVD();
175  gplib::rmat temp1 = prec_prod(sinv, trans(u));
176  SensitivityInv = prec_prod(trans(vt), temp1);
177  //gplib::rmat temp2 = prec_prod(DataCovar,trans(SensitivityInv));
178  //return prec_prod(SensitivityInv,temp2);
179  return prec_prod(SensitivityInv, trans(SensitivityInv));
180  }
181 gplib::rmat ModelAnalysis::GetModelCorrelation(const gplib::rmat &DataCovar)
182  {
183  gplib::rmat temp1 = GetModelCovariance(DataCovar);
184  gplib::rmat temp2 = temp1;
185  for (size_t i = 0; i < temp1.size1(); ++i)
186  for (size_t j = 0; j < temp1.size2(); ++j)
187  {
188  if (std::abs(temp1(i, i)) < 1e-38 || std::abs(temp1(j, j))
189  < 1e-38)
190  temp2(i, j) = 0.0;
191  else
192  {
193  temp2(i, j) = temp1(i, j) / (sqrt(temp1(i, i))
194  * sqrt(temp1(j, j)));
195  //std::cout << i << " " << j << " " << temp2(i,j) << " " << temp1(i,j) << " " << temp1(i,i) << " " << temp1(j,j) << std::endl;
196  }
197  }
198  return temp2;
199  }
200 
202  {
203  CalcSVD();
204  return s;
205  }
gplib::rmat GetModelCorrelation(const gplib::rmat &DataCovar)
Definition: GradFunc.cpp:181
gplib::rmat CalcPartialDerivs(GeneralObjective &Objective, const gplib::rvec &Model, const gplib::rvec varfactor)
Calculate the matrix of partial derivatives (or sensitivity matrix) dD/dm, for objective function Obj...
Definition: GradFunc.cpp:42
gplib::rmat GetDataResolution()
Definition: GradFunc.cpp:160
gplib::rmat GetModelNullspace()
Definition: GradFunc.cpp:165
gplib::rvec GetSingularValues()
Definition: GradFunc.cpp:201
gplib::rvec CalcGradient(GeneralObjective &Objective, const gplib::rvec &Model)
Calculate the Gradient dO(m)/dm of the objective function Objective at the point given by Model...
Definition: GradFunc.cpp:6
void SetModel(const gplib::rvec &TheModel)
Definition: GradFunc.cpp:87
gplib::rmat GetModelCovariance(const gplib::rmat &DataCovar)
The calculation of the Model Covariance is based on Menke, p. 122 formula 7.37.
Definition: GradFunc.cpp:172
gplib::rmat GetModelResolution()
Definition: GradFunc.cpp:155