casa
$Rev:20696$
|
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