mirror of
https://github.com/PaddlePaddle/FastDeploy.git
synced 2025-10-06 09:07:10 +08:00
140 lines
4.4 KiB
C++
140 lines
4.4 KiB
C++
#include <Eigen/Core>
|
|
#include <Eigen/Dense>
|
|
#include <Eigen/IterativeLinearSolvers>
|
|
#include <iostream>
|
|
#include <unsupported/Eigen/IterativeSolvers>
|
|
|
|
class MatrixReplacement;
|
|
using Eigen::SparseMatrix;
|
|
|
|
namespace Eigen {
|
|
namespace internal {
|
|
// MatrixReplacement looks-like a SparseMatrix, so let's inherits its traits:
|
|
template <>
|
|
struct traits<MatrixReplacement>
|
|
: public Eigen::internal::traits<Eigen::SparseMatrix<double> > {};
|
|
}
|
|
}
|
|
|
|
// Example of a matrix-free wrapper from a user type to Eigen's compatible type
|
|
// For the sake of simplicity, this example simply wrap a Eigen::SparseMatrix.
|
|
class MatrixReplacement : public Eigen::EigenBase<MatrixReplacement> {
|
|
public:
|
|
// Required typedefs, constants, and method:
|
|
typedef double Scalar;
|
|
typedef double RealScalar;
|
|
typedef int StorageIndex;
|
|
enum {
|
|
ColsAtCompileTime = Eigen::Dynamic,
|
|
MaxColsAtCompileTime = Eigen::Dynamic,
|
|
IsRowMajor = false
|
|
};
|
|
|
|
Index rows() const { return mp_mat->rows(); }
|
|
Index cols() const { return mp_mat->cols(); }
|
|
|
|
template <typename Rhs>
|
|
Eigen::Product<MatrixReplacement, Rhs, Eigen::AliasFreeProduct> operator*(
|
|
const Eigen::MatrixBase<Rhs>& x) const {
|
|
return Eigen::Product<MatrixReplacement, Rhs, Eigen::AliasFreeProduct>(
|
|
*this, x.derived());
|
|
}
|
|
|
|
// Custom API:
|
|
MatrixReplacement() : mp_mat(0) {}
|
|
|
|
void attachMyMatrix(const SparseMatrix<double>& mat) { mp_mat = &mat; }
|
|
const SparseMatrix<double> my_matrix() const { return *mp_mat; }
|
|
|
|
private:
|
|
const SparseMatrix<double>* mp_mat;
|
|
};
|
|
|
|
// Implementation of MatrixReplacement * Eigen::DenseVector though a
|
|
// specialization of internal::generic_product_impl:
|
|
namespace Eigen {
|
|
namespace internal {
|
|
|
|
template <typename Rhs>
|
|
struct generic_product_impl<MatrixReplacement, Rhs, SparseShape, DenseShape,
|
|
GemvProduct> // GEMV stands for matrix-vector
|
|
: generic_product_impl_base<MatrixReplacement, Rhs,
|
|
generic_product_impl<MatrixReplacement, Rhs> > {
|
|
typedef typename Product<MatrixReplacement, Rhs>::Scalar Scalar;
|
|
|
|
template <typename Dest>
|
|
static void scaleAndAddTo(Dest& dst, const MatrixReplacement& lhs,
|
|
const Rhs& rhs, const Scalar& alpha) {
|
|
// This method should implement "dst += alpha * lhs * rhs" inplace,
|
|
// however, for iterative solvers, alpha is always equal to 1, so let's not
|
|
// bother about it.
|
|
assert(alpha == Scalar(1) && "scaling is not implemented");
|
|
EIGEN_ONLY_USED_FOR_DEBUG(alpha);
|
|
|
|
// Here we could simply call dst.noalias() += lhs.my_matrix() * rhs,
|
|
// but let's do something fancier (and less efficient):
|
|
for (Index i = 0; i < lhs.cols(); ++i)
|
|
dst += rhs(i) * lhs.my_matrix().col(i);
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
int main() {
|
|
int n = 10;
|
|
Eigen::SparseMatrix<double> S =
|
|
Eigen::MatrixXd::Random(n, n).sparseView(0.5, 1);
|
|
S = S.transpose() * S;
|
|
|
|
MatrixReplacement A;
|
|
A.attachMyMatrix(S);
|
|
|
|
Eigen::VectorXd b(n), x;
|
|
b.setRandom();
|
|
|
|
// Solve Ax = b using various iterative solver with matrix-free version:
|
|
{
|
|
Eigen::ConjugateGradient<MatrixReplacement, Eigen::Lower | Eigen::Upper,
|
|
Eigen::IdentityPreconditioner>
|
|
cg;
|
|
cg.compute(A);
|
|
x = cg.solve(b);
|
|
std::cout << "CG: #iterations: " << cg.iterations()
|
|
<< ", estimated error: " << cg.error() << std::endl;
|
|
}
|
|
|
|
{
|
|
Eigen::BiCGSTAB<MatrixReplacement, Eigen::IdentityPreconditioner> bicg;
|
|
bicg.compute(A);
|
|
x = bicg.solve(b);
|
|
std::cout << "BiCGSTAB: #iterations: " << bicg.iterations()
|
|
<< ", estimated error: " << bicg.error() << std::endl;
|
|
}
|
|
|
|
{
|
|
Eigen::GMRES<MatrixReplacement, Eigen::IdentityPreconditioner> gmres;
|
|
gmres.compute(A);
|
|
x = gmres.solve(b);
|
|
std::cout << "GMRES: #iterations: " << gmres.iterations()
|
|
<< ", estimated error: " << gmres.error() << std::endl;
|
|
}
|
|
|
|
{
|
|
Eigen::DGMRES<MatrixReplacement, Eigen::IdentityPreconditioner> gmres;
|
|
gmres.compute(A);
|
|
x = gmres.solve(b);
|
|
std::cout << "DGMRES: #iterations: " << gmres.iterations()
|
|
<< ", estimated error: " << gmres.error() << std::endl;
|
|
}
|
|
|
|
{
|
|
Eigen::MINRES<MatrixReplacement, Eigen::Lower | Eigen::Upper,
|
|
Eigen::IdentityPreconditioner>
|
|
minres;
|
|
minres.compute(A);
|
|
x = minres.solve(b);
|
|
std::cout << "MINRES: #iterations: " << minres.iterations()
|
|
<< ", estimated error: " << minres.error() << std::endl;
|
|
}
|
|
}
|