2 #include <vnl/algo/vnl_qr.h> 7 const double NNLSOptimizer::m_EpsilonValue = 1.0e-12;
11 unsigned int parametersSize = m_DataMatrix.cols();
12 unsigned int numEquations = m_DataMatrix.rows();
14 if ((numEquations != m_Points.size())||(numEquations == 0)||(parametersSize == 0))
15 itkExceptionMacro(
"Wrongly sized inputs to NNLS, aborting");
17 m_CurrentPosition.SetSize(parametersSize);
18 m_CurrentPosition.Fill(0.0);
19 m_TreatedIndexes.resize(parametersSize);
20 std::fill(m_TreatedIndexes.begin(), m_TreatedIndexes.end(),0);
21 m_ProcessedIndexes.clear();
22 m_WVector.resize(parametersSize);
24 unsigned int numProcessedIndexes = 0;
26 this->ComputeWVector();
28 bool continueMainLoop =
true;
29 double previousMaxW = -1;
30 while (continueMainLoop)
34 for (
unsigned int i = 0;i < parametersSize;++i)
36 if (m_TreatedIndexes[i] == 0)
43 else if (maxW < m_WVector[i])
51 if (maxW <= m_EpsilonValue)
53 continueMainLoop =
false;
58 m_TreatedIndexes[maxIndex] = 1;
59 m_ProcessedIndexes.push_back(maxIndex);
60 numProcessedIndexes = m_ProcessedIndexes.size();
61 this->ComputeSPVector();
63 double minSP = m_SPVector[0];
64 for (
unsigned int i = 1;i < numProcessedIndexes;++i)
66 if (m_SPVector[i] < minSP)
67 minSP = m_SPVector[i];
73 bool foundOne =
false;
75 double indexSelected = 0;
76 for (
unsigned int i = 0;i < numProcessedIndexes;++i)
78 if (m_SPVector[i] > 0)
81 double tmpAlpha = m_CurrentPosition[m_ProcessedIndexes[i]] / (m_CurrentPosition[m_ProcessedIndexes[i]] - m_SPVector[i] + m_EpsilonValue);
82 if ((tmpAlpha < alpha)||(!foundOne))
85 indexSelected = m_ProcessedIndexes[i];
90 for (
unsigned int i = 0;i < parametersSize;++i)
91 m_CurrentPosition[i] -= alpha * m_CurrentPosition[i];
94 for (
unsigned int i = 0;i < numProcessedIndexes;++i)
96 m_CurrentPosition[m_ProcessedIndexes[i]] += alpha * m_SPVector[i];
98 if (std::abs(m_CurrentPosition[m_ProcessedIndexes[i]]) <= m_EpsilonValue)
99 m_TreatedIndexes[m_ProcessedIndexes[i]] = 0;
102 m_CurrentPosition[indexSelected] = 0;
103 m_TreatedIndexes[indexSelected] = 0;
106 numProcessedIndexes = this->UpdateProcessedIndexes();
107 if (numProcessedIndexes == 0)
110 this->ComputeSPVector();
112 minSP = m_SPVector[0];
113 for (
unsigned int i = 1;i < numProcessedIndexes;++i)
115 if (m_SPVector[i] < minSP)
116 minSP = m_SPVector[i];
120 m_CurrentPosition.Fill(0);
121 for (
unsigned int i = 0;i < numProcessedIndexes;++i)
122 m_CurrentPosition[m_ProcessedIndexes[i]] = m_SPVector[i];
124 if (numProcessedIndexes == parametersSize)
126 continueMainLoop =
false;
130 this->ComputeWVector();
134 void NNLSOptimizer::ComputeWVector()
136 unsigned int parametersSize = m_DataMatrix.cols();
137 unsigned int numEquations = m_DataMatrix.rows();
139 m_WVector.resize(parametersSize);
141 std::fill(m_WVector.begin(),m_WVector.end(),0.0);
142 if (!m_SquaredProblem)
144 for (
unsigned int i = 0;i < numEquations;++i)
146 double tmpValue = m_Points[i];
147 for (
unsigned int j = 0;j < parametersSize;++j)
148 tmpValue -= m_DataMatrix.get(i,j) * m_CurrentPosition[j];
150 for (
unsigned int j = 0;j < parametersSize;++j)
151 m_WVector[j] += m_DataMatrix.get(i,j) * tmpValue;
156 for (
unsigned int i = 0;i < numEquations;++i)
158 m_WVector[i] = m_Points[i];
159 for (
unsigned int j = 0;j < parametersSize;++j)
160 m_WVector[i] -= m_DataMatrix.get(i,j) * m_CurrentPosition[j];
165 unsigned int NNLSOptimizer::UpdateProcessedIndexes()
167 unsigned int numProcessedIndexes = 0;
168 unsigned int parametersSize = m_DataMatrix.cols();
170 for (
unsigned int i = 0;i < parametersSize;++i)
171 numProcessedIndexes += m_TreatedIndexes[i];
173 m_ProcessedIndexes.resize(numProcessedIndexes);
174 unsigned int pos = 0;
175 for (
unsigned int i = 0;i < parametersSize;++i)
177 if (m_TreatedIndexes[i] != 0)
179 m_ProcessedIndexes[pos] = i;
184 return numProcessedIndexes;
187 void NNLSOptimizer::ComputeSPVector()
189 unsigned int numEquations = m_DataMatrix.rows();
190 unsigned int numProcessedIndexes = m_ProcessedIndexes.size();
192 if (!m_SquaredProblem)
194 m_DataMatrixP.set_size(numEquations,numProcessedIndexes);
195 m_SPVector.set_size(numProcessedIndexes);
196 m_SPVector.fill(0.0);
199 for (
unsigned int i = 0;i < numEquations;++i)
201 for (
unsigned int j = 0;j < numProcessedIndexes;++j)
202 m_DataMatrixP.put(i,j,m_DataMatrix.get(i,m_ProcessedIndexes[j]));
205 m_SPVector = vnl_qr <double> (m_DataMatrixP).solve(m_Points);
209 m_DataMatrixP.set_size(numProcessedIndexes,numProcessedIndexes);
210 m_SPVector.set_size(numProcessedIndexes);
211 m_DataMatrixP.fill(0.0);
212 m_SPVector.fill(0.0);
214 for (
unsigned int i = 0;i < numProcessedIndexes;++i)
216 unsigned int iIndex = m_ProcessedIndexes[i];
217 m_SPVector[i] = m_Points[iIndex];
218 for (
unsigned int j = i;j < numProcessedIndexes;++j)
220 unsigned int jIndex = m_ProcessedIndexes[j];
221 m_DataMatrixP.put(i,j,m_DataMatrix.get(iIndex,jIndex));
224 m_DataMatrixP.put(j,i,m_DataMatrixP.get(i,j));
236 double residualValue = 0;
238 for (
unsigned int i = 0;i < m_DataMatrix.rows();++i)
241 for (
unsigned int j = 0;j < m_DataMatrix.cols();++j)
242 tmpVal += m_DataMatrix.get(i,j) * m_CurrentPosition[j];
244 residualValue += (tmpVal - m_Points[i]) * (tmpVal - m_Points[i]);
247 return residualValue;
void PerformDecomposition()
Performs LDL decomposition from input matrix.
void SetInputMatrix(const MatrixType &matrix)
Set input matrix to decompose.
void SolveLinearSystemInPlace(VectorType &b)
Solves linear system Ax=b and outputs result in input b variable.
void StartOptimization() ITK_OVERRIDE
double GetCurrentResidual()