TestEigenValue.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /**
  2. * @file TestEigenValue.cpp
  3. * @brief TestEigenValue
  4. * @author Michael Koch
  5. * @date Di Aug 4 2009
  6. */
  7. #include "TestEigenValue.h"
  8. #include <string>
  9. #include "core/basics/cppunitex.h"
  10. #include "core/basics/numerictools.h"
  11. #include "core/vector/Distance.h"
  12. #include "core/algebra/EigValues.h"
  13. #include "core/algebra/EigValuesTRLAN.h"
  14. #include "core/algebra/GenericMatrix.h"
  15. #include "core/algebra/GMStandard.h"
  16. using namespace std;
  17. using namespace NICE;
  18. CPPUNIT_TEST_SUITE_REGISTRATION(TestEigenValue);
  19. void TestEigenValue::setUp()
  20. {
  21. }
  22. void TestEigenValue::tearDown()
  23. {
  24. }
  25. void TestEigenValue::TestEigenValueComputation()
  26. {
  27. // size of the matrix
  28. uint rows = 100;
  29. uint cols = rows;
  30. // number of eigenvalues used
  31. uint k = 10;
  32. uint maxiterations = 200;
  33. double mindelta = 1e-8;
  34. double sparse_prob = 0.3;
  35. int trlan_magnitude = 1;
  36. NICE::Matrix T(rows, cols, 0.0);
  37. // use a fixed seed, its a test case
  38. #ifdef WIN32
  39. srand(0);
  40. #else
  41. srand48(0);
  42. #endif
  43. // generate random symmetric matrix
  44. for (uint i = 0 ; i < rows ; i++)
  45. for (uint j = i ; j < cols ; j++)
  46. {
  47. #ifdef WIN32
  48. if (sparse_prob != 0.0)
  49. if ( double( rand() ) / RAND_MAX < sparse_prob)
  50. continue;
  51. T(i, j) = double( rand() ) / RAND_MAX;
  52. #else
  53. if (sparse_prob != 0.0)
  54. if (drand48() < sparse_prob)
  55. continue;
  56. T(i, j) = drand48();
  57. #endif
  58. T(j, i) = T(i, j);
  59. }
  60. // create a positive definite matrix
  61. T = T*T;
  62. EigValues *eig;
  63. for (int trlan = 0;trlan <= 1;trlan++) //this is creepy but funny
  64. {
  65. if (trlan) //this is creepy but saves lot of code
  66. {
  67. #ifdef NICE_USELIB_TRLAN
  68. eig = new EigValuesTRLAN(trlan_magnitude);
  69. #else
  70. cerr << "EigValuesTRLAN is not checked, because TRLAN was not installed." << endl;
  71. break;
  72. #endif
  73. }
  74. else
  75. {
  76. eig = new EVArnoldi(false, maxiterations, mindelta);
  77. }
  78. NICE::Vector eigvalues_dense;
  79. NICE::Matrix eigvect_dense;
  80. NICE::Vector eigvalues_sparse;
  81. NICE::Matrix eigvect_sparse;
  82. GMStandard Tg(T);
  83. eig->getEigenvalues(Tg, eigvalues_dense, eigvect_dense, k);
  84. GMSparse Ts(T);
  85. eig->getEigenvalues(Ts, eigvalues_sparse, eigvect_sparse, k);
  86. // test property
  87. NICE::EuclidianDistance<double> eucliddist;
  88. for (uint i = 0 ; i < k ; i++)
  89. {
  90. NICE::Vector v_dense = eigvect_dense.getColumn(i);
  91. double lambda_dense = eigvalues_dense[i];
  92. NICE::Vector Tv_dense;
  93. Tv_dense.multiply(T, v_dense);
  94. NICE::Vector lv_dense = v_dense;
  95. lv_dense *= lambda_dense;
  96. double err_dense = eucliddist(Tv_dense, lv_dense);
  97. // check whether the eigenvector definition holds
  98. NICE::Vector v_sparse = eigvect_sparse.getColumn(i);
  99. double lambda_sparse = eigvalues_sparse[i];
  100. NICE::Vector Tv_sparse;
  101. Tv_sparse.multiply(T, v_sparse);
  102. NICE::Vector lv_sparse = v_sparse;
  103. lv_sparse *= lambda_sparse;
  104. double err_sparse = eucliddist(Tv_sparse, lv_sparse);
  105. // cerr << "||Av - lambda v|| (dense) = " << err_dense << endl;
  106. // cerr << "||Av - lambda v|| (sparse) = " << err_sparse << endl;
  107. // use relative errors instead of absolute errors
  108. err_sparse /= Tv_sparse.normL2();
  109. err_dense /= Tv_dense.normL2();
  110. CPPUNIT_ASSERT_DOUBLES_EQUAL_NOT_NAN(0.0,err_dense,1e-2);
  111. CPPUNIT_ASSERT_DOUBLES_EQUAL_NOT_NAN(0.0,err_sparse,1e-2);
  112. }
  113. }
  114. }