DGtal  0.6.devel
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
AngleLinearMinimizer.cpp
1 
33 
34 #include "DGtal/math/AngleLinearMinimizer.h"
36 
38 // class AngleLinearMinimizer
40 
42 // Standard services - public :
43 
44 
46 {
47  reset();
48 }
49 
50 
52  : myValues( 0 )
53 {
54 }
55 
56 
57 void
59 {
60  if ( myValues != 0 )
61  {
62  delete[] myValues;
63  myValues = 0;
64  }
65  mySum = 0.0;
66  myMax = 0.0;
67 }
68 
69 
70 void
71 DGtal::AngleLinearMinimizer::init( unsigned int nbMax )
72 {
73  reset();
74  myValues = new ValueInfo[ nbMax ];
75  myMaxSize = nbMax;
76  mySize = nbMax;
77  myIsCurveOpen = false;
78 }
79 
80 
81 
82 
84 // ------------------------- Optimization services --------------------------
85 
86 double
87 DGtal::AngleLinearMinimizer::getEnergy( unsigned int i1, unsigned int i2 ) const
88 {
89  ModuloComputer<unsigned int> mc( size() );
90  double E = 0.0;
91  for ( unsigned int i = mc.next( i1 ); i != i2; )
92  {
93  unsigned int inext = mc.next( i );
94  const ValueInfo & vi = this->ro( i );
95  const ValueInfo & viprev = this->ro( mc.previous( i ) );
96  double dev = AngleComputer::deviation( vi.value, viprev.value );
97  E += (dev * dev) / viprev.distToNext;
98  i = inext;
99  }
100  return E;
101 }
102 
103 
104 
105 double
106 DGtal::AngleLinearMinimizer::getFormerEnergy( unsigned int i1, unsigned int i2 ) const
107 {
108  ModuloComputer<unsigned int> mc( size() );
109  double E = 0.0;
110  for ( unsigned int i = mc.next( i1 ); i != i2; )
111  {
112  unsigned int inext = mc.next( i );
113  const ValueInfo & vi = this->ro( i );
114  const ValueInfo & viprev = this->ro( mc.previous( i ) );
115  double dev = AngleComputer::deviation( vi.oldValue, viprev.oldValue );
116  E += (dev * dev) / viprev.distToNext;
117  i = inext;
118  }
119  return E;
120 }
121 
122 
123 
124 
125 std::vector<double>
127 {
128  ModuloComputer<unsigned int> mc( size() );
129 
130  vector<double> grad( size() );
131  for ( unsigned int i = 0; i < size(); i++ )
132  {
133  unsigned int iprev = mc.previous( i );
134  unsigned int inext = mc.next( i );
135  const ValueInfo & vi = this->ro( i );
136  double val = vi.value;
137  if ( myIsCurveOpen && ( i == ( size() - 1 ) ) )
138  { // free extremity to the front/right.
139  const ValueInfo & viprev = this->ro( iprev );
140  double valp = viprev.value;
141  grad[ i ] = 2.0 * AngleComputer::deviation( val, valp ) / viprev.distToNext;
142  }
143  else if ( myIsCurveOpen && ( i == 0 ) )
144  { // free extremity to the back/left.
145  const ValueInfo & vinext = this->ro( inext );
146  double valn = vinext.value;
147  grad[ i ] = -2.0 * AngleComputer::deviation( valn, val ) / vi.distToNext;
148  }
149  else
150  { // standard case.
151  const ValueInfo & viprev = this->ro( iprev );
152  const ValueInfo & vinext = this->ro( inext );
153  double valp = viprev.value;
154  double valn = vinext.value;
155  grad[ i ] = 2.0*( AngleComputer::deviation( val, valp ) / viprev.distToNext
156  - AngleComputer::deviation( valn, val ) / vi.distToNext ) ;
157  }
158  }
159  return grad;
160 }
161 
162 
163 
164 
165 std::vector<double>
167 {
168  ModuloComputer<unsigned int> mc( size() );
169 
170  vector<double> grad( size() );
171  for ( unsigned int i = 0; i < size(); i++ )
172  {
173  unsigned int iprev = mc.previous( i );
174  unsigned int inext = mc.next( i );
175  const ValueInfo & vi = this->ro( i );
176  double val = vi.oldValue;
177  if ( myIsCurveOpen && ( i == ( size() - 1 ) ) )
178  { // free extremity to the front/right.
179  const ValueInfo & viprev = this->ro( iprev );
180  double valp = viprev.oldValue;
181  grad[ i ] = 2.0 * AngleComputer::deviation( val, valp ) / viprev.distToNext;
182  }
183  else if ( myIsCurveOpen && ( i == 0 ) )
184  { // free extremity to the back/left.
185  const ValueInfo & vinext = this->ro( inext );
186  double valn = vinext.oldValue;
187  grad[ i ] = -2.0 * AngleComputer::deviation( valn, val ) / vi.distToNext;
188  }
189  else
190  { // standard case.
191  const ValueInfo & viprev = this->ro( iprev );
192  const ValueInfo & vinext = this->ro( inext );
193  double valp = viprev.oldValue;
194  double valn = vinext.oldValue;
195  grad[ i ] = 2.0*( AngleComputer::deviation( val, valp ) / viprev.distToNext
196  - AngleComputer::deviation( valn, val ) / vi.distToNext ) ;
197  }
198  }
199  return grad;
200 }
201 
202 
203 double
205 {
206  return optimize( 0, 0 );
207 }
208 
209 
210 double
211 DGtal::AngleLinearMinimizer::optimize( unsigned int i1, unsigned int i2 )
212 {
213  ASSERT( size() > 2 );
214  ModuloComputer<unsigned int> mc( size() );
215 
216  unsigned int i = i1;
217  // (I) first pass to work on old values.
218  do
219  {
220  ValueInfo & vi = this->rw( i );
221  vi.oldValue = vi.value;
222  // go to next.
223  i = mc.next( i );
224  }
225  while ( i != i2 );
226  this->oneStep( i1, i2 );
227 
228  mySum = 0.0;
229  myMax = 0.0;
230  i = i1;
231  do
232  {
233  const ValueInfo & vi = this->ro( i );
234  double diff = fabs( AngleComputer::deviation( vi.value, vi.oldValue ) );
235  if ( diff > myMax )
236  myMax = diff;
237  mySum += diff;
238  i = mc.next( i );
239  }
240  while ( i != i2 );
241 
242  return mySum;
243 }
244 
245 
246 double
248 {
249  return max();
250 }
251 
252 
253 void
254 DGtal::AngleLinearMinimizer::oneStep( unsigned int i1, unsigned int i2 )
255 {
256  ModuloComputer<unsigned int> mc( size() );
257 
258  double mid;
259  unsigned int i = i1;
260  unsigned int iprev = mc.previous( i );
261  do
262  {
263  unsigned int inext = mc.next( i );
264  ValueInfo & vi = this->rw( i );
265  if ( myIsCurveOpen && ( i == ( size() - 1 ) ) )
266  { // free extremity to the front/right.
267  const ValueInfo & viprev = this->ro( iprev );
268  mid = viprev.oldValue; // - viprev.delta;
269  }
270  else if ( myIsCurveOpen && ( i == 0 ) )
271  { // free extremity to the back/left.
272  const ValueInfo & vinext = this->ro( inext );
273  mid = vinext.oldValue; // + vi.delta;
274  }
275  else
276  { // standard case.
277  const ValueInfo & viprev = this->ro( iprev );
278  const ValueInfo & vinext = this->ro( inext );
279  double valp = viprev.oldValue; // - viprev.delta;
280  double valn = vinext.oldValue; // + vi.delta;
281 
282  // old
283  double y = AngleComputer::deviation( valn, valp );
284  mid = ( viprev.distToNext * y )
285  / ( vi.distToNext + viprev.distToNext );
286  mid = AngleComputer::cast( mid + valp );
287 
288  }
289  if ( AngleComputer::less( mid, vi.min ) ) mid = vi.min;
290  if ( AngleComputer::less( vi.max, mid ) ) mid = vi.max;
291  double mvt = AngleComputer::deviation( mid, vi.oldValue );
292  vi.value = AngleComputer::cast( vi.oldValue + 0.5 * mvt );
293  // go to next.
294  iprev = i;
295  i = inext;
296  }
297  while ( i != i2 );
298 
299 
300 }
301 
302 
303 
304 void
305 DGtal::AngleLinearMinimizerByRelaxation::oneStep( unsigned int i1, unsigned int i2 )
306 {
307  ModuloComputer<unsigned int> mc( size() );
308 
309  double mid;
310  unsigned int i = i1;
311  unsigned int iprev = mc.previous( i );
312  do
313  {
314  unsigned int inext = mc.next( i );
315  ValueInfo & vi = this->rw( i );
316  // vi.oldValue = vi.value;
317  if ( myIsCurveOpen && ( i == ( size() - 1 ) ) )
318  { // free extremity to the front/right.
319  const ValueInfo & viprev = this->ro( iprev );
320  mid = viprev.value; // - viprev.delta;
321  }
322  else if ( myIsCurveOpen && ( i == 0 ) )
323  { // free extremity to the back/left.
324  const ValueInfo & vinext = this->ro( inext );
325  mid = vinext.oldValue; // + vi.delta;
326  }
327  else
328  { // standard case.
329  const ValueInfo & viprev = this->ro( iprev );
330  const ValueInfo & vinext = this->ro( inext );
331  double valp = viprev.value; // - viprev.delta;
332  double valn = vinext.value;
333 
334  // old
335  double y = AngleComputer::deviation( valn, valp );
336  mid = ( viprev.distToNext * y )
337  / ( vi.distToNext + viprev.distToNext );
338  mid = AngleComputer::cast( mid + valp );
339  }
340  if ( AngleComputer::less( mid, vi.min ) ) mid = vi.min;
341  if ( AngleComputer::less( vi.max, mid ) ) mid = vi.max;
342  vi.value = mid;
343  iprev = i;
344  i = inext;
345  }
346  while ( i != i2 );
347 }
348 
349 
350 
351 
352 double
354 {
355  return max();
356 }
357 
358 
359 
360 void
361 DGtal::AngleLinearMinimizerByGradientDescent::oneStep( unsigned int i1, unsigned int i2 )
362 {
363  ModuloComputer<unsigned int> mc( size() );
364 
365  vector<double> grad ( getFormerGradient() );
366  double mid;
367  unsigned int i = i1;
368  do
369  {
370  unsigned int inext = mc.next( i );
371  ValueInfo & vi = this->rw( i );
372  double val = vi.oldValue;
373  mid = AngleComputer::cast( val - myStep*grad[ i ] );
374  if ( AngleComputer::less( mid, vi.min ) ) mid = vi.min;
375  if ( AngleComputer::less( vi.max, mid ) ) mid = vi.max;
376  vi.value = mid;
377  // go to next.
378  i = inext;
379  }
380  while ( i != i2 );
381  double E1 = getFormerEnergy( i1, i2 );
382  double E2 = getEnergy( i1, i2 );
383  cerr << "E1=" << E1 << " E2=" << E2 << " s=" << myStep << endl;
384 }
385 
386 
387 
388 double
390 {
391  vector<double> grad ( getFormerGradient() );
392  double ninf = 0.0;
393  for ( unsigned int i = 0; i < size(); i++ )
394  {
395  const ValueInfo & vi = this->ro( i );
396  if ( vi.value != vi.oldValue )
397  {
398  double n = fabs( grad[ i ] );
399  if ( n > ninf ) ninf = n;
400  }
401  }
402  return ninf;
403 }
404 
405 
406 
407 
408 void
410 {
411  ModuloComputer<unsigned int> mc( size() );
412  vector<double> grad ( getFormerGradient() );
413 
414  double mid;
415  unsigned int i = i1;
416  do
417  {
418  unsigned int inext = mc.next( i );
419  ValueInfo & vi = this->rw( i );
420  double val = vi.oldValue;
421  mid = AngleComputer::cast( val - myStep*grad[ i ] );
422  if ( AngleComputer::less( mid, vi.min ) ) mid = vi.min;
423  if ( AngleComputer::less( vi.max, mid ) ) mid = vi.max;
424  vi.value = mid;
425  // go to next.
426  i = inext;
427  }
428  while ( i != i2 );
429 
430  double E1 = getFormerEnergy( i1, i2 );
431  double E2 = getEnergy( i1, i2 );
432  cerr << "E1=" << E1 << " E2=" << E2 << " s=" << myStep << endl;
433  if ( E1 <= E2 )
434  {
435  myStep /= 4.0;
436  }
437  else
438  {
439  /* doubling step. */
440  myStep *= 2.0;
441  }
442 }
443 
444 
445 
446 double
448 {
449  vector<double> grad ( getFormerGradient() );
450  double ninf = 0.0;
451  for ( unsigned int i = 0; i < size(); i++ )
452  {
453  const ValueInfo & vi = this->ro( i );
454  if ( vi.value != vi.oldValue )
455  {
456  double n = fabs( grad[ i ] );
457  if ( n > ninf ) ninf = n;
458  }
459  }
460  return ninf;
461 }
462 
463 
464 
465 
467 // Interface - public :
468 
473 void
474 DGtal::AngleLinearMinimizer::selfDisplay ( std::ostream & aStream ) const
475 {
476  aStream << "[AngleLinearMinimizer::standard 0.5]";
477 }
478 
479 
484 void
486 {
487  aStream << "[LinearMinimizer::relaxation]";
488 }
489 
494 void
496 {
497  aStream << "[LinearMinimizer::gradient descent " << myStep << "]";
498 }
499 
504 void
506 {
507  aStream << "[LinearMinimizer::gradient descent with adaptive step " << myStep << "]";
508 }
509 
514 bool
516 {
517  return true;
518 }
519 
520 
521 
523 // Internals - private :
524 
525 // //