Syntax C/C++ | #include <MFstd.h>
float MF_nonlinfit( fVector A, iVector AStatus, unsigned npars,
fVector X, fVector Y, fMatrix Z, ui htZ, ui lenZ,
void modelfunc(fMatrix ZModel, ui htZ, ui lenZ, fVector X, fVector Y, fVector A ),
void derivatives(fMatrix dZdAi, ui htZ, ui lenZ, fVector X, fVector Y, unsigned ipar, fVector A, MF_NONLINFITWORKSPACE *ws),
VF_NONLINFITOPTIONS *FitOpts,
MF_NONLINFITWORKSPACE *WorkSpace );
float MF_nonlinfitwW( fVector A, fMatrix Covar, iVector AStatus, unsigned npars,
fVector X, fVector Y, fMatrix Z, fMatrix InvVar, ui htZ, ui lenZ,
void modelfunc(fMatrix ZModel, ui htZ, ui lenZ, fVector X, fVector Y, fVector A ),
void derivatives(fMatrix dZdAi, ui htZ, ui lenZ, fVector X, fVector Y, unsigned ipar, fVector A, MF_NONLINFITWORKSPACE *ws),
VF_NONLINFITOPTIONS *FitOpts,
MF_NONLINFITWORKSPACE *WorkSpace ); |
Syntax C/C++ vereinfacht | #include <MFstd.h>
float MF_nonlinfit( fVector A, iVector AStatus, unsigned npars,
fVector X, fVector Y, fMatrix Z, ui htZ, ui lenZ,
void modelfunc(fMatrix ZModel, ui htZ, ui lenZ, fVector X, fVector Y, fVector A ),
void derivatives(fMatrix dZdAi, ui htZ, ui lenZ, fVector X, fVector Y, unsigned ipar, fVector A, MF_NONLINFITWORKSPACE *ws) );
float MF_nonlinfitwW( fVector A, fMatrix Covar, iVector AStatus, unsigned npars,
fVector X, fVector Y, fMatrix Z, fMatrix InvVar, ui htZ, ui lenZ,
void modelfunc(fMatrix ZModel, ui htZ, ui lenZ, fVector X, fVector Y, fVector A ),
void derivatives(fMatrix dZdAi, ui htZ, ui lenZ, fVector X, fVector Y, unsigned ipar, fVector A, MF_NONLINFITWORKSPACE *ws) ); |
C++ MatObj | #include <OptiVec.h>
void vector<T>::nonlinfit( const vector<int>& AStatus,
const vector<T>& X, const vector<T>& Y, const matrix<T>& MZ,
void modelfunc(fMatrix ZModel, ui htZ, ui lenZ, fVector X, fVector Y, fVector A ),
void derivatives(fMatrix dZdAi, ui htZ, ui lenZ, fVector X, fVector Y, unsigned ipar, fVector A, MF_NONLINFITWORKSPACE *ws),
VF_NONLINFITOPTIONS *FitOpts,
MF_NONLINFITWORKSPACE *WorkSpace );
void vector<T>::nonlinfitwW( matrix<T> Covar, const vector<int>& AStatus,
const vector<T>& X, const vector<T>& Y, const matrix<T>& MZ, const matrix<T>& MInvVar,
void modelfunc(fMatrix ZModel, ui htZ, ui lenZ, fVector X, fVector Y, fVector A ),
void derivatives(fMatrix dZdAi, ui htZ, ui lenZ, fVector X, fVector Y, unsigned ipar, fVector A, MF_NONLINFITWORKSPACE *ws),
VF_NONLINFITOPTIONS *FitOpts,
MF_NONLINFITWORKSPACE *WorkSpace );
void vector<T>::nonlinfitwW( matrix<T>* Covar, const vector<int>& AStatus,
const vector<T>& X, const vector<T>& Y, const matrix<T>& MZ, const matrix<T>& MInvVar,
void modelfunc(fMatrix ZModel, ui htZ, ui lenZ, fVector X, fVector Y, fVector A ),
void derivatives(fMatrix dZdAi, ui htZ, ui lenZ, fVector X, fVector Y, unsigned ipar, fVector A, MF_NONLINFITWORKSPACE *ws),
VF_NONLINFITOPTIONS *FitOpts,
MF_NONLINFITWORKSPACE *WorkSpace ); |
C++ MatObj vereinfacht | #include <OptiVec.h>
void vector<T>::nonlinfit( const vector<int>& AStatus,
const vector<T>& X, const vector<T>& Y, const matrix<T>& MZ,
void modelfunc(fMatrix ZModel, ui htZ, ui lenZ, fVector X, fVector Y, fVector A ),
void derivatives(fMatrix dZdAi, ui htZ, ui lenZ, fVector X, fVector Y, unsigned ipar, fVector A, MF_NONLINFITWORKSPACE *ws) );
void vector<T>::nonlinfitwW( matrix<T> Covar, const vector<int>& AStatus,
const vector<T>& X, const vector<T>& Y, const matrix<T>& MZ, const matrix<T>& MInvVar,
void modelfunc(fMatrix ZModel, ui htZ, ui lenZ, fVector X, fVector Y, fVector A ),
void derivatives(fMatrix dZdAi, ui htZ, ui lenZ, fVector X, fVector Y, unsigned ipar, fVector A, MF_NONLINFITWORKSPACE *ws) );
void vector<T>::nonlinfitwW( matrix<T>* Covar, const vector<int>& AStatus,
const vector<T>& X, const vector<T>& Y, const matrix<T>& MZ, const matrix<T>& MInvVar,
void modelfunc(fMatrix ZModel, ui htZ, ui lenZ, fVector X, fVector Y, fVector A ),
void derivatives(fMatrix dZdAi, ui htZ, ui lenZ, fVector X, fVector Y, unsigned ipar, fVector A, MF_NONLINFITWORKSPACE *ws) ); |
Pascal/Delphi | uses MFnlfit;
function MF_nonlinfit( A: fVector; AStatus: iVector; nParameters: UInt;
X, Y: fVector; MZ: fMatrix; htZ, lenZ:UIntSize;
ModelFunc, Derivatives: Pointer;
FitOpts: PVF_NONLINFITOPTIONS;
WorkSpace: PMF_NONLINFITWORKSPACE ): Single;
function MF_nonlinfitwW( A: fVector; Covar: fMatrix; AStatus: iVector; nParameters: UInt;
X, Y: fVector; MZ, MInvVar: fMatrix; htZ, lenZ:UIntSize;
ModelFunc, Derivatives: Pointer;
FitOpts: PVF_NONLINFITOPTIONS;
WorkSpace: PMF_NONLINFITWORKSPACE ): Single;
Syntax der als Parameter übergebenen Funktionen ModelFunc und Derivatives:
procedure ModelFunc( ZModel:fMatrix; htZ, lenZ:UIntSize; X, Y:fVector; A:fVector );
procedure Derivatives( dZdAi:fMatrix; htZ, lenZ:UIntSize; X, Y:fVector; ipar:UInt; A:fVector; ws:PMF_NONLINFITWORKSPACE );
|
Pascal/Delphi vereinfacht | uses MFnlfit;
function MF_nonlinfit( A: fVector; AStatus: iVector; nParameters: UInt;
X, Y: fVector; MZ: fMatrix; htZ, lenZ:UIntSize;
ModelFunc, Derivatives: Pointer ): Single;
function MF_nonlinfitwW( A: fVector; Covar: fMatrix; AStatus: iVector; nParameters: UInt;
X, Y: fVector; MZ, MInvVar: fMatrix; htZ, lenZ:UIntSize;
ModelFunc, Derivatives: Pointer ): Single; | |
Beschreibung | Die X-Y-Z-Eingabedaten werden benutzt, um den Parameter-Vektor A mit npars Elementen ai für eine beliebige Modell-Funktion z = f(x, y) zu bestimmen.
Argumente:
A | Vektor der Länge npars; gibt die berechneten Koeffizienten zurück |
Covar | Matrix der Dimensionen [npars, npars]; gibt die Kovarianzen der Koeffizenten zurück |
AStatus | Vektor der Länge npars; entscheidet darüber, welche Parameter frei oder eingefroren sind |
npars | Gesamtzahl der Parameter |
X, Y | Vektoren der Länge lenZbzw. htZ, die das X-Y-Koordinatensystem der Matrix Z aufspannen |
MZ, MInvVar | Matrizen der Dimensionen [htZ, lenZ] mit den Eingabedaten sowie, bei der gewichteten Variante, dem Kehrwert von deren Varianzen |
modelfunc | Benutzer-definierte Modell-Funktion |
derivatives | Benutzer-definierte Funktion, die die partiellen Ableitungen der Modellfunktion nach den einzelnen Parametern berechnet |
FitOpts | Zeiger auf eine Struktur mit Anpassungs-Optionen, siehe chap. 13.3 |
WorkSpace | Zeiger auf eine Struktur mit internen Variablen, siehe chap. 13.3 |
Die Modell-Funktion (und damit der Parameter-Vektor) kann mehr Parameter enthalten als tatsächlich angepaßt werden sollen. Daher muss ein zusätzlicher Vektor AStatus die Information darüber enthalten, welche Parameter bei ihren Eingabe-Werten eingefroren bleiben sollen (AStatus[i] = 0) und welche anzupassen sind (AStatus[i] = 1). Alle (also auch die freien!) Parameter müssen in A vor dem Aufruf von MF_nonlinfit initialisiert sein. Je besser man sie "errät", desto schneller konvergiert diese Routine. npars bezeichnet die Gesamtzahl der Parameter in A (also nicht nur die freien Parameter!).
Die Modell-Funktion "modelfunc" ist vom Anwender zu schreiben. Sie hat für eine gegebene X-Y-Vektorpaare die entsprechenden theoretischen MZ-Werte zu berechnen. In C/C++ muss sie wie folgt geschrieben werden:
| Modell-Funktion für C/C++ |
void _cdecl MyFunc( fMatrix Z, ui htZ, ui lenZ, fVector X, fVector Y, fVector A )
{
for(ui i=0; i<htZ; i++ )
for(ui j=0; j<lenZ; j++ )
MZ[i][j] = f( X[j], Y[i] );
}
Dabei ist f( X[j], Y[i] ) eine beliebige Funktion, die so kompliziert sein darf, wie es Ihre Anwendung erfordert. Sie darf aber keine Singularitäten besitzen, zumindest innerhalb der ggf. spezifizierten Unter- und Obergrenzen der Parameter (siehe NONLINFITOPTIONS).
Zusätzlich zu der Modell-Funktion benötigt MF_nonlinfit die partiellen Ableitungen von MZ nach allen Parametern A[ipar] entsprechend dem gewählten Modell. Falls sie zumindest zum Teil analytisch bekannt sind, solte man eine Funktion MyDerivs schreiben. Dabei können diejenigen partiellen Ableitungen, die man doch nicht kennt, durch Aufruf von MF_nonlinfit_autoDeriv numerisch berechnet werden.
| Partielle Ableitungen für C/C++ |
void _cdecl MyDerivs( fMatrix dZdAi, ui htZ, ui lenZ, fVector X, fVector Y, unsigned ipar, fVector A, MF_NONLINFITWORKSPACE *ws )
{
ui i;
switch( ipar )
{
case 0:
for(i=0; i<htZ; i++ )
for( j=0; j<lenZ; j++ )
dZdAi[i][j] = part_Abl_MZ_nach_A0( X[j], Y[i] );
break;
case 1:
for(i=0; i<htZ; i++ )
for( j=0; j<lenZ; j++ )
dZdAi[i][j] = part_Abl_MZ_nach_A1( X[j], Y[i] );
break;
default: /* für alle unbekannten Ableitungen: */
MF_nonlinfit_autoDeriv( dZdAi, htZ, lenZ, X, Y, ipar, A, ws );
}
}
Ein Aufruf von MF_nonlinfit wird wie folgt aussehen:
MF_nonlinfit( A, AStatus, npars, X, Y, MZ, htZ, lenZ, MyFunc, MyDerivs, &FitOpts, &WorkSpace );
oder in vereinfachter Syntax (nur, wenn kein expliziter Aufruf von MF_nonlinfit_autoDeriv erforderlich ist):
MF_nonlinfit( A, AStatus, npars, X, Y, MZ, htZ, lenZ, MyFunc, MyDerivs );
Falls überhaupt keine der partiellen Ableitungen analytisch bekannt sind, definiere man auch MyDerivs nicht, sondern setze derivatives = NULL im Aufruf von MF_nonlinfit.
MF_nonlinfit( A, AStatus, npars, X, Y, MZ, htZ, lenZ, MyFunc, NULL );
| Modell-Funktion für Pascal/Delphi |
In Pascal/Delphi muss die Modell-Funktion wie folgt geschrieben werden:
procedure MyFunc( MZ:fMatrix; htZ, lenZ:UIntSize; X, Y, A:fVector );
var i, j:UIntSize;
begin
for i:=0 to htZ-1 do
for j:=0 to lenZ-1 do
MF_Pelement( MZ, htZ, lenZ, i, j )^ :=
f( VF_element( X, j ), VF_element( Y, i ) );
end;
Dabei ist f( Xj, Yi ) eine beliebige Funktion, die so kompliziert sein darf, wie es Ihre Anwendung erfordert. Sie darf aber keine Singularitäten besitzen, zumindest innerhalb der ggf. spezifizierten Unter- und Obergrenzen der Parameter (siehe NONLINFITOPTIONS).
Zusätzlich zu der Modell-Funktion benötigt MF_nonlinfit die partiellen Ableitungen von MZ nach allen Parametern A[ipar] entsprechend dem gewählten Modell. Falls sie zumindest zum Teil analytisch bekannt sind, solte man eine Funktion MyDerivs schreiben. Dabei können diejenigen partiellen Ableitungen, die man doch nicht kennt, durch Aufruf von MF_nonlinfit_autoDeriv numerisch berechnet werden.
| Partielle Ableitungen für Pascal/Delphi |
procedure MyDerivs( dZdAi:fMatrix; htZ, lenZ:UIntSize; X, Y:fVector; ipar:UInt; A:fVector; ws:PMF_NONLINFITWORKSPACE );
var i, j:UIntSize;
begin
case ipar of
0: begin
for i:=0 to ht-1 do
for j:=0 to len-1 do
MF_Pelement( dZdAi, htZ, lenZ, i, j )^ := part_Abl_MZ_nach_A0(VF_element( X, j ),
VF_element( Y, i ));
end;
1: begin
for i:=0 to ht-1 do
for j:=0 to len-1 do
MF_Pelement( dZdAi, htZ, lenZ, i, j )^ := part_Abl_MZ_nach_A1(VF_element( X, j ),
VF_element( Y, i ));
end;
else (* für alle unbekannten Ableitungen: *)
MF_nonlinfit_autoDeriv( dZdAi, htZ, lenZ, X, Y, ipar, A, ws );
end;
end;
Ein Aufruf von MF_nonlinfit sieht dann so aus:
MF_nonlinfit( A, AStatus, npars, MZ, htZ, lenZ, X, Y, @MyFunc, @MyDerivs );
oder in vereinfachter Syntax (nur, wenn kein expliziter Aufruf von MF_nonlinfit_autoDeriv erforderlich ist:
MF_nonlinfit( A, AStatus, npars, MZ, htZ, lenZ, X, Y, @MyFunc, @MyDerivs );
Man beachte die Adress-Operatoren vor "MyFunc " und "MyDerivs". Falls überhaupt keine der partiellen Ableitungen analytisch bekannt sind, definiere man auch MyDerivs nicht, sondern setze derivatives := nil im Aufruf von MF_nonlinfit:
MF_nonlinfit( A, AStatus, npars, MZ, htZ, lenZ, X, Y, @MyFunc, nil );
In der gewichteten Variante MF_nonlinfitwW muss die Matrix MInvVar den Kehrwert der Varianzen der einzelnen X-Y-Z-Datenpunkte enthalten, und die Matrix MCovar gibt die Kovarianzen der Parameter ai zurück: MCovari,j = covariance( ai, aj ). Theoretisch gilt covariance(ai, aj) = covariance(aj, ai); durch Rundungsfehler kann es aber zu geringfügigen Abweichungen kommen.
| Sowohl C/C++ als auch Pascal/Delphi: |
Bezüglich der vielen verschieden Optionen zur Steuerung der nicht-linearen Datenapassungs-Routinen von OptiVec lese man Kap. 13.3. Hilfsfunktionen zum Abbruch überlang laufender Anpassungen und zur Überwachung des Fortganges dieser oft sehr zeitaufwendigen Prozeduren sind in Kap. 13.5 zusammengefaßt und, im Spezialfall von MF_nonlinfit, hier beschrieben. |
|