32#include "../../Eigen/Core"
33#include "../../Eigen/QR"
65template <
class MatrixType_>
68 typedef MatrixType_ MatrixType;
71 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
72 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
73 Options = MatrixType::Options,
74 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
75 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
78 typedef typename MatrixType::Scalar Scalar;
79 typedef typename MatrixType::RealScalar RealScalar;
80 typedef typename MatrixType::Index Index;
105 template <
typename MatrixDerived>
139 Index
maxIterations()
const {
return max_iter_ < 0 ? 2 * A_.cols() : max_iter_; }
146 max_iter_ = maxIters;
158 void moveToInactiveSet_(
Index idx);
161 void moveToActiveSet_(
Index idx);
194 IndicesType index_sets_;
208template <
typename MatrixType>
209NNLS<MatrixType>::NNLS()
214 tolerance_(NumTraits<Scalar>::dummy_precision()) {}
216template <
typename MatrixType>
217NNLS<MatrixType>::NNLS(
const MatrixType &A, Index max_iter, Scalar tol) : max_iter_(max_iter), tolerance_(tol) {
221template <
typename MatrixType>
222template <
typename MatrixDerived>
229 info_ = ComputationInfo::Success;
233 AtA_.noalias() = A_.transpose() * A_;
234 x_.resize(A_.cols());
235 gradient_.resize(A_.cols());
236 y_.resize(A_.cols());
237 Atb_.resize(A_.cols());
238 index_sets_.resize(A_.cols());
239 QR_.resize(A_.rows(), A_.cols());
240 qrCoeffs_.resize(A_.cols());
241 tempSolutionVector_.resize(A_.cols());
242 tempRhsVector_.resize(A_.rows());
247template <
typename MatrixType>
251 info_ = ComputationInfo::NumericalIssue;
254 index_sets_ = IndicesType::LinSpaced(A_.cols(), 0, A_.cols() - 1);
258 Atb_.noalias() = A_.transpose() * b;
265 if (A_.cols() == numInactive_) {
266 info_ = ComputationInfo::Success;
273 gradient_.noalias() = Atb_ - AtA_ * x_;
275 const Index numActive = A_.cols() - numInactive_;
276 Index argmaxGradient = -1;
277 const Scalar maxGradient = gradient_(index_sets_.tail(numActive)).maxCoeff(&argmaxGradient);
278 argmaxGradient += numInactive_;
280 if (maxGradient < tolerance_) {
281 info_ = ComputationInfo::Success;
285 moveToInactiveSet_(argmaxGradient);
291 info_ = ComputationInfo::NoConvergence;
299 solveInactiveSet_(b);
303 bool feasible =
true;
305 Index infeasibleIdx = -1;
306 for (Index i = 0; i < numInactive_; i++) {
307 Index idx = index_sets_[i];
310 Scalar t = -x_(idx) / (y_(idx) - x_(idx));
318 eigen_assert(feasible || 0 <= infeasibleIdx);
327 for (Index i = 0; i < numInactive_; i++) {
328 Index idx = index_sets_[i];
329 x_(idx) += alpha * (y_(idx) - x_(idx));
333 moveToActiveSet_(infeasibleIdx);
338template <
typename MatrixType>
339void NNLS<MatrixType>::moveToInactiveSet_(
Index idx) {
341 std::swap(index_sets_(idx), index_sets_(numInactive_));
345 internal::householder_qr_inplace_update(QR_, qrCoeffs_, A_.col(index_sets_(numInactive_ - 1)), numInactive_ - 1,
346 tempSolutionVector_.data());
349template <
typename MatrixType>
350void NNLS<MatrixType>::moveToActiveSet_(Index idx) {
352 std::swap(index_sets_(idx), index_sets_(numInactive_ - 1));
355 for (Index i = idx; i < numInactive_; i++) {
356 Index col = index_sets_(i);
357 internal::householder_qr_inplace_update(QR_, qrCoeffs_, A_.col(col), i, tempSolutionVector_.data());
361template <
typename MatrixType>
362void NNLS<MatrixType>::solveInactiveSet_(
const RhsVectorType &b) {
363 eigen_assert(numInactive_ > 0);
369 tempRhsVector_.applyOnTheLeft(
370 householderSequence(QR_.leftCols(numInactive_), qrCoeffs_.head(numInactive_)).transpose());
374 tempSolutionVector_.head(numInactive_) =
375 QR_.topLeftCorner(numInactive_, numInactive_)
376 .template triangularView<Upper>()
377 .solve(tempRhsVector_.head(numInactive_));
380 tempSolutionVector_.tail(y_.size() - numInactive_).setZero();
383 y_.noalias() = index_sets_.asPermutation() * tempSolutionVector_.head(y_.size());
Matrix< Scalar, RowsAtCompileTime, 1 > RhsVectorType
Definition NNLS:85
Matrix< Scalar, ColsAtCompileTime, 1 > SolutionVectorType
Definition NNLS:83
Index iterations() const
Definition NNLS:151
ComputationInfo info() const
Definition NNLS:154
NNLS< MatrixType > & compute(const EigenBase< MatrixDerived > &A)
Definition NNLS:223
const SolutionVectorType & x() const
Returns the solution if a problem was solved. If not, an uninitialized vector may be returned.
Definition NNLS:119
Scalar tolerance() const
Definition NNLS:124
NNLS< MatrixType > & setMaxIterations(Index maxIters)
Definition NNLS:145
NNLS< MatrixType > & setTolerance(const Scalar &tolerance)
Definition NNLS:131
const SolutionVectorType & solve(const RhsVectorType &b)
Solves the NNLS problem.
Definition NNLS:248
Index maxIterations() const
Definition NNLS:139
Derived & setZero(Index rows, Index cols)
HouseholderSequence< VectorsType, CoeffsType > householderSequence(const VectorsType &v, const CoeffsType &h)
Namespace containing all symbols from the Eigen library.
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
constexpr Derived & derived()