32 #include "../../Eigen/Core"
33 #include "../../Eigen/QR"
65 template <
class MatrixType_>
78 typedef typename MatrixType::Scalar
Scalar;
80 typedef typename MatrixType::Index
Index;
105 template <
typename MatrixDerived>
208 template <
typename MatrixType>
216 template <
typename MatrixType>
221 template <
typename MatrixType>
222 template <
typename MatrixDerived>
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());
247 template <
typename MatrixType>
254 index_sets_ = IndicesType::LinSpaced(A_.cols(), 0, A_.cols() - 1);
258 Atb_.noalias() = A_.transpose() *
b;
260 const Index maxIterations = this->maxIterations();
265 if (A_.cols() == numInactive_) {
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_) {
285 moveToInactiveSet_(argmaxGradient);
290 if (iterations_ >= maxIterations) {
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));
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);
338 template <
typename MatrixType>
341 std::swap(index_sets_(idx), index_sets_(numInactive_));
346 tempSolutionVector_.data());
349 template <
typename MatrixType>
352 std::swap(index_sets_(idx), index_sets_(numInactive_ - 1));
355 for (
Index i = idx;
i < numInactive_;
i++) {
361 template <
typename MatrixType>
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());
SparseMatrix< double > A(n, n)
ColXpr col(Index i) const
#define EIGEN_STATIC_ASSERT(X, MSG)
Implementation of the Non-Negative Least Squares (NNLS) algorithm.
RhsVectorType tempRhsVector_
const SolutionVectorType & x() const
Returns the solution if a problem was solved. If not, an uninitialized vector may be returned.
Matrix< Scalar, RowsAtCompileTime, 1 > RhsVectorType
SolutionVectorType gradient_
NNLS< MatrixType > & setMaxIterations(Index maxIters)
Matrix< Scalar, ColsAtCompileTime, 1 > SolutionVectorType
MatrixType::Scalar Scalar
Matrix< Index, ColsAtCompileTime, 1 > IndicesType
void moveToActiveSet_(Index idx)
SolutionVectorType qrCoeffs_
ComputationInfo info() const
MatrixType::RealScalar RealScalar
NNLS< MatrixType > & compute(const EigenBase< MatrixDerived > &A)
SolutionVectorType tempSolutionVector_
void solveInactiveSet_(const RhsVectorType &b)
NNLS< MatrixType > & setTolerance(const Scalar &tolerance)
Matrix< Scalar, ColsAtCompileTime, ColsAtCompileTime > MatrixAtAType
const SolutionVectorType & solve(const RhsVectorType &b)
Solves the NNLS problem.
void moveToInactiveSet_(Index idx)
Index maxIterations() const
HouseholderSequence< VectorsType, CoeffsType > householderSequence(const VectorsType &v, const CoeffsType &h)
void householder_qr_inplace_update(MatrixQR &mat, HCoeffs &hCoeffs, const VectorQR &newColumn, typename MatrixQR::Index k, typename MatrixQR::Scalar *tempData)
: TensorContractionSycl.h, provides various tensor contraction kernel for SYCL backend
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
SparseMatrix< double, Options_, StorageIndex_ > & derived()