EigendecompositionResult eigendecomposition_impl_dense(const MatrixType& wm, IndexType target_dimension, unsigned int skip) { timed_context context("Eigen library dense eigendecomposition"); DenseMatrix dense_wm = wm; DenseSelfAdjointEigenSolver solver(dense_wm); if (solver.info() == Eigen::Success) { if (MatrixOperationType::largest) { assert(skip==0); DenseMatrix selected_eigenvectors = solver.eigenvectors().rightCols(target_dimension); return EigendecompositionResult(selected_eigenvectors,solver.eigenvalues().tail(target_dimension)); } else { DenseMatrix selected_eigenvectors = solver.eigenvectors().leftCols(target_dimension+skip).rightCols(target_dimension); return EigendecompositionResult(selected_eigenvectors,solver.eigenvalues().segment(skip,skip+target_dimension)); } } else { throw eigendecomposition_error("eigendecomposition failed"); } return EigendecompositionResult(); }
EigendecompositionResult generalized_eigendecomposition_impl_dense(const LMatrixType& lhs, const RMatrixType& rhs, IndexType target_dimension, unsigned int skip) { timed_context context("Eigen dense generalized eigendecomposition"); DenseMatrix dense_lhs = lhs; DenseMatrix dense_rhs = rhs; Eigen::GeneralizedSelfAdjointEigenSolver<DenseMatrix> solver(dense_lhs, dense_rhs); if (solver.info() == Eigen::Success) { if (MatrixOperationType::largest) { assert(skip==0); DenseMatrix selected_eigenvectors = solver.eigenvectors().rightCols(target_dimension); return EigendecompositionResult(selected_eigenvectors,solver.eigenvalues().tail(target_dimension)); } else { DenseMatrix selected_eigenvectors = solver.eigenvectors().leftCols(target_dimension+skip).rightCols(target_dimension); return EigendecompositionResult(selected_eigenvectors,solver.eigenvalues().segment(skip,skip+target_dimension)); } } else { throw eigendecomposition_error("eigendecomposition failed"); } return EigendecompositionResult(); }
EigendecompositionResult eigendecomposition_impl_randomized(const MatrixType& wm, IndexType target_dimension, unsigned int skip) { timed_context context("Randomized eigendecomposition"); DenseMatrix O(wm.rows(), target_dimension+skip); for (IndexType i=0; i<O.rows(); ++i) { for (IndexType j=0; j<O.cols(); j++) { O(i,j) = tapkee::gaussian_random(); } } MatrixOperationType operation(wm); DenseMatrix Y = operation(O); for (IndexType i=0; i<Y.cols(); i++) { for (IndexType j=0; j<i; j++) { ScalarType r = Y.col(i).dot(Y.col(j)); Y.col(i) -= r*Y.col(j); } ScalarType norm = Y.col(i).norm(); if (norm < 1e-4) { for (int k = i; k<Y.cols(); k++) Y.col(k).setZero(); } Y.col(i) *= (1.f / norm); } DenseMatrix B1 = operation(Y); DenseMatrix B = Y.householderQr().solve(B1); DenseSelfAdjointEigenSolver eigenOfB(B); if (eigenOfB.info() == Eigen::Success) { if (MatrixOperationType::largest) { assert(skip==0); DenseMatrix selected_eigenvectors = (Y*eigenOfB.eigenvectors()).rightCols(target_dimension); return EigendecompositionResult(selected_eigenvectors,eigenOfB.eigenvalues()); } else { DenseMatrix selected_eigenvectors = (Y*eigenOfB.eigenvectors()).leftCols(target_dimension+skip).rightCols(target_dimension); return EigendecompositionResult(selected_eigenvectors,eigenOfB.eigenvalues()); } } else { throw eigendecomposition_error("eigendecomposition failed"); } return EigendecompositionResult(); }
EigendecompositionResult generalized_eigendecomposition(EigenMethod method, const LMatrixType& lhs, const RMatrixType& rhs, IndexType target_dimension, unsigned int skip) { LoggingSingleton::instance().message_info("Using the " + get_eigen_method_name(method) + " eigendecomposition method."); switch (method) { #ifdef TAPKEE_WITH_ARPACK case Arpack: return generalized_eigendecomposition_impl_arpack<LMatrixType, RMatrixType, MatrixOperationType>(lhs, rhs, target_dimension, skip); #endif case Dense: return generalized_eigendecomposition_impl_dense<LMatrixType, RMatrixType, MatrixOperationType>(lhs, rhs, target_dimension, skip); case Randomized: throw unsupported_method_error("Randomized method is not supported for generalized eigenproblems"); return EigendecompositionResult(); default: break; } return EigendecompositionResult(); }
EigendecompositionResult generalized_eigendecomposition_impl_arpack(const LMatrixType& lhs, const RMatrixType& rhs, IndexType target_dimension, unsigned int skip) { timed_context context("ARPACK DSXUPD generalized eigendecomposition"); ArpackGeneralizedSelfAdjointEigenSolver<LMatrixType, RMatrixType, MatrixOperationType> arpack(lhs,rhs,target_dimension+skip,"SM"); if (arpack.info() == Eigen::Success) { std::string message = formatting::format("Took {} iterations.", arpack.getNbrIterations()); LoggingSingleton::instance().message_info(message); DenseMatrix selected_eigenvectors = (arpack.eigenvectors()).rightCols(target_dimension); return EigendecompositionResult(selected_eigenvectors,arpack.eigenvalues().tail(target_dimension)); } else { throw eigendecomposition_error("eigendecomposition failed"); } return EigendecompositionResult(); }
EigendecompositionResult eigendecomposition_impl_arpack(const MatrixType& wm, IndexType target_dimension, unsigned int skip) { timed_context context("ARPACK eigendecomposition"); ArpackGeneralizedSelfAdjointEigenSolver<MatrixType, MatrixType, MatrixOperationType> arpack(wm,target_dimension+skip,MatrixOperationType::ARPACK_CODE); if (arpack.info() == Eigen::Success) { std::stringstream ss; ss << "Took " << arpack.getNbrIterations() << " iterations."; LoggingSingleton::instance().message_info(ss.str()); DenseMatrix selected_eigenvectors = arpack.eigenvectors().rightCols(target_dimension); return EigendecompositionResult(selected_eigenvectors,arpack.eigenvalues().tail(target_dimension)); } else { throw eigendecomposition_error("eigendecomposition failed"); } return EigendecompositionResult(); }
EigendecompositionResult arpack(const SparseWeightMatrix& lhs, const DenseDiagonalMatrix& rhs, const ComputationStrategy& strategy, const EigendecompositionStrategy& eigen_strategy, IndexType target_dimension) { if (strategy.is(HomogeneousCPUStrategy)) { if (eigen_strategy.is(SmallestEigenvalues)) return generalized_eigendecomposition_impl_arpack <SparseWeightMatrix,DenseDiagonalMatrix,SparseInverseMatrixOperation> (lhs,rhs,target_dimension,eigen_strategy.skip()); unsupported(); } unsupported(); return EigendecompositionResult(); }
EigendecompositionResult dense(const DenseMatrix& lhs, const DenseMatrix& rhs, const ComputationStrategy& strategy, const EigendecompositionStrategy& eigen_strategy, IndexType target_dimension) { if (strategy.is(HomogeneousCPUStrategy)) { if (eigen_strategy.is(SmallestEigenvalues)) return generalized_eigendecomposition_impl_dense <DenseMatrix,DenseMatrix,DenseInverseMatrixOperation> (lhs,rhs,target_dimension,0); unsupported(); } unsupported(); return EigendecompositionResult(); }
EigendecompositionResult generalized_eigendecomposition(const EigenMethod& method, const ComputationStrategy& strategy, const EigendecompositionStrategy& eigen_strategy, const LMatrixType& lhs, const RMatrixType& rhs, IndexType target_dimension) { LoggingSingleton::instance().message_info(formatting::format("Using the {} eigendecomposition method.", get_eigen_method_name(method))); #ifdef TAPKEE_WITH_ARPACK if (method.is(Arpack)) return generalized_eigendecomposition_impl<LMatrixType, RMatrixType>() .arpack(lhs, rhs, strategy, eigen_strategy, target_dimension); #endif if (method.is(Dense)) return generalized_eigendecomposition_impl<LMatrixType, RMatrixType>() .dense(lhs, rhs, strategy, eigen_strategy, target_dimension); if (method.is(Randomized)) throw unsupported_method_error("Randomized method is not supported for generalized eigenproblems"); return EigendecompositionResult(); }
EigendecompositionResult eigendecomposition(EigenMethod method, const MatrixType& m, IndexType target_dimension, unsigned int skip) { LoggingSingleton::instance().message_info("Using the " + get_eigen_method_name(method) + " eigendecomposition method."); switch (method) { #ifdef TAPKEE_WITH_ARPACK case Arpack: return eigendecomposition_impl_arpack<MatrixType, MatrixOperationType>(m, target_dimension, skip); #endif case Randomized: return eigendecomposition_impl_randomized<MatrixType, MatrixOperationType>(m, target_dimension, skip); case Dense: return eigendecomposition_impl_dense<MatrixType, MatrixOperationType>(m, target_dimension, skip); default: break; } return EigendecompositionResult(); }