ug4
Loading...
Searching...
No Matches
line_search.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010-2015: G-CSC, Goethe University Frankfurt
3 * Author: Andreas Vogel, modifications nested Newton: Markus Knodel
4 *
5 * This file is part of UG4.
6 *
7 * UG4 is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License version 3 (as published by the
9 * Free Software Foundation) with the following additional attribution
10 * requirements (according to LGPL/GPL v3 §7):
11 *
12 * (1) The following notice must be displayed in the Appropriate Legal Notices
13 * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 *
15 * (2) The following notice must be displayed at a prominent place in the
16 * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 *
18 * (3) The following bibliography is recommended for citation and must be
19 * preserved in all covered files:
20 * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 * parallel geometric multigrid solver on hierarchically distributed grids.
22 * Computing and visualization in science 16, 4 (2013), 151-164"
23 * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 * flexible software system for simulating pde based models on high performance
25 * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU Lesser General Public License for more details.
31 */
32
33#ifndef __H__UG__LIB_DISC__OPERATOR__NON_LINEAR_OPERATOR__LINE_SEARCH__
34#define __H__UG__LIB_DISC__OPERATOR__NON_LINEAR_OPERATOR__LINE_SEARCH__
35
36#include <ostream>
37#include <string>
38#include <vector>
39#include <cmath>
40#include <sstream>
41#include <limits>
42
43#include "common/common.h"
44
45//#include "lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h"
46
47//#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE
48
50
51//#endif
52
53
54
55namespace ug{
56
59// Line Search
62
69template <typename TVector>
71{
72 public:
73 typedef TVector vector_type;
74
75 public:
77 virtual void set_offset(std::string offset) = 0;
78
93 vector_type& d, number defect) = 0;
94
96
103 virtual std::string config_string() const = 0;
104
106 virtual ~ILineSearch() {}
107
108//#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE
110//#endif
111 virtual bool createNewtonUpdater() = 0;
112
113};
114
116template <typename TVector>
117class StandardLineSearch : public ILineSearch<TVector>
118{
119 public:
120 // type of
121 typedef TVector vector_type;
122
123 public:
126 : m_maxSteps(10), m_lambdaStart(1.0), m_lambdaReduce(0.5), m_alpha(0.25),
127 m_maxDefect(1e+10), m_verbose(true), m_bAcceptBest(false), m_bCheckAll(false), m_offset(""),
129//#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE
130// ,
131// m_newtonUpdater(new NewtonUpdaterGeneric<vector_type>{})
132//#endif
133 {};
134
136 StandardLineSearch(int maxSteps, number lambdaStart, number lambdaReduce, bool bAcceptBest)
137 : m_maxSteps(maxSteps), m_lambdaStart(lambdaStart), m_lambdaReduce(lambdaReduce), m_alpha(0.25),
138 m_maxDefect(1e+10), m_verbose(true), m_bAcceptBest(bAcceptBest), m_bCheckAll(false), m_offset(""),
140//#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE
141// ,
142// m_newtonUpdater(new NewtonUpdaterGeneric<vector_type>{})
143//#endif
144 {};
145
147 StandardLineSearch(int maxSteps, number lambdaStart, number lambdaReduce, bool bAcceptBest, bool bCheckAll)
148 : m_maxSteps(maxSteps), m_lambdaStart(lambdaStart), m_lambdaReduce(lambdaReduce), m_alpha(0.25),
149 m_maxDefect(1e+10), m_verbose(true), m_bAcceptBest(bAcceptBest), m_bCheckAll(bCheckAll), m_offset(""),
151//#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE
152// ,
153// m_newtonUpdater(new NewtonUpdaterGeneric<vector_type>{})
154//#endif
155 {};
156
158 virtual std::string config_string() const
159 {
160 std::stringstream ss;
161 ss << "StandardLineSearch( maxSteps = " << m_maxSteps << ", lambdaStart = " << m_lambdaStart << ", lambdaReduce = " << m_lambdaReduce << ", accept best = " <<
162 (m_bAcceptBest ? "true" : "false") << " check all = " << (m_bCheckAll ? "true" : "false");
163 return ss.str();
164
165 }
166
168 void set_maximum_steps(int steps) {m_maxSteps = steps;}
169
171 void set_lambda_start(number start) {m_lambdaStart = start;}
172
174 void set_reduce_factor(number factor) {m_lambdaReduce = factor;}
175
177 void set_suff_descent_factor(number factor) {m_alpha = factor;}
178
180 void set_accept_best(bool bAcceptBest) {m_bAcceptBest = bAcceptBest;}
181
183 void set_check_all(bool bCheckAll) {m_bCheckAll = bCheckAll;}
184
186 void set_maximum_defect(number maxDef) {m_maxDefect = maxDef;}
187
189 void set_verbose(bool level) {m_verbose = level;}
190
192 virtual void set_offset(std::string offset) {m_offset = offset;};
193
197 vector_type& d, number defect)
198 {
199 PROFILE_BEGIN_GROUP(StandardLineSearch_search, ""); // group?
200 // clone pattern for s
201 s.resize(u.size());
202
203 // start factor
204 number lambda = m_lambdaStart;
205
206 // some values
207 number norm, norm_old = defect;
208 bool converged = false;
209 std::vector<number> vRho;
210
211 // remember u
212 s = u;
213
214 // print heading line
215 if(m_verbose)
216 UG_LOG(m_offset << " ++++ Line Search:\n"
217 << " + Iter lambda Defect Rate \n");
218
219
220 // loop line search steps
221 for(int k = 1; k <= m_maxSteps; ++k)
222 {
223//#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE
224 if( m_newtonUpdater != SPNULL )
225 {
226 // try on line u := u - lambda*p
227
228 bool acceptedNewtonUpdate = m_newtonUpdater->updateSolution(u, 1.0, u, (-1)*lambda, p);
229
230 if( ! acceptedNewtonUpdate )
231 {
232 UG_LOG("Update in Line Search did not work.\n");
233 norm = std::numeric_limits<number>::max();
234 //VecScaleAdd(u, 1.0, u, (-1)*lambda, p);
235 //return false;
236 }
237 else
238 {
239 // compute new Defect
240 spOp->prepare(u);
241 spOp->apply(d, u);
242
243 // compute new Residuum
244 norm = d.norm();
245 }
246 }
247 else
248 {
249//#else
250 // try on line u := u - lambda*p
251 VecScaleAdd(u, 1.0, u, (-1)*lambda, p);
252
253 // compute new Defect
254 spOp->prepare(u);
255 spOp->apply(d, u);
256
257 // compute new Residuum
258 norm = d.norm();
259 }
260//#endif
261
262
263 // compute reduction
264 vRho.push_back(norm/norm_old);
265
266 // print rate
267 if(m_verbose)
268 UG_LOG(m_offset << " + " << std::setw(4)
269 << k << ": " << std::setw(11)
270 << std::resetiosflags( ::std::ios::scientific )<<
271 lambda << " "
272 << std::scientific << norm << " " << vRho.back() <<"\n");
273
274 // check if reduction fits
275 if(vRho.back() <= 1 - m_alpha * std::fabs(lambda))
276 {
277 converged = true;
278 if(!m_bCheckAll) break;
279 }
280
281 lambda *= m_lambdaReduce;
282
283 // check if maximum number of steps reached
284 if(k == m_maxSteps)
285 {
286 // if not accept best, line search failed
287 if(!m_bAcceptBest)
288 {
289 UG_LOG(m_offset << " ++++ Line Search did not converge.\n");
290 return false;
291 }
292
293 // search minimum
294 size_t best = 0;
295 number rho_min = vRho.front();
296 for(size_t i = 1; i < vRho.size(); ++i)
297 {
298 if(rho_min > vRho[i])
299 {
300 rho_min = vRho[i];
301 best = i;
302 }
303 }
304
305 /* check if best is converging (i.e. rho < 1)
306 if(vRho[best] >= 1)
307 {
308 UG_LOG(m_offset << " ++++ Accept Best: No try with "
309 "Rate < 1, cannot accept any line search step.\n");
310 UG_LOG(m_offset << " ++++ Line Search did not converge.\n");
311 return false;
312 }*/
313
314 // accept best
315 if(m_verbose)
316 UG_LOG(m_offset << " ++++ Accept Best: Accepting step " <<
317 best+1 << ", Rate = "<< vRho[best] <<".\n");
318
319//#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE
320 if( m_newtonUpdater != SPNULL )
321 {
322 // try on line u := u - lambda*p
323
324 if( ! m_newtonUpdater->updateSolution(u, 1.0, s, (-1)*m_lambdaStart*std::pow(m_lambdaReduce, (number)best), p) )
325 {
326 UG_LOG("Update in Line Search kmax did not work.\n");
327
328 norm = std::numeric_limits<number>::max();
329 //return false;
330 }
331 else
332 {
333 spOp->prepare(u);
334 spOp->apply(d, u);
335
336 // compute new Residuum
337 norm = d.norm();
338 }
339 }
340 else
341 {
342//#else
343 // try on line u := u - lambda*p
344 VecScaleAdd(u, 1.0, s, (-1)*m_lambdaStart*std::pow(m_lambdaReduce, (number)best), p);
345 // compute new Defect
346 spOp->prepare(u);
347 spOp->apply(d, u);
348
349 // compute new Residuum
350 norm = d.norm();
351 }
352//#endif
353
354
355 // check if defect-norm is smaller than maximum allowed defect value
356 if (norm > m_maxDefect)
357 {
358 UG_LOG("ERROR in 'StandardLineSearch::search':"
359 " maximum defect-limit is reached.\n");
360 return false;
361 }
362
363 // break to finish
364 break;
365 }
366
367//#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE
368
369 if( m_newtonUpdater != SPNULL )
370 {
371 // reset u and eventual local variables
372 m_newtonUpdater->resetSolution(u,s);
373 }
374 else
375 {
376//#else
377 // reset u
378 u = s;
379 }
380//#endif
381
382 }
383
384 // print end line
385 if(m_verbose)
386 {
387 //only for rate < 1, we call it "Line Search converged"
388 if(converged)
389 UG_LOG(m_offset << " ++++ Line Search converged.\n");
390 }
391
392
393//#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE
394 if( m_newtonUpdater != SPNULL )
395 {
396 if( ! m_newtonUpdater->tellAndFixUpdateEvents(u) )
397 {
398 UG_LOG("unable to fix local Newton updates" << std::endl );
399 return false;
400 }
401 }
402//#endif
403 // we're done
404 return true;
405 }
406
407
408//#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE
409
411 {
412 m_newtonUpdater = nU;
413 }
414
415 virtual bool createNewtonUpdater()
416 {
417 if( m_newtonUpdater != SPNULL )
418 {
421
422 return true;
423 }
424
425 return false;
426
427 }
428
429
430//#endif
431
432 protected:
435
436 protected:
439
442
445
448
451
454
457
460
462 std::string m_offset;
463
464//#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE
465private:
467//#endif
468};
469
470} // end namespace ug
471
472#endif /* __H__UG__LIB_DISC__OPERATOR__NON_LINEAR_OPERATOR__LINE_SEARCH__ */
parameterString p
Definition smart_pointer.h:108
Definition line_search.h:71
virtual std::string config_string() const =0
returns information about configuration parameters
virtual bool createNewtonUpdater()=0
virtual void set_offset(std::string offset)=0
set string to be printed before each output of line search
virtual ~ILineSearch()
virtual destructor
Definition line_search.h:106
virtual void setNewtonUpdater(SmartPtr< NewtonUpdaterGeneric< TVector > > nU)=0
TVector vector_type
Definition line_search.h:73
virtual bool search(SmartPtr< IOperator< vector_type > > spOp, vector_type &u, vector_type &p, vector_type &d, number defect)=0
describes a mapping X->Y
Definition operator.h:86
Definition newtonUpdaterGeneric.h:25
standard implementation of the line search based on the "sufficient descent"
Definition line_search.h:118
SmartPtr< NewtonUpdaterGeneric< TVector > > m_newtonUpdater
Definition line_search.h:466
void set_reduce_factor(number factor)
sets factor by which line search factor is multiplied in each step
Definition line_search.h:174
std::string m_offset
number of spaces inserted before output
Definition line_search.h:462
number m_lambdaStart
initial step length scaling
Definition line_search.h:441
int m_maxSteps
maximum number of steps to be performed
Definition line_search.h:438
void set_check_all(bool bCheckAll)
sets iff all the max_steps line search steps must be tested even if the sufficient descent is achieve...
Definition line_search.h:183
void set_suff_descent_factor(number factor)
sets the factor controlling the sufficient descent
Definition line_search.h:177
vector_type s
solution in line direction
Definition line_search.h:434
number m_alpha
sufficient descent factor
Definition line_search.h:447
virtual std::string config_string() const
returns information about configuration parameters
Definition line_search.h:158
TVector vector_type
Definition line_search.h:121
number m_maxDefect
maximum allowed defect
Definition line_search.h:450
void set_maximum_defect(number maxDef)
sets maximum allowed norm of the defect (an exception is thrown if this value if exceeded)
Definition line_search.h:186
virtual void set_offset(std::string offset)
set string to be printed before each output of line search
Definition line_search.h:192
void set_maximum_steps(int steps)
sets maximum number of line search steps
Definition line_search.h:168
void set_verbose(bool level)
sets if info should be printed
Definition line_search.h:189
virtual void setNewtonUpdater(SmartPtr< NewtonUpdaterGeneric< TVector > > nU)
Definition line_search.h:410
void set_lambda_start(number start)
sets start factor
Definition line_search.h:171
StandardLineSearch(int maxSteps, number lambdaStart, number lambdaReduce, bool bAcceptBest)
constructor
Definition line_search.h:136
StandardLineSearch()
default constructor (setting default values)
Definition line_search.h:125
void set_accept_best(bool bAcceptBest)
sets iff after max_steps the best try is used
Definition line_search.h:180
bool m_bAcceptBest
accept best
Definition line_search.h:456
virtual bool search(SmartPtr< IOperator< vector_type > > spOp, vector_type &u, vector_type &p, vector_type &d, number defect)
Definition line_search.h:195
bool m_bCheckAll
check all
Definition line_search.h:459
bool m_verbose
verbosity level
Definition line_search.h:453
StandardLineSearch(int maxSteps, number lambdaStart, number lambdaReduce, bool bAcceptBest, bool bCheckAll)
constructor
Definition line_search.h:147
number m_lambdaReduce
reduction factor for the step length
Definition line_search.h:444
virtual bool createNewtonUpdater()
Definition line_search.h:415
const NullSmartPtr SPNULL
The equivalent to NULL for smart pointers.
Definition smart_pointer.h:90
#define UG_LOG(msg)
Definition log.h:367
double number
Definition types.h:124
void VecScaleAdd(vector_t &vOut, typename vector_t::value_type s1, const vector_t &v1, typename vector_t::value_type s2, const vector_t &v2)
Scales two Vectors, adds them and returns the sum in a third vector.
Definition math_vector_functions_common_impl.hpp:265
the ug namespace
#define PROFILE_BEGIN_GROUP(name, groups)
Definition profiler.h:255