VF_nonlinfit VD_nonlinfit VE_nonlinfit
VF_nonlinfitwW VD_nonlinfitwW VE_nonlinfitwW
Funktionnicht-lineare Modellfunktion an y=f(x)-Daten anpassen
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),
    VF_NONLINFITOPTIONS *FitOpts,
    VF_NONLINFITWORKSPACE *WorkSpace );

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),
    VF_NONLINFITOPTIONS *FitOpts,
    VF_NONLINFITWORKSPACE *WorkSpace );

Syntax C/C++ vereinfacht#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) );

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),
    VF_NONLINFITOPTIONS *FitOpts,
    VF_NONLINFITWORKSPACE *WorkSpace );

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),
    VF_NONLINFITOPTIONS *FitOpts,
    VF_NONLINFITWORKSPACE *WorkSpace );

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),
    VF_NONLINFITOPTIONS *FitOpts,
    VF_NONLINFITWORKSPACE *WorkSpace );

C++ MatObj vereinfacht#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/Delphiuses VFnlfit;
function VF_nonlinfit( A: fVector; AStatus: iVector; nParameters: UInt;
    X, Y: fVector; sizex:UIntSize;
    ModelFunc, Derivatives: Pointer;
    FitOpts: PVF_NONLINFITOPTIONS;
    WorkSpace: PVF_NONLINFITWORKSPACE ): Single;

function VF_nonlinfitwW( A: fVector; Covar: fMatrix; AStatus: iVector; nParameters: UInt;
    X, Y, InvVar:fVector; sizex:UIntSize;
    ModelFunc, Derivatives: Pointer;
    FitOpts: PVF_NONLINFITOPTIONS;
    WorkSpace: PVF_NONLINFITWORKSPACE ): Single;

Pascal/Delphi vereinfachtuses VFnlfit;
function VF_nonlinfit( A: fVector; AStatus: iVector; nParameters: UInt;
    X, Y: fVector; sizex:UIntSize;
    ModelFunc, Derivatives: Pointer ): Single;

function VF_nonlinfitwW( A: fVector; Covar: fMatrix; AStatus: iVector; nParameters: UInt;
    X, Y, InvVar:fVector; sizex:UIntSize;
    ModelFunc, Derivatives: Pointer ): Single;

BeschreibungDie X-Y-Eingabedaten werden benutzt, um den Parameter-Vektor A mit npars Elementen ai für eine beliebige Modell-Funktion y = f(x) zu bestimmen.

Argumente:
AVektor der Länge npars; gibt die berechneten Koeffizienten zurück
CovarMatrix der Dimensionen [npars, npars]; gibt die Kovarianzen der Koeffizenten zurück
AStatusVektor der Länge npars; entscheidet darüber, welche Parameter frei oder eingefroren sind
nparsGesamtzahl der Parameter
X, Y, InvVarVektoren der Länge sizex mit den Eingabe-Daten sowie, bei der gewichteten Variante, dem Kehrwert von deren Varianzen
modelfuncBenutzer-definierte Modell-Funktion
derivativesBenutzer-definierte Funktion, die die partiellen Ableitungen der Modellfunktion nach den einzelnen Parametern berechnet
FitOptsZeiger auf eine Struktur mit Anpassungs-Optionen, siehe chap. 13.3
WorkSpaceZeiger 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 muß 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 VF_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 einen gegebenen X-Vektor die entsprechenden Y-Werte zu berechnen. In C/C++ muß sie wie folgt geschrieben werden:

Modell-Funktion für C/C++ void _cdecl MyFunc( fVector Y, fVector X, ui size )
{
  for(ui i=0; i<size; i++ )
    Y[i] = f( X[i] );
}

Dabei ist f( X[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 VF_nonlinfit die partiellen Ableitungen von Y 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 VF_nonlinfit_autoDeriv numerisch berechnet werden.
Partielle Ableitungen für C/C++ VF_NONLINFITWORKSPACE WorkSpace; /* sollte eine globale Variable sein, dieselbe, die an VF_nonlinfit übergeben wird */

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_Abl_Y_nach_A0( X[i] );
    break;
    case 1: for(i=0; i<size; i++ )
              dYdAi[i] = part_Abl_Y_nach_A1( X[i] );
    break;
    default: /* für alle unbekannten Ableitungen: */
            VF_nonlinfit_autoDeriv( dYdAi, X, size:UIntSize; ipar, &WorkSpace);
  }
}

Ein Aufruf von VF_nonlinfit sieht dann so aus:
VF_nonlinfit( A, AStatus, npars, X, Y, sizex, MyFunc, MyDerivs, &FitOpts, &WorkSpace );
oder in vereinfachter Syntax (nur, falls in MyDerivs alle Ableitungen analytisch bekannt sind und kein Aufruf von VF_nonlinfit_autoDeriv erforderlich ist): VF_nonlinfit( A, AStatus, npars, X, Y, sizex, MyFunc, MyDerivs );
Falls überhaupt keine der partiellen Ableitungen analytisch bekannt sind, definiere man auch MyDerivs nicht, sondern setze derivatives = NULL im Aufruf von VF_nonlinfit:
VF_nonlinfit( A, AStatus, npars, X, Y, sizex, MyFunc, NULL );
 

Modell-Funktion für Pascal/Delphi In Pascal/Delphi muß die Modell-Funktion wie folgt geschrieben werden:
procedure MyFunc( Y, X:fVector; size:UIntSize );
var i:UIntSize;
begin
  for i:=0 to size-1 do
    VF_Pelement( Y, i )^ := f( VF_element( X, i ) );
end;

Dabei ist f( Xi ) 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 VF_nonlinfit die partiellen Ableitungen von Y 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 VF_nonlinfit_autoDeriv numerisch berechnet werden.
Partielle Ableitungen für Pascal/Delphi var WorkSpace: VF_NONLINFITWORKSPACE; (* sollte eine globale Variable sein, dieselbe, die an VF_nonlinfit übergeben wird *)

procedure MyDerivs( dYdAi, X:fVector; size:UIntSize; ipar:UInt );
var i:UIntSize;
begin
  case ipar of
    0: begin
      for i:=0 to size-1 do
        VF_Pelement( dYdAi, i )^ :=
        part_Abl_Y_nach_A0(VF_element( X, i )); end;
    1: begin
      for i:=0 to size-1 do
        VF_Pelement( dYdAi, i )^ :=
        part_Abl_Y_nach_A0(VF_element( X, i )); end;
  else (* für alle unbekannten Ableitungen: *)
    VF_nonlinfit_autoDeriv( dYdAi, X, size:UIntSize; ipar, @WorkSpace );
  end;
end;

Ein Aufruf von VF_nonlinfit sieht dann folgendermaßen aus:
VF_nonlinfit( A, AStatus, npars, X, Y, sizex, @MyFunc, @MyDerivs, @FitOpts, @WorkSpace );
oder in vereinfachter Syntax (nur, wenn kein expliziter Aufruf von VF_nonlinfit_autoDeriv erforderlich ist):
VF_nonlinfit( A, AStatus, npars, X, Y, sizex, @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 VF_nonlinfit:
VF_nonlinfit( A, AStatus, npars, X, Y, sizex, @MyFunc, nil );

In der gewichteten Variante VF_nonlinfitwW muß der Vektor InvVar den Kehrwert der Varianzen der einzelnen X-Y -Datenpunkte enthalten, und die Matrix MCovar gibt die Kovarianzen der Parameter ai zurück: MCovari,j = covariance( ai, aj ).

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 VF_nonlinfit, hier beschrieben.
Beschränkungen des Multi-threadingDie in den OptiVec-Versionen bis einschließlich 6.1 vorhandenen Multi-Threading-Einschränkungen sind mit Version 6.2 aufgehoben.

Diese Funktionen dürfen nicht aufgerufen werden, wenn die FPU auf reduzierte Genauigkeit geschaltet wurde. Andernfalls können sie in einer unendlichen Schleife hängenbleiben, siehe V_setFPAccuracy.

FehlerbehandlungÜbersteigt die Zahl der freien Parameter (also derjenigen mit AStatus[i] = 1) die Gesamtzahl der anzupassenden Datenpunkte, so wird eine Fehlermeldung "Invalid parameter(s)" ausgegeben und das Programm abgebrochen.
RückgabewertBei Erfolg: Anpassungstest-Wert c2 (chi-Quadrat)
Wenn keine Verbesserung des Parametersatzes erzielt werden konnte: -1
QuerverweisVF_setNonlinfitOptions,   MF_nonlinfit,   VF_linfit,   Kap. 13,  FITDEMO*.*

MatrixLib Inhaltsverzeichnis  OptiVec Home