File: itkMoreThuenteLineSearchOptimizer.h

package info (click to toggle)
elastix 5.3.1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 45,644 kB
  • sloc: cpp: 85,720; lisp: 4,118; python: 1,045; sh: 200; xml: 182; makefile: 33
file content (394 lines) | stat: -rw-r--r-- 13,316 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
/*=========================================================================
 *
 *  Copyright UMC Utrecht and contributors
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#ifndef itkMoreThuenteLineSearchOptimizer_h
#define itkMoreThuenteLineSearchOptimizer_h

#include "itkLineSearchOptimizer.h"

namespace itk
{
/**
 * \class MoreThuenteLineSearchOptimizer
 *
 * \brief ITK version of the MoreThuente line search algorithm.
 *
 * This class is an ITK version of the netlib function mcsrch_. It
 * gives exactly the same results.
 *
 * The purpose of this optimizer is to find a step which satisfies
 * a sufficient decrease condition and a curvature condition.
 *
 * At each stage the subroutine updates an interval of
 * uncertainty with endpoints stx and sty. The interval of
 * uncertainty is initially chosen so that it contains a
 * minimizer of the modified function
 *
 *   \f[ f(x+stp*s) - f(x) - ValueTolerance*stp*(gradf(x)'s). \f]
 *
 * If a step is obtained for which the modified function
 * has a nonpositive function value and nonnegative derivative,
 * then the interval of uncertainty is chosen so that it
 * contains a minimizer of \f$f(x+stp*s)\f$.
 *
 * The algorithm is designed to find a step which satisfies
 * the sufficient decrease condition
 *
 *   \f[ f(x+stp*s) <= f(x) + ValueTolerance*stp*(gradf(x)'s), \f]
 *
 * and the curvature condition
 *
 *   \f[ \| gradf(x+stp*s)'s) \| <= GradientTolerance * \| gradf(x)'s \|. \f]
 *
 * (together also called the Strong Wolfe Conditions)
 *
 * if the ValueTolerance is less than the GradientTolerance and if,
 * for example, the function is bounded below, then there is always
 * a step which satisfies both conditions. If no step can be found
 * which satisfies both conditions, then the algorithm usually stops
 * when rounding errors prevent further progress. In this case stp only
 * satisfies the sufficient decrease condition.
 *
 *
 * \ingroup Numerics Optimizers
 */

class MoreThuenteLineSearchOptimizer : public LineSearchOptimizer
{
public:
  ITK_DISALLOW_COPY_AND_MOVE(MoreThuenteLineSearchOptimizer);

  using Self = MoreThuenteLineSearchOptimizer;
  using Superclass = LineSearchOptimizer;
  using Pointer = SmartPointer<Self>;
  using ConstPointer = SmartPointer<const Self>;

  itkNewMacro(Self);
  itkOverrideGetNameOfClassMacro(MoreThuenteLineSearchOptimizer);

  using Superclass::MeasureType;
  using Superclass::ParametersType;
  using Superclass::DerivativeType;
  using Superclass::CostFunctionType;

  enum StopConditionType
  {
    StrongWolfeConditionsSatisfied,
    MetricError,
    MaximumNumberOfIterations,
    StepTooSmall,
    StepTooLarge,
    IntervalTooSmall,
    RoundingError,
    AscentSearchDirection,
    Unknown
  };

  void
  StartOptimization() override;

  virtual void
  StopOptimization();

  /** If initial derivative and/or value are given we can save some
   * computation time!
   */
  void
  SetInitialDerivative(const DerivativeType & derivative) override;

  void
  SetInitialValue(MeasureType value) override;

  /** Progress information: value, derivative, and directional derivative
   * at the current position.
   */
  void
  GetCurrentValueAndDerivative(MeasureType & value, DerivativeType & derivative) const override;

  void
  GetCurrentDerivative(DerivativeType & derivative) const override;

  MeasureType
  GetCurrentValue() const override;

  virtual double
  GetCurrentDirectionalDerivative() const;

  /** Progress information: about the state of convergence */
  itkGetConstMacro(CurrentIteration, unsigned long);
  itkGetConstReferenceMacro(StopCondition, StopConditionType);
  itkGetConstMacro(SufficientDecreaseConditionSatisfied, bool);
  itkGetConstMacro(CurvatureConditionSatisfied, bool);

  /** Setting: the maximum number of iterations. 20 by default. */
  itkGetConstMacro(MaximumNumberOfIterations, unsigned long);
  itkSetClampMacro(MaximumNumberOfIterations, unsigned long, 1, NumericTraits<unsigned long>::max());

  /** Setting: the value tolerance. By default set to 1e-4.
   *
   * The line search tries to find a StepLength that satisfies
   * the sufficient decrease condition:
   * F(X + StepLength * s) <= F(X) + ValueTolerance * StepLength * dF/ds(X)
   * where s is the search direction
   *
   * It must be larger than 0.0, and smaller than the GradientTolerance.
   */
  itkSetClampMacro(ValueTolerance, double, 0.0, NumericTraits<double>::max());
  itkGetConstMacro(ValueTolerance, double);

  /** Setting: the gradient tolerance. By default set to 0.9.
   *
   * The line search tries to find a StepLength that satisfies
   * the curvature condition:
   * ABS(dF/ds(X + StepLength * s) <= GradientTolerance * ABS(dF/ds(X)
   *
   * The lower this value, the more accurate the line search. It must
   * be larger than the ValueTolerance.
   */
  itkSetClampMacro(GradientTolerance, double, 0.0, NumericTraits<double>::max());
  itkGetConstMacro(GradientTolerance, double);

  /** Setting: the interval tolerance. By default set to the
   * the machine precision.
   *
   * If value and gradient tolerance can not be satisfied
   * both, the algorithm stops when rounding errors prevent
   * further progress: when the interval of uncertainty is
   * smaller than the interval tolerance.
   */
  itkSetClampMacro(IntervalTolerance, double, 0.0, NumericTraits<double>::max());
  itkGetConstMacro(IntervalTolerance, double);

protected:
  MoreThuenteLineSearchOptimizer();
  ~MoreThuenteLineSearchOptimizer() override = default;

  void
  PrintSelf(std::ostream & os, Indent indent) const override;

  unsigned long     m_CurrentIteration{};
  bool              m_InitialDerivativeProvided{};
  bool              m_InitialValueProvided{};
  StopConditionType m_StopCondition{};
  bool              m_Stop{};
  bool              m_SufficientDecreaseConditionSatisfied{};
  bool              m_CurvatureConditionSatisfied{};

  /** Load the initial value and derivative into m_f and m_g. */
  virtual void
  GetInitialValueAndDerivative();

  /** Check the input settings for errors. */
  virtual int
  CheckSettings();

  /** Initialize the interval of uncertainty etc. */
  void
  InitializeLineSearch();

  /** Set the minimum and maximum steps to correspond to the
   * the present interval of uncertainty.
   */
  virtual void
  UpdateIntervalMinimumAndMaximum();

  /** Force a step to be within the bounds MinimumStepLength and MaximumStepLength */
  void
  BoundStep(double & step) const;

  /** Set m_step to the best step until now, if unusual termination is expected */
  virtual void
  PrepareForUnusualTermination();

  /** Ask the cost function to compute m_f and m_g at the current position. */
  virtual void
  ComputeCurrentValueAndDerivative();

  /** Check for convergence */
  virtual void
  TestConvergence(bool & stop);

  /** Update the interval of uncertainty and compute the new step */
  virtual void
  ComputeNewStepAndInterval();

  /** Force a sufficient decrease in the size of the interval of uncertainty */
  virtual void
  ForceSufficientDecreaseInIntervalWidth();

  /** Advance a step along the line search direction and update
   * the interval of uncertainty.
   */
  virtual int
  SafeGuardedStep(double &     stx,
                  double &     fx,
                  double &     dx,
                  double &     sty,
                  double &     fy,
                  double &     dy,
                  double &     stp,
                  const double fp,
                  const double dp,
                  bool &       brackt,
                  const double stpmin,
                  const double stpmax) const;

  double m_step{};
  double m_stepx{};
  double m_stepy{};
  double m_stepmin{};
  double m_stepmax{};

  MeasureType m_f{}; // CurrentValue
  MeasureType m_fx{};
  MeasureType m_fy{};
  MeasureType m_finit{};

  DerivativeType m_g{};  // CurrentDerivative
  double         m_dg{}; // CurrentDirectionalDerivative
  double         m_dginit{};
  double         m_dgx{};
  double         m_dgy{};
  double         m_dgtest{};

  double m_width{};
  double m_width1{};

  bool m_brackt{};
  bool m_stage1{};
  bool m_SafeGuardedStepFailed{};

private:
  unsigned long m_MaximumNumberOfIterations{};
  double        m_ValueTolerance{};
  double        m_GradientTolerance{};
  double        m_IntervalTolerance{};
};

} // end namespace itk

/** ***************** Original documentation ***********************************
 *
 * The implementation of this class is based on the netlib function mcsrch_.
 * The original documentation of this function is included below
 */

/*                     SUBROUTINE MCSRCH */

/*     A slight modification of the subroutine CSRCH of More' and Thuente. */
/*     The changes are to allow reverse communication, and do not affect */
/*     the performance of the routine. */

/*     THE PURPOSE OF MCSRCH IS TO FIND A STEP WHICH SATISFIES */
/*     A SUFFICIENT DECREASE CONDITION AND A CURVATURE CONDITION. */

/*     AT EACH STAGE THE SUBROUTINE UPDATES AN INTERVAL OF */
/*     UNCERTAINTY WITH ENDPOINTS STX AND STY. THE INTERVAL OF */
/*     UNCERTAINTY IS INITIALLY CHOSEN SO THAT IT CONTAINS A */
/*     MINIMIZER OF THE MODIFIED FUNCTION */

/*          F(X+STP*S) - F(X) - FTOL*STP*(GRADF(X)'S). */

/*     IF A STEP IS OBTAINED FOR WHICH THE MODIFIED FUNCTION */
/*     HAS A NONPOSITIVE FUNCTION VALUE AND NONNEGATIVE DERIVATIVE, */
/*     THEN THE INTERVAL OF UNCERTAINTY IS CHOSEN SO THAT IT */
/*     CONTAINS A MINIMIZER OF F(X+STP*S). */

/*     THE ALGORITHM IS DESIGNED TO FIND A STEP WHICH SATISFIES */
/*     THE SUFFICIENT DECREASE CONDITION */

/*           F(X+STP*S) .LE. F(X) + FTOL*STP*(GRADF(X)'S), */

/*     AND THE CURVATURE CONDITION */

/*           ABS(GRADF(X+STP*S)'S)) .LE. GTOL*ABS(GRADF(X)'S). */

/*     IF FTOL IS LESS THAN GTOL AND IF, FOR EXAMPLE, THE FUNCTION */
/*     IS BOUNDED BELOW, THEN THERE IS ALWAYS A STEP WHICH SATISFIES */
/*     BOTH CONDITIONS. IF NO STEP CAN BE FOUND WHICH SATISFIES BOTH */
/*     CONDITIONS, THEN THE ALGORITHM USUALLY STOPS WHEN ROUNDING */
/*     ERRORS PREVENT FURTHER PROGRESS. IN THIS CASE STP ONLY */
/*     SATISFIES THE SUFFICIENT DECREASE CONDITION. */

/*     THE SUBROUTINE STATEMENT IS */

/*        SUBROUTINE MCSRCH(N,X,F,G,S,STP,FTOL,XTOL, MAXFEV,INFO,NFEV,WA) */
/*     WHERE */

/*       N IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE NUMBER */
/*         OF VARIABLES. */

/*       X IS AN ARRAY OF LENGTH N. ON INPUT IT MUST CONTAIN THE */
/*         BASE POINT FOR THE LINE SEARCH. ON OUTPUT IT CONTAINS */
/*         X + STP*S. */

/*       F IS A VARIABLE. ON INPUT IT MUST CONTAIN THE VALUE OF F */
/*         AT X. ON OUTPUT IT CONTAINS THE VALUE OF F AT X + STP*S. */

/*       G IS AN ARRAY OF LENGTH N. ON INPUT IT MUST CONTAIN THE */
/*         GRADIENT OF F AT X. ON OUTPUT IT CONTAINS THE GRADIENT */
/*         OF F AT X + STP*S. */

/*       S IS AN INPUT ARRAY OF LENGTH N WHICH SPECIFIES THE */
/*         SEARCH DIRECTION. */

/*       STP IS A NONNEGATIVE VARIABLE. ON INPUT STP CONTAINS AN */
/*         INITIAL ESTIMATE OF A SATISFACTORY STEP. ON OUTPUT */
/*         STP CONTAINS THE FINAL ESTIMATE. */

/*       FTOL AND GTOL ARE NONNEGATIVE INPUT VARIABLES. (In this reverse */
/*         communication implementation GTOL is defined in a COMMON */
/*         statement.) TERMINATION OCCURS WHEN THE SUFFICIENT DECREASE */
/*         CONDITION AND THE DIRECTIONAL DERIVATIVE CONDITION ARE */
/*         SATISFIED. */

/*       XTOL IS A NONNEGATIVE INPUT VARIABLE. TERMINATION OCCURS */
/*         WHEN THE RELATIVE WIDTH OF THE INTERVAL OF UNCERTAINTY */
/*         IS AT MOST XTOL. */

/*       STPMIN AND STPMAX ARE NONNEGATIVE INPUT VARIABLES WHICH */
/*         SPECIFY LOWER AND UPPER BOUNDS FOR THE STEP. (In this reverse */
/*         communication implementatin they are defined in a COMMON */
/*         statement). */

/*       MAXFEV IS A POSITIVE INTEGER INPUT VARIABLE. TERMINATION */
/*         OCCURS WHEN THE NUMBER OF CALLS TO FCN IS AT LEAST */
/*         MAXFEV BY THE END OF AN ITERATION. */

/*       INFO IS AN INTEGER OUTPUT VARIABLE SET AS FOLLOWS: */

/*         INFO = 0  IMPROPER INPUT PARAMETERS. */

/*        INFO =-1  A RETURN IS MADE TO COMPUTE THE FUNCTION AND GRADIENT.  */
/*       NFEV IS AN INTEGER OUTPUT VARIABLE SET TO THE NUMBER OF */
/*         CALLS TO FCN. */

/*       WA IS A WORK ARRAY OF LENGTH N. */

/*     SUBPROGRAMS CALLED */

/*       MCSTEP */

/*       FORTRAN-SUPPLIED...ABS,MAX,MIN */

/*     ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JUNE 1983 */
/*     JORGE J. MORE', DAVID J. THUENTE */

/*     ********** */

#endif // #ifndef itkMoreThuenteLineSearchOptimizer_h