Isis 3 Programmer Reference
MaximumLikelihoodWFunctions.cpp
1 
7 /* SPDX-License-Identifier: CC0-1.0 */
8 
9 #include "MaximumLikelihoodWFunctions.h"
10 
11 #include <QDataStream>
12 #include <QString>
13 
14 #include <math.h>
15 #include <stdio.h>
16 
17 #include "IException.h"
18 #include "IString.h"
19 
20 namespace Isis {
26  this->setModel(Huber);
27  } // choose Model and define the tweaking constant
28 
29 
30 
39  // choose Model and define the tweaking constant
40  this->setModel(modelSelection);
41  }
42 
43 
44 
57  double tweakingConstant) {
58  // choose Model and define the tweaking constant
59  setModel(modelSelection, tweakingConstant);
60  }
61 
63  const MaximumLikelihoodWFunctions &other)
64  : m_model(other.m_model),
65  m_tweakingConstant(other.m_tweakingConstant) {
66  }
67 
68 
69  MaximumLikelihoodWFunctions::~MaximumLikelihoodWFunctions() {
70  } // empty destructor
71 
72 
73  MaximumLikelihoodWFunctions &MaximumLikelihoodWFunctions::operator=(
74  const MaximumLikelihoodWFunctions &other) {
75  m_model = other.m_model;
76  m_tweakingConstant = other.m_tweakingConstant;
77  return *this;
78  }
79 
88  // choose Model and use default tweaking constant
89  m_model = modelSelection;
91  }
92 
93 
94 
99  // default tweaking constants for the various likelihood models
100  switch (m_model) {
101  case Huber:
102  m_tweakingConstant = 1.345; // "95% asymptotic efficiecy on the standard normal distribution"
103  // is obtained with this constant,
104  // see Zhang's "Parameter Estimation"
105  break;
106  case HuberModified:
107  m_tweakingConstant = 1.2107;// "95% asymptotic efficiecy on the standard normal distribution"
108  // is obtained with this constant,
109  // see Zhang's "Parameter Estimation"
110  break;
111  case Welsch:
112  m_tweakingConstant = 2.9846;// "95% asymptotic efficiecy on the standard normal distribution"
113  // is obtained with this constant,
114  // see Zhang's "Parameter Estimation"
115  break;
116  case Chen:
117  m_tweakingConstant = 1; // This is the constant used by Chen in his paper,
118  // no specific reason why is stated
119  break;
120  default:
121  m_tweakingConstant = 1; // default, though at the time of writing this class,
122  // this value should never actually be used
123  }
124  }
125 
126 
127 
139  void MaximumLikelihoodWFunctions::setModel(Model modelSelection, double tweakingConstant) {
140  // choose Model and define the tweaking constant
141  m_model = modelSelection;
143  }
144 
145 
146 
156  void MaximumLikelihoodWFunctions::setTweakingConstant(double tweakingConstant) {
157  // leave model type unaltered and change tweaking constant
158  if (tweakingConstant <= 0.0) {
159  IString msg = "Maximum likelihood estimation tweaking constants must be > 0.0";
160  throw IException(IException::Programmer, msg, _FILEINFO_);
161  }
163  }
164 
165 
166 
171  return m_tweakingConstant;
172  }
173 
174 
175 
186  double MaximumLikelihoodWFunctions::weightScaler(double residualZScore) {
187  // this is likely the least usefull of the scaler functions but it is provided for completness.
188  // This directly provides the scaler for the weight (instead of the radical weight), thus it
189  // provides sqrtWeightScaler^2
190  switch(m_model) {
191  case Huber:
192  return this->huber(residualZScore);
193  case HuberModified:
194  return this->huberModified(residualZScore);
195  case Welsch:
196  return this->welsch(residualZScore);
197  case Chen:
198  return this->chen(residualZScore);
199  default:
200  return 1.0; // default to prevent nonsense from being returned,
201  // but the program should never reach this line
202  }
203  }
204 
205 
206 
217  double MaximumLikelihoodWFunctions::sqrtWeightScaler(double residualZScore) {
218  // it is often convient to use square roots of weights when building normals, this function
219  // provides the scaler for the square root of the weight directly
220  double scaler = this->weightScaler(residualZScore);
221  if (scaler <= 0.0) {
222  return 0.0; // <0 should never happen, but 0.0 may be quite frequent
223  // (thus this saves some time)
224  }
225  return sqrt(scaler);
226  }
227 
228 
229 
240  double MaximumLikelihoodWFunctions::huber(double residualZScore) {
241  // huber weight function
242  if ( fabs(residualZScore) < m_tweakingConstant) {
243  return 1.0;
244  }
245  else {
246  return m_tweakingConstant/fabs(residualZScore);
247  }
248  }
249 
250 
251 
262  double MaximumLikelihoodWFunctions::huberModified(double residualZScore) {
263  // huber modified weight function
264  if ( fabs(residualZScore)/m_tweakingConstant < Isis::HALFPI) {
265  return m_tweakingConstant*(sin(residualZScore/m_tweakingConstant)/residualZScore);
266  }
267  else {
268  return m_tweakingConstant / fabs(residualZScore);
269  }
270  }
271 
272 
273 
284  double MaximumLikelihoodWFunctions::welsch(double residualZScore) {
285  // welsch weight function
286  double weightFactor = residualZScore / m_tweakingConstant;
287  return exp(-(weightFactor)*(weightFactor));
288  }
289 
290 
291 
302  double MaximumLikelihoodWFunctions::chen(double residualZScore) {
303  // chen weight function
304  if ( fabs(residualZScore) <= m_tweakingConstant) {
305  double weightFactor = m_tweakingConstant * m_tweakingConstant
306  - residualZScore * residualZScore;
307  return 6 * weightFactor * weightFactor; // use of weight factor variable reduces number of
308  // operations from 7 to 4
309  }
310  else {
311  return 0.0;
312  }
313  }
314 
315 
316 
325  // returns which quantile of the sqaured residuals is recommended to use as the tweaking
326  // constants, this varies as a function of the model being employed desired quantiles for
327  // various models, these parameters are estimated based on inspection of the fucntions and
328  // should be tested and revised with experience
329  switch(m_model) {
330  case Huber:
331  return 0.5; // In this model m_tweakingConstant determines the point at which residuals stop having
332  // increased influence on the solution, so after the median all the measures will
333  // have the same effect on the solution regardless of magnitude
334  case HuberModified:
335  return 0.4; // In this model after residualZScore >= m_tweakingConstant*Isis::HALFPI the residuals have the same
336  // influence on the solution,
337  case Welsch:
338  return 0.7; // at about double m_tweakingConstant the residuals have very little influence
339  case Chen:
340  return 0.98; // after r > m_tweakingConstant residuals have no influence
341  default:
342  return 0.5; // default, though at the time of writing this should never actually be used
343  }
344  }
345 
346 
347 
356  if (model == MaximumLikelihoodWFunctions::Huber) return "Huber";
357  else if (model == MaximumLikelihoodWFunctions::HuberModified) return "HuberModified";
358  else if (model == MaximumLikelihoodWFunctions::Welsch) return "Welsch";
359  else if (model == MaximumLikelihoodWFunctions::Chen) return "Chen";
361  "Unknown estimation model enum [" + toString(model) + "].",
362  _FILEINFO_);
363  }
364 
365 
366 
367  MaximumLikelihoodWFunctions::Model MaximumLikelihoodWFunctions::stringToModel(QString modelName) {
368  if (modelName.compare("HUBER", Qt::CaseInsensitive) == 0) {
369  return Huber;
370  }
371  else if (modelName.compare("HUBER_MODIFIED", Qt::CaseInsensitive) == 0 ||
372  modelName.compare("HUBERMODIFIED", Qt::CaseInsensitive) == 0 ||
373  modelName.compare("HUBER MODIFIED", Qt::CaseInsensitive) == 0) {
374  return HuberModified;
375  }
376  else if (modelName.compare("WELSCH", Qt::CaseInsensitive) == 0) {
377  return Welsch;
378  }
379  else if (modelName.compare("CHEN", Qt::CaseInsensitive) == 0) {
380  return Chen;
381  }
382  else {
383  throw IException(IException::Programmer,
384  "Unknown maximum likelihood model name " + modelName + ".",
385  _FILEINFO_);
386  }
387  }
388 
389 
390 
400  if (m_model == Huber || m_model == HuberModified) return "N/A";
401  else if (m_model == Welsch) return toString(m_tweakingConstant * 1.5);
402  else if (m_model == Chen) return toString(m_tweakingConstant);
403  else throw IException(IException::Programmer, "Estimation model has not been set.", _FILEINFO_);
404  }
405 
406 
407 
414  return m_model;
415  }
416 
417 
418 
419  QDataStream &MaximumLikelihoodWFunctions::write(QDataStream &stream) const {
420  stream << (qint32)m_model
422  return stream;
423  }
424 
425 
426 
427  QDataStream &MaximumLikelihoodWFunctions::read(QDataStream &stream) {
428  qint32 model;
429  stream >> model >> m_tweakingConstant;
431  return stream;
432  }
433 
434 
435 
436  QDataStream &operator<<(QDataStream &stream, const MaximumLikelihoodWFunctions &mlwf) {
437  return mlwf.write(stream);
438  }
439 
440 
441 
442  QDataStream &operator>>(QDataStream &stream, MaximumLikelihoodWFunctions &mlwf) {
443  return mlwf.read(stream);
444  }
445 
446 
447 
448  QDataStream &operator<<(QDataStream &stream, const MaximumLikelihoodWFunctions::Model &modelEnum) {
449  stream << (qint32)modelEnum;
450  return stream;
451  }
452 
453 
454 
455  QDataStream &operator>>(QDataStream &stream, MaximumLikelihoodWFunctions::Model &modelEnum) {
456  qint32 modelInteger;
457  stream >> modelInteger;
458  modelEnum = (MaximumLikelihoodWFunctions::Model)modelInteger;
459  return stream;
460  }
461 
462 }// end namespace Isis
Isis::HALFPI
const double HALFPI
The mathematical constant PI/2.
Definition: Constants.h:41
Isis::operator<<
QDebug operator<<(QDebug debug, const Hillshade &hillshade)
Print this class out to a QDebug object.
Definition: Hillshade.cpp:314
Isis::MaximumLikelihoodWFunctions::weightScaler
double weightScaler(double residualZScore)
This provides the scalar for the weight (not the scaler for the square root of the weight,...
Definition: MaximumLikelihoodWFunctions.cpp:186
Isis::MaximumLikelihoodWFunctions::Model
Model
The supported maximum likelihood estimation models.
Definition: MaximumLikelihoodWFunctions.h:56
Isis::MaximumLikelihoodWFunctions::setModel
void setModel(Model modelSelection)
Allows the maximum likelihood model to be changed together and the default tweaking constant to be se...
Definition: MaximumLikelihoodWFunctions.cpp:87
Isis::MaximumLikelihoodWFunctions::tweakingConstantQuantile
double tweakingConstantQuantile()
Suggest a quantile of the probility distribution of the residuals to use as the tweaking constants ba...
Definition: MaximumLikelihoodWFunctions.cpp:324
Isis::MaximumLikelihoodWFunctions::setTweakingConstantDefault
void setTweakingConstantDefault()
Sets default tweaking constants based on the maximum likelihood estimation model being used.
Definition: MaximumLikelihoodWFunctions.cpp:98
Isis::MaximumLikelihoodWFunctions::huberModified
double huberModified(double residualZScore)
Modified Huber maximum likelihood estimation function evaluation.
Definition: MaximumLikelihoodWFunctions.cpp:262
Isis::toString
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:211
Isis::MaximumLikelihoodWFunctions::chen
double chen(double residualZScore)
Modified Huber maximum likelihood estimation function evaluation.
Definition: MaximumLikelihoodWFunctions.cpp:302
Isis::MaximumLikelihoodWFunctions::weightedResidualCutoff
QString weightedResidualCutoff()
Method to return a string represtentation of the weighted residual cutoff (if it exists) for the Maxi...
Definition: MaximumLikelihoodWFunctions.cpp:399
Isis::MaximumLikelihoodWFunctions::modelToString
static QString modelToString(Model model)
Static method to return a string represtentation for a given MaximumLikelihoodWFunctions::Model enum.
Definition: MaximumLikelihoodWFunctions.cpp:355
Isis::MaximumLikelihoodWFunctions::HuberModified
@ HuberModified
A modification to Huber's method propsed by William J.J.
Definition: MaximumLikelihoodWFunctions.h:73
Isis::MaximumLikelihoodWFunctions::MaximumLikelihoodWFunctions
MaximumLikelihoodWFunctions()
Sets up a maximumlikelihood estimation function with Huber model and default tweaking constant.
Definition: MaximumLikelihoodWFunctions.cpp:25
Isis::IException
Isis exception class.
Definition: IException.h:91
Isis::MaximumLikelihoodWFunctions::tweakingConstant
double tweakingConstant() const
Returns the current tweaking constant.
Definition: MaximumLikelihoodWFunctions.cpp:170
Isis::MaximumLikelihoodWFunctions::model
Model model() const
Accessor method to return the MaximumLikelihoodWFunctions::Model enumeration.
Definition: MaximumLikelihoodWFunctions.cpp:413
Isis::MaximumLikelihoodWFunctions::m_tweakingConstant
double m_tweakingConstant
The tweaking constant for the maximum likelihood models.
Definition: MaximumLikelihoodWFunctions.h:143
Isis::IException::Programmer
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:146
Isis::MaximumLikelihoodWFunctions::Welsch
@ Welsch
The Welsch method aggresively discounts measures with large resiudals.
Definition: MaximumLikelihoodWFunctions.h:84
Isis::MaximumLikelihoodWFunctions::huber
double huber(double residualZScore)
Huber maximum likelihood estimation function evaluation.
Definition: MaximumLikelihoodWFunctions.cpp:240
Isis::MaximumLikelihoodWFunctions::Huber
@ Huber
According to Zhang (Parameter Estimation: A Tutorial with application to conic fitting) "[Huber's] es...
Definition: MaximumLikelihoodWFunctions.h:65
Isis::MaximumLikelihoodWFunctions
Class provides maximum likelihood estimation functions for robust parameter estimation,...
Definition: MaximumLikelihoodWFunctions.h:49
Isis::IString
Adds specific functionality to C++ strings.
Definition: IString.h:165
Isis::MaximumLikelihoodWFunctions::sqrtWeightScaler
double sqrtWeightScaler(double residualZScore)
This provides the scaler to the sqrt of the weight, which is very useful for building normal equation...
Definition: MaximumLikelihoodWFunctions.cpp:217
Isis::MaximumLikelihoodWFunctions::m_model
Model m_model
The enumerated value for the maximum likelihood estimation model to be used.
Definition: MaximumLikelihoodWFunctions.h:142
Isis::operator>>
std::istream & operator>>(std::istream &is, CSVReader &csv)
Input read operator for input stream sources.
Definition: CSVReader.cpp:447
Isis::MaximumLikelihoodWFunctions::setTweakingConstant
void setTweakingConstant(double tweakingConstant)
Allows the tweaking constant to be changed without changing the maximum likelihood function.
Definition: MaximumLikelihoodWFunctions.cpp:156
Isis::MaximumLikelihoodWFunctions::welsch
double welsch(double residualZScore)
Modified Huber maximum likelihood estimation function evaluation.
Definition: MaximumLikelihoodWFunctions.cpp:284
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16
Isis::MaximumLikelihoodWFunctions::Chen
@ Chen
The Chen method was found in "Robust Regression with Projection Based M-estimators" Chen,...
Definition: MaximumLikelihoodWFunctions.h:94