EigValues.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /**
  2. * @file EigValues.cpp
  3. * @brief EigValues Class
  4. * @author Michael Koch
  5. * @date 08/19/2008
  6. */
  7. #include <iostream>
  8. #include "EigValues.h"
  9. #define DEBUG_ARNOLDI
  10. using namespace NICE;
  11. using namespace std;
  12. void
  13. EVArnoldi::getEigenvalues ( const GenericMatrix & data, Vector & eigenvalues,
  14. Matrix & eigenvectors, uint k )
  15. {
  16. if ( data.rows () != data.cols () )
  17. {
  18. throw ( "EVArnoldi: matrix has to be quadratic" );
  19. }
  20. if ( k <= 0 )
  21. {
  22. throw ( "EVArnoldi: please use k>0." );
  23. }
  24. if ( verbose )
  25. cerr << "Initialize Matrices";
  26. uint n = data.cols ();
  27. NICE::Matrix rmatrix ( n, k, 0 ); //=eigenvectors
  28. NICE::Matrix qmatrix ( n, k, 0 ); //saves data =eigenvectors
  29. eigenvalues.resize ( k );
  30. NICE::Vector q ( n );
  31. NICE::Vector r ( n );
  32. if ( verbose )
  33. cerr << "Random Initialization" << endl;
  34. //random initialisation
  35. for ( uint i = 0; i < k; i++ )
  36. for ( uint j = 0; j < n; j++ )
  37. #ifdef WIN32
  38. rmatrix (j, i) = double(rand())/RAND_MAX;
  39. #else
  40. rmatrix (j, i) = drand48 ();
  41. #endif
  42. // rmatrix ( j, i ) = 0.5;
  43. //TODO the random initialization might help, but it is bad for reproducibility :(
  44. //reduceddim
  45. double delta = 1.0;
  46. uint iteration = 0;
  47. while ( delta > mindelta && iteration < maxiterations )
  48. {
  49. NICE::Vector rold ( rmatrix.getColumn ( k - 1 ) );
  50. // meta-comment: i is an index for the iteration, j is an index for the basis
  51. // element (1 <= j <= k)
  52. for ( uint reduceddim = 0; reduceddim < k; reduceddim++ )
  53. {
  54. // -> get r^i_j from R matrix
  55. q = rmatrix.getColumn ( reduceddim );
  56. // q^i_j = r^i_j / ||r^i_j||
  57. q.normalizeL2 ();
  58. // -> store in Q matrix
  59. qmatrix.getColumnRef ( reduceddim ) = q;
  60. // this line copies a vector with external memory!
  61. // changing currentcol leads to a change in the R matrix!!
  62. Vector currentCol = rmatrix.getColumnRef ( reduceddim );
  63. // r^{i+1}_j = A * q^i_j ( r^i_j is overwritten by r^{i+1}_j )
  64. data.multiply ( currentCol, q );
  65. // for all j: r^{i+1}_j -= q^i_j * < q^i_j, r^{i+1}_j >
  66. for ( uint j = 0; j < reduceddim; j++ )
  67. rmatrix.getColumnRef ( reduceddim ) -=
  68. qmatrix.getColumn ( j ) *
  69. ( qmatrix.getColumn ( j ).
  70. scalarProduct ( rmatrix.getColumn ( reduceddim ) ) );
  71. }
  72. //convergence stuff
  73. NICE::Vector diff = rold - rmatrix.getColumn ( k - 1 );
  74. delta = diff.normL2 ();
  75. iteration++;
  76. if ( verbose )
  77. cerr << "EVArnoldi: [" << iteration << "] delta=" << delta << endl;
  78. }
  79. eigenvectors = rmatrix;
  80. for ( uint i = 0; i < k; i++ )
  81. {
  82. NICE::Vector tmp;
  83. eigenvectors.getColumnRef ( i ).normalizeL2 ();
  84. data.multiply ( tmp, eigenvectors.getColumn ( i ) );
  85. eigenvalues[i] = tmp.scalarProduct ( eigenvectors.getColumn ( i ) );
  86. }
  87. }