TestLinearSolve.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /**
  2. * @file TestLinearSolve.cpp
  3. * @brief TestLinearSolve
  4. * @author Erik Rodner
  5. * @date 21.12.2011
  6. */
  7. #include "TestLinearSolve.h"
  8. #include <string>
  9. #include <vector>
  10. #include "core/basics/cppunitex.h"
  11. #include "core/basics/numerictools.h"
  12. #include "core/vector/Distance.h"
  13. #include "core/vector/Algorithms.h"
  14. #include "core/algebra/ILSPlainGradient.h"
  15. #include "core/algebra/ILSConjugateGradients.h"
  16. #include "core/algebra/ILSConjugateGradientsLanczos.h"
  17. #include "core/algebra/ILSSymmLqLanczos.h"
  18. #include "core/algebra/ILSMinResLanczos.h"
  19. #include "core/algebra/GMStandard.h"
  20. #include "core/algebra/GBCDSolver.h"
  21. using namespace std;
  22. using namespace NICE;
  23. CPPUNIT_TEST_SUITE_REGISTRATION(TestLinearSolve);
  24. void TestLinearSolve::setUp()
  25. {
  26. }
  27. void TestLinearSolve::tearDown()
  28. {
  29. }
  30. void TestLinearSolve::TestLinearSolveComputation()
  31. {
  32. // verbose flag for additional output for each iteration
  33. bool verbose = false;
  34. // size of the matrix
  35. uint rows = 15;
  36. uint cols = rows;
  37. // probability of zero entries
  38. double sparse_prob = 0.0;
  39. NICE::Matrix T(rows, cols, 0.0);
  40. // use a fixed seed, its a test case
  41. #ifdef WIN32
  42. srand(0);
  43. #else
  44. srand48(0);
  45. #endif
  46. // generate random symmetric matrix
  47. for (uint i = 0 ; i < rows ; i++)
  48. for (uint j = i ; j < cols ; j++)
  49. {
  50. if (sparse_prob != 0.0)
  51. #ifdef WIN32
  52. if (sparse_prob != 0.0)
  53. if ( double( rand() ) / RAND_MAX < sparse_prob)
  54. continue;
  55. T(i, j) = double( rand() ) / RAND_MAX;
  56. #else
  57. if (sparse_prob != 0.0)
  58. if (drand48() < sparse_prob)
  59. continue;
  60. T(i, j) = drand48();
  61. #endif
  62. T(j, i) = T(i, j);
  63. }
  64. // use positive definite matrices
  65. T = T*T;
  66. T.addIdentity(1.0);
  67. NICE::Vector b = Vector::UniformRandom( rows, 0.0, 1.0, 0 );
  68. GMStandard Tg(T);
  69. GMSparse Ts(T, 0.0);
  70. CPPUNIT_ASSERT_EQUAL((int)T.rows(),(int)Ts.rows());
  71. CPPUNIT_ASSERT_EQUAL((int)T.cols(),(int)Ts.cols());
  72. // first of all test the generic matrix interface
  73. for ( uint i = 0 ; i < rows ; i++ )
  74. {
  75. NICE::Vector x ( rows );
  76. for ( uint j = 0 ; j < x.size(); j++ )
  77. #ifdef WIN32
  78. x[j] = double( rand() ) / RAND_MAX;
  79. #else
  80. x[j] = drand48();
  81. #endif
  82. Vector yg;
  83. Vector ys;
  84. Tg.multiply ( yg, x );
  85. Ts.multiply ( ys, x );
  86. CPPUNIT_ASSERT_DOUBLES_EQUAL_NOT_NAN(0.0,(yg-ys).normL2(),1e-10);
  87. }
  88. vector< IterativeLinearSolver * > methods;
  89. int max_iterations = 100;
  90. methods.push_back ( new ILSPlainGradient(verbose, max_iterations*10) );
  91. methods.push_back ( new ILSConjugateGradients(verbose, max_iterations) );
  92. methods.push_back ( new ILSConjugateGradientsLanczos(verbose, max_iterations) );
  93. methods.push_back ( new ILSSymmLqLanczos(verbose, max_iterations) );
  94. methods.push_back ( new ILSMinResLanczos(verbose, max_iterations) );
  95. // the following method is pretty instable!! and needs to much time
  96. //methods.push_back ( new ILSPlainGradient(verbose, max_iterations, false /* minResidual */) );
  97. //methods.push_back ( new ILSPlainGradient(verbose, max_iterations, true /* minResidual */) );
  98. //Vector solstd;
  99. //solveLinearEquationQR( T, b, solstd );
  100. for ( vector< IterativeLinearSolver * >::const_iterator i = methods.begin();
  101. i != methods.end(); i++ )
  102. {
  103. IterativeLinearSolver *method = *i;
  104. Vector solg (Tg.cols(), 0.0);
  105. Vector sols (Ts.cols(), 0.0);
  106. if ( verbose )
  107. cerr << "solving the sparse system ..." << endl;
  108. method->solveLin ( Ts, b, sols );
  109. if ( verbose )
  110. cerr << "solving the dense system ..." << endl;
  111. method->solveLin ( Tg, b, solg );
  112. Vector bg;
  113. Tg.multiply ( bg, solg );
  114. Vector bs;
  115. Ts.multiply ( bs, sols );
  116. // compute residuals
  117. if ( verbose )
  118. {
  119. cerr << "solg = " << solg << endl;
  120. cerr << "sols = " << sols << endl;
  121. cerr << "bg = " << bg << endl;
  122. cerr << "bs = " << bs << endl;
  123. cerr << "b = " << b << endl;
  124. }
  125. double err_dense = ( b - bg ).normL2();
  126. double err_sparse = ( b - bs ).normL2();
  127. CPPUNIT_ASSERT_DOUBLES_EQUAL_NOT_NAN(0.0,err_dense,1e-1);
  128. CPPUNIT_ASSERT_DOUBLES_EQUAL_NOT_NAN(0.0,err_sparse,1e-1);
  129. }
  130. // ---------- check the greedy block coordinate descent method
  131. Vector solg (0.0);
  132. GBCDSolver gbcd ( 5, 10, verbose, 100 /*maximum iterations*/ );
  133. gbcd.solveLin ( Tg, b, solg );
  134. Vector bg;
  135. Tg.multiply ( bg, solg );
  136. double err_dense = ( b - bg ).normL2();
  137. CPPUNIT_ASSERT_DOUBLES_EQUAL_NOT_NAN(0.0,err_dense,1e-4);
  138. }