Isis 3 Programmer Reference
MaximumLikelihoodWFunctions.cpp
2 
3 #include <QDataStream>
4 #include <QString>
5 
6 #include <math.h>
7 #include <stdio.h>
8 
9 #include "IException.h"
10 #include "IString.h"
11 
12 namespace Isis {
18  this->setModel(Huber);
19  } // choose Model and define the tweaking constant
20 
21 
22 
31  // choose Model and define the tweaking constant
32  this->setModel(modelSelection);
33  }
34 
35 
36 
49  double tweakingConstant) {
50  // choose Model and define the tweaking constant
51  setModel(modelSelection, tweakingConstant);
52  }
53 
55  const MaximumLikelihoodWFunctions &other)
56  : m_model(other.m_model),
57  m_tweakingConstant(other.m_tweakingConstant) {
58  }
59 
60 
61  MaximumLikelihoodWFunctions::~MaximumLikelihoodWFunctions() {
62  } // empty destructor
63 
64 
65  MaximumLikelihoodWFunctions &MaximumLikelihoodWFunctions::operator=(
66  const MaximumLikelihoodWFunctions &other) {
67  m_model = other.m_model;
68  m_tweakingConstant = other.m_tweakingConstant;
69  return *this;
70  }
71 
80  // choose Model and use default tweaking constant
81  m_model = modelSelection;
83  }
84 
85 
86 
91  // default tweaking constants for the various likelihood models
92  switch (m_model) {
93  case Huber:
94  m_tweakingConstant = 1.345; // "95% asymptotic efficiecy on the standard normal distribution"
95  // is obtained with this constant,
96  // see Zhang's "Parameter Estimation"
97  break;
98  case HuberModified:
99  m_tweakingConstant = 1.2107;// "95% asymptotic efficiecy on the standard normal distribution"
100  // is obtained with this constant,
101  // see Zhang's "Parameter Estimation"
102  break;
103  case Welsch:
104  m_tweakingConstant = 2.9846;// "95% asymptotic efficiecy on the standard normal distribution"
105  // is obtained with this constant,
106  // see Zhang's "Parameter Estimation"
107  break;
108  case Chen:
109  m_tweakingConstant = 1; // This is the constant used by Chen in his paper,
110  // no specific reason why is stated
111  break;
112  default:
113  m_tweakingConstant = 1; // default, though at the time of writing this class,
114  // this value should never actually be used
115  }
116  }
117 
118 
119 
131  void MaximumLikelihoodWFunctions::setModel(Model modelSelection, double tweakingConstant) {
132  // choose Model and define the tweaking constant
133  m_model = modelSelection;
135  }
136 
137 
138 
148  void MaximumLikelihoodWFunctions::setTweakingConstant(double tweakingConstant) {
149  // leave model type unaltered and change tweaking constant
150  if (tweakingConstant <= 0.0) {
151  IString msg = "Maximum likelihood estimation tweaking constants must be > 0.0";
153  }
155  }
156 
157 
158 
163  return m_tweakingConstant;
164  }
165 
166 
167 
178  double MaximumLikelihoodWFunctions::weightScaler(double residualZScore) {
179  // this is likely the least usefull of the scaler functions but it is provided for completness.
180  // This directly provides the scaler for the weight (instead of the radical weight), thus it
181  // provides sqrtWeightScaler^2
182  switch(m_model) {
183  case Huber:
184  return this->huber(residualZScore);
185  case HuberModified:
186  return this->huberModified(residualZScore);
187  case Welsch:
188  return this->welsch(residualZScore);
189  case Chen:
190  return this->chen(residualZScore);
191  default:
192  return 1.0; // default to prevent nonsense from being returned,
193  // but the program should never reach this line
194  }
195  }
196 
197 
198 
209  double MaximumLikelihoodWFunctions::sqrtWeightScaler(double residualZScore) {
210  // it is often convient to use square roots of weights when building normals, this function
211  // provides the scaler for the square root of the weight directly
212  double scaler = this->weightScaler(residualZScore);
213  if (scaler <= 0.0) {
214  return 0.0; // <0 should never happen, but 0.0 may be quite frequent
215  // (thus this saves some time)
216  }
217  return sqrt(scaler);
218  }
219 
220 
221 
232  double MaximumLikelihoodWFunctions::huber(double residualZScore) {
233  // huber weight function
234  if ( fabs(residualZScore) < m_tweakingConstant) {
235  return 1.0;
236  }
237  else {
238  return m_tweakingConstant/fabs(residualZScore);
239  }
240  }
241 
242 
243 
254  double MaximumLikelihoodWFunctions::huberModified(double residualZScore) {
255  // huber modified weight function
256  if ( fabs(residualZScore)/m_tweakingConstant < Isis::HALFPI) {
257  return m_tweakingConstant*(sin(residualZScore/m_tweakingConstant)/residualZScore);
258  }
259  else {
260  return m_tweakingConstant / fabs(residualZScore);
261  }
262  }
263 
264 
265 
276  double MaximumLikelihoodWFunctions::welsch(double residualZScore) {
277  // welsch weight function
278  double weightFactor = residualZScore / m_tweakingConstant;
279  return exp(-(weightFactor)*(weightFactor));
280  }
281 
282 
283 
294  double MaximumLikelihoodWFunctions::chen(double residualZScore) {
295  // chen weight function
296  if ( fabs(residualZScore) <= m_tweakingConstant) {
297  double weightFactor = m_tweakingConstant * m_tweakingConstant
298  - residualZScore * residualZScore;
299  return 6 * weightFactor * weightFactor; // use of weight factor variable reduces number of
300  // operations from 7 to 4
301  }
302  else {
303  return 0.0;
304  }
305  }
306 
307 
308 
317  // returns which quantile of the sqaured residuals is recommended to use as the tweaking
318  // constants, this varies as a function of the model being employed desired quantiles for
319  // various models, these parameters are estimated based on inspection of the fucntions and
320  // should be tested and revised with experience
321  switch(m_model) {
322  case Huber:
323  return 0.5; // In this model m_tweakingConstant determines the point at which residuals stop having
324  // increased influence on the solution, so after the median all the measures will
325  // have the same effect on the solution regardless of magnitude
326  case HuberModified:
327  return 0.4; // In this model after residualZScore >= m_tweakingConstant*Isis::HALFPI the residuals have the same
328  // influence on the solution,
329  case Welsch:
330  return 0.7; // at about double m_tweakingConstant the residuals have very little influence
331  case Chen:
332  return 0.98; // after r > m_tweakingConstant residuals have no influence
333  default:
334  return 0.5; // default, though at the time of writing this should never actually be used
335  }
336  }
337 
338 
339 
348  if (model == MaximumLikelihoodWFunctions::Huber) return "Huber";
349  else if (model == MaximumLikelihoodWFunctions::HuberModified) return "HuberModified";
350  else if (model == MaximumLikelihoodWFunctions::Welsch) return "Welsch";
351  else if (model == MaximumLikelihoodWFunctions::Chen) return "Chen";
353  "Unknown estimation model enum [" + toString(model) + "].",
354  _FILEINFO_);
355  }
356 
357 
358 
359  MaximumLikelihoodWFunctions::Model MaximumLikelihoodWFunctions::stringToModel(QString modelName) {
360  if (modelName.compare("HUBER", Qt::CaseInsensitive) == 0) {
361  return Huber;
362  }
363  else if (modelName.compare("HUBER_MODIFIED", Qt::CaseInsensitive) == 0 ||
364  modelName.compare("HUBERMODIFIED", Qt::CaseInsensitive) == 0 ||
365  modelName.compare("HUBER MODIFIED", Qt::CaseInsensitive) == 0) {
366  return HuberModified;
367  }
368  else if (modelName.compare("WELSCH", Qt::CaseInsensitive) == 0) {
369  return Welsch;
370  }
371  else if (modelName.compare("CHEN", Qt::CaseInsensitive) == 0) {
372  return Chen;
373  }
374  else {
375  throw IException(IException::Programmer,
376  "Unknown maximum likelihood model name " + modelName + ".",
377  _FILEINFO_);
378  }
379  }
380 
381 
382 
392  if (m_model == Huber || m_model == HuberModified) return "N/A";
393  else if (m_model == Welsch) return toString(m_tweakingConstant * 1.5);
394  else if (m_model == Chen) return toString(m_tweakingConstant);
395  else throw IException(IException::Programmer, "Estimation model has not been set.", _FILEINFO_);
396  }
397 
398 
399 
406  return m_model;
407  }
408 
409 
410 
411  QDataStream &MaximumLikelihoodWFunctions::write(QDataStream &stream) const {
412  stream << (qint32)m_model
414  return stream;
415  }
416 
417 
418 
419  QDataStream &MaximumLikelihoodWFunctions::read(QDataStream &stream) {
420  qint32 model;
421  stream >> model >> m_tweakingConstant;
423  return stream;
424  }
425 
426 
427 
428  QDataStream &operator<<(QDataStream &stream, const MaximumLikelihoodWFunctions &mlwf) {
429  return mlwf.write(stream);
430  }
431 
432 
433 
434  QDataStream &operator>>(QDataStream &stream, MaximumLikelihoodWFunctions &mlwf) {
435  return mlwf.read(stream);
436  }
437 
438 
439 
440  QDataStream &operator<<(QDataStream &stream, const MaximumLikelihoodWFunctions::Model &modelEnum) {
441  stream << (qint32)modelEnum;
442  return stream;
443  }
444 
445 
446 
447  QDataStream &operator>>(QDataStream &stream, MaximumLikelihoodWFunctions::Model &modelEnum) {
448  qint32 modelInteger;
449  stream >> modelInteger;
450  modelEnum = (MaximumLikelihoodWFunctions::Model)modelInteger;
451  return stream;
452  }
453 
454 }// end namespace Isis
void setTweakingConstant(double tweakingConstant)
Allows the tweaking constant to be changed without changing the maximum likelihood function...
double tweakingConstantQuantile()
Suggest a quantile of the probility distribution of the residuals to use as the tweaking constants ba...
double sqrtWeightScaler(double residualZScore)
This provides the scaler to the sqrt of the weight, which is very useful for building normal equation...
According to Zhang (Parameter Estimation: A Tutorial with application to conic fitting) "[Huber&#39;s] es...
double weightScaler(double residualZScore)
This provides the scalar for the weight (not the scaler for the square root of the weight...
QString weightedResidualCutoff()
Method to return a string represtentation of the weighted residual cutoff (if it exists) for the Maxi...
const double HALFPI
The mathematical constant PI/2.
Definition: Constants.h:57
Model m_model
The enumerated value for the maximum likelihood estimation model to be used.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
double chen(double residualZScore)
Modified Huber maximum likelihood estimation function evaluation.
Model
The supported maximum likelihood estimation models.
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:162
double huber(double residualZScore)
Huber maximum likelihood estimation function evaluation.
The Chen method was found in "Robust Regression with Projection Based M-estimators" Chen...
A modification to Huber&#39;s method propsed by William J.J.
The Welsch method aggresively discounts measures with large resiudals.
void setModel(Model modelSelection)
Allows the maximum likelihood model to be changed together and the default tweaking constant to be se...
MaximumLikelihoodWFunctions()
Sets up a maximumlikelihood estimation function with Huber model and default tweaking constant...
void setTweakingConstantDefault()
Sets default tweaking constants based on the maximum likelihood estimation model being used...
double m_tweakingConstant
The tweaking constant for the maximum likelihood models.
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
std::istream & operator>>(std::istream &is, CSVReader &csv)
Input read operator for input stream sources.
Definition: CSVReader.cpp:463
Class provides maximum likelihood estimation functions for robust parameter estimation, e.g.
double huberModified(double residualZScore)
Modified Huber maximum likelihood estimation function evaluation.
double welsch(double residualZScore)
Modified Huber maximum likelihood estimation function evaluation.
Model model() const
Accessor method to return the MaximumLikelihoodWFunctions::Model enumeration.
Isis exception class.
Definition: IException.h:107
Adds specific functionality to C++ strings.
Definition: IString.h:181
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
double tweakingConstant() const
Returns the current tweaking constant.
static QString modelToString(Model model)
Static method to return a string represtentation for a given MaximumLikelihoodWFunctions::Model enum...
QDebug operator<<(QDebug debug, const Hillshade &hillshade)
Print this class out to a QDebug object.
Definition: Hillshade.cpp:308