File: itkScaledSingleValuedNonLinearOptimizer.h

package info (click to toggle)
elastix 5.2.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 42,480 kB
  • sloc: cpp: 68,403; lisp: 4,118; python: 1,013; xml: 182; sh: 177; makefile: 33
file content (196 lines) | stat: -rw-r--r-- 7,109 bytes parent folder | download
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
/*=========================================================================
 *
 *  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 itkScaledSingleValuedNonLinearOptimizer_h
#define itkScaledSingleValuedNonLinearOptimizer_h

#include "itkSingleValuedNonLinearOptimizer.h"
#include "itkScaledSingleValuedCostFunction.h"

namespace itk
{
/** \class ScaledSingleValuedNonLinearOptimizer
 *
 * Optimizers that inherit from this class optimize a scaled
 * cost function \f$F(y)\f$ instead of the original function \f$f(x)\f$:
 *
 *   \f[ y    = x \cdot s  \f]
 *   \f[ F(y) = f(y/s) \f]
 *
 * where \f$y\f$ are the scaled parameters, \f$x\f$ the original parameters
 * and \f$s\f$ the scales.
 *
 * During optimization the inheriting classes should update the
 * ScaledCurrentPosition (\f$y\f$) instead of the CurrentPosition (\f$y/s\f$).
 *
 * When an optimizer needs the value at a (scaled) position \f$y\f$,
 * it should use the function this->GetScaledValue(\f$y\f$)
 * instead of the GetValue method. Similar for the derivative.
 *
 * Typically, in StartOptimization() the following line should be present:\n
 *   <tt>this->SetCurrentPosition(this->GetInitialPosition);</tt>\n
 * This makes sure that the initial position \f$y_0 = x_0 \cdot s\f$, where \f$x_0\f$ is
 * the initial (unscaled) position entered by the user.
 *
 * Note that:
 * - GetScaledCurrentPosition returns the current \f$y\f$.
 * - GetCurrentPosition returns the current \f$x = y/s\f$. This array is only
 * computed when asked for by the user.
 * - It is NOT necessary to set the CurrentPosition!! In fact, it is
 * not possible anymore: the SetCurrentPosition(param) method is overrided
 * and calls SetScaledCurrentPositon(param*scales).
 * - The ITK convention is to set the squared scales in the optimizer.
 * So, if you want a scaling s, you must call SetScales(\f$s.*s\f$) (where .*
 * symbolises the element-wise product of \f$s\f$ with \f$s\f$)
 *
 */

class ScaledSingleValuedNonLinearOptimizer : public SingleValuedNonLinearOptimizer
{
public:
  ITK_DISALLOW_COPY_AND_MOVE(ScaledSingleValuedNonLinearOptimizer);

  /** Standard ITK-stuff. */
  using Self = ScaledSingleValuedNonLinearOptimizer;
  using Superclass = SingleValuedNonLinearOptimizer;
  using Pointer = SmartPointer<Self>;
  using ConstPointer = SmartPointer<const Self>;

  /** Method for creation through the object factory. */
  itkNewMacro(Self);

  /** Run-time type information (and related methods). */
  itkTypeMacro(ScaledSingleValuedNonLinearOptimizer, SingleValuedNonLinearOptimizer);

  /** Typedefs inherited from the superclass. */
  using Superclass::MeasureType;
  using Superclass::ParametersType;
  using Superclass::DerivativeType;
  using Superclass::CostFunctionType;

  using ScalesType = NonLinearOptimizer::ScalesType;
  using ScaledCostFunctionType = ScaledSingleValuedCostFunction;
  using ScaledCostFunctionPointer = ScaledCostFunctionType::Pointer;

  /** Configure the scaled cost function. This function
   * sets the current scales in the ScaledCostFunction.
   * NB: it assumes that the scales entered by the user
   * are the squared scales (following the ITK convention).
   * Call this method in StartOptimization() and after
   * entering new scales.
   */
  virtual void
  InitializeScales();

  /** Setting: SetCostFunction. */
  void
  SetCostFunction(CostFunctionType * costFunction) override;

  /** Setting: Turn on/off the use of scales. Set this flag to false when no
   * scaling is desired.
   */
  virtual void
  SetUseScales(bool arg);

  bool
  GetUseScales() const;

  /** Get the current scaled position. */
  itkGetConstReferenceMacro(ScaledCurrentPosition, ParametersType);

  /** Get the current unscaled position: get the ScaledCurrentPosition
   * and divide each element through its scale.
   */
  const ParametersType &
  GetCurrentPosition() const override;

  /** Get a pointer to the scaled cost function. */
  itkGetConstObjectMacro(ScaledCostFunction, ScaledCostFunctionType);

  /** Setting: set to 'true' if you want to maximize the cost function.
   * It forces the scaledCostFunction to negate the cost function value
   * and its derivative.
   */
  itkBooleanMacro(Maximize);
  virtual void
  SetMaximize(bool _arg);

  itkGetConstMacro(Maximize, bool);

protected:
  /** The constructor. */
  ScaledSingleValuedNonLinearOptimizer();
  /** The destructor. */
  ~ScaledSingleValuedNonLinearOptimizer() override = default;

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

  /** Member variables. */
  ParametersType            m_ScaledCurrentPosition{};
  ScaledCostFunctionPointer m_ScaledCostFunction{};

  /** Set m_ScaledCurrentPosition. */
  virtual void
  SetScaledCurrentPosition(const ParametersType & parameters);

  /** Set the scaled current position by entering the non-scaled
   * parameters. The method multiplies param by the scales and
   * calls SetScaledCurrentPosition.
   *
   * Note: It is not possible (and needed) anymore to set m_CurrentPosition.
   * Optimizers that inherit from this class should optimize the scaled
   * parameters!
   *
   * This method will probably only be used to convert the InitialPosition
   * entered by the user.
   */
  void
  SetCurrentPosition(const ParametersType & param) override;

  /** Divide the (scaled) parameters by the scales and call the GetValue routine
   * of the unscaled cost function.
   */
  virtual MeasureType
  GetScaledValue(const ParametersType & parameters) const;

  /** Divide the (scaled) parameters by the scales, call the GetDerivative routine
   * of the unscaled cost function and divide the resulting derivative by
   * the scales.
   */
  virtual void
  GetScaledDerivative(const ParametersType & parameters, DerivativeType & derivative) const;

  /** Same procedure as in GetValue and GetDerivative. */
  virtual void
  GetScaledValueAndDerivative(const ParametersType & parameters,
                              MeasureType &          value,
                              DerivativeType &       derivative) const;

private:
  /** Variable to store the CurrentPosition, when the function
   * GetCurrentPosition is called. This method needs a member variable,
   * because the GetCurrentPosition return something by reference.
   */
  mutable ParametersType m_UnscaledCurrentPosition{};
  bool                   m_Maximize{};
};

} // end namespace itk

#endif //#ifndef itkScaledSingleValuedNonLinearOptimizer_h