SVD überprüfen | Die folgende Routine demonstriert SVD und Überprüfung ihres Ergebnisses.
#include <VDstd.h>
#include <MDstd.h>
#include <conio.h>
void SVDtest( void )
{
unsigned ht=386, len=52, // beliebige Werte
maxhtlen, sizeA, sizeV;
dMatrix MA, MU, MV, MOne, MA2, MUV2, MDiffA, MDiffOne;
dVector W;
double err;
maxhtlen = (ht >= len ? ht : len);
sizeA = ht*len;
sizeV = len*len;
MA = MD_matrix( ht, len ); // Eingabe-Matrix
MU = MD_matrix( maxhtlen, len );
MV = MD_matrix( len, len );
W = VD_vector( len );
MOne = MD_matrix( len, len ); // Einheits-Matrix zum Vergleich
MD_equ1( MOne, len );
MA2 = MD_matrix( maxhtlen, len );
// wird MU*W*MVT erhalten zum Vergleich mit der Eingabe-Matrix
// führende Dimension maxhtlen ist für unter-determinierte Matrizen nötig
MUV2 = MD_matrix( len, len );
// wird MUT*MU, MVT*MV, MV*MVT erhalten zum Vergleich mit MOne
MDiffA = MD_matrix( ht, len ); // für Zwischenergebnisse
MDiffOne = MD_matrix( len, len ); // für Zwischenergebnisse
MD_random( MA, ht, len, 1, -1., +1. );
// MA mit Zufallszahlen zwischen -1 und +1 füllen
// alternativ auf irgendeinem anderen Weg eine Test-Matrix erzeugen oder einlesen
MD_SVdecompose( MU, MV, W, MA, ht, len );
/* prüfen, ob MA = MU*W*MVT; Auswertung von rechts nach links: */
MDdia_mulMT( MUV2, W, MV, len, len ); // MUV2 speichert W * MVT
MD_mulM( MA2, MU, MUV2, maxhtlen, len, len );
MD_subM( MDiffA, MA, MA2, ht, len );
// für unter-determinierte Matrizen werden die Zeilen von ht bis maxhtlen-1 ignoriert
err = VD_absmax( MDiffA[0], sizeA );
printf( "SVDtest: Test für die SVD-Routine von OptiVec\n\n"
"In den folgenden Tests in Double-Genauigkeit\n"
"sind Fehler bis zu einigen Malen 1.e-14 in Ordnung\n"
"bei Matrizen der Größenordnung 100x100 bis 1000x1000 Elemente:\n\n"
"max. Fehler der Matrix-Rekonstruktion MA = MU*W*MVT: %lg", err );
/* prüfe, ob MU orthogonal, also MUT*MU = (1): */
MD_TmulM( MUV2, MU, MU, maxhtlen, len, len );
MD_subM( MDiffOne, MUV2, MOne, len, len );
err = VD_absmax( MDiffOne[0], sizeV );
printf( "\nmax. Fehler von MUT*MU = (1): %lg", err );
/* prüfe, ob MV orthogonal, also MVT*MV = (1): */
MD_TmulM( MUV2, MV, MV, len, len, len );
MD_subM( MDiffOne, MUV2, MOne, len, len );
err = VD_absmax( MDiffOne[0], sizeV );
printf( "\nmax. Fehler von MVT*MV = (1): %lg", err );
/* prüfe, ob MV auch orthonormal, also MV*MVT = (1): */
MD_mulMT( MUV2, MV, MV, len, len, len );
MD_subM( MDiffOne, MUV2, MOne, len, len );
err = VD_absmax( MDiffOne[0], sizeV );
printf( "\nmax. Fehler von MV*MVT = (1): %lg", err );
printf( "\n\nZum Beenden des Tests beliebige Taste drücken!" ); _getch();
M_nfree( 8, MA, MU, MV, MOne, MA2, MUV2, MDiffA, MDiffOne );
V_free( W );
} |