ILSConjugateGradients.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /**
  2. * @file ILSConjugateGradients.cpp
  3. * @brief abstract interface for iterative linear solvers working with GenericMatrix
  4. * @author Erik Rodner
  5. * @date 12/21/2011
  6. */
  7. #include <iostream>
  8. #include <core/basics/Timer.h>
  9. #include "ILSConjugateGradients.h"
  10. using namespace NICE;
  11. using namespace std;
  12. ILSConjugateGradients::ILSConjugateGradients( bool verbose, uint maxIterations, double minDelta, double minResidual, bool useFlexibleVersion )
  13. {
  14. this->minDelta = minDelta;
  15. this->maxIterations = maxIterations;
  16. this->verbose = verbose;
  17. this->minResidual = minResidual;
  18. this->useFlexibleVersion = useFlexibleVersion;
  19. this->timeAnalysis = false;
  20. }
  21. ILSConjugateGradients::~ILSConjugateGradients()
  22. {
  23. }
  24. void ILSConjugateGradients::setTimeAnalysis( bool timeAnalysis )
  25. {
  26. this->timeAnalysis = timeAnalysis;
  27. }
  28. void ILSConjugateGradients::setJacobiPreconditioner ( const Vector & jacobiPreconditioner )
  29. {
  30. this->jacobiPreconditioner = jacobiPreconditioner;
  31. }
  32. int ILSConjugateGradients::solveLin ( const GenericMatrix & gm, const Vector & b, Vector & x )
  33. {
  34. Timer t;
  35. if ( timeAnalysis )
  36. t.start();
  37. if ( b.size() != gm.rows() ) {
  38. fthrow(Exception, "Size of vector b (" << b.size() << ") mismatches with the size of the given GenericMatrix (" << gm.rows() << ").");
  39. }
  40. if ( x.size() != gm.cols() )
  41. {
  42. x.resize(gm.cols());
  43. x.set(0.0); // bad initial solution, but whatever
  44. }
  45. // CG-Method: http://www.netlib.org/templates/templates.pdf
  46. //
  47. Vector a;
  48. // compute r^0 = b - A*x^0
  49. gm.multiply( a, x );
  50. Vector r = b - a;
  51. if ( timeAnalysis ) {
  52. t.stop();
  53. cerr << "ILSConjugateGradients: TIME " << t.getSum() << " " << r.normL2() << " " << r.normInf() << endl;
  54. t.start();
  55. }
  56. Vector rold ( r.size(), 0.0 );
  57. // store optimal values
  58. double res_min = r.scalarProduct(r);
  59. Vector current_x = x;
  60. double rhoold = 0.0;
  61. Vector z ( r.size() );
  62. Vector p ( z.size() );
  63. uint i = 1;
  64. while ( i <= maxIterations )
  65. {
  66. // pre-conditioned vector, currently M=I, i.e. no pre-condition
  67. // otherwise set z = M * r
  68. if ( jacobiPreconditioner.size() != r.size() ) {
  69. z = r;
  70. } else {
  71. // use simple Jacobi pre-conditioning
  72. for ( uint jj = 0 ; jj < z.size() ; jj++ )
  73. z[jj] = r[jj] / jacobiPreconditioner[jj];
  74. }
  75. double rho = z.scalarProduct( r );
  76. if ( verbose ) {
  77. cerr << "ILSConjugateGradients: iteration " << i << " / " << maxIterations << endl;
  78. if ( current_x.size() <= 20 )
  79. cerr << "ILSConjugateGradients: current solution " << current_x << endl;
  80. }
  81. if ( i == 1 ) {
  82. p = z;
  83. } else {
  84. double beta;
  85. if ( useFlexibleVersion ) {
  86. beta = ( rho - z.scalarProduct(rold) ) / rhoold;
  87. } else {
  88. beta = rho / rhoold;
  89. }
  90. p = z + beta * p;
  91. }
  92. Vector q ( gm.rows() );
  93. // q = A*p
  94. gm.multiply ( q, p );
  95. // sp = p^T A p
  96. // if A is next to zero this gets nasty, because we divide by sp
  97. // later on
  98. double sp = p.scalarProduct(q);
  99. if ( fabs(sp) < 1e-20 ) {
  100. // we achieved some kind of convergence, at least this
  101. // is a termination condition used in the wiki article
  102. if ( verbose )
  103. cerr << "ILSConjugateGradients: p^T*q is quite small" << endl;
  104. break;
  105. }
  106. double alpha = rho / sp;
  107. current_x = current_x + alpha * p;
  108. rold = r;
  109. r = r - alpha * q;
  110. double res = r.scalarProduct(r);
  111. double resMax = r.normInf();
  112. // store optimal x that produces smallest residual
  113. if (res < res_min) {
  114. x = current_x;
  115. res_min = res;
  116. }
  117. // check convergence
  118. double delta = fabs(alpha) * p.normL2();
  119. if ( verbose ) {
  120. cerr << "ILSConjugateGradients: delta = " << delta << " lower bound = " << minDelta << endl;
  121. cerr << "ILSConjugateGradients: residual = " << res << endl;
  122. cerr << "ILSConjugateGradients: L_inf residual = " << resMax << " lower bound = " << minResidual << endl;
  123. if (resMax < 0)
  124. {
  125. std::cerr << "WARNING: resMax is smaller than zero! " << std::endl;
  126. std::cerr << "ILSConjugateGradients: vector r: " << r << std::endl;
  127. }
  128. }
  129. if ( timeAnalysis ) {
  130. t.stop();
  131. cerr << "ILSConjugateGradients: TIME " << t.getSum() << " " << res << " " << resMax << endl;
  132. t.start();
  133. }
  134. if ( delta < minDelta ) {
  135. if ( verbose )
  136. cerr << "ILSConjugateGradients: small delta" << endl;
  137. break;
  138. }
  139. //fabs was necessary, since the IPP-implementation from normInf was not working correctly
  140. // if ( fabs(resMax) < minResidual ) {
  141. if ( resMax < minResidual ) {
  142. if ( verbose )
  143. {
  144. cerr << "ILSConjugateGradients: small residual -- resMax: "<< resMax << " minRes: " << minResidual << endl;
  145. }
  146. break;
  147. }
  148. rhoold = rho;
  149. i++;
  150. }
  151. if (verbose)
  152. {
  153. cerr << "ILSConjugateGradients: iterations needed: " << std::min<uint>(i,maxIterations) << endl;
  154. cerr << "ILSConjugateGradients: minimal residual achieved: " << res_min << endl;
  155. }
  156. if (verbose)
  157. {
  158. if ( x.size() <= 20 )
  159. cerr << "ILSConjugateGradients: optimal solution: " << x << endl;
  160. }
  161. return 0;
  162. }
  163. void ILSConjugateGradients::setVerbose(const bool& _verbose)
  164. {
  165. this->verbose = _verbose;
  166. }