|
MatrixLibInhaltsverzeichnis1. Einführung1.1 Matrix-Datentypen 1.2 Präfixe von MatrixLib-Funktionen 1.3 C/C++ -spezifisch 1.3.1 MatObj, das objekt-orientierte Interface für Matrix-Funktionen 1.3.2 Alternative Aufruf-Form von Matrix-Funktionen mit direkten Zeigern 1.4 Pascal/Delphi-spezifisch 2. Dynamische Allokation von Matrizen 3. Initialisierung von Matrizen 4. Datentyp-Umwandlungen 5. Symmetrie-Operationen (Transposition, Rotation, Spiegelung), Interpolation, Erweiterung, Verkleinerung, Extraktion sowie Initialisierung von Teilen von Matrizen 6. Arithmetische Operationen einer einzelnen Zeile, Spalte oder der Diagonalen 7. Operationen, die auf alle Zeilen oder alle Spalten gleichzeitig oder auf die Diagonale wirken; Schwerpunkt einer Matrix 8. Operationen von zwei Zeilen oder zwei Spalten 9. Arithmetik ganzer Matrizen: Addition und Multiplikation 10. Lineare Algebra 11. Eigenwerte und Eigenvektoren, Quadratwurzel 12. Zwei-dimensionale Fourier-Transform-Methoden 13. Datenanpassung (Fitting) 13.1 Polynome 13.2 Allgemeine lineare Modellfunktionen 13.3 Nicht-lineare Modelle 13.4 Anpassung von Mehrfach-Datensätzen 13.5 Hilfsfunktionen für nicht-lineare Anpassungen 13.6 Übersicht der Anpassungsfunktionen 14. Matrix-Eingabe und -Ausgabe 15. Graphische Darstellung von Matrizen 16. Alphabetische Referenz für MatrixLib 1. EinführungDer MatrixLib-Teil von OptiVec baut auf den im VectorLib-Teil eingeführten Prinzipien auf. Sie sollten die Einführungskapitel der VectorLib-Dokumentation gelesen haben, bevor Sie hier mit MatrixLib fortsetzen.Zurück zum MatrixLib-Inhaltsverzeichnis OptiVec Home 1.1 Matrix-DatentypenIn Analogie zu den Vektor-Datentypen von VectorLib definiert MatrixLib die folgenden Matrix-Datentypen:
Die Speicher-Ordnung der Matrix-Elemente ist dieselbe wie in den zwei-dimensionalen Feldern des jeweiligen Compilers. Dies bedeutet, daß die MatrixLib-Versionen für C und C++ Matrizen zeilenweise speichern, während die Pascal/Delphi-Versionen mit spaltenweiser Ordnung arbeiten. Wir empfehlen, in Ihren Programmen ausschließlich mit diesen dynamisch allozierten Matrizen zu arbeiten. Es ist aber möglich, statische Matrizen, die z.B. als
Zurück zum MatrixLib-Inhaltsverzeichnis OptiVec Home 1.2 Präfixe von MatrixLib-FunktionenJede MatrixLib-Funktion besitzt ein Präfix, das den Datentyp anzeigt, den die betreffende Funktion verarbeitet:
In einigen Fällen wird das Präfix um einen Code aus drei Buchstaben erweitert, der spezielle Matrix-Eigenschaften anzeigt:
Zurück zum MatrixLib-Inhaltsverzeichnis OptiVec Home 1.3 C/C++ -spezifisch:1.3.1 MatObj, das objekt-orientierte Interface für Matrix-FunktionenAnalog zu den Vektor-Objekten von VecObj ist das objekt-orientierte Interface für die Matrix-Funktionen in den Include-Dateien <fMatObj.h>, <dMatObj.h> etc. implementiert, wobei jeder in OptiVec vorhandene Datentyp seine eigene Include-Datei erhält. Es sei aber daran erinnert, daß das gesamte Interface (für alle Vektor- und Matrix-Typen zusammen) durch Einschluß von <OptiVec.h> zur Verfügung gestellt wird.Um irgendeine Vektor- oder Matrix-Graphikfunktion benutzen zu können, muß immer <OptiVec.h> eingeschlossen werden. Ähnlich den Alias-Namen der Vektor-Objekte erhalten die Matrix-Objekte die Alternativ-Namen fMatObj, dMatObj usw., wobei wie immer der Datentyp durch die ersten ein oder zwei Buchstaben des Klassen-Namens angegeben wird. Die Matrix-Konstruktoren sind:
Für die Matrix-Klassen sind die arithmetischen Operatoren
Sollten Sie einmal in die Lage kommen, ein MatObj-Matrixobjekt mit einer "klassischen" C-MatrixLib-Funktion verarbeiten zu wollen, benutzen Sie bitte die Member-Funktionen Die Syntax aller MatObj-Funktionen wird unten bei allen MatrixLib-Funktionen mit angegeben, so weit sie von tMatObj gekapselt werden. Die strikte Kontrolle der Matrix-Dimensionen auf Konsistenz führt zu einigen Besonderheiten gegenüber den "normalen" MF_-Funktionen:
1.3.2 Alternative Aufruf-Form von Matrix-Funktionen mit direkten ZeigernIn der C/C++-Version von MatrixLib existieren alle Funktionen, die Matrizen als Argumente erwarten, in einer zweiten Form. In dieser sind alle Matrix-Argumente ersetzt durch Zeiger auf das Element [0,0] der jeweiligen Matrix. Man kann diese zweite Form explizit verwenden, indem der Unterstrich des Funktions-Präfixes fortgelassen wird. Ein Aufruf vonMF_mulM( MC, MA, MB, htA, lenA, lenB ); ist äquivalent zu MFmulM(&(MC[0][0]),&(MA[0][0]),&(MB[0][0]),htA,lenA,lenB); oder MFmulM( MC[0], MA[0], MB[0], htA, lenA, lenB ); Tatsächlich besteht die Laufzeitversion aller MatrixLib-Routinen aus dieser zweiten Form, in die die in <MFstd.h> usw. definierten Maktros alle Aufrufe der ersten Form umwandeln. Zurück zum MatrixLib-Inhaltsverzeichnis OptiVec Home 1.4 Pascal/Delphi- spezifisch:In der Pascal/Delphi-Version von MatrixLib werden die Matrizen aller Datentypen als Zeiger zu dem Element M[0][0] implementiert. Dies bedeutet, daß statische Matrizen (wie z.B. MX: array[0..5][0..5] of Single; ) an MatrixLib-Funktionen mit dem Adressen-Operator übergeben werden können:MF_equ1( @(MX[0][0]), 6 ); Delphi 4 oder höher:
Im zweidimensionalen Fall ist die Situation leider etwas komplizierter. Dynamische 2-D-Felder werden in Delphi als "array of fArray", "array of dArray" usw. deklariert. Auch hierfür bietet die VecLib-unit Kurzdefinitionen: f2DArray, d2DArray, usw. Aus der beschriebenen Implementation zweidimensionaler Felder in Delphi ergibt sich, daß jede Zeile einer Matrix als separater Vektor gespeichert wird. Dies hat zur Folge, daß die Matrix-Elemente nicht mehr innerhalb eines zusammenhängenden Speicherbereiches abgelegt werden, was sich wiederum sehr ungünstig auf die Performance von Matrix-Funktionen auswirkt und verhindert, daß Delphi-2DArrays direkt in MatrixLib-Funktionen eingesetzt werden können. Stattdessen müssen sie in "echte" Matrizen kopiert werden mittels MF_2DArrayToMatrix usw., bevor sie an MatrixLib-Funktionen übergeben werden können. Die Rück-Umwandlung wird durch MF_MatrixTo2DArray bewerkstelligt. Die folgenden Kapitel bieten eine kurze Übersicht aller MatrixLib-Funktionen, geordnet nach ihrer Funktionalität. Am Schluß dieser Datei enthält Kap. 16 eine detaillierte Beschreibung der einzelnen Funktionen in alphabetischer Ordnung. Zurück zum MatrixLib-Inhaltsverzeichnis OptiVec Home 2. Dynamische Allokation von Matrizen
Die dynamisch allozierten Matrizen von OptiVec sind an 64-ByteGrenzen ausgerichtet und dadurch optimal angepaßt an die Cache-Organisation moderner Prozessoren. Nur C/C++-Version:
Sowohl C/C++- als auch Pascal/Delphi-Version:
Um einem spezifischen Matrix-Element einen Wert zuzuweisen, gebrauche man die Syntax *(MF_Pelement( MX, ht, len, 3, 4 )) = 3.0; /* für C/C++*/ MF_Pelement( MX, ht, len, 3, 4 )^ := 3.0; (* für Pascal/Delphi *) Zurück zum MatrixLib-Inhaltsverzeichnis OptiVec Home 3. Initialisierung von MatrizenUm alle Matrix-Elemente mit ein- und demselben Wert zu initialisieren, oder um dieselbe arithmetische Operation auf alle Matrix-Elemente gleichzeitig anzuwenden, kann man die entsprechende VectorLib-Funktion aufrufen. Dies ist möglich, da alle Matrizen tatsächlich als Vektoren gespeichert sind und einen zusammenhängenden Speicherbereich belegen. Man muß lediglich die erste Zeile der Matrix (anstelle der Matrix selbst) an die gewünschte Vektor-Funktion übergeben. Um beispielsweise alle Matrix-Elemente mit einer Konstanten C zu initialisieren, rufe man:VF_equC( MA[0], ht*len, C ); /* C/C++ */ VF_equC( MA, ht*len, C ); (* Pascal/Delphi *) Die gebräuchlichsten Operationen dieser Art sind auch explizit als Matrix-Funktionen in MatrixLib definiert, wie die Initialisierung mit 0, MF_equ0, oder die Multiplikation mit einer Konstanten, MF_mulC (siehe Kap. 9). Die typischen Matrix-Initialisierungen sind:
Zwei-dimensionale Fenster für räumliche Spektralanalyse werden geliefert durch:
Zurück zum MatrixLib-Inhaltsverzeichnis OptiVec Home 4. Datatyp-UmwandlungenMatrizen jeden Datentyps können in jeden anderen Datentyp ungewandelt werden. Ein paar Beispiele hierfür sollten genügen. Der Rest ergibt sich wohl von selbst.
Zurück zum MatrixLib-Inhaltsverzeichnis OptiVec Home 5. Symmetrie-Operationen (Transposition, Rotation, , Spiegelung),
|
MF_transpose | Matrix transponieren: MB = MAT |
MCF_hermconj | Hermitesch konjugierte Matrix: MB = MAT* |
MF_rotate90 | Matrix 90° im Uhrzeigersinn rotieren |
MF_rotate180 | Matrix 180° rotieren |
MF_rotate270 | Matrix 270° im Uhrzeigersinn (bzw. 90 ° entgegen dem Uhrzeigersinn) rotieren |
MF_Rows_rev | Umkehrung der Element-Reihenfolge innerhalb der Zeilen. Dies entspricht einer Spiegelung der Matrix an der Y-Achse |
MF_Cols_rev | Umkehrung der Element-Reihenfolge innerhalb der Spalten. Dies entspricht einer Spiegelung der Matrix an der X-Achse |
MF_Rows_reflect | obere Hälfte (d.h. höhere Indizes) aller Zeilen gleich der am Mittelpunkt reflektierten unteren Hälfte setzen |
MF_Cols_reflect | obere Hälfte (d.h. höhere Indizes) aller Spalten gleich der am Mittelpunkt reflektierten unteren Hälfte setzen |
MF_UequL | Unterdiagonal- (engl. "lower-diagonal")Elemente durch Reflexion an der Diagonalen in die Überdiagonal- (engl. upper-diagonal) Elemente kopieren, um eine symmetrische Matrix zu erhalten |
MF_LequU | Überdiagonal- in Unterdiagonal-Elemente kopieren |
MF_polyinterpol | Polynom-Interpolation |
MF_ratinterpol | rationale Interpolation |
MF_natCubSplineInterpol | "natürliche" kubische Spline-Interpolation |
MF_equMblock | einen Block, d.h. eine aus benachbarten Zeilen bzw. Spalten bestehende Teilmatrix, extrahieren |
MF_equMblockT | die Transponierte eines Blocks extrahieren |
MF_submatrix | Teilmatrix extrahieren, wobei die Abtast-Intervalle entlang der Zeilen bzw. Spalten von 1 verschieden sein dürfen |
MF_block_equM | Matrix in einen Block einer anderen (normalerweise größeren) Matrix kopieren |
MF_block_equMT | transponierte Matrix in einen Block einer anderen (normalerweise größeren) Matrix kopieren |
MF_submatrix_equM | Matrix in eine Teilmatrix einer (normalerweise größeren) Matrix kopieren |
MF_Row_extract | Einzelne Zeile extrahieren und in einen Vektor kopieren |
MF_Col_extract | Einzelne Spalte extrahieren und in einen Vektor kopieren |
MF_Dia_extract | Diagonale extrahieren und in einen Vektor kopieren |
MF_Trd_extract | tridiagonale Matrix aus allgemeiner Matrix extrahieren |
MF_Row_insert | Matrix durch Einfügen einer Zeile erweitern |
MF_Col_insert | Matrix durch Einfügen einer Spalte erweitern |
MF_Row_delete | Matrix durch Entfernen einer Zeile verkleinern |
MF_Col_delete | Matrix durch Entfernen einer Spalte verkleinern |
nur C++ mit dynamisch allozierten Matrizen:
Fall MA durch Spalten-Einfügung oder -Löschung von MB überschrieben wird, geht die Möglichkeit verloren, einzelne Matrix-Elemente als MB[i][j] anzusprechen. Der Grund hierfür ist, daß die Zeilen-Zeiger der Ausgabe-Matrix immer noch dieselben wie in der Eingabe-Matrix bleiben. Dann bieten nur noch MF_element und MF_Pelement Zugang zu den einzelnen Elementen. Falls auf der anderen Seite ausschließlich Zeilen eingefügt oder gelöscht werden, bleiben die Zeilen-Zeiger gültig.
Zurück zum MatrixLib-Inhaltsverzeichnis OptiVec Home
MF_Row_neg | Multiplikation aller Elemente einer bestimmten Zeile mit -1 |
MF_Col_neg | Multiplikation aller Elemente einer bestimmten Spalte mit -1 |
MF_Row_addC | eine Konstante zu allen Elementen einer bestimmten Zeile hinzuaddieren |
MF_Col_addC | eine Konstante zu allen Elementen einer bestimmten Spalte hinzuaddieren |
MF_Dia_addC | eine Konstante zu allen Elementen der Diagonalen hinzuaddieren |
MF_Row_addV | Vektor-Elemente zu den korrespondierenden Elementen einer bestimmten Zeile hinzuaddieren |
MF_Col_addV | Vektor-Elemente zu den korrespondierenden Elementen einer bestimmten Spalte hinzuaddieren |
MF_Dia_addV | Vektor-Elemente zu den korrespondierenden Elementen der Diagonalen hinzuaddieren |
MF_Row_subC | eine Konstante von allen Elementen einer bestimmten Zeile subtrahieren |
MF_Col_subrC | umgekehrte Subtraktion: Differenz zwischen Spalten-Elementen und einer Konstanten |
MF_Dia_mulV | Diagonal-Elements mit korrespondierenden Vector-Elementen multiplizieren |
MF_Row_divV | Elemente einer bestimmten Zeile durch korrespondierende Vektor-Elemente dividieren |
MF_Col_divrC | umgekehrte Division: eine Konstante durch die einzelnen Elemente einer Spalte dividieren |
Zurück zum MatrixLib-Inhaltsverzeichnis OptiVec Home
MF_Rows_max | Maxima der einzelnen Zeilen in einem Spaltenvektor speichern |
MF_Cols_max | Maxima der einzelnen Spalten in einem Zeilenvektor speichern |
MF_Dia_max | Maximum der Diagonalen als Skalar zurückgeben |
MF_Rows_absmax | Betrags-Maxima der einzelnen Zeilen in einem Spaltenvektor speichern |
MF_Cols_absmax | Betrags-Maxima der einzelnen Spalten in einem Zeilenvektor speichern |
MF_Dia_absmax | Betrags-Maximum der Diagonalen als Skalar zurückgeben |
MF_Rows_sum | Summen über die einzelnen Zeilen in einem Spaltenvektor speichern |
MF_Cols_sum | Summen über die einzelnen Spalen in einem Zeilenvektor speichern |
MF_Dia_sum | Summe der Diagonalelemente |
MF_Rows_prod | Produkte über die einzelnen Zeilen in einem Spaltenvektor speichern |
MF_Cols_prod | Producte über die einzelnen Spalen in einem Zeilenvektor speichern |
MF_Dia_prod | Produkt der Diagonal-Elemente |
MF_Rows_runsum | laufende Summe entlang der Zeilen |
MF_Cols_runsum | laufende Summe entlang der Spalten |
MF_Rows_runprod | laufendes Produkt entlang der Zeilen |
MF_Cols_runprod | laufendes Produkt entlang der Spalten |
MF_Rows_rotate | alle Zeilen um eine bestimmte Anzahl von Positionen rotieren |
MF_Cols_rotate | alle Spalten um eine bestimmte Anzahl von Positionen rotieren |
MF_Rows_reflect | obere Hälfte (d.h. höhere Indizes) aller Zeilen gleich der am Mittelpunkt reflektierten unteren Hälfte setzen |
MF_Cols_reflect | obere Hälfte (d.h. höhere Indizes) aller Spalten gleich der am Mittelpunkt reflektierten unteren Hälfte setzen |
Man beachte, daß die Multiplikation aller Zeilen oder aller Spalten mit ein- und demselben Vektor äquivalent zur Multiplikation mit einer Diagonal-Matrix ist. Diese Operation wird durch MF_mulMdia und MF_TmulMdia bewerkstelligt.
Zu allen oben aufgeführten Maximum-Funktionen (...max, ...absmax) existieren die entsprechenden Minimum-Funktionen und sind als ...min bzw. ...absmin benannt.
Für komplexe Zahlen lassen sich verschiedene Kriterien zur Definition eines Maximums definieren. Die folgende Tabelle faßt die existierenden Maximum-Funktionen für komplexe Matrizen zusammen. Natürlich existieren auch hier die entsprechenden Minimum-Funktionen.
MCF_Rows_absmax | Betrags-Maxima der einzelnen Zeilen in einem (reellen) Spaltenvektor speichern |
MCF_Cols_absmax | Betrags-Maxima der einzelnen Spalten in einem (reellen) Zeilenvektor speichern |
MCF_Dia_absmax | Betrags-Maximum der Diagonale als (reellen) Skalarwert zurückgeben |
MCF_Rows_absmaxReIm | betragsmäßig größte Real- und Imaginärteile einzeln entlang der Zeilen suchen und als Real- bzw. Imaginärteile eines komplexen Spaltenvektors speichern |
MCF_Cols_absmaxReIm | betragsmäßig größte Real- und Imaginärteile einzeln entlang der Spalten suchen und als Real- bzw. Imaginärteile eines komplexen Zeilenvektors speichern |
MCF_Dia_absmaxReIm | betragsmäßig größten Real- und Imaginärteil einzeln entlang der Diagonale suchen und als Real- bzw. Imaginärteil einer komplexen Zahl zurückgeben |
MCF_Rows_cabsmax | bezüglich Absolutwert definierte Maxima der einzelnen Zeilen in einem Spaltenvektor speichern |
MCF_Cols_cabsmax | bezüglich Absolutwert definierte Maxima der einzelnen Spalten in einem Zeilenvektor speichern |
MCF_Dia_cabsmax | bezüglich Absolutwert definiertes Maximum entlang der Diagonale suchen und als Skalar zurückgeben |
MCF_Rows_maxReIm | größte Real- und Imaginärteile einzeln entlang der Zeilen suchen und als Real- bzw. Imaginärteile eines komplexen Spaltenvektors speichern |
MCF_Cols_maxReIm | größte Real- und Imaginärteile einzeln entlang der Spalten suchen und als Real- bzw. Imaginärteile eines komplexen Zeilenvektors speichern |
MCF_Dia_maxReIm | größten Real- und Imaginärteil einzeln entlang der Diagonale suchen und als Real- bzw. Imaginärteil einer komplexen Zahl zurückgeben |
MCF_Rows_sabsmax | bezüglich der Summe |Re|+|Im| definierte Maxima der einzelnen Zeilen in einem Spaltenvektor speichern |
MCF_Cols_sabsmax | bezüglich der Summe |Re|+|Im| definierte Maxima der einzelnen Spalten in einem Zeilenvektor speichern |
MCF_Dia_sabsmax | bezüglich der Summe |Re|+|Im| definiertes Maximum entlang der Diagonale suchen und als Skalar zurückgeben |
Zur Berechnung des Schwerpunktes einer Matrix stehen zwei Funktionen zur Verfügung:
MF_centerOfGravityInd | Schwerpunkt einer Matrix in Form interpolierter Element-Indizes |
MF_centerOfGravityV | Schwerpunkt einer MZ-Matrix bei explizit gegebener X- und Y-Achse |
Zurück zum MatrixLib-Inhaltsverzeichnis OptiVec Home
MF_Rows_exchange | zwei Zeilen vertauschen |
MF_Cols_exchange | zwei Spalten vertauschen |
MF_Rows_add | eine Zeile zu einer anderen hinzuaddieren (Ziel += Quelle) |
MF_Cols_add | eine Spalte zu einer anderen hinzuaddieren |
MF_Rows_sub | eine Zeile von einer anderen abziehen (Ziel -= Quelle) |
MF_Cols_sub | eine Spalte von einer anderen abziehen |
MF_Rows_Cadd | eine mit einem konstanten Faktor skalierte Zeile zu einer anderen Zeile hinzuaddieren (Ziel += C * Quelle) |
MF_Cols_Cadd | eine mit einem konstanten Faktor skalierte Spalte zu einer anderen Spalte hinzuaddieren |
MF_Rows_lincomb | Linearkombination zweier Zeilen |
MF_Cols_lincomb | Linearkombination zweier Spalten |
Zurück zum MatrixLib-Inhaltsverzeichnis OptiVec Home
MF_addM | zwei Matrizen addieren |
MF_addMT | eine Matrix und die Transponierte einer weiteren Matrix addieren MC = MA + MBT |
MF_subM | eine Matrix von einer anderen subtrahieren |
MF_subMT | transponierte Matrix subtrahieren MC = MA - MBT |
MF_subrMT | Matrix von der Transponierten einer anderen Matrix subtrahieren MC = MBT - MA |
MF_mulC | alle Matrix-Elemente mit einer Konstanten multiplizieren |
MCF_mulReC | alle Elemente einer komplexen Matrix mit einer reellen Konstanten multiplizieren |
MF_divC | alle Matrix-Elemente durch eine Konstante dividieren |
MCF_divReC | alle Elemente einer komplexen Matrix durch eine reelle Konstante dividieren |
MFs_addM | skalierte Addition zweier Matrizen MC = c * (MA + MB) |
MFs_addMT | skalierte Addition von einer Matrix und einer transponierten anderen MC = c * (MA + MBT) |
MFs_subM | skalierte Subtraktion zweier Matrizen MC = c * (MA - MB) |
MFs_subMT | skalierte Subtraktion von einer Matrix minus der Transponierten einer anderen MC = c * (MA - MBT) |
MFs_subrMT | skalierte umgekehrte Subtraktion: transponierte Matrix minus eine andere MC = c * (MBT - MA) |
MF_lincomb | Linearkombination MC = ca * MA + cb * MB |
b) Matrix-Multiplikation
MF_mulV | Matrix mit einem Spaltenvektor multiplizieren: Y = MA * X |
MF_TmulV | transponierte Matrix mit einem Spaltenvektor multiplizieren: Y = MAT * X |
VF_mulM | Zeilenvektor mit einer Matrix multiplizieren: Y = X * MA |
VF_mulMT | Zeilenvektor mit transponierter Matrix multiplizieren: Y = X * MAT |
MF_mulM | Multiplikation zweier Matrizen: MC = MA * MB |
MF_mulMT | eine Matrix mit der Transponierten einer anderen multiplizieren: MC = MA * MBT |
MF_TmulM | transponierte Matrix mit einer anderen Matrix multiplizieren: MC = MAT * MB |
MF_TmulMT | transponierte Matrix mit einer anderen transponierten Matrix multiplizieren: MC = MAT * MBT |
MCF_mulMH | eine Matrix mit der Hermitesch-konjugierten Form einer anderen multiplizieren: MC = MA * MBT * |
MCF_HmulM | Hermitesch-konjugierte Form einer Matrix mit einer anderen Matrix multiplizieren: MC = MAT * * MB |
c) Multiplikation von allgemeinen Matrizen mit Diagonalmatrizen und umgekehrt
Die Diagonalmatrix wird an die jeweilige Funktion als Vektor übergeben, der nur aus den Diagonalelementen besteht.
MF_mulMdia | allgemeine Matrix mit Diagonalmatrix multiplizieren: MC = MA * MBDia |
MF_TmulMdia | transponierte allgemeine Matrix mit Diagonalmatrix multiplizieren: MC = MAT * MBDia |
MFdia_mulM | Diagonalmatrix mit allgemeiner Matrix mutliplizieren: MC = MADia * MB |
MFdia_mulMT | Diagonalmatrix mit transponierter allgemeiner Matrix mutliplizieren: MC = MADia * MBT |
Zurück zum MatrixLib-Inhaltsverzeichnis OptiVec Home
Hier sind zunächst die einfachen Funktionen:
MF_solve | Lösen eines linearen Gleichungs-Systems (unter Verwendung von LU-Faktorisierung) |
MF_inv | Matrix invertieren |
MF_det | Determinante einer Matrix |
MFsym_solve | Lösen eines symmetrischen linearen Gleichungs-Systems, das als positiv-definit angenommen wird (unter Verwendung von Cholesky-Faktorisierung; falls das System sich dabei als nicht-positiv-definit herausstellt, wird LU-Faktorisierung angewandt) |
MFsym_inv | Symmetrische, als positiv-definit angenommene Matrix invertieren |
MFsym_det | Determinante einer symmetrischen, als positiv-definit angenommenen Matrix |
MF_solveBySVD | Lineares Gleichungssystem unter Verwendung von Singulärwert-Zerlegung (SVD) lösen |
MF_safeSolve | "sicheres" Lösen eines linearen Gleichungssystemes: zuerst wird Lösung über LUD versucht; schlägt diese fehl, wird SVD angewandt |
MF_LUdecompose | Faktorisierung in die LU-Form |
MF_LUDresult | prüfen, ob MF_LUdecompose erfolgreich war |
MF_LUDsetEdit | Editier-Schwelle für MF_LUdecompose setzen; dies kann zur Umgehung von Singularitäten dienen |
MF_LUDgetEdit | aktuell eingestellte Editier-Schwelle lesen |
MF_LUsolve | Lösung eines linearen Gleichungssystems bei Vorliegen der Matrix in LU-Form |
MF_LUimprove | Genauigkeit der über LU-Faktorisierung erzielten Lösung eines linearen Gleichungssystems iterativ verbessern |
MF_LUinv | Bereits in LU-Form faktorisierte Matrix invertieren |
MF_LUdet | Determinante einer bereits in LU-Form vorliegenden Matrix |
MF_CholeskyLdecompose | Cholesky-Faktorisierung in linke Dreiecksmatrix |
MF_CholeskyRdecompose | Cholesky-Faktorisierung in rechte Dreiecksmatrix |
MF_CholeskyLsolve | Lösung eines positiv-definiten Gleichungssystems bei Vorliegen der Matrix in linker Dreiecks-Form |
MF_CholeskyRsolve | Lösung eines positiv-definiten Gleichungssystems bei Vorliegen der Matrix in rechter Dreiecks-Form |
MF_CholeskyLimprove | Genauigkeit der über Cholesky-Faktorisierung in L-Form erzielten Lösung eines linearen Gleichungssystems iterativ verbessern |
MF_CholeskyRimprove | Genauigkeit der über Cholesky-Faktorisierung in R-Form erzielten Lösung eines linearen Gleichungssystems iterativ verbessern |
MF_CholeskyLinv | Bereits durch Cholesky-Faktorisierung in L-Form vorliegende Matrix invertieren |
MF_CholeskyRinv | Bereits durch Cholesky-Faktorisierung in R-Form vorliegende Matrix invertieren |
MF_CholeskyDet | Determinante einer entweder in L- oder in R-Form vorliegenden Matrix |
MF_SVdecompose | Singulärwert-Zerlegung |
MF_SVsort | Sortierung von Singulärwerten in absteigender Reihenfolge unter entsprechender Um-Ordnung der linken und rechten Singulär-Vektoren |
MF_SVsolve | Singulärwert-zerlegtes Gleichungssystem lösen |
MF_SVDsetEdit | Editier-Schwelle für Dimensions-Reduktion bei SV-Lösung setzen |
MF_SVDgetEdit | aktuell eingestellte Editier-Schwelle für Dimensions-Reduktion bei SV-Lösung lesen |
Zurück zum MatrixLib-Inhaltsverzeichnis OptiVec Home
MFsym_eigenvalues | Eigenwerte mit oder ohne Eigenvektoren einer symmetrischen reellen Matrix |
MFsym_sqrt | Quadratwurzel einer symmetrischen Matrix mit ausschließlich positiven Eigenwerten |
Zurück zum MatrixLib-Inhaltsverzeichnis OptiVec Home
MF_FFTtoC | Schnelle Fourier-Transformation (engl.: Fast Fourier Transform, FFT) einer rellen Matrix in Vorwärts-Richtung; das Ergebnis ist eine komplexe Matrix |
MF_FFT | Vorwärts- und Rückwärts-FFT reeller Matrizen; unter Verwendung von Symmetrie-Eigenschaften wird das komplexe Ergebnis in eine reelle Matrix derselben Dimensionen wie die Eingabe-Matrix gepackt |
MCF_FFT | Vorwärts- und Rückwärts-FFT komplexer Matrizen |
MF_convolve | Faltung (engl.: convolution) mit einer räumlichen Impulsantwort-Funktion |
MF_deconvolve | Entfaltung (engl.: deconvolution) |
MF_filter | Räumliche Filterung |
MF_autocorr | Räumliche Autokorrelation |
MF_xcorr | Räumliche Kreuzkorrelation |
MF_spectrum | Raumfrequenz-Spektrum |
MF_Rows_FFT | Fourier-Transformation der Zeilen |
MF_Cols_FFT | Fourier-Transformation der Spalten |
Zurück zum MatrixLib-Inhaltsverzeichnis OptiVec Home
VF_linregress | lineare Regression von X-Y-Daten mit gleicher Wichtung aller Datenpunkte |
VF_linregresswW | dasselbe mit ungleicher Wichtung |
VF_polyfit | Koeffizienten eines Polynoms an vorhandene X-Y-Daten anpassen |
VF_polyfitwW | dasselbe mit ungleicher Wichtung der Datenpunkte |
VF_linfit | Koeffizienten einer beliebigen, in ihren Parametern linearen Funktion an vorhandene X-Y-Daten anpassen |
VF_linfitwW | dasselbe mit ungleicher Wichtung der Datenpunkte |
VF_nonlinfit | Koeffizienten einer beliebigen, möglicherweise nicht-linearen Funktion an vorhandene X-Y-Daten anpassen |
VF_nonlinfitwW | dasselbe mit ungleicher Wichtung der Datenpunkte |
VF_multiLinfit | mehrere X-Y-Datensätze gleichzeitig an eine gemeinsame lineare Funktion anpassen |
VF_multiLinfitwW | dasselbe mit ungleicher Wichtung der Datenpunkte |
VF_multiNonlinfit | mehrere X-Y-Datensätze gleichzeitig an eine gemeinsame nicht-lineare Funktion anpassen |
VF_multiNonlinfitwW | dasselbe mit ungleicher Wichtung der Datenpunkte |
MF_linfit | Koeffizienten einer in ihren Parametern linearen Funktion an X-Y-Z-Daten anpassen |
MF_linfitwW | dasselbe mit ungleicher Wichtung der Datenpunkte |
MF_nonlinfit | Koeffizienten einer nicht-linearen Funktion an X-Y-Z-Daten anpassen |
MF_nonlinfitwW | dasselbe mit ungleicher Wichtung der Datenpunkte |
MF_multiLinfit | mehrere X-Y-Z-Datensätze gleichzeitig an eine gemeinsame lineare Funktion anpassen |
MF_multiLinfitwW | dasselbe mit ungleicher Wichtung der Datenpunkte |
MF_multiNonlinfit | mehrere X-Y-Z-Datensätze gleichzeitig an eine gemeinsame nicht-lineare Funktion anpassen |
MF_multiNonlinfitwW | dasselbe mit ungleicher Wichtung der Datenpunkte |
Im folgenden werden die verschiedenen Klassen von Modellfunktionen einzeln besprochen. Das einfachste Modell besteht aus einer Geraden:
Yi = a * Xi + b;
Die Anpassung von Y = f(X)-Daten an eine Gerade heißt "lineare Regression" und wird durch VF_linregress durchgeführt.
Die nächst-höhere Stufe von Modellfunktionen stellen Polynome dar, die im folgenden Absatz besprochen werden:
void LinModel( fVector BasFuncs, float x, unsigned nfuncs )
{
BasFuncs[0] = sin(x);
BasFuncs[1] = cos(x);
}
Man beachte, daß die Koeffizienten ai in der Modellfunktion gar nicht auftauchen. Das Argument nfuncs (das im obigen Beispiel ignoriert wird) ermöglicht es, eine variable Anzahl von Basisfunktionen zu verwenden. Man kann außerdem Anpassungsparameter "an" und "aus" schalten, d.h. zwischen "freien" und "eingefrorenen" Parametern wechseln. Hierfür übernimmt die Routine VF_linfit einen "Status"-Vektor als Argument. Für alle Elemente des Parameter-Vektors, die als frei behandelt werden sollen, muß der entsprechende "Status"-Eintrag auf 1 gesetzt werden. Setzt man Statusi gleich 0, so wird der entsprechende Parameter ai auf seinem Anfangswert eingefroren. Eingefrorene Werte müssen vor Aufruf von VF_linfit initialisiert werden.
Intern verwendet VF_linfit einen SVD-Algorithmus, um eine Lösung selbst für (nahezu) singuläre lineare Gleichungssysteme zu erhalten. Koeffizienten ai, deren Signifikanz unter einer bestimmten Schwelle Thresh liegt, werden dabei gleich 0 anstatt Unendlich gesetzt. Die Schwelle kann durch Aufruf von VF_setLinfitNeglect modifiert werden. Um den aktuell eingestellten Schwellenwert zu lesen, rufe man VF_getLinfitNeglect.
Nachdem bereits oben bemerkt wurde, daß Funktionen wie
y = sin(a0x)+ cos(a1x)
ihre eigene Behandlung erfordern, erreichen wir die letzte und allgemeinste Klasse von Modellfunktionen:
void NonlinModel( fVector Y, fVector X, ui size, fVector A)
{
for( ui i=0; i<size; i++ )
Y[i] = sin( A[0]*X[i] ) + cos( A[1]*X[i] );
}
Aus der beschriebenen Arbeitsweise der Anpassungs-Routine wird klar, dass sie den größten Teil der Rechenzeit in Ihrer Modellfunktion (und deren Ableitungen, siehe unten) verbringen wird. Daher sollte diese weitestmöglich mit Hilfe der in OptiVec bereitgestellten Vektor-Funktionen optimiert werden. Hierzu könnten Sie vor dem Aufruf von VF_nonlinfit einen fVector YHelp bereitstellen (entweder global mittels VF_vector alloziert oder bei kleineren Vektoren auch lokal auf dem Stack). Dann können Sie schreiben:
void OptNonlinModel( fVector Y, fVector X, ui size, fVector A)
{
VFx_sin( YHelp, X, size, A[0], 0.0, 1.0 );
VFx_cos( Y, X, size, A[1], 0.0, 1.0 );
VF_addV( Y, Y, YHelp, size );
}
Der Parameter-Vektor "A", den Sie als Argument an VF_nonlinfit übergeben, wird im Verlauf des Anpassungs-Prozesses immer weiter verbessert. Beim Aufruf von VF_nonlinfit muss "A" mit bereits möglichst "guten" Werten der Parameter initialisiert sein. Je besser Sie diese "raten", umso schneller wird VF_nonlinfit konvergieren. Raten Sie gar zu schlecht, kann die Konvergenz wesentlich langsamer oder im schlimmsten Fall auch überhaupt nicht erreicht werden.
Alle nonlinfit-Funktionen geben den Anpassungstest-Wert (für Anpassung nach kleinsten Fehlerquadraten: c2, chi-Quadrat; für Anpassung nach kleinstem Absolut-Fehler: |c|, chiabs) des besten Parameter-Satzes "A" zurück.
Um die Anpassung durchführen zu können, benötigen diese Funktionen nicht nur die Modellfunktion selbst, sondern auch noch deren partielle Ableitungen nach den einzelnen Koeffizienten. Hierfür dient das Argument "Derivatives", das an alle nonlinfit-Funktionen übergeben werden muss. Falls Sie die partiellen Ableitungen in analytischer Form kennen, sollte Derivatives auf eine Funktion zeigen, die diese berechnet. Kennen Sie sie nicht, setzen Sie beim Funktionsaufruf Derivatives = NULL (nil in Pascal/Delphi). Im letzteren Fall werden alle Ableitungen numerisch innerhalb der Routinen bestimmt. In Fällen, wo Sie zwar einige, aber nicht alle der partiellen Ableitungen von Y nach den Koeffizienten ai kennen, können Sie dY / dai selbst berechnen, wo immer Sie die analytische Formel kennen, und VF_nonlinfit_autoDeriv für die übrigen Koeffizienten aufrufen. Um diese Möglichkeiten zu demonstrieren, sei hier erneut unser nicht-lineares sinus- und cosinus-Beispiel bemüht:
void DerivModel( fVector dYdAi, fVector X, ui size, unsigned iPar, fVector A, VF_NONLINFITWORKSPACE *ws )
{
switch( iPar )
{
case 0:
for( ui i=0; i<size; i++ )
dYdAi[i] = X[i] * cos( A[0]*X[i] );
break;
case 1: /* wir kennen diese Ableitung zwar; aber nehmen wir einmal an, dies wäre nicht der Fall: */
VF_nonlinfit_autoDeriv( dYdAi, X, size:UIntSize; ipar, A, ws );
}
}
Bevor Sie allerdings VF_nonlinfit_autoDeriv tatsächlich einsetzen, sollten Sie alle Anstrengungen unternehmen, eine eventuell existierende analytische Lösung herauszufinden: Die für die numerische Ableitung notwendige Zahl von Funktionsaufrufen kann Ihre Anpassung leicht um einen Faktor von 3 bis 10 verlangsamen! Ohnehin sollten, ähnlich wie oben die Modellfunktion, auch deren Ableitungen möglichst mit Hilfe von Vektorfunktionen programmiert werden. Die optimierte Version von DerivModel lautet dann wie folgt:
void OptDerivModel( fVector dYdAi, fVector X, ui size, unsigned iPar, fVector A, VF_NONLINFITWORKSPACE *ws )
{
switch( iPar )
{
case 0:
VFx_cos( dYdAi, X, size, A[0], 0.0, 1.0 );
VF_mulV( dYdAi, dYdAi, X, size ); break;
case 1:
VFx_sin( dYdAi, X, size, A[1], 0.0, -1.0 );
VF_mulV( dYdAi, dYdAi, X, size );
}
}
Vollständige Beispiele für Anpassung an Polynome, allgemeine lineare und allgemeine nicht-lineare Modelle sind in den Dateien FITDEMO.CPP, FITDEMOW.CPP, FITDEMOB.BPR, FITDEMO.PAS und FITDEMO.DPR enthalten.
Die nichtlinearen Anpassungs-Routinen von OptiVecsind sehr vielseitig einstellbar mit Hilfe von Optionen, die durch Aufruf der Funktion V_setNonlinfitOptions gewählt werden können. Um die aktuell eingestellten Optionen zu lesen, rufe man V_getNonlinfitOptions.
Alle Optionen sind in eine Struktur (struct in C/C++, record in Pascal/Delphi) namens VF_NONLINFITOPTIONS zusammengefaßt. Diese besteht aus den folgenden Feldern:
int FigureOfMerit; | 0: kleinste Fehlerquadrate als Qualitätskriterium der Anpassung
1: "robuste" Anpassung, die auf betragsmäßig minimale Abweichung hin optimiert (Standard: 0) |
float AbsTolChi; | absolute Änderung von c2 (Standard: EPSILON) |
float FracTolChi; | relative Änderung von c2 (Standard: SQRT_EPSILON) |
float AbsTolPar; | absolute Änderung aller Parameter (Standard: SQRT_MIN) |
float FracTolPar; | relative Änderung aller Parameter (Standard: SQRT_EPSILON)
Die vier xxxTolChi und xxxTolPar-Parameter beschreiben die Konvergenz-Kriterien: Wenn die in aufeinanderfolgenden Iterationen erreichten Verbesserungen kleiner als nach Maßgabe dieser Parameter verlangt ausfällt, signalisiert dies erreichte Konvergenz. Nicht-anwendbare Kriterien sollten auf 0.0 gesetzt werden. Mindestens ein Konvergenz-Kriterium muß aber ungleich 0 sein! |
unsigned HowOftenFulfill; | Wie oft hintereinander soll eine der obigen Begingungen erfüllt sein, bevor Konvergenz als erreicht betrachtet wird? (Standard: 3) |
unsigned LevelOfMethod; | 1: Levenberg-Marquardt-Methode,
2: Downhill Simplex-Methode nach Nelder und Mead, 3: beide Methoden abwechselnd; man addiere hierzu 4, um auch einen "Ausbruch" aus lokalen Minima zu versuchen, in denen die Routine ansonsten "hängenbleiben" würde, ohne jemals das globale Minimum zu erreichen; 0: keine Anpassung, nur c2 (und Covar) berechnen (Standard: 1) |
unsigned LevMarIterations; | max. Anzahl erfolgreicher LevMar -Iterationen während eines Durchgangs (Standard: 100) |
unsigned LevMarStarts; | Anzahl von LevMar-Neustarts pro Durchgang (Standard: 2) |
float LambdaStart,
LambdaMin, LambdaMax, LambdaDiv, LambdaMul; | Behandlung des LevMar-Parameters Lambda (nicht verändern, außer Sie kennen sich mit dem Algorithmus aus!) |
unsigned DownhillIterations; | max. Anzahl erfolgreicher Downhill-Simplex-Iterationen während eines Durchgangs (Standard: 200) |
float DownhillReflection,
DownhillContraction, DownhillExpansion; | Behandlung der Form-Anpassung des Simplex in der Downhill-Simplex-Methode (nicht verändern, außer Sie kennen sich mit dem Algorithmus aus!) |
unsigned TotalStarts; | max. Anzahl von LevMar/Downhill-Paaren (Standard: 16) |
fVector UpperLimits, LowerLimits; | obere und/oder untere Grenzen für die Parameter festlegen. Standard für beides: NULL or nil |
void (*Restrictions)(void); | Zeiger zu einer benutzerdefinierten Funktion, die Beschränkungen der Parameter implementiert, die nicht als einfache Unter- und Obergrenzen formuliert werden können. Diese Funktion muss den ganzen Parameter-Vektor prüfen und die Parameter nach Bedarf editieren. Standard: NULL or nil.
Ein Beispiel für den Einsatz von Restrictions wäre ein Modell, in dem die Parameter Ai in (auf- oder absteigender) Ordnung sein müssen. Ihre Restrictions-Funktion würde dann VF_sort aufrufen, um diese Ordnung durch eventuellen Austausch von Ai-Einträgen zu garantieren. Von solchen doch sehr speziellen Fällen abgesehen, ist es aber generell besser, Restrictions gar nicht zu nutzen, sondern die nonlinfit-Routine ihre Arbeit ohne "Einmischung" tun zu lassen. |
Wie oben beschrieben, benötigen alle nicht-linearen Anpassungsfunktionen einen Satz von internen Variablen, der zusammengefasst als struct (Delphi: record) VF_NONLINFITWORKSPACE über seine Adresse an die jeweilige Funktion übergeben und wiederum von dieser verwendet wird, um alle benötigten Daten an Unter- und Hilfsfunktionen zu übergeben. Dieser Variablen-Satz muss nicht initialisiert werden; er enthält keine nutzbaren Informationen für den Anwender. Bei den Funktionen der MF_nonlinfit-Familie wird analog ein (von VF_NONLINFITWORKSPACE leicht verschiedener) Variablen-Satz als MF_NONLINFITWORKSPACE benötigt.
Man schreibe also in C/C++:
VF_NONLINFITWORKSPACE ws;
VF_NONLINFITOPTIONS fopt;
V_getNonlinfitOptions( &fopt );
// an dieser Stelle "fopt" nach Bedarf modifizieren...
VF_nonlinfit( ParValues, AStatus, nParameters, X, Y, sz, ModelFunc, DerivativeFuncs, &ws, &fopt );
oder in Delphi:
ws: VF_NONLINFITWORKSPACE;
fopt: V_NONLINFITOPTIONS;
V_getNonlinfitOptions( @fopt );
// an dieser Stelle "fopt" nach Bedarf modifizieren...
VF_nonlinfit( ParValues, AStatus, nParameters, X, Y, sz, @ModelFunc, @DerivativeFuncs, @ws, @fopt );
Wird beim Aufruf von VF_nonlinfit der entsprechende Paremeter gleich NULL / nil gesetzt, so erzeugt und verwendet die aufgerufene Funktion ihren eigenen Workspace.
fVector X, Y; | X und Y-Vektoren: unabhängige Variable x und gemessene Daten y=f(x) |
fVector InvVar; | Kehrwert der Varianzen der einzelnen Meßwerte (wird nur für die "gewichteten" Varianten benötigt) |
ui size; | Zahl der x-y-Meßwerte |
float WeightOfExperiment; | Gewicht, daß dem gesamten Experiment zugewiesen werden soll (wiederum nur für die "gewichteten" Varianten benötigt) |
fVector X, Y; | X und Y-Vektoren (unabhängige Variablen x und y) |
fMatrix Z; | gemessene z=f(x,y)-Daten |
fMatrix InvVar; | Kehrwert der Varianzen der einzelnen Meßwerte (wird nur für die "gewichteten" Varianten benötigt) |
unsigned htZ, lenZ; | Matrix-Dimensionen |
float WeightOfExperiment; | Gewicht, daß dem gesamten Experiment zugewiesen werden soll (wiederum nur für die "gewichteten" Varianten benötigt) |
type VF_EXPERIMENT = record
X, Y, InvVar: fVector;
size: UInt;
WeightOfExperiment: Single;
end;
type PVF_EXPERIMENT = ^VF_EXPERIMENT;
type MF_EXPERIMENT = record
X, Y: fVector;
MZ, MInvVar: fMatrix;
htZ, lenZ: UInt;
WeightOfExperiment: Single;
end;
type PMF_EXPERIMENT = ^MF_EXPERIMENT;
Sowohl in VF_EXPERIMENT als auch in MF_EXPERIMENT sollten InvVar und WeightOfExperiment nur für die gewichteten Varianten der multifit-Funktionen gesetzt werden.
VF_nonlinfit_getBestValues | bislang bester Parameter-Satz |
VF_nonlinfit_getFOM | bislang bester Anpassungstest-Wert (c2, chi-Quadrat) |
VF_nonlinfit_getTestDir | aktuelle Test-Richtung (+1 für aufwärts, -1 für abwärts) während "Ausbruchs"-Versuchen (LevelOfMethod größer als 3, siehe die obige Beschreibung von VF_NONLINFITOPTIONS) |
VF_nonlinfit_getTestPar | Index des derzeit bezüglich "Ausbruchs" geprüften Parameters |
VF_nonlinfit_getTestRun | Indes des aktuellen "Ausbruchs"-Durchlaufs (für jeden Fit-Parameter wird ein Testdurchlauf durchgeführt) |
VF_nonlinfit_stop | Anpassung nach Vervollständigung des laufenden Levenberg-Marquardt- oder Downhill-Simplex-Zyklus beenden |
Es gibt zwei Möglichkeiten, diese Funktionen aufzurufen. Erstens können sie aus der ja vom Benutzer zu schreibenden Modellfunktion heraus angesprochen werden. Sie könnten hierfür beispielsweise einen Zähler in Ihrer Modellfunktion installieren, der alle hundert Aufrufe das erreichte c2, den Parametersatz usw. ausliest. Der zweite Weg steht nur Multithread-Programmen offen: Ein Thread führt die Anpassung aus, und ein weiterer ist für den Aufruf der obigen Hilfs-Funktionen zuständig, um den Fortgang der Anpassung zu überprüfen.
Beide Wege verlangen, dass der verwendete VF_NONLINFITWORKSPACE global zugänglich ist. Wenn eine Nonlinfit-Funktion aus mehreren Threads gleichzeitig aufgerufen wird, gibt es natürlich ein Problem, vor allem, wenn der Aufruf der Hilfsfunktionen aus der Modellfunktion heraus erfolgen soll: Woher soll die Modellfunktion "wissen", von welchem Thread heraus sie aufgerufen wurde? Die Lösung: Man speichere einen Thread-Index in den einzelnen Parameter-Vektoren A. Dies könnte in Ihrem Hauptprogramm beispielsweise so ähnlich aussehen wie:
float A1[11], A2[11], ...;
int AStatus1[11], AStatus2[11], ...;
VF_NONLINFITWORKSPACE ws1, ws2, ...;
....
VF_random( A1, 10, 1, -1.0, +1.0 ); // Startwerte
VI_equC( AStatus1, 10, 1 ); // die ersten 10 Parameter sollen angepasst werden
A1[10] = 1; // Thread-Index = 1
AStatus1[10] = 0; // der Thread-Index bleibt natürlich eingefroren
... Thread #1 erzeugen mit VF_nonlinfit und A1, AStatus1, ws1 als Argumenten
VF_random( A2, 10, 1, -1.0, +1.0 ); // Startwerte des 2. Satzes
VI_equC( AStatus2, 10, 1 ); // wieder die ersten 10 Parameter anpassen
A2[10] = 2; // Thread-Index = 2
AStatus2[10] = 0; // Thread-Index wieder eingefroren
... Thread #2 erzeugen mit VF_nonlinfit und A2, AStatus2, ws2 als Argumenten
In Ihrer Modellfunktion hätten Sie dann etwas in der Art von:
void ModelFunc( fVector Y, fVector X, ui size, fVector A )
{
static unsigned counter1=0, counter2=0, ...;
float CurrentFOM;
....
switch( (unsigned)(A[10]) )
{
case 1: if( (++counter1 % 1024) == 0 )
{ CurrentFOM = VF_nonlinfit_getFOM( ws1 );
printf( "\nCount 1: %u, FOM: %f", counter1, CurrentFOM );
} break;
case 1: if( (++counter2 % 1024) == 0 )
{ CurrentFOM = VF_nonlinfit_getFOM( ws2 );
printf( "\nCount 2: %u, FOM: %f", counter2, CurrentFOM );
} break;
....
}
....
}
Zurück zum MatrixLib-Inhaltsverzeichnis OptiVec Home
MF_cprint | Matrix auf dem Bildschirm ausgeben. Falls nötig, werden Zeilen am Bildschirmrand abgeschnitten. Falls mehr Zeilen auszugeben sind als auf einen Schirm passen, wird die Matrix auf mehrere Seiten aufgeteilt. (nur für Delphi) |
MF_print | Matrix auf dem Bildschirm ausgeben (ohne Abschneiden von Zeilen und ohne Aufteilung auf mehrere Seiten; nur für Delphi) |
MF_fprint | Matrix im ASCII-Format in einen Stream schreiben |
MF_store | im Binärformat speichern |
MF_recall | im Binärformat einlesen |
MF_write | im ASCII-Format in einen Stream schreiben |
MF_read | im ASCII-Format von einem Stream einlesen |
Zurück zum MatrixLib-Inhaltsverzeichnis OptiVec Home
MF_xyzAutoDensityMap | Farbton-Plot für z=f(x,y) mit automatischer Skalierung der x und y-Achsen und der Farbton-Skala zwischen mincolor und maxcolor |
MF_xyzDataDensityMap | Farbton-Plot für z=f(x,y) in ein bereits existierendes Koordinatensystem unter Verwendung der durch einen früheren Aufruf einer AutoDensityMap-Funktion berechneten Farbton-Skala |
MF_zAutoDensityMap | Farbton-Plot für z=f(i,j) mit automatischer Skalierung der x und y-Achsen und der Farbton-Skala zwischen mincolor und maxcolor. i und j sind die Matrix-Indizes in x und y-Richtung |
MF_zDataDensityMap | Farbton-Plot für z=f(i,j) in ein bereits existierendes Koordinatensystem unter Verwendung der durch einen früheren Aufruf einer AutoDensityMap-Funktion berechneten Farbton-Skala |
M_setDensityBounds | Festsetzen einer Farbton-Skala |
M_setDensityMapBounds | Festsetzen einer Farbton-Skala und Zeichnung eines X-Y-Koordinatensystems |
M_findDensityMapBounds | Berechnung einer Farbton-Skala und Zeichnung eines X-Y-Koordinatensystems, wobei sichergestellt wird, daß die Rasterlinien des Koordinatensystems jeweils exakten (und nicht nur gerundeten) Zahlenwerten entsprechen |
Zurück zum MatrixLib-Inhaltsverzeichnis OptiVec Home
Copyright © 1996-2020 OptiCode – Dr. Martin Sander Software Development