|
@@ -18,20 +18,38 @@ void
|
|
|
EVArnoldi::getEigenvalues ( const GenericMatrix & data, Vector & eigenvalues,
|
|
|
Matrix & eigenvectors, uint k )
|
|
|
{
|
|
|
+ /////////////////////////////////////
|
|
|
+ ///////// check input arguments /////
|
|
|
+ /////////////////////////////////////
|
|
|
|
|
|
if ( data.rows () != data.cols () )
|
|
|
{
|
|
|
throw ( "EVArnoldi: matrix has to be quadratic" );
|
|
|
}
|
|
|
+
|
|
|
if ( k <= 0 )
|
|
|
{
|
|
|
throw ( "EVArnoldi: please use k>0." );
|
|
|
}
|
|
|
+
|
|
|
+ // did we specify more eigenvalues than the matrix can actually have?
|
|
|
+ if ( k > data.rows() )
|
|
|
+ {
|
|
|
+ throw ( "EVArnoldi: specified k is larger then dimension of matrix! Aborting..." );
|
|
|
+ }
|
|
|
+
|
|
|
+ //////////////////////////////////////
|
|
|
+ ///////// initialize variables ///////
|
|
|
+ //////////////////////////////////////
|
|
|
|
|
|
if ( verbose )
|
|
|
- cerr << "Initialize Matrices";
|
|
|
+ cerr << "Initialize Matrices" << std::endl;
|
|
|
|
|
|
uint n = data.cols ();
|
|
|
+
|
|
|
+ if ( verbose )
|
|
|
+ std::cerr << "EVArnoldi: n: " << n << " k: " << k << std::endl;
|
|
|
+
|
|
|
NICE::Matrix rmatrix ( n, k, 0 ); //=eigenvectors
|
|
|
NICE::Matrix qmatrix ( n, k, 0 ); //saves data =eigenvectors
|
|
|
eigenvalues.resize ( k );
|
|
@@ -52,12 +70,24 @@ EVArnoldi::getEigenvalues ( const GenericMatrix & data, Vector & eigenvalues,
|
|
|
// rmatrix ( j, i ) = 0.5;
|
|
|
//TODO the random initialization might help, but it is bad for reproducibility :(
|
|
|
|
|
|
+ ////////////////////////////////////
|
|
|
+ ///////// start computation ///////
|
|
|
+ ////////////////////////////////////
|
|
|
+ if ( verbose )
|
|
|
+ std::cerr << "EVArnoldi: start main computation" << std::endl;
|
|
|
+
|
|
|
//reduceddim
|
|
|
double delta = 1.0;
|
|
|
uint iteration = 0;
|
|
|
while ( delta > mindelta && iteration < maxiterations )
|
|
|
{
|
|
|
- NICE::Vector rold ( rmatrix.getColumn ( k - 1 ) );
|
|
|
+ //replace Vector rold by matrix rold to check for convergence of all eigenvectors
|
|
|
+ //NICE::Vector rold ( rmatrix.getColumn ( k - 1 ) );
|
|
|
+ NICE::Matrix rold(rmatrix);
|
|
|
+
|
|
|
+ if ( verbose )
|
|
|
+ std::cerr << "EVArnoldi: start for loop over reduced dims" << std::endl;
|
|
|
+
|
|
|
// 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++ )
|
|
@@ -82,16 +112,34 @@ EVArnoldi::getEigenvalues ( const GenericMatrix & data, Vector & eigenvalues,
|
|
|
( qmatrix.getColumn ( j ).
|
|
|
scalarProduct ( rmatrix.getColumn ( reduceddim ) ) );
|
|
|
}
|
|
|
- //convergence stuff
|
|
|
- NICE::Vector diff = rold - rmatrix.getColumn ( k - 1 );
|
|
|
- delta = diff.normL2 ();
|
|
|
+
|
|
|
+ if ( verbose )
|
|
|
+ std::cerr << "EVArnoldi: ended for loop over reduced dims" << std::endl;
|
|
|
+
|
|
|
+ //convergence stuff (replaced by checking all eigenvectors instead of a single one
|
|
|
+ //NICE::Vector diff = rold - rmatrix.getColumn ( k - 1 );
|
|
|
+ //delta = diff.normL2 ();
|
|
|
+ NICE::Vector tmpDiff;
|
|
|
+ double norm_tmpDiff;
|
|
|
+ delta = 0.0;
|
|
|
+ for ( uint j = 0; j < k; j++ )
|
|
|
+ {
|
|
|
+ tmpDiff = rold.getColumn(j) - rmatrix.getColumn(j);
|
|
|
+ norm_tmpDiff = tmpDiff.normL2();
|
|
|
+ if (norm_tmpDiff > delta)
|
|
|
+ delta = norm_tmpDiff;
|
|
|
+ }
|
|
|
iteration++;
|
|
|
|
|
|
if ( verbose )
|
|
|
cerr << "EVArnoldi: [" << iteration << "] delta=" << delta << endl;
|
|
|
}
|
|
|
+
|
|
|
+ if ( verbose )
|
|
|
+ std::cerr << "EVArnoldi: while-loop done" << std::endl;
|
|
|
+
|
|
|
eigenvectors = rmatrix;
|
|
|
-
|
|
|
+
|
|
|
for ( uint i = 0; i < k; i++ )
|
|
|
{
|
|
|
NICE::Vector tmp;
|
|
@@ -99,4 +147,45 @@ EVArnoldi::getEigenvalues ( const GenericMatrix & data, Vector & eigenvalues,
|
|
|
data.multiply ( tmp, eigenvectors.getColumn ( i ) );
|
|
|
eigenvalues[i] = tmp.scalarProduct ( eigenvectors.getColumn ( i ) );
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+ // post-processing: ensure that eigenvalues are in correct order!
|
|
|
+
|
|
|
+ if ( this->b_verifyDecreasingOrder && (k > 1) )
|
|
|
+ {
|
|
|
+ NICE::VectorT< int > ewPermutation;
|
|
|
+ eigenvalues.sortDescend ( ewPermutation );
|
|
|
+
|
|
|
+ NICE::Vector tmpRow;
|
|
|
+ int tmpIdx (-1);
|
|
|
+ for ( uint i = 0; i < k; i++ )
|
|
|
+ {
|
|
|
+ if ( i == ewPermutation[i] )
|
|
|
+ {
|
|
|
+ //identity - nothing to do here
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if ( tmpIdx == -1 )
|
|
|
+ {
|
|
|
+ tmpIdx = i;
|
|
|
+ tmpRow = eigenvectors.getColumn ( i );
|
|
|
+ eigenvectors.getColumnRef ( i ) = eigenvectors.getColumn ( ewPermutation[i] );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if ( tmpIdx != ewPermutation[i] )
|
|
|
+ {
|
|
|
+ eigenvectors.getColumnRef ( i ) = eigenvectors.getColumn ( ewPermutation[i] );
|
|
|
+ }
|
|
|
+ else // tmpIdx == ewPermutation[i]
|
|
|
+ {
|
|
|
+ eigenvectors.getColumnRef ( i ) = tmpRow;
|
|
|
+ tmpIdx = -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }// sorting is only useful if we compute more then 1 ew
|
|
|
}
|