Heidelberg Educational Numerics Library Version 0.24 (from 9 September 2011)
|
00001 // -*- tab-width: 4; indent-tabs-mode: nil -*- 00002 #ifndef HDNUM_NEWTON_HH 00003 #define HDNUM_NEWTON_HH 00004 00005 #include "lr.hh" 00006 00011 namespace hdnum { 00012 00019 template<class N> 00020 class SquareRootProblem 00021 { 00022 public: 00024 typedef std::size_t size_type; 00025 00027 typedef N number_type; 00028 00030 SquareRootProblem (number_type a_) 00031 : a(a_) 00032 {} 00033 00035 std::size_t size () const 00036 { 00037 return 1; 00038 } 00039 00041 void F (const Vector<N>& x, Vector<N>& result) const 00042 { 00043 result[0] = x[0]*x[0] - a; 00044 } 00045 00047 void F_x (const Vector<N>& x, DenseMatrix<N>& result) const 00048 { 00049 result[0][0] = number_type(2.0)*x[0]; 00050 } 00051 00052 private: 00053 number_type a; 00054 }; 00055 00056 00063 class Newton 00064 { 00065 typedef std::size_t size_type; 00066 00067 public: 00069 Newton () 00070 : maxit(25), linesearchsteps(10), verbosity(0), 00071 reduction(1e-14), abslimit(1e-30), converged(false) 00072 {} 00073 00075 void set_maxit (size_type n) 00076 { 00077 maxit = n; 00078 } 00079 00081 void set_linesearchsteps (size_type n) 00082 { 00083 linesearchsteps = n; 00084 } 00085 00087 void set_verbosity (size_type n) 00088 { 00089 verbosity = n; 00090 } 00091 00093 void set_abslimit (double l) 00094 { 00095 abslimit = l; 00096 } 00097 00099 void set_reduction (double l) 00100 { 00101 reduction = l; 00102 } 00103 00105 template<class M> 00106 void solve (const M& model, Vector<typename M::number_type> & x) const 00107 { 00108 typedef typename M::number_type N; 00109 Vector<N> r(model.size()); // residual 00110 DenseMatrix<N> A(model.size(),model.size()); // Jacobian matrix 00111 Vector<N> y(model.size()); // temporary solution in line search 00112 Vector<N> z(model.size()); // solution of linear system 00113 Vector<N> s(model.size()); // scaling factors 00114 Array<size_type> p(model.size()); // row permutations 00115 Array<size_type> q(model.size()); // column permutations 00116 00117 model.F(x,r); // compute nonlinear residual 00118 N R0(norm(r)); // norm of initial residual 00119 N R(R0); // current residual norm 00120 if (verbosity>=1) 00121 { 00122 std::cout << "Newton " 00123 << " norm=" << std::scientific << std::showpoint 00124 << std::setprecision(4) << R0 00125 << std::endl; 00126 } 00127 00128 converged = false; 00129 for (size_type i=1; i<=maxit; i++) // do Newton iterations 00130 { 00131 // check absolute size of residual 00132 if (R<=abslimit) 00133 { 00134 converged = true; 00135 return; 00136 } 00137 00138 // solve Jacobian system for update 00139 model.F_x(x,A); // compute Jacobian matrix 00140 row_equilibrate(A,s); // equilibrate rows 00141 lr_fullpivot(A,p,q); // LR decomposition of A 00142 z = N(0.0); // clear solution 00143 apply_equilibrate(s,r); // equilibration of right hand side 00144 permute_forward(p,r); // permutation of right hand side 00145 solveL(A,r,r); // forward substitution 00146 solveR(A,z,r); // backward substitution 00147 permute_backward(q,z); // backward permutation 00148 00149 // line search 00150 N lambda(1.0); // start with lambda=1 00151 for (size_type k=0; k<linesearchsteps; k++) 00152 { 00153 y = x; 00154 y.update(-lambda,z); // y = x+lambda*z 00155 model.F(y,r); // r = F(y) 00156 N newR(norm(r)); // compute norm 00157 if (verbosity>=3) 00158 { 00159 std::cout << " line search " << std::setw(2) << k 00160 << " lambda=" << std::scientific << std::showpoint 00161 << std::setprecision(4) << lambda 00162 << " norm=" << std::scientific << std::showpoint 00163 << std::setprecision(4) << newR 00164 << " red=" << std::scientific << std::showpoint 00165 << std::setprecision(4) << newR/R 00166 << std::endl; 00167 } 00168 if (newR<(1.0-0.25*lambda)*R) // check convergence 00169 { 00170 if (verbosity>=2) 00171 { 00172 std::cout << " step" << std::setw(3) << i 00173 << " norm=" << std::scientific << std::showpoint 00174 << std::setprecision(4) << newR 00175 << " red=" << std::scientific << std::showpoint 00176 << std::setprecision(4) << newR/R 00177 << std::endl; 00178 } 00179 x = y; 00180 R = newR; 00181 break; // continue with Newton loop 00182 } 00183 else lambda *= 0.5; // reduce damping factor 00184 if (k==linesearchsteps-1) 00185 { 00186 if (verbosity>=3) 00187 std::cout << " line search not converged within " << linesearchsteps << " steps" << std::endl; 00188 return; 00189 } 00190 } 00191 00192 // check convergence 00193 if (R<=reduction*R0) 00194 { 00195 if (verbosity>=1) 00196 { 00197 std::cout << "Newton converged in " << i << " steps" 00198 << " reduction=" << std::scientific << std::showpoint 00199 << std::setprecision(4) << R/R0 00200 << std::endl; 00201 } 00202 converged = true; 00203 return; 00204 } 00205 if (i==maxit) 00206 { 00207 if (verbosity>=2) 00208 std::cout << "Newton not converged within " << maxit << " iterations" << std::endl; 00209 } 00210 } 00211 } 00212 00213 bool has_converged () const 00214 { 00215 return converged; 00216 } 00217 00218 private: 00219 size_type maxit; 00220 size_type linesearchsteps; 00221 size_type verbosity; 00222 double reduction; 00223 double abslimit; 00224 mutable bool converged; 00225 }; 00226 00227 00228 00229 00237 class Banach 00238 { 00239 typedef std::size_t size_type; 00240 00241 public: 00243 Banach () 00244 : maxit(25), linesearchsteps(10), verbosity(0), 00245 reduction(1e-14), abslimit(1e-30), sigma(1.0), converged(false) 00246 {} 00247 00249 void set_maxit (size_type n) 00250 { 00251 maxit = n; 00252 } 00253 00255 void set_sigma (double sigma_) 00256 { 00257 sigma = sigma_; 00258 } 00259 00261 void set_linesearchsteps (size_type n) 00262 { 00263 linesearchsteps = n; 00264 } 00265 00267 void set_verbosity (size_type n) 00268 { 00269 verbosity = n; 00270 } 00271 00273 void set_abslimit (double l) 00274 { 00275 abslimit = l; 00276 } 00277 00279 void set_reduction (double l) 00280 { 00281 reduction = l; 00282 } 00283 00285 template<class M> 00286 void solve (const M& model, Vector<typename M::number_type> x) const 00287 { 00288 typedef typename M::number_type N; 00289 Vector<N> r(model.size()); // residual 00290 Vector<N> y(model.size()); // temporary solution in line search 00291 00292 model.F(x,r); // compute nonlinear residual 00293 N R0(norm(r)); // norm of initial residual 00294 N R(R0); // current residual norm 00295 if (verbosity>=1) 00296 { 00297 std::cout << "Banach " 00298 << " norm=" << std::scientific << std::showpoint 00299 << std::setprecision(4) << R0 00300 << std::endl; 00301 } 00302 00303 converged = false; 00304 for (size_type i=1; i<=maxit; i++) // do iterations 00305 { 00306 // check absolute size of residual 00307 if (R<=abslimit) 00308 { 00309 converged = true; 00310 return; 00311 } 00312 00313 // next iterate 00314 y = x; 00315 y.update(-sigma,r); // y = x+lambda*z 00316 model.F(y,r); // r = F(y) 00317 N newR(norm(r)); // compute norm 00318 if (verbosity>=2) 00319 { 00320 std::cout << " " << std::setw(3) << i 00321 << " norm=" << std::scientific << std::showpoint 00322 << std::setprecision(4) << newR 00323 << " red=" << std::scientific << std::showpoint 00324 << std::setprecision(4) << newR/R 00325 << std::endl; 00326 } 00327 x = y; // accept new iterate 00328 R = newR; // remember new norm 00329 00330 // check convergence 00331 if (R<=reduction*R0 || R<=abslimit) 00332 { 00333 if (verbosity>=1) 00334 { 00335 std::cout << "Banach converged in " << i << " steps" 00336 << " reduction=" << std::scientific << std::showpoint 00337 << std::setprecision(4) << R/R0 00338 << std::endl; 00339 } 00340 converged = true; 00341 return; 00342 } 00343 } 00344 } 00345 00346 bool has_converged () const 00347 { 00348 return converged; 00349 } 00350 00351 private: 00352 size_type maxit; 00353 size_type linesearchsteps; 00354 size_type verbosity; 00355 double reduction; 00356 double abslimit; 00357 double sigma; 00358 mutable bool converged; 00359 }; 00360 00361 } // namespace hdnum 00362 00363 #endif