Shapeworks Studio  2.1
Shape analysis software suite
itkPSMGradientDescentOptimizer.hxx
1 /*=========================================================================
2  *
3  * Copyright Insight Software Consortium
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef __itkPSMGradientDescentOptimizer_hxx
19 #define __itkPSMGradientDescentOptimizer_hxx
20 #include "itkPSMGradientDescentOptimizer.h"
21 
22 namespace itk
23 {
24 template <class TGradientNumericType, unsigned int VDimension>
25 PSMGradientDescentOptimizer<TGradientNumericType, VDimension>
26 ::PSMGradientDescentOptimizer()
27 {
28  m_StopOptimization = false;
29  m_NumberOfIterations = 0;
30  m_MaximumNumberOfIterations = 0;
31  m_Tolerance = 1.0e-8;
32  m_TimeStep = 1.0;
33  m_OptimizationMode = 0;
34 }
35 
36 /*** GAUSS SEIDEL ***/
37 template <class TGradientNumericType, unsigned int VDimension>
38 void
39 PSMGradientDescentOptimizer<TGradientNumericType, VDimension>
40 ::StartGaussSeidelOptimization()
41 {
42  // NOTE: THIS METHOD WILL NOT WORK AS WRITTEN IF PARTICLES ARE
43  // ADDED TO THE SYSTEM DURING OPTIMIZATION.
44  m_StopOptimization = false;
45  m_NumberOfIterations = 0;
46  m_CostFunction->SetParticleSystem(m_ParticleSystem);
47 
48  VectorType gradient;
49  PointType newpoint;
50 
51  while (m_StopOptimization == false)
52  {
53  m_CostFunction->BeforeIteration();
54  double maxdt;
55  double movement = 0.0f;
56 
57  // Iterate over each domain
58  for (unsigned int dom = 0; dom < m_ParticleSystem->GetNumberOfDomains(); dom++)
59  {
60  // skip any flagged domains
61  if (m_ParticleSystem->GetDomainFlag(dom) == false)
62  {
63  // Tell function which domain we are working on.
64  m_CostFunction->SetDomainNumber(dom);
65 
66  // Iterate over each particle position
67  unsigned int k = 0;
68  typename ParticleSystemType::PointContainerType::ConstIterator endit =
69  m_ParticleSystem->GetPositions(dom)->GetEnd();
70  for (typename ParticleSystemType::PointContainerType::ConstIterator it
71  = m_ParticleSystem->GetPositions(dom)->GetBegin(); it != endit; it++, k++)
72  {
73  // Compute gradient update.
74  m_CostFunction->BeforeEvaluate(it.GetIndex(), dom, m_ParticleSystem);
75  gradient = m_CostFunction->Evaluate(it.GetIndex(), dom, m_ParticleSystem,
76  maxdt);
77 
78  // May modify gradient
79  dynamic_cast<DomainType *>(m_ParticleSystem->GetDomain(dom))
80  ->ApplyVectorConstraints(gradient,
81  m_ParticleSystem->GetPosition(it.GetIndex(), dom), maxdt);
82 
83  // Hack to avoid blowing up under certain conditions.
84  if (gradient.magnitude() > maxdt)
85  { gradient = (gradient / gradient.magnitude()) * maxdt; }
86 
87  // Compute particle move based on update.
88  for (unsigned int i = 0; i < VDimension; i++)
89  {
90  newpoint[i] = (*it)[i] - gradient[i] * m_TimeStep;
91  }
92 
93  // Keep the biggest particle movement.
94  if ( gradient.magnitude() > movement) movement = gradient.magnitude();
95 
96  // Apply update
97  m_ParticleSystem->SetPosition(newpoint, it.GetIndex(), dom);
98  } // for each particle
99  } // if not flagged
100  }// for each domain
101 
102  m_NumberOfIterations++;
103  m_CostFunction->AfterIteration();
104  this->InvokeEvent(itk::IterationEvent());
105 
106  // Has a maximum number of iterations been specified?
107  if ((m_MaximumNumberOfIterations != 0) && (m_NumberOfIterations >= m_MaximumNumberOfIterations))
108  {
109  m_StopOptimization = true;
110  }
111 
112  if (movement <= m_Tolerance) m_StopOptimization = true;
113 
114  } // end while
115 
116  }
117 
118 template <class TGradientNumericType, unsigned int VDimension>
119 void
120 PSMGradientDescentOptimizer<TGradientNumericType, VDimension>
121 ::StartJacobiOptimization()
122 {
123  // NOTE: THIS METHOD WILL NOT WORK AS WRITTEN IF PARTICLES ARE
124  // ADDED TO THE SYSTEM DURING OPTIMIZATION.
125  m_StopOptimization = false;
126  m_NumberOfIterations = 0;
127  m_CostFunction->SetParticleSystem(m_ParticleSystem);
128 
129  // Vector for storing updates.
130  std::vector<std::vector<PointType> > updates(m_ParticleSystem->GetNumberOfDomains());
131 
132  for (unsigned int d = 0; d < m_ParticleSystem->GetNumberOfDomains(); d++)
133  {
134  updates[d].resize(m_ParticleSystem->GetPositions(d)->GetSize());
135  }
136  VectorType gradient;
137  PointType newpoint;
138 
139  while (m_StopOptimization == false)
140  {
141  m_CostFunction->BeforeIteration();
142  double maxdt;
143  double movement = 0.0f;
144 
145  // Iterate over each domain
146  for (unsigned int dom = 0; dom < m_ParticleSystem->GetNumberOfDomains(); dom++)
147  {
148  // skip any flagged domains
149  if (m_ParticleSystem->GetDomainFlag(dom) == false)
150  {
151  // Tell function which domain we are working on.
152  m_CostFunction->SetDomainNumber(dom);
153 
154  // Iterate over each particle position
155  unsigned int k = 0;
156  typename ParticleSystemType::PointContainerType::ConstIterator endit =
157  m_ParticleSystem->GetPositions(dom)->GetEnd();
158  for (typename ParticleSystemType::PointContainerType::ConstIterator it
159  = m_ParticleSystem->GetPositions(dom)->GetBegin(); it != endit; it++, k++)
160  {
161  // Compute gradient update.
162  m_CostFunction->BeforeEvaluate(it.GetIndex(), dom, m_ParticleSystem);
163  gradient = m_CostFunction->Evaluate(it.GetIndex(), dom, m_ParticleSystem,
164  maxdt);
165  // May modify gradient
166  dynamic_cast<DomainType *>(m_ParticleSystem->GetDomain(dom))
167  ->ApplyVectorConstraints(gradient, m_ParticleSystem->GetPosition(it.GetIndex(), dom), maxdt);
168 
169  // Hack to avoid blowing up under certain conditions.
170  if (gradient.magnitude() > maxdt)
171  {
172  gradient = (gradient / gradient.magnitude()) * maxdt;
173  }
174 
175  // Compute particle move based on update.
176  for (unsigned int i = 0; i < VDimension; i++)
177  {
178  newpoint[i] = (*it)[i] - gradient[i] * m_TimeStep;
179  }
180 
181 
182  // Keep the biggest particle movement.
183  if ( gradient.magnitude() > movement) movement = gradient.magnitude();
184 
185  // Store update
186  updates[dom][k] = newpoint;
187  } // for each particle
188  } // if not flagged
189  }// for each domain
190 
191  for (unsigned int dom = 0; dom < m_ParticleSystem->GetNumberOfDomains(); dom++)
192  {
193  // skip any flagged domains
194  if (m_ParticleSystem->GetDomainFlag(dom) == false)
195  {
196  unsigned int k = 0;
197  typename ParticleSystemType::PointContainerType::ConstIterator endit =
198  m_ParticleSystem->GetPositions(dom)->GetEnd();
199  for (typename ParticleSystemType::PointContainerType::ConstIterator it
200  = m_ParticleSystem->GetPositions(dom)->GetBegin(); it != endit; it++, k++)
201  {
202  m_ParticleSystem->SetPosition(updates[dom][k], it.GetIndex(), dom);
203  } // for each particle
204  } // if not flagged
205  } // for each domain
206 
207  m_NumberOfIterations++;
208  m_CostFunction->AfterIteration();
209  this->InvokeEvent(itk::IterationEvent());
210 
211  // Has a maximum number of iterations been specified?
212  if ((m_MaximumNumberOfIterations != 0) && (m_NumberOfIterations >= m_MaximumNumberOfIterations))
213  {
214  m_StopOptimization = true;
215  }
216 
217  // Otherwise, converge based on a tolerance.
218  if (movement <= m_Tolerance) m_StopOptimization = true;
219 
220  } // end while
221 
222 }
223 
224 } // end namespace
225 
226 #endif