LMFitter.cxx
Go to the documentation of this file.
1 
12 #ifdef _MSC_VER
13 #include "msdevstudio/MSconfig.h"
14 #endif
15 
16 #include "LMFitter.h"
17 
18 #include "NumLinAlg.h"
19 #include "StatedFCN.h"
20 
21 #include <algorithm>
22 
23 #include <cmath>
24 #include <cassert>
25 
26 #include <climits>
27 
28 #ifdef ITERATOR_MEMBER_DEFECT
29 using namespace std;
30 #else
31 using std::abs;
32 using std::distance;
33 using std::swap;
34 using std::vector;
35 #endif
36 
37 using namespace hippodraw::Numeric;
38 
39 using namespace hippodraw;
40 
41 LMFitter::
42 LMFitter ( const char * name )
43  : Fitter ( name ),
44  m_chi_cutoff ( 0.000001 ),
45  m_start_lambda ( 0.001 ),
46  m_lambda_shrink_factor( 9.8 ),
47  m_lambda_expand_factor( 10.2 )
48 {
49 }
50 
51 
53 LMFitter ( const LMFitter & fitter )
54  : Fitter ( fitter ),
55  m_chi_cutoff ( fitter.m_chi_cutoff ),
56  m_start_lambda ( fitter.m_start_lambda ),
57  m_lambda_shrink_factor ( fitter.m_lambda_shrink_factor ),
58  m_lambda_expand_factor ( fitter.m_lambda_expand_factor )
59 {
60 }
61 
62 
63 Fitter *
65 clone ( ) const
66 {
67  return new LMFitter ( *this );
68 }
69 
73 {
74  m_fcn -> calcAlphaBeta ( m_alpha, m_beta );
75  unsigned int num_parms = m_beta.size();
76 
77  unsigned int j = 0; // for MS VC++
78  for ( ; j < num_parms; j++ ) {
79  for ( unsigned int k = 0; k < j; k++ ) {
80  m_alpha[k][j] = m_alpha[j][k];
81  }
82  }
83 
84  j = 0; // for MS VC++
85  for ( ; j < num_parms; j++ ) {
86  m_alpha[j][j] *= ( 1.0 + m_lambda );
87  }
88 }
89 
95 int LMFitter::calcCovariance ( std::vector < std::vector < double > >& cov )
96 {
97  m_lambda = 0;
98  calcAlpha ();
99 
100  // Invert the semi hessian to get the error covarience matrix
101  // Since we use cholesky factorisation we can conclude if the
102  // given matrix is positive definite or not. So the return value
103  // is EXIT_SUCCESS if m_alpha is Positive Definite, EXIT_FAILURE otherwise.
104  return invertMatrix ( m_alpha, cov );
105 }
106 
108 {
109  unsigned int num_parms = m_beta.size ();
110 
111  vector< int > ipiv ( num_parms, 0 );
112 
113  vector< int > indxr ( num_parms, -1 );
114  vector< int > indxc ( num_parms, -1 );
115 
116  unsigned int irow = UINT_MAX;
117  unsigned int icol = UINT_MAX;
118 
119  for ( unsigned int i = 0; i < num_parms; i++ ) {
120  double big = 0.0;
121 
122  for ( unsigned int j = 0; j < num_parms; j++ ) {
123  if ( ipiv[j] != 1 ) {
124 
125  for ( unsigned int k = 0; k < num_parms; k++ ) {
126  if ( ipiv[k] == 0 ) {
127  if ( abs ( m_alpha[j][k] ) >= big ) {
128  big = abs ( m_alpha[j][k] );
129  irow = j;
130  icol = k;
131  }
132  }
133  else if ( ipiv[k] > 1 ) {
134  return false;
135  }
136  }
137  }
138  }
139 
140  if ( irow == UINT_MAX ) { // something is wrong, can't do fit.
141  return false;
142  }
143 
144  ++ipiv[icol];
145  if ( irow != icol ) {
146  for ( unsigned int l = 0; l < num_parms; l++ ) {
147  swap ( m_alpha[irow][l], m_alpha[icol][l] );
148  }
149  swap ( m_beta[irow], m_beta[icol] );
150  }
151  indxr[i] = irow;
152  indxc[i] = icol;
153  if ( m_alpha[icol][icol] == 0.0 ) {
154  return false;
155  }
156  double pivinv = 1.0 / m_alpha[icol][icol];
157  m_alpha[icol][icol] = 1.0;
158 
159  for ( unsigned int l = 0; l < num_parms; l++ ) {
160  m_alpha[icol][l] *= pivinv;
161  }
162  m_beta[icol] *= pivinv;
163 
164  for ( unsigned int ll = 0; ll < num_parms; ll++ ) {
165  if ( ll != icol ) {
166  double dum = m_alpha[ll][icol];
167  m_alpha[ll][icol] = 0.0;
168 
169  for ( unsigned int l = 0; l < num_parms; l++ ) {
170  m_alpha[ll][l] -= m_alpha[icol][l] * dum;
171  }
172  m_beta[ll] -= m_beta[icol] * dum;
173  }
174  }
175  }
176 
177  for ( int l = num_parms - 1; l >= 0; l-- ) {
178  if ( indxr[l] != indxc[l] ) {
179 
180  for ( unsigned int k = 0; k < num_parms; k++ ) {
181  swap ( m_alpha[k][indxr[l]], m_alpha[k][indxc[l]] );
182  }
183  }
184  }
185  return true;
186 }
187 
189 {
190  calcAlpha ();
191  bool ok = solveSystem ();
192 
193  return ok;
194 }
195 
197 {
199 
200  int i = 0;
201  for ( ; i < m_max_iterations; i++ ) {
202 
203  double old_chisq = objectiveValue ();
204 
205  vector< double > old_parms;
206  m_fcn -> fillFreeParameters ( old_parms );
207 
208  bool ok = calcStep ();
209  assert ( old_parms.size() == m_beta.size() );
210 
211  vector< double > new_parms ( old_parms );
212  vector< double >::iterator pit = new_parms.begin ( );
213  vector< double >::iterator dit = m_beta.begin ( );
214 
215  while ( pit != new_parms.end () ) {
216  *pit++ += *dit++;
217  }
218  m_fcn -> setFreeParameters ( new_parms );
219 
220  double new_chisq = objectiveValue ();
221 
222  if ( abs ( old_chisq - new_chisq ) < m_chi_cutoff ) break;
223 
224  if ( new_chisq < old_chisq ) {
226  }
227  else {
229  m_fcn -> setFreeParameters ( old_parms );
230  }
231 
232  if ( ! ok ) return ok;
233  }
234 
235  return i < m_max_iterations;
236 }
237 
238 
239 void
241 setFCN ( StatedFCN * fcn )
242 {
243  Fitter::setFCN ( fcn );
244  fcn -> setNeedsDerivatives ( true );
245 }
void fillFreeParameters(std::vector< double > &) const
Fills the vector with the free parameters values.
Definition: Fitter.cxx:142
unsigned int i
Collection of linear algebra functions.
virtual bool calcStep()
Takes a step in the fitting and returns the change to the parameters of the function.
Definition: LMFitter.cxx:188
double m_start_lambda
The starting lambda factor.
Definition: LMFitter.h:54
virtual bool calcBestFit()
Calculates the best fit.
Definition: LMFitter.cxx:196
double m_lambda_expand_factor
The factor by which lambda is divided if it is too small.
Definition: LMFitter.h:63
virtual void calcAlpha()
Calculates the alpha matrix.
Definition: LMFitter.cxx:72
int m_max_iterations
The maximum number of iterations allowed in attempting the fit.
Definition: Fitter.h:62
virtual int calcCovariance(std::vector< std::vector< double > > &cov)
Calculates the covariance matrix.
Definition: LMFitter.cxx:95
virtual void setFCN(StatedFCN *fcn)
Sets the objective function object.
Definition: Fitter.cxx:64
The base class for fitters.
Definition: Fitter.h:33
bool ok
Definition: CanvasView.cxx:163
Fitter * clone() const
Makes a copy of the receiving object.
Definition: LMFitter.cxx:65
LMFitter(const LMFitter &)
The copy constructor.
Definition: LMFitter.cxx:53
int invertMatrix(const std::vector< std::vector< double > > &A, std::vector< std::vector< double > > &Ainv)
Inverts a SPD matrix a to get inverse Ainv using the cholesky factorization.
Definition: NumLinAlg.cxx:356
double m_chi_cutoff
The Chi Squared cut-off parameter.
Definition: LMFitter.h:51
std::vector< double > m_beta
The beta vector.
Definition: LMFitter.h:46
double m_lambda_shrink_factor
The factor by which lambda is divided if it is too large.
Definition: LMFitter.h:60
A Fitter class.
Definition: LMFitter.h:33
double m_lambda
The current lambda factor.
Definition: LMFitter.h:57
LMFitter class interface.
virtual double objectiveValue() const
Calculates the value of the objective function at the current set of parameters.
Definition: Fitter.cxx:222
hippodraw::StatedFCN class interface
A derived class for FCNBase class.
Definition: StatedFCN.h:70
StatedFCN * m_fcn
The objective function.
Definition: Fitter.h:59
virtual bool solveSystem()
Solves the system.
Definition: LMFitter.cxx:107
virtual void setFCN(StatedFCN *fcn)
Sets the objective function.
Definition: LMFitter.cxx:241
std::vector< std::vector< double > > m_alpha
The alpha matrix.
Definition: LMFitter.h:43

Generated for HippoDraw Class Library by doxygen