1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- /**
- * @file EigValues.cpp
- * @brief EigValues Class
- * @author Michael Koch
- * @date 08/19/2008
- */
- #include <iostream>
- #include "EigValues.h"
- #define DEBUG_ARNOLDI
- using namespace NICE;
- using namespace std;
- void
- EVArnoldi::getEigenvalues ( const GenericMatrix & data, Vector & eigenvalues,
- Matrix & eigenvectors, uint k )
- {
- if ( data.rows () != data.cols () )
- {
- throw ( "EVArnoldi: matrix has to be quadratic" );
- }
- if ( k <= 0 )
- {
- throw ( "EVArnoldi: please use k>0." );
- }
- if ( verbose )
- cerr << "Initialize Matrices";
- uint n = data.cols ();
- NICE::Matrix rmatrix ( n, k, 0 ); //=eigenvectors
- NICE::Matrix qmatrix ( n, k, 0 ); //saves data =eigenvectors
- eigenvalues.resize ( k );
- NICE::Vector q ( n );
- NICE::Vector r ( n );
- if ( verbose )
- cerr << "Random Initialization" << endl;
- //random initialisation
- for ( uint i = 0; i < k; i++ )
- for ( uint j = 0; j < n; j++ )
- rmatrix ( j, i ) = drand48 ();
- // rmatrix ( j, i ) = 0.5;
- //TODO the random initialization might help, but it is bad for reproducibility :(
- //reduceddim
- double delta = 1.0;
- uint iteration = 0;
- while ( delta > mindelta && iteration < maxiterations )
- {
- NICE::Vector rold ( rmatrix.getColumn ( k - 1 ) );
- // meta-comment: i is an index for the iteration, j is an index for the basis
- // element (1 <= j <= k)
- for ( uint reduceddim = 0; reduceddim < k; reduceddim++ )
- {
- // -> get r^i_j from R matrix
- q = rmatrix.getColumn ( reduceddim );
- // q^i_j = r^i_j / ||r^i_j||
- q.normalizeL2 ();
- // -> store in Q matrix
- qmatrix.getColumnRef ( reduceddim ) = q;
- // this line copies a vector with external memory!
- // changing currentcol leads to a change in the R matrix!!
- Vector currentCol = rmatrix.getColumnRef ( reduceddim );
- // r^{i+1}_j = A * q^i_j ( r^i_j is overwritten by r^{i+1}_j )
- data.multiply ( currentCol, q );
- // for all j: r^{i+1}_j -= q^i_j * < q^i_j, r^{i+1}_j >
- for ( uint j = 0; j < reduceddim; j++ )
- rmatrix.getColumnRef ( reduceddim ) -=
- qmatrix.getColumn ( j ) *
- ( qmatrix.getColumn ( j ).
- scalarProduct ( rmatrix.getColumn ( reduceddim ) ) );
- }
- //convergence stuff
- NICE::Vector diff = rold - rmatrix.getColumn ( k - 1 );
- delta = diff.normL2 ();
- iteration++;
- if ( verbose )
- cerr << "EVArnoldi: [" << iteration << "] delta=" << delta << endl;
- }
- eigenvectors = rmatrix;
- for ( uint i = 0; i < k; i++ )
- {
- NICE::Vector tmp;
- eigenvectors.getColumnRef ( i ).normalizeL2 ();
- data.multiply ( tmp, eigenvectors.getColumn ( i ) );
- eigenvalues[i] = tmp.scalarProduct ( eigenvectors.getColumn ( i ) );
- }
- }
|