sparseqr.cpp File Reference
#include "sparse.h"
#include <Eigen/SparseQR>

Functions

template<typename MatrixType , typename DenseMat >
int generate_sparse_rectangular_problem (MatrixType &A, DenseMat &dA, int maxRows=300, int maxCols=150)
 
template<typename Scalar >
void test_sparseqr_scalar ()
 
 EIGEN_DECLARE_TEST (sparseqr)
 

Function Documentation

◆ EIGEN_DECLARE_TEST()

EIGEN_DECLARE_TEST ( sparseqr  )
135  {
136  for (int i = 0; i < g_repeat; ++i) {
137  CALL_SUBTEST_1(test_sparseqr_scalar<double>());
138  CALL_SUBTEST_2(test_sparseqr_scalar<std::complex<double> >());
139  }
140 }
int i
Definition: BiCGSTAB_step_by_step.cpp:9
static int g_repeat
Definition: main.h:191
void test_sparseqr_scalar()
Definition: sparseqr.cpp:43
#define CALL_SUBTEST_1(FUNC)
Definition: split_test_helper.h:4
#define CALL_SUBTEST_2(FUNC)
Definition: split_test_helper.h:10

References CALL_SUBTEST_1, CALL_SUBTEST_2, Eigen::g_repeat, i, and test_sparseqr_scalar().

◆ generate_sparse_rectangular_problem()

template<typename MatrixType , typename DenseMat >
int generate_sparse_rectangular_problem ( MatrixType A,
DenseMat &  dA,
int  maxRows = 300,
int  maxCols = 150 
)
13  {
14  eigen_assert(maxRows >= maxCols);
15  typedef typename MatrixType::Scalar Scalar;
16  int rows = internal::random<int>(1, maxRows);
17  int cols = internal::random<int>(1, maxCols);
18  double density = (std::max)(8. / (rows * cols), 0.01);
19 
20  A.resize(rows, cols);
21  dA.resize(rows, cols);
22  initSparse<Scalar>(density, dA, A, ForceNonZeroDiag);
23  A.makeCompressed();
24  int nop = internal::random<int>(0, internal::random<double>(0, 1) > 0.5 ? cols / 2 : 0);
25  for (int k = 0; k < nop; ++k) {
26  int j0 = internal::random<int>(0, cols - 1);
27  int j1 = internal::random<int>(0, cols - 1);
28  Scalar s = internal::random<Scalar>();
29  A.col(j0) = s * A.col(j1);
30  dA.col(j0) = s * dA.col(j1);
31  }
32 
33  // if(rows<cols) {
34  // A.conservativeResize(cols,cols);
35  // dA.conservativeResize(cols,cols);
36  // dA.bottomRows(cols-rows).setZero();
37  // }
38 
39  return rows;
40 }
#define eigen_assert(x)
Definition: Macros.h:910
int rows
Definition: Tutorial_commainit_02.cpp:1
int cols
Definition: Tutorial_commainit_02.cpp:1
SCALAR Scalar
Definition: bench_gemm.cpp:45
The matrix class, also used for vectors and row-vectors.
Definition: Eigen/Eigen/src/Core/Matrix.h:186
EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
Definition: PlainObjectBase.h:294
#define max(a, b)
Definition: datatypes.h:23
RealScalar s
Definition: level1_cplx_impl.h:130
char char char int int * k
Definition: level2_impl.h:374
density
Definition: UniformPSDSelfTest.py:19
@ ForceNonZeroDiag
Definition: sparse.h:32

References cols, UniformPSDSelfTest::density, eigen_assert, ForceNonZeroDiag, k, max, Eigen::PlainObjectBase< Derived >::resize(), rows, and s.

Referenced by test_sparseqr_scalar().

◆ test_sparseqr_scalar()

template<typename Scalar >
void test_sparseqr_scalar ( )
43  {
44  typedef typename NumTraits<Scalar>::Real RealScalar;
46  typedef Matrix<Scalar, Dynamic, Dynamic> DenseMat;
48  MatrixType A;
49  DenseMat dA;
50  DenseVector refX, x, b;
53 
54  b = dA * DenseVector::Random(A.cols());
55  solver.compute(A);
56 
57  // Q should be MxM
58  VERIFY_IS_EQUAL(solver.matrixQ().rows(), A.rows());
59  VERIFY_IS_EQUAL(solver.matrixQ().cols(), A.rows());
60 
61  // R should be MxN
62  VERIFY_IS_EQUAL(solver.matrixR().rows(), A.rows());
63  VERIFY_IS_EQUAL(solver.matrixR().cols(), A.cols());
64 
65  // Q and R can be multiplied
66  DenseMat recoveredA = solver.matrixQ() * DenseMat(solver.matrixR().template triangularView<Upper>()) *
67  solver.colsPermutation().transpose();
68  VERIFY_IS_EQUAL(recoveredA.rows(), A.rows());
69  VERIFY_IS_EQUAL(recoveredA.cols(), A.cols());
70 
71  // and in the full rank case the original matrix is recovered
72  if (solver.rank() == A.cols()) {
73  VERIFY_IS_APPROX(A, recoveredA);
74  }
75 
76  if (internal::random<float>(0, 1) > 0.5f)
77  solver.factorize(A); // this checks that calling analyzePattern is not needed if the pattern do not change.
78  if (solver.info() != Success) {
79  std::cerr << "sparse QR factorization failed\n";
80  exit(0);
81  return;
82  }
83  x = solver.solve(b);
84  if (solver.info() != Success) {
85  std::cerr << "sparse QR factorization failed\n";
86  exit(0);
87  return;
88  }
89 
90  // Compare with a dense QR solver
92  refX = dqr.solve(b);
93 
94  bool rank_deficient = A.cols() > A.rows() || dqr.rank() < A.cols();
95  if (rank_deficient) {
96  // rank deficient problem -> we might have to increase the threshold
97  // to get a correct solution.
98  RealScalar th =
99  RealScalar(20) * dA.colwise().norm().maxCoeff() * (A.rows() + A.cols()) * NumTraits<RealScalar>::epsilon();
100  for (Index k = 0; (k < 16) && !test_isApprox(A * x, b); ++k) {
101  th *= RealScalar(10);
102  solver.setPivotThreshold(th);
103  solver.compute(A);
104  x = solver.solve(b);
105  }
106  }
107 
108  VERIFY_IS_APPROX(A * x, b);
109 
110  // For rank deficient problem, the estimated rank might
111  // be slightly off, so let's only raise a warning in such cases.
112  if (rank_deficient) ++g_test_level;
113  VERIFY_IS_EQUAL(solver.rank(), dqr.rank());
114  if (rank_deficient) --g_test_level;
115 
116  if (solver.rank() == A.cols()) // full rank
117  VERIFY_IS_APPROX(x, refX);
118  // else
119  // VERIFY((dA * refX - b).norm() * 2 > (A * x - b).norm() );
120 
121  // Compute explicitly the matrix Q
122  MatrixType Q, QtQ, idM;
123  Q = solver.matrixQ();
124  // Check ||Q' * Q - I ||
125  QtQ = Q * Q.adjoint();
126  idM.resize(Q.rows(), Q.rows());
127  idM.setIdentity();
128  VERIFY(idM.isApprox(QtQ));
129 
130  // Q to dense
131  DenseMat dQ;
132  dQ = solver.matrixQ();
133  VERIFY_IS_APPROX(Q, dQ);
134 }
bool test_isApprox(const AnnoyingScalar &a, const AnnoyingScalar &b)
Definition: AnnoyingScalar.h:196
Matrix< Scalar, Dynamic, 1 > DenseVector
Definition: BenchSparseUtil.h:24
BiCGSTAB< SparseMatrix< double > > solver
Definition: BiCGSTAB_simple.cpp:5
MatrixXf Q
Definition: HouseholderQR_householderQ.cpp:1
Scalar * b
Definition: benchVecAdd.cpp:17
Matrix< SCALARA, Dynamic, Dynamic, opt_A > A
Definition: bench_gemm.cpp:47
NumTraits< Scalar >::Real RealScalar
Definition: bench_gemm.cpp:46
MatrixXf MatrixType
Definition: benchmark-blocking-sizes.cpp:52
Householder rank-revealing QR decomposition of a matrix with column-pivoting.
Definition: ColPivHouseholderQR.h:54
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT
Definition: PlainObjectBase.h:192
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT
Definition: PlainObjectBase.h:191
Sparse left-looking QR factorization with numerical column pivoting.
Definition: SparseQR.h:88
@ Success
Definition: Constants.h:440
#define VERIFY_IS_APPROX(a, b)
Definition: integer_types.cpp:13
#define VERIFY(a)
Definition: main.h:362
#define VERIFY_IS_EQUAL(a, b)
Definition: main.h:367
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:83
static int g_test_level
Definition: main.h:190
list x
Definition: plotDoE.py:28
int generate_sparse_rectangular_problem(MatrixType &A, DenseMat &dA, int maxRows=300, int maxCols=150)
Definition: sparseqr.cpp:13
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition: NumTraits.h:217

References b, Eigen::PlainObjectBase< Derived >::cols(), Eigen::g_test_level, generate_sparse_rectangular_problem(), k, Q, Eigen::ColPivHouseholderQR< MatrixType_, PermutationIndex_ >::rank(), Eigen::PlainObjectBase< Derived >::rows(), Eigen::SolverBase< Derived >::solve(), solver, Eigen::Success, test_isApprox(), VERIFY, VERIFY_IS_APPROX, VERIFY_IS_EQUAL, and plotDoE::x.

Referenced by EIGEN_DECLARE_TEST().