USGS

Isis 3.0 Object Programmers' Reference

Home

MaximumLikelihoodWFunctions.cpp
2 #include "math.h"
3 #include "IException.h"
4 #include "IString.h"
5 #include <stdio.h>
6 
7 namespace Isis {
8 
16  MaximumLikelihoodWFunctions::MaximumLikelihoodWFunctions(Model modelSelection, double tweakingConstant) {
17  //choose Model and define the tweaking constant
18  m_PI = acos(-1.0);
19  m_model = modelSelection;
20  if (tweakingConstant <= 0.0) {
21  IString msg = "Maximum likelihood estimation tweaking constants must be > 0.0";
23  }
25  }
26 
27 
32  MaximumLikelihoodWFunctions::MaximumLikelihoodWFunctions(Model modelSelection) {
33  //choose Model and define the tweaking constant
34  m_PI = acos(-1.0);
35  m_model = modelSelection;
37  }
38 
39 
47  bool MaximumLikelihoodWFunctions::setModel(Model modelSelection, double tweakingConstant) {
48  //choose Model and define the tweaking constant
49  m_model = modelSelection;
50  if (tweakingConstant <= 0.0) {
51  IString msg = "Maximum likelihood estimation tweaking constants must be > 0.0";
53  return false;
54  }
56  return true;
57  }
58 
59 
65  //choose Model and use default tweaking constant
66  m_model = modelSelection;
68  return true;
69  }
70 
71  void MaximumLikelihoodWFunctions::maximumLikelihoodModel(char *model) {
72  switch(m_model) {
73  case Huber:
74  strcpy(model,"Huber");
75  return;
76  case HuberModified:
77  strcpy(model,"HuberModified");
78  return;
79  case Welsch:
80  strcpy(model,"Welsch");
81  return;
82  case Chen:
83  strcpy(model,"Chen");
84  return;
85  default:
86  strcpy(model,"None");
87  return; //default to prevent nonsense from being returned, but the program should never reach this line
88  }
89  }
90 
97  bool MaximumLikelihoodWFunctions::setTweakingConstant(double tweakingConstant) {
98  //leave model type unaltered and change tweaking constant
99  if (tweakingConstant <= 0.0) return false; //the constant must be positive
100  if (tweakingConstant <= 0.0) {
101  IString msg = "Maximum likelihood estimation tweaking constants must be > 0.0";
103  return false;
104  }
106  return true;
107  }
108 
112  return m_c;
113  }
114 
115 
116  void MaximumLikelihoodWFunctions::weightedResidualCutoff(char *cutoff) {
117  switch(m_model) {
118  case Huber:
119  strcpy(cutoff,"N/A");
120  return;
121  case HuberModified:
122  strcpy(cutoff,"N/A");
123  return;
124  case Welsch:
125  sprintf(cutoff,"%lf",m_c*1.5);
126  return;
127  case Chen:
128  sprintf(cutoff,"%lf",m_c);
129  return;
130  default:
131  strcpy(cutoff,"None");
132  return; //default to prevent nonsense from being returned, but the program should never reach this line
133  }
134  }
135 
136 
142  double MaximumLikelihoodWFunctions::weightScaler(double residualZScore) {
143  //this is likely the least usefull of the scaler functions but it is provided for completness. This directly provides the scaler for the weight (instead of the radical weight), thus it provides sqrtWeightScaler^2
144  switch(m_model) {
145  case Huber:
146  return this->huber(residualZScore);
147  case HuberModified:
148  return this->huberModified(residualZScore);
149  case Welsch:
150  return this->welsch(residualZScore);
151  case Chen:
152  return this->chen(residualZScore);
153  default:
154  return 1.0; //default to prevent nonsense from being returned, but the program should never reach this line
155  }
156  }
157 
158 
164  double MaximumLikelihoodWFunctions::sqrtWeightScaler(double residualZScore) {
165  //it is often convient to use square roots of weights when building normals, this function provides the scaler for the square root of the weight directly
166  double scaler = this->weightScaler(residualZScore);
167  if (scaler <= 0.0) return 0.0; //<0 should never happen, but 0.0 may be quite frequent (thus this saves some time)
168  return sqrt(scaler);
169  }
170 
171 
177  double MaximumLikelihoodWFunctions::huber(double residualZScore) {
178  //huber weight function
179  if ( fabs(residualZScore) < m_c) return 1.0;
180  else return m_c/fabs(residualZScore);
181  }
182 
183 
189  double MaximumLikelihoodWFunctions::huberModified(double residualZScore) {
190  //huber modified weight function
191  if ( fabs(residualZScore)/m_c < m_PI/2.0) return m_c*(sin(residualZScore/m_c)/residualZScore);
192  else return m_c/fabs(residualZScore);
193  }
194 
195 
201  double MaximumLikelihoodWFunctions::welsch(double residualZScore) {
202  //welsch weight function
203  return exp(-((residualZScore/m_c)*(residualZScore/m_c)));
204  }
205 
206 
212  double MaximumLikelihoodWFunctions::chen(double residualZScore) {
213  //chen weight function
214  if ( fabs(residualZScore) <= m_c) return 6*(m_c*m_c-residualZScore*residualZScore)*(m_c*m_c-residualZScore*residualZScore);
215  else return 0.0;
216  }
217 
218 
223  //default tweaking constants for the various likelihood models
224  switch(m_model) {
225  case Huber:
226  m_c = 1.345; //"95% asymptotice efficiecy on the standard normal distribution" is obtained with this constant, see Zhang's "Parameter Estimation"
227  break;
228  case HuberModified:
229  m_c = 1.2107; //"95% asymptotice efficiecy on the standard normal distribution" is obtained with this constant, see Zhang's "Parameter Estimation"
230  break;
231  case Welsch:
232  m_c=2.9846; //"95% asymptotice efficiecy on the standard normal distribution" is obtained with this constant, see Zhang's "Parameter Estimation"
233  break;
234  case Chen:
235  m_c=1; //This is the constant used by Chen in his paper, no specific reason why is stated
236  break;
237  default:
238  m_c=1; //default, though at the time of writing this should never actually be used
239  break;
240  }
241  return true;
242  }
243 
244 
250  //returns which quantile of the sqaured residuals is recommended to use as the tweaking constants, this varies as a function of the model being employed
251  //desired quantiles for various models, these parameters are estimated based on inspection of the fucntions and should be tested and revised with experience
252  switch(m_model) {
253  case Huber:
254  return 0.5; //In this model m_c determines the point at which residuals stop having increased influence on the solution, so after the median all the measures will have the same effect on the solution regardless of magnitude
255  case HuberModified:
256  return 0.4; //In this model after residualZScore >= m_c*m_PI/2.0 the residuals have the same influence on the solution,
257  case Welsch:
258  return 0.7; //at about double m_c the residuals have very little influence
259  case Chen:
260  return 0.98; //after r > m_c residuals have no influence
261  default:
262  return 0.5; //default, though at the time of writing this should never actually be used
263  }
264  }
265 
266 }//end namespace Isis