primatologist-gpl  5.1.2
wolfe_d.h
Go to the documentation of this file.
1 /* Copyright (C) 2000-2013 CEA
2  *
3  * This software and supporting documentation were developed by
4  * bioPICSEL
5  * CEA/DSV/I²BM/MIRCen/LMN, Batiment 61,
6  * 18, route du Panorama
7  * 92265 Fontenay-aux-Roses
8  * France
9  */
10 
11 #ifndef PRIMATOLOGIST_OPTIMIZATION_WOLFE_D_H
12 #define PRIMATOLOGIST_OPTIMIZATION_WOLFE_D_H
13 
15 #include <cmath> // std::abs
16 #include <iostream> // std::cout / std::endl
17 #include <iomanip> // std::setw / std::setprecision
18 #include <string> // std::string
19 
20 namespace aims {
21 
22  //--------------------------------------------------------------------------
23  // CONSTRUCTOR / DESTRUCTOR / COPY
24  //--------------------------------------------------------------------------
25 
26  template <typename O>
28  const Vector & x,
29  const Vector & p ):
30  _f(f),
31  _x(x),
32  _p(p)
33  {
34  setC1();
35  setC2();
37  setMaximize();
39  setVerbose();
40  }
41 
42  template <typename O>
44  _f(other._f),
45  _x(other._x),
46  _p(other._p),
47  _c1(other._c1),
48  _c2(other._c2),
49  _strong(other._strong),
50  _maximize(other._maximize),
51  _max_it(other._max_it),
52  _verbose(other._verbose),
53  _previous_value(other._previous_value),
54  _previous_scalarprod(other._previous_scalarprod),
55  _current_value(other._current_value)
56  {}
57 
58  template <typename O>
60  {}
61 
62  template <typename O>
65  {
66  if( this != &other )
67  {
68  _f = other._f;
69  _x = other._x;
70  _p = other._p;
71  _c1 = other._c1;
72  _c2 = other._c2;
73  _strong = other._strong;
74  _maximize = other._maximize;
75  _max_it = other._max_it;
76  _verbose = other._verbose;
77  _previous_value = other._previous_value;
78  _previous_scalarprod = other._previous_scalarprod;
79  _current_value = other._current_value;
80  }
81  return *this;
82  }
83 
84  //--------------------------------------------------------------------------
85  // SET PARAMETERS
86  //--------------------------------------------------------------------------
87  template <typename O>
88  void WolfeLineSearch<O>::setC1( float c1 )
89  {
90  _c1 = c1;
91  }
92 
93  template <typename O>
94  void WolfeLineSearch<O>::setC2( float c2 )
95  {
96  _c2 = c2;
97  }
98 
99  template <typename O>
101  {
102  _x = x;
103  }
104 
105  template <typename O>
107  {
108  _p = p;
109  }
110 
111  template <typename O>
113  {
114  _f = f;
115  }
116 
117  template <typename O>
119  {
120  _strong = strong;
121  }
122 
123  template <typename O>
125  {
126  _verbose = v;
127  }
128 
129  template <typename O>
130  void WolfeLineSearch<O>::setMaximize( bool maximize )
131  {
132  _maximize = maximize;
133  }
134 
135  template <typename O>
137  {
138  _max_it = n;
139  }
140 
141  //--------------------------------------------------------------------------
142  // GET PARAMETERS
143  //--------------------------------------------------------------------------
144 
145  template <typename O>
147  {
148  return _c1;
149  }
150 
151  template <typename O>
153  {
154  return _c2;
155  }
156 
157  template <typename O>
158  const typename WolfeLineSearch<O>::Vector &
160  {
161  return _x;
162  }
163 
164  template <typename O>
165  const typename WolfeLineSearch<O>::Vector &
167  {
168  return _p;
169  }
170 
171  template <typename O>
172  const typename WolfeLineSearch<O>::Objective &
174  {
175  return _f;
176  }
177 
178  template <typename O>
180  {
181  return _strong;
182  }
183 
184  template <typename O>
186  {
187  return _verbose;
188  }
189 
190  template <typename O>
192  {
193  return _maximize;
194  }
195 
196  template <typename O>
198  {
199  return _max_it;
200  }
201 
202  //--------------------------------------------------------------------------
203  // EXECUTE
204  //--------------------------------------------------------------------------
205 
206  template <typename O>
209  {
210  if( verbose() > 1 )
211  {
212  std::cout << std::string(80, '-') << std::endl;
213  std::cout << std::setw(7) << "Search "
214  << std::setw(4) << "i "
215  << std::setw(15) << "f"
216  << std::setw(15) << "a"
217  << std::endl;
218  std::cout << std::string(80, '-') << std::endl;
219  }
220 
221  if( verbose() > 0 )
222  {
223  std::cout << std::setw(7) << "W"
224  << std::setw(4) << 0
225  << std::setw(15) << std::setprecision(5) << _previous_value
226  << std::setw(15) << std::setprecision(5) << 0.;
227  }
228 
229  if( !checkDirection() )
230  {
231  if( verbose() > 0 )
232  {
233  std::cout << " Not "
234  << std::string( maximize() ? "an ascent" : "a descent" )
235  << std::string( " direction." ) << std::endl;
236  }
237  return _x;
238  }
239  else if( verbose() > 0 )
240  std::cout << std::endl;
241 
242  float a = 1.;
243  bool ok = false;
244  int i = 0;
245  float a_min = 0., a_max;
246  bool a_max_set = false;
247 
248  do {
249  ++i;
250  _current_value = objectiveFunction().value( _x + a * _p );
251  if( ( maximize() &&_current_value <= _previous_value ) ||
252  _current_value >= _previous_value )
253  {
254  // Because we know the direction is an ascent direction, the objective
255  // function should not decrease. If this is the case, it is because
256  // we took a step too big and found ourseleves farther than the
257  // local maxima.
258  // In this case, we thus decrease the step length.
259  if( verbose() > 0 )
260  {
261  std::cout << std::setw(7) << "W"
262  << std::setw(4) << i
263  << std::setw(15) << std::setprecision(5) << _current_value
264  << std::setw(15) << std::setprecision(5) << a
265  << " B"
266  << std::endl;
267  }
268  ok = false;
269  a_max = a;
270  a = ( a_max - a_min ) / 2. + a_min;
271  }
272  else if( not wolfe1(a) or not wolfe2(a) )
273  {
274  if( verbose() > 0 )
275  {
276  std::cout << std::setw(7) << "W"
277  << std::setw(4) << i
278  << std::setw(15) << std::setprecision(5) << _current_value
279  << std::setw(15) << std::setprecision(5) << a
280  << " W"
281  << std::endl;
282  }
283  ok = false;
284  a_min = a;
285  if( a_max_set )
286  a = ( a_max - a_min ) / 2. + a_min;
287  else
288  a *= 2.;
289  }
290  else
291  {
292  if( verbose() > 0 )
293  {
294  std::cout << std::setw(7) << "W"
295  << std::setw(4) << i
296  << std::setw(15) << std::setprecision(5) << _current_value
297  << std::setw(15) << std::setprecision(5) << a
298  << " OK"
299  << std::endl;
300  }
301  ok = true;
302  }
303 
304  } while( not ok and ( maxIterations() < 0 or i < maxIterations() ) );
305 
306  if( verbose() > 0 and maxIterations() > 0 and i >= maxIterations() )
307  std::cout << "Maximum number of iterations reached." << std::endl;
308 
309  return _x + a * _p;
310  }
311 
312  //--------------------------------------------------------------------------
313  // LINE SEARCH
314  //--------------------------------------------------------------------------
315 
316  template <typename O>
318  {
319  _previous_value = objectiveFunction().value( _x );
320  _previous_scalarprod = (math::transpose( _p ) * objectiveFunction().derivative( _x )).at(0);
321  if( maximize() )
322  return _previous_scalarprod > 0;
323  else
324  return _previous_scalarprod < 0;
325  }
326 
327  template <typename O>
328  bool WolfeLineSearch<O>::wolfe1( float a ) const
329  {
330  float righthand = _previous_value + _c1 * a * _previous_scalarprod;
331  if( maximize() )
332  return _current_value >= righthand;
333  else
334  return _current_value <= righthand;
335  }
336 
337  template <typename O>
338  bool WolfeLineSearch<O>::wolfe2w( float a ) const
339  {
340  float current_scalarprod = (math::transpose(_p) * objectiveFunction().derivative( _x + a * _p )).at(0);
341  float righthand = _c2 * _previous_scalarprod;
342  if( maximize() )
343  return current_scalarprod <= righthand;
344  else
345  return current_scalarprod >= righthand;
346  }
347 
348  template <typename O>
349  bool WolfeLineSearch<O>::wolfe2s( float a ) const
350  {
351  float current_scalarprod = (math::transpose(_p) * objectiveFunction().derivative( _x + a * _p )).at(0);
352  float righthand = _c2 * _previous_scalarprod;
353  return std::abs(current_scalarprod) <= std::abs(righthand);
354  }
355 
356  template <typename O>
357  bool WolfeLineSearch<O>::wolfe2( float a ) const
358  {
359  if( _strong )
360  return wolfe2s(a);
361  else
362  return wolfe2w(a);
363  }
364 
365 } // namespace aims
366 
367 #endif // PRIMATOLOGIST_OPTIMIZATION_WOLFE_D_H
Once an ascent direction is given, this class performs a line search that respects wolfe conditions.
Definition: wolfe_decl.h:39
WolfeLineSearch(const Objective &f=Objective(), const Vector &x=Vector(), const Vector &p=Vector())
Definition: wolfe_d.h:27
void setMaxIterations(int n=- 1)
Definition: wolfe_d.h:136
WolfeLineSearch< O > & operator=(const WolfeLineSearch< O > &other)
Definition: wolfe_d.h:64
bool strongWolfe() const
Definition: wolfe_d.h:179
float _c1
Wolfe c1.
Definition: wolfe_decl.h:101
Objective _f
objectiveFunction
Definition: wolfe_decl.h:105
bool wolfe1(float a) const
Armijo (= Wolfe 1st) condition.
Definition: wolfe_d.h:328
bool maximize() const
Definition: wolfe_d.h:191
void setSearchDirection(const Vector &p=Vector())
Definition: wolfe_d.h:106
float _c2
Wolfe c2.
Definition: wolfe_decl.h:102
void setObjectiveFunction(const Objective &f)
Definition: wolfe_d.h:112
void setMaximize(bool maximize=false)
Definition: wolfe_d.h:130
bool wolfe2w(float a) const
weak 2nd Wolfe condition
Definition: wolfe_d.h:338
float _previous_value
f(x)
Definition: wolfe_decl.h:120
bool checkDirection()
Compute f(x) and <p, g(x)>.
Definition: wolfe_d.h:317
Vector _x
position
Definition: wolfe_decl.h:103
const Objective & objectiveFunction() const
Definition: wolfe_d.h:173
void setStrongWolfe(bool strong=false)
Definition: wolfe_d.h:118
void setPosition(const Vector &x=Vector())
Definition: wolfe_d.h:100
float _previous_scalarprod
<p, g(x)>
Definition: wolfe_decl.h:122
int maxIterations() const
Definition: wolfe_d.h:197
void setC1(float c1=1E-4)
Definition: wolfe_d.h:88
bool _maximize
maximize or minimize
Definition: wolfe_decl.h:108
float c2() const
Definition: wolfe_d.h:152
int _max_it
maximum number of iterations
Definition: wolfe_decl.h:109
int verbose() const
Definition: wolfe_d.h:185
bool wolfe2s(float a) const
strong 2nd Wolfe condition
Definition: wolfe_d.h:349
void setC2(float c2=0.9)
Definition: wolfe_d.h:94
int _verbose
verbosity level
Definition: wolfe_decl.h:107
float c1() const
Definition: wolfe_d.h:146
void setVerbose(int v=carto::verbose)
Definition: wolfe_d.h:124
bool _strong
strongWolfe
Definition: wolfe_decl.h:106
const Vector & searchDirection() const
Definition: wolfe_d.h:166
const Vector & position() const
Definition: wolfe_d.h:159
Vector _p
ascentDirection
Definition: wolfe_decl.h:104
bool wolfe2(float a) const
select condition based on _strong
Definition: wolfe_d.h:357
float _current_value
f(x + a.p)
Definition: wolfe_decl.h:121
Matrix class implementing matrix operations.
Definition: matrix.h:50
const T & at(const carto::VolumeRef< T > &vol, long px, long py, long pz, long pt, const Point4dl &fullsize, const Point4dl &binf)
MatrixBase< T > transpose(const MatrixBase< T > &)
Matrix transposition.
Definition: matrix_d.h:165