casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
NonLinearFit.h
Go to the documentation of this file.
00001 //# NonLinearFit.h: Class for non-linear least-squares fit.
00002 //# Copyright (C) 1994,1995,1996,1999,2000,2001,2002,2004
00003 //# Associated Universities, Inc. Washington DC, USA.
00004 //#
00005 //# This library is free software; you can redistribute it and/or modify it
00006 //# under the terms of the GNU Library General Public License as published by
00007 //# the Free Software Foundation; either version 2 of the License, or (at your
00008 //# option) any later version.
00009 //#
00010 //# This library is distributed in the hope that it will be useful, but WITHOUT
00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013 //# License for more details.
00014 //#
00015 //# You should have received a copy of the GNU Library General Public License
00016 //# along with this library; if not, write to the Free Software Foundation,
00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00018 //#
00019 //# Correspondence concerning AIPS++ should be addressed as follows:
00020 //#        Internet email: aips2-request@nrao.edu.
00021 //#        Postal address: AIPS++ Project Office
00022 //#                        National Radio Astronomy Observatory
00023 //#                        520 Edgemont Road
00024 //#                        Charlottesville, VA 22903-2475 USA
00025 //#
00026 //# $Id: NonLinearFit.h 20229 2008-01-29 15:19:06Z gervandiepen $
00027 
00028 #ifndef SCIMATH_NONLINEARFIT_H
00029 #define SCIMATH_NONLINEARFIT_H
00030 
00031 //# Includes
00032 #include <casa/aips.h>
00033 #include <scimath/Fitting/GenericL2Fit.h>
00034 namespace casa { //# begin namesapce casa
00035 //# Forward declarations
00036 
00037 //
00038 // <summary> Class for non-linear least-squares fit.
00039 // </summary>
00040 //
00041 // <reviewed reviewer="wbrouw" date="2006/06/15" tests="tNonLinearFitLM.cc">
00042 // </reviewed>
00043 //
00044 // <prerequisite>
00045 //   <li> <linkto class="Functional">Functional</linkto> 
00046 //   <li> <linkto class="Function">Function</linkto> 
00047 //   <li> <linkto module="Fitting">Fitting</linkto>
00048 // </prerequisite>
00049 //
00050 // <etymology>
00051 // A nonlinear function is used to fit a set of data points.  
00052 // </etymology>
00053 //
00054 // <synopsis>
00055 // NOTE: Constraints added. Documentation out of date at moment, check
00056 // the tLinearFitSVD and tNonLinearFirLM programs for examples.
00057 //
00058 // The following is a brief summary of the non-linear least-squares fit
00059 // problem.
00060 // See module header, <linkto module="Fitting">Fitting</linkto>,
00061 // for a more complete description.  
00062 //
00063 // Given a set of N data points (measurements), (x(i), y(i)) i = 0,...,N-1, 
00064 // along with a set of standard deviations, sigma(i), for the data points, 
00065 // and a specified non-linear function, f(x;a) where a = a(j) j = 0,...,M-1 
00066 // are a set of parameters to be 
00067 // determined, the non-linear least-squares fit tries to minimize
00068 // <srcblock>
00069 // chi-square = [(y(0)-f(x(0);a)/sigma(0)]^2 + [(y(1)-f(x(1);a)/sigma(1)]^2 + 
00070 //              ... + [(y(N-1)-f(x(N-1);a))/sigma(N-1)]^2.
00071 // </srcblock>
00072 // by adjusting {a(j)} in the equation.
00073 //
00074 // For multidimensional functions, x(i) is a vector, and
00075 // <srcblock> 
00076 // f(x(i);a) = f(x(i,0), x(i,1), x(i,2), ...;a)
00077 // </srcblock>
00078 //
00079 // If the measurement errors (standard deviation sigma) are not known 
00080 // at all, they can all be set to one initially.  In this case, we assume all 
00081 // measurements have the same standard deviation, after minimizing
00082 // chi-square, we recompute
00083 // <srcblock>  
00084 // sigma^2 = {(y(0)-z(0))^2 + (y(1)-z(1))^2 + ... 
00085 //           + (y(N-1)-z(N-1))^2}/(N-M) = chi-square/(N-M).
00086 // </srcblock> 
00087 //
00088 // A statistic weight can be also be assigned to each measurement if the 
00089 // standard deviation is not available. sigma can be calculated from
00090 // <srcblock>
00091 // sigma = 1/ sqrt(weight)
00092 // </srcblock>
00093 // Alternatively a 'weight' switch can be set with <src>asWeight()</src>.
00094 // For best arithmetic performance, weight should be normalized to a maximum
00095 // value of one. Having a large weight value can sometimes lead to overflow
00096 // problems.
00097 //
00098 // The function to be fitted to the data can be given as an instance of the
00099 // <linkto class="Function">Function</linkto> class.
00100 // One can also form a sum of functions using the
00101 // <linkto class="CompoundFunction">CompoundFunction</linkto>.  
00102 //
00103 // For small datasets the usage of the calls is:
00104 // <ul>
00105 //  <li> Create a functional description of the parameters
00106 //  <li> Create a fitter: NonLinearFit<T> fitter();
00107 //  <li> Set the functional representation: fitter.setFunction()
00108 //  <li> Do the fit to the data: fitter.fit(x, data, sigma)
00109 //      (or do a number of calls to buildNormalMatrix(x, data, sigma)
00110 //      and finish of with fitter.fit() or fitter.sol())
00111 //  <li> if needed the covariance; residuals; chiSquared, parameter errors
00112 //       can all be obtained
00113 // </ul>
00114 // Note that the fitter is reusable. An example is given in the following.
00115 //
00116 // The solution of a fit always produces the total number of parameters given 
00117 // to the fitter. I.e. including any parameters that were fixed. In the
00118 // latter case the solution returned will be the fixed value.
00119 // 
00120 // <templating arg=T>
00121 // <li> Float
00122 // <li> Double
00123 // <li> Complex
00124 // <li> DComplex   
00125 // </templating>
00126 //
00127 // If there are a large number of unknowns or a large number of data points
00128 // machine memory limits (or timing reasons) may not allow a complete
00129 // in-core fitting to be performed.  In this case one can incrementally
00130 // build the normal equation (see buildNormalMatrix()).
00131 //
00132 // The normal operation of the class tests for real inversion problems
00133 // only. If tests are needed for almost collinear columns in the
00134 // solution matrix, the collinearity can be set as the square of the sine of
00135 // the minimum angle allowed.
00136 //
00137 // Singular Value Decomposition is supported by setting the 'svd' switch,
00138 // which has a behaviour completely identical to, apart from a
00139 // default collinearity check of 1e-8. 
00140 //
00141 // Other information (see a.o. <linkto class=LSQaips>LSQaips</linkto>) can
00142 // be set and obtained as well.
00143 // </synopsis>
00144 //
00145 // <motivation>
00146 // The creation of the class module was driven by the need to write code
00147 // to fit Gaussian functions to data points.
00148 // </motivation>
00149 //
00150 // <example>
00151 // </example>
00152 
00153 template<class T> class NonLinearFit : public GenericL2Fit<T>
00154 {
00155 public: 
00156   //# Constants
00157   // Default maximum number of iterations (30)
00158   static const uInt MAXITER = 30;
00159   // Default convergence criterium (0.001)
00160   static const Double CRITERIUM;
00161 
00162   //# Constructors
00163   // Create a fitter: the normal way to generate a fitter object. Necessary
00164   // data will be deduced from the Functional provided with
00165   // <src>setFunction()</src>.
00166   // Create optionally a fitter with SVD behaviour specified.
00167   explicit NonLinearFit(Bool svd=False);
00168   // Copy constructor (deep copy)
00169   NonLinearFit(const NonLinearFit &other);
00170   // Assignment (deep copy)
00171   NonLinearFit &operator=(const NonLinearFit &other);
00172 
00173   // Destructor
00174   virtual ~NonLinearFit();
00175 
00176   // setMaxIter() sets the maximum number of iterations to do before stopping.
00177   // Default value is 30.
00178   void setMaxIter(uInt maxIter=MAXITER);
00179 
00180   // getMaxIter() queries what the maximum number of iterations currently is
00181   uInt getMaxIter() const { return maxiter_p; };
00182 
00183   // currentIteration() queries what the current iteration is
00184   uInt currentIteration() const { return maxiter_p - curiter_p; };
00185 
00186   // setCriteria() sets the convergence criteria. The actual value and
00187   // its interpretation depends on the derived class used to do the
00188   // actual iteration. Default value is 0.001.
00189   void setCriteria(const Double criteria=CRITERIUM) {criterium_p = criteria; };
00190 
00191   // getCriteria() queries the current criteria
00192   Double getCriteria() const { return criterium_p; };
00193 
00194   // Check to see if the fit has converged
00195   Bool converged() const { return converge_p; };
00196 
00197 protected:
00198   //#Data
00199   // Maximum number of iterations
00200   uInt maxiter_p;
00201   // Current iteration number
00202   uInt curiter_p;
00203   // Convergence criteria
00204   Double criterium_p;
00205   // Has fit converged
00206   Bool converge_p;
00207 
00208   //# Member functions
00209   // Generalised fitter
00210   virtual Bool fitIt
00211     (Vector<typename FunctionTraits<T>::BaseType> &sol, 
00212      const Array<typename FunctionTraits<T>::BaseType> &x, 
00213      const Vector<typename FunctionTraits<T>::BaseType> &y,
00214      const Vector<typename FunctionTraits<T>::BaseType> *const sigma,
00215      const Vector<Bool> *const mask=0) = 0;
00216   
00217 private: 
00218   //# Data
00219   
00220   //# Member functions
00221   
00222 protected:
00223   //# Make members of parent classes known.
00224   using GenericL2Fit<T>::pCount_p;
00225   using GenericL2Fit<T>::ptr_derive_p;
00226   using GenericL2Fit<T>::arg_p;
00227   using GenericL2Fit<T>::sol_p;
00228   using GenericL2Fit<T>::fsol_p;
00229   using GenericL2Fit<T>::solved_p;
00230   using GenericL2Fit<T>::nr_p;
00231   using GenericL2Fit<T>::svd_p;
00232   using GenericL2Fit<T>::condEq_p;
00233   using GenericL2Fit<T>::fullEq_p;
00234   using GenericL2Fit<T>::err_p;
00235   using GenericL2Fit<T>::ferr_p;
00236   using GenericL2Fit<T>::errors_p;
00237   using GenericL2Fit<T>::valder_p;
00238   using GenericL2Fit<T>::set;
00239   using GenericL2Fit<T>::buildConstraint;
00240   using GenericL2Fit<T>::fillSVDConstraints;
00241   using GenericL2Fit<T>::isReady;
00242 };
00243 
00244 } //# End namespace casa
00245 #ifndef CASACORE_NO_AUTO_TEMPLATES
00246 #include <scimath/Fitting/NonLinearFit.tcc>
00247 #endif //# CASACORE_NO_AUTO_TEMPLATES
00248 #endif