| VF_nonlinfit
| VD_nonlinfit |
VE_nonlinfit |
| VF_nonlinfitwW |
VD_nonlinfitwW |
VE_nonlinfitwW |
|
| Function | fit y=f(x) data to a model-function which may be nonlinear in its parameters |
|
| Syntax C/C++ | #include <MFstd.h>
float VF_nonlinfit( fVector A, iVector AStatus, unsigned npars, fVector X, fVector Y, ui sizex,
void modelfunc(fVector YModel, fVector XModel, ui size),
void derivatives(fVector dYdAi, fVector X, ui size, unsigned iPar) );
float VF_nonlinfitwW( fVector A, fMatrix Covar, iVector AStatus, unsigned npars, fVector X, fVector Y, fVector InvVar, ui sizex,
void modelfunc(fVector YModel, fVector X, ui size),
void derivatives(fVector dYdAi, fVector X, ui size, unsigned i) ); |
void VF_linfit( fVector A, iVector AStatus, unsigned npars, fVector X, fVector Y, ui sizex,
void funcs(fVector BasFuncs, float x, unsigned nfuncs));
void VF_linfitwW( fVector A, fMatrix Covar, iVector AStatus, unsigned npars, fVector X, fVector Y, fVector InvVar, ui sizex,
void funcs(fVector BasFuncs, float x, unsigned nfuncs));
| C++ MatObj | #include <OptiVec.h>
void vector<T>::nonlinfit( const vector<int>& AStatus, const vector<T>& X, const vector<T>& Y,
void modelfunc(fVector YModel, fVector XModel, ui size),
void derivatives(fVector dYdAi, fVector X, ui size, unsigned iPar) );
void vector<T>::nonlinfitwW( matrix<T> Covar, const vector<int>& AStatus, const vector<T>& X, const vector<T>& Y, const vector<T>& InvVar,
void modelfunc(fVector YModel, fVector XModel, ui size),
void derivatives(fVector dYdAi, fVector X, ui size, unsigned iPar) );
void vector<T>::nonlinfitwW( matrix<T>* Covar, const vector<int>& AStatus, const vector<T>& X, const vector<T>& Y, const vector<T>& InvVar,
void modelfunc(fVector YModel, fVector XModel, ui size),
void derivatives(fVector dYdAi, fVector X, ui size, unsigned iPar) ); |
| Pascal/Delphi | uses VFnlfit;
function VF_nonlinfit( A: fVector; AStatus: iVector; nParameters: UInt; X, Y: fVector; sizex: UInt; ModelFunc, Derivatives: Pointer ): Single;
function VF_nonlinfitwW( A: fVector; Covar: fMatrix; AStatus: iVector; nParameters: UInt; X, Y, InvVar:fVector; sizex: UInt; ModelFunc, Derivatives: Pointer ): Single; |
|
| Description | The input data X, Y (and InvVar) are used to evaluate the parameter array A with npars elements ai of an arbitrary model function y = f(x).
Arguments:
| A | vector of size npars; returns the coefficients |
| Covar | matrix of dimensions [npars, npars]; returns the covariances of the coefficients |
| AStatus | vector of size npars; decides which parameters are treated as free or as fixed |
| npars | total number of parameters |
| X, Y, InvVar | vectors of size sizex, holding the input data |
| modelfunc | user-defined model function |
| derivatives | user-defined function, calculating the partial derivatives with respect to all parameters |
The model function (and, consequently, the vector A as well) may actually contain more parameters than you wish to treat as adjustable. This is why you have to provide an additional vector, AStatus, which contains the necessary information about which parameters are to be held fixed at their input values (AStatus[i] = 0) and which are free (AStatus[i] = 1). All parameters must be initialized in A prior to calling VF_nonlinfit. The better your initial guess of the parameters, the faster VF_nonlinfit shall converge. The argument npars denotes the total number of parameters in A (not only the free parameters!).
You must provide a model function "modelfunc" which, for a given vector of x-values, must calculate the corresponding "theoretical" y-values. In C/C++, it has to be defined as
| | Model function for C/C++ |
void _cdecl MyFunc( fVector Y, fVector X, ui size )
{
for (ui i=0; i<size; i++ )
Y[i] = f( X[i] );
}
f( X[i] ) is any arbitrary function, which may be as complicated as you like and your application needs. The only condition is that it have no singularities, at least within the parameter space specified by upper and lower boundaries (see NONLINFITOPTIONS).
In addition to the model function, VF_nonlinfit needs the partial derivatives of Y with respect to all parameters A[ipar], according to your model. If you know them analytically, you should write a function MyDerivs. If you happen to know only some, but not all of the partial derivatives, you may rely on VF_nonlinfit_autoDeriv to calculate the unknown derivatives numerically.
| | Partial derivatives coded for C/C++ |
void _cdecl MyDerivs( fVector dYdAi, fVector X, ui size, unsigned ipar )
{
ui i;
switch( ipar )
{
case 0: for(i=0; i<size; i++ )
dYdAi[i] = part_derv_of_Y_w_resp_to_A0( X[i] );
break;
case 1: for(i=0; i<size; i++ )
dYdAi[i] = part_derv_of_Y_w_resp_to_A1( X[i] );
break;
default: /* for all derivatives we don't know: */
VF_nonlinfit_autoDeriv( dYdAi, X, size, ipar);
}
}
A call to VF_nonlinfit will look like:
VF_nonlinfit( A, AStatus, npars, X, Y, sizex, MyFunc, MyDerivs );
In case you do not know any of the partial derivatives, do not define MyDerivs, but call VF_nonlinfit with derivaties = NULL:
VF_nonlinfit( A, AStatus, npars, X, Y, sizex, MyFunc, NULL );
| | Model function for Pascal/Delphi |
In Pascal/Delphi, the model function has to be defined as
procedure MyFunc( Y, X:fVector; size:UInt );
var i:UInt;
begin
for i:=0 to size-1 do
VF_Pelement( Y, i )^ := f( VF_element( X, i ) );
end;
f( X[i] ) is any arbitrary function, which may be as complicated as you like and your application needs. The only condition is that it have no singularities, at least within the parameter space specified by upper and lower boundaries (see NONLINFITOPTIONS).
In addition to the model function, VF_nonlinfit needs the partial derivatives of Y with respect to all parameters A[ipar], according to your model. If you know them analytically, you should write a function MyDerivs. If you happen to know only some, but not all of the partial derivatives, you may rely on VF_nonlinfit_autoDeriv to calculate the unknown derivatives numerically.
| | Partial derivatives coded for Pascal/Delphi |
procedure MyDerivs( dYdAi, X:fVector; size, ipar:UInt );
var i:UInt;
begin
case ipar of
0: begin
for i:=0 to size-1 do
VF_Pelement( dYdAi, i )^ := part_derv_of_Y_w_resp_to_A0(VF_element( X, i )); end;
1: begin
for i:=0 to size-1 do
VF_Pelement( dYdAi, i )^ := part_derv_of_Y_w_resp_to_A0(VF_element( X, i )); end;
else (* for all derivatives we don't know: *)
VF_nonlinfit_autoDeriv( dYdAi, X, size, ipar );
end;
end;
A call to VF_nonlinfit will look like:
VF_nonlinfit( A, AStatus, npars, X, Y, sizex, @MyFunc, @MyDerivs );
Note the address-of operator in front of "MyFunc." and "MyDerivs". In Turbo Pascal, both MyFunc and MyDerivs must be compiled with the Force-Far-Calls option {$F+}. In case you do not know any of the partial derivatives, do not define MyDerivs, but call VF_nonlinfit with derivaties = nil:
VF_nonlinfit( A, AStatus, npars, X, Y, sizex, @MyFunc, nil );
In the weighted variant, VF_nonlinfitwW, the vector InvVar has to contain the inverse of the variances of the individual X-Y data points, and the matrix MCovar will be filled with the covariances of the parameters ai on output: MCovari,j = covariance( ai, aj ).
| | Both C/C++ and Pascal/Delphi: |
For the many different options controlling nonlinear data-fitting functions, please consult chapter 13.3. Helper functions for breaking off excessively long fitting runs and for the monitoring of these often very time-consuming procedures are summarized in chapter 13.5 and, in the special case of VF_nonlinfit, described here.
|
|
| Multi-threading restrictions | In order to allow the monitoring functions to access intermediate results, these had to be made global. Therefore, only one instance of a given nonlinear fitting function can be active at a time. If the same function would run in two or more parallel threads, they would overwrite each other's intermediate results. Additionally, in the Delphi version, VF_nonlinfit and VF_nonlinfitwW cannot run simultaneously either. The same is true on the VD_ and on the VE_ level. It is, however, possible, to run VF_nonlinfit and VD_nonlinfit in parallel.
These functions may not be called while the FPU is set to reduced accuracy, or else they might hang in an infinite loop. See V_setFPAccuracy. |
|
| Error handling | If the number of free parameters (i.e., those with AStatus[i] = 1) exceeds the total number of data points, an error message "Invalid parameter(s)" is generated and the program aborted. |
|
| Return value | in case of success: goodness-of-fit parameter c2 (chi-square); in case of failure: -1 |
|
|