2 #include <vnl/algo/vnl_qr.h> 9 unsigned int parametersSize = m_DataMatrix.cols();
10 unsigned int numEquations = m_DataMatrix.rows();
12 if ((numEquations != m_Points.size())||(numEquations == 0)||(parametersSize == 0))
13 itkExceptionMacro(
"Wrongly sized inputs to BVLS, aborting");
15 m_bPrimeVector.set_size(numEquations);
16 m_CurrentPosition.SetSize(parametersSize);
17 m_ParametersAtBoundsVector.resize(parametersSize);
19 this->InitializeSolutionByProjection();
21 bool continueLoop =
true;
22 bool wRequired =
true;
27 this->ComputeWVector();
28 continueLoop = this->TestKuhnTuckerConvergence();
34 unsigned int maxIndex = 0;
35 for (
unsigned int i = 0;i < parametersSize;++i)
37 double testVal = m_WVector[i] * m_ParametersAtBoundsVector[i];
46 m_ParametersAtBoundsVector[maxIndex] = 0;
48 bool continueInternalLoop =
true;
49 while (continueInternalLoop)
52 unsigned int numReducedParameters = 0;
53 for (
unsigned int i = 0;i < parametersSize;++i)
54 numReducedParameters += (m_ParametersAtBoundsVector[i] == 0);
56 if (numReducedParameters == 0)
59 m_ReducedDataMatrix.set_size(numEquations,numReducedParameters);
60 for (
unsigned int j = 0;j < numEquations;++j)
62 m_bPrimeVector[j] = m_Points[j];
64 for (
unsigned int k = 0;k < parametersSize;++k)
66 if (m_ParametersAtBoundsVector[k] != 0)
67 m_bPrimeVector[j] -= m_DataMatrix(j,k) * m_CurrentPosition[k];
70 m_ReducedDataMatrix[j][pos] = m_DataMatrix[j][k];
77 m_ReducedSolution = vnl_qr <double> (m_ReducedDataMatrix).solve(m_bPrimeVector);
80 bool reducedOk =
true;
82 for (
unsigned int i = 0;i < parametersSize;++i)
84 if (m_ParametersAtBoundsVector[i] != 0)
87 if ((m_ReducedSolution[pos] <= m_LowerBounds[i])||
88 (m_ReducedSolution[pos] >= m_UpperBounds[i]))
99 continueInternalLoop =
false;
101 for (
unsigned int i = 0;i < parametersSize;++i)
103 if (m_ParametersAtBoundsVector[i] != 0)
106 m_CurrentPosition[i] = m_ReducedSolution[pos];
115 double minAlpha = 2.0;
116 unsigned int minIndex = 0;
119 for (
unsigned int i = 0;i < parametersSize;++i)
121 if (m_ParametersAtBoundsVector[i] != 0)
124 if ((m_ReducedSolution[pos] <= m_LowerBounds[i])||
125 (m_ReducedSolution[pos] >= m_UpperBounds[i]))
127 double denom = m_ReducedSolution[pos] - m_CurrentPosition[i];
129 if (m_ReducedSolution[pos] >= m_UpperBounds[i])
130 alpha = m_UpperBounds[i] - m_CurrentPosition[i];
132 alpha = m_LowerBounds[i] - m_CurrentPosition[i];
135 alpha = std::max(0.0,alpha);
137 if (alpha < minAlpha)
147 if ((minAlpha == 0.0) && (minIndex == maxIndex))
149 m_WVector[maxIndex] = 0.0;
151 continueInternalLoop =
false;
153 if (m_CurrentPosition[maxIndex] == m_LowerBounds[maxIndex])
154 m_ParametersAtBoundsVector[maxIndex] = 1;
155 else if (m_CurrentPosition[maxIndex] == m_UpperBounds[maxIndex])
156 m_ParametersAtBoundsVector[maxIndex] = -1;
162 for (
unsigned int i = 0;i < parametersSize;++i)
164 if (m_ParametersAtBoundsVector[i] != 0)
169 double addonValue = minAlpha * (m_ReducedSolution[pos] - m_CurrentPosition[i]);
170 m_CurrentPosition[i] += addonValue;
174 if (m_ReducedSolution[pos] <= m_LowerBounds[i])
175 m_CurrentPosition[i] = m_LowerBounds[i];
177 m_CurrentPosition[i] = m_UpperBounds[i];
180 if (m_CurrentPosition[i] <= m_LowerBounds[i])
182 m_ParametersAtBoundsVector[i] = 1;
183 m_CurrentPosition[i] = m_LowerBounds[i];
185 else if (m_CurrentPosition[i] >= m_UpperBounds[i])
187 m_ParametersAtBoundsVector[i] = -1;
188 m_CurrentPosition[i] = m_UpperBounds[i];
200 void BVLSOptimizer::InitializeSolutionByProjection()
202 unsigned int parametersSize = m_DataMatrix.cols();
203 m_CurrentPosition.SetSize(parametersSize);
204 m_ParametersAtBoundsVector.resize(parametersSize);
205 std::fill(m_ParametersAtBoundsVector.begin(), m_ParametersAtBoundsVector.end(),0);
207 unsigned int countBounded = 0;
208 unsigned int diffCountBounded = 1;
209 unsigned int numEquations = m_DataMatrix.rows();
211 while ((diffCountBounded != 0) && (countBounded < parametersSize))
213 unsigned int numParameters = parametersSize - countBounded;
215 m_ReducedDataMatrix.set_size(numEquations,numParameters);
216 for (
unsigned int j = 0;j < numEquations;++j)
218 m_bPrimeVector[j] = m_Points[j];
219 unsigned int pos = 0;
220 for (
unsigned int k = 0;k < parametersSize;++k)
222 if (m_ParametersAtBoundsVector[k] != 0)
223 m_bPrimeVector[j] -= m_DataMatrix[j][k] * m_CurrentPosition[k];
226 m_ReducedDataMatrix[j][pos] = m_DataMatrix[j][k];
232 m_ReducedSolution = vnl_qr <double> (m_ReducedDataMatrix).solve(m_bPrimeVector);
233 diffCountBounded = 0;
234 unsigned int pos = 0;
235 for (
unsigned int i = 0;i < parametersSize;++i)
237 if (m_ParametersAtBoundsVector[i] != 0)
240 if (m_ReducedSolution[pos] <= m_LowerBounds[i])
242 m_CurrentPosition[i] = m_LowerBounds[i];
243 m_ParametersAtBoundsVector[i] = 1;
246 else if (m_ReducedSolution[pos] >= m_UpperBounds[i])
248 m_CurrentPosition[i] = m_UpperBounds[i];
249 m_ParametersAtBoundsVector[i] = -1;
253 m_CurrentPosition[i] = m_ReducedSolution[pos];
258 countBounded += diffCountBounded;
262 void BVLSOptimizer::ComputeWVector()
264 unsigned int numEqs = m_Points.size();
265 unsigned int numParameters = m_DataMatrix.cols();
266 m_TmpVector.resize(numEqs);
267 m_WVector.resize(numParameters);
269 for (
unsigned int i = 0;i < numEqs;++i)
271 m_TmpVector[i] = m_Points[i];
272 for (
unsigned int j = 0;j < numParameters;++j)
273 m_TmpVector[i] -= m_DataMatrix[i][j] * m_CurrentPosition[j];
276 for (
unsigned int i = 0;i < numParameters;++i)
280 for (
unsigned int j = 0;j < numEqs;++j)
281 m_WVector[i] += m_DataMatrix[j][i] * m_TmpVector[j];
285 bool BVLSOptimizer::TestKuhnTuckerConvergence()
287 bool freeSetFull =
true;
288 bool allNegativeWsForL =
true;
289 bool allPositiveWsForU =
true;
290 bool encounteredL =
false;
291 bool encounteredU =
false;
293 unsigned int parametersSize = m_DataMatrix.cols();
294 for (
unsigned int i = 0;i < parametersSize;++i)
296 if (m_ParametersAtBoundsVector[i] == 0)
300 if (m_ParametersAtBoundsVector[i] == 1)
303 if (m_WVector[i] > 0.0)
304 allNegativeWsForL =
false;
309 if (m_WVector[i] < 0.0)
310 allPositiveWsForU =
false;
314 bool returnValue = !freeSetFull;
317 if (encounteredL && encounteredU)
318 returnValue = !(allNegativeWsForL && allPositiveWsForU);
319 else if (encounteredL)
320 returnValue = !allNegativeWsForL;
321 else if (encounteredU)
322 returnValue = !allPositiveWsForU;
330 double residualValue = 0;
332 for (
unsigned int i = 0;i < m_DataMatrix.rows();++i)
335 for (
unsigned int j = 0;j < m_DataMatrix.cols();++j)
336 tmpVal += m_DataMatrix[i][j] * m_CurrentPosition[j];
338 residualValue += (tmpVal - m_Points[i]) * (tmpVal - m_Points[i]);
341 return residualValue;
double GetCurrentResidual()
void StartOptimization() ITK_OVERRIDE