sparseqr.cpp
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2012 Desire Nuentsa Wakam <desire.nuentsa_wakam@inria.fr>
5 // Copyright (C) 2014 Gael Guennebaud <gael.guennebaud@inria.fr>
6 //
7 // This Source Code Form is subject to the terms of the Mozilla
8 // Public License v. 2.0. If a copy of the MPL was not distributed
9 #include "sparse.h"
10 #include <Eigen/SparseQR>
11 
12 template<typename MatrixType,typename DenseMat>
13 int generate_sparse_rectangular_problem(MatrixType& A, DenseMat& dA, int maxRows = 300, int maxCols = 150)
14 {
15  eigen_assert(maxRows >= maxCols);
16  typedef typename MatrixType::Scalar Scalar;
17  int rows = internal::random<int>(1,maxRows);
18  int cols = internal::random<int>(1,maxCols);
19  double density = (std::max)(8./(rows*cols), 0.01);
20 
21  A.resize(rows,cols);
22  dA.resize(rows,cols);
23  initSparse<Scalar>(density, dA, A,ForceNonZeroDiag);
24  A.makeCompressed();
25  int nop = internal::random<int>(0, internal::random<double>(0,1) > 0.5 ? cols/2 : 0);
26  for(int k=0; k<nop; ++k)
27  {
28  int j0 = internal::random<int>(0,cols-1);
29  int j1 = internal::random<int>(0,cols-1);
30  Scalar s = internal::random<Scalar>();
31  A.col(j0) = s * A.col(j1);
32  dA.col(j0) = s * dA.col(j1);
33  }
34 
35 // if(rows<cols) {
36 // A.conservativeResize(cols,cols);
37 // dA.conservativeResize(cols,cols);
38 // dA.bottomRows(cols-rows).setZero();
39 // }
40 
41  return rows;
42 }
43 
44 template<typename Scalar> void test_sparseqr_scalar()
45 {
46  typedef typename NumTraits<Scalar>::Real RealScalar;
48  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMat;
50  MatrixType A;
51  DenseMat dA;
52  DenseVector refX,x,b;
55 
56  b = dA * DenseVector::Random(A.cols());
57  solver.compute(A);
58 
59  // Q should be MxM
60  VERIFY_IS_EQUAL(solver.matrixQ().rows(), A.rows());
61  VERIFY_IS_EQUAL(solver.matrixQ().cols(), A.rows());
62 
63  // R should be MxN
64  VERIFY_IS_EQUAL(solver.matrixR().rows(), A.rows());
65  VERIFY_IS_EQUAL(solver.matrixR().cols(), A.cols());
66 
67  // Q and R can be multiplied
68  DenseMat recoveredA = solver.matrixQ()
69  * DenseMat(solver.matrixR().template triangularView<Upper>())
70  * solver.colsPermutation().transpose();
71  VERIFY_IS_EQUAL(recoveredA.rows(), A.rows());
72  VERIFY_IS_EQUAL(recoveredA.cols(), A.cols());
73 
74  // and in the full rank case the original matrix is recovered
75  if (solver.rank() == A.cols())
76  {
77  VERIFY_IS_APPROX(A, recoveredA);
78  }
79 
80  if(internal::random<float>(0,1)>0.5f)
81  solver.factorize(A); // this checks that calling analyzePattern is not needed if the pattern do not change.
82  if (solver.info() != Success)
83  {
84  std::cerr << "sparse QR factorization failed\n";
85  exit(0);
86  return;
87  }
88  x = solver.solve(b);
89  if (solver.info() != Success)
90  {
91  std::cerr << "sparse QR factorization failed\n";
92  exit(0);
93  return;
94  }
95 
96  // Compare with a dense QR solver
98  refX = dqr.solve(b);
99 
100  bool rank_deficient = A.cols()>A.rows() || dqr.rank()<A.cols();
101  if(rank_deficient)
102  {
103  // rank deficient problem -> we might have to increase the threshold
104  // to get a correct solution.
105  RealScalar th = RealScalar(20)*dA.colwise().norm().maxCoeff()*(A.rows()+A.cols()) * NumTraits<RealScalar>::epsilon();
106  for(Index k=0; (k<16) && !test_isApprox(A*x,b); ++k)
107  {
108  th *= RealScalar(10);
109  solver.setPivotThreshold(th);
110  solver.compute(A);
111  x = solver.solve(b);
112  }
113  }
114 
115  VERIFY_IS_APPROX(A * x, b);
116 
117  // For rank deficient problem, the estimated rank might
118  // be slightly off, so let's only raise a warning in such cases.
119  if(rank_deficient) ++g_test_level;
120  VERIFY_IS_EQUAL(solver.rank(), dqr.rank());
121  if(rank_deficient) --g_test_level;
122 
123  if(solver.rank()==A.cols()) // full rank
124  VERIFY_IS_APPROX(x, refX);
125 // else
126 // VERIFY((dA * refX - b).norm() * 2 > (A * x - b).norm() );
127 
128  // Compute explicitly the matrix Q
129  MatrixType Q, QtQ, idM;
130  Q = solver.matrixQ();
131  //Check ||Q' * Q - I ||
132  QtQ = Q * Q.adjoint();
133  idM.resize(Q.rows(), Q.rows()); idM.setIdentity();
134  VERIFY(idM.isApprox(QtQ));
135 
136  // Q to dense
137  DenseMat dQ;
138  dQ = solver.matrixQ();
139  VERIFY_IS_APPROX(Q, dQ);
140 }
142 {
143  for(int i=0; i<g_repeat; ++i)
144  {
145  CALL_SUBTEST_1(test_sparseqr_scalar<double>());
146  CALL_SUBTEST_2(test_sparseqr_scalar<std::complex<double> >());
147  }
148 }
149 
Index cols() const
Definition: SparseMatrix.h:140
const Solve< ColPivHouseholderQR< _MatrixType >, Rhs > solve(const MatrixBase< Rhs > &b) const
Definition: SolverBase.h:106
SCALAR Scalar
Definition: bench_gemm.cpp:46
#define max(a, b)
Definition: datatypes.h:20
Quaternion Q
Scalar * b
Definition: benchVecAdd.cpp:17
SparseQRMatrixQReturnType< SparseQR > matrixQ() const
Definition: SparseQR.h:186
Index rows() const
Definition: SparseMatrix.h:138
ComputationInfo info() const
Reports whether previous computation was successful.
Definition: SparseQR.h:268
MatrixXf MatrixType
BiCGSTAB< SparseMatrix< double > > solver
Holds information about the various numeric (i.e. scalar) types allowed by Eigen. ...
Definition: NumTraits.h:232
Matrix< SCALARA, Dynamic, Dynamic, opt_A > A
Definition: bench_gemm.cpp:48
void test_sparseqr_scalar()
Definition: sparseqr.cpp:44
const QRMatrixType & matrixR() const
Definition: SparseQR.h:156
void factorize(const MatrixType &mat)
Performs the numerical QR factorization of the input matrix.
Definition: SparseQR.h:361
Matrix< Scalar, Dynamic, 1 > DenseVector
Sparse left-looking QR factorization with numerical column pivoting.
Definition: SparseQR.h:16
#define VERIFY_IS_APPROX(a, b)
#define VERIFY_IS_EQUAL(a, b)
Definition: main.h:386
#define CALL_SUBTEST_1(FUNC)
Householder rank-revealing QR decomposition of a matrix with column-pivoting.
static int g_repeat
Definition: main.h:169
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:74
#define eigen_assert(x)
Definition: Macros.h:1037
Point2(* f)(const Point3 &, OptionalJacobian< 2, 3 >)
RealScalar s
NumTraits< Scalar >::Real RealScalar
Definition: bench_gemm.cpp:47
int generate_sparse_rectangular_problem(MatrixType &A, DenseMat &dA, int maxRows=300, int maxCols=150)
Definition: sparseqr.cpp:13
#define VERIFY(a)
Definition: main.h:380
EIGEN_DECLARE_TEST(sparseqr)
Definition: sparseqr.cpp:141
Index rank() const
Definition: SparseQR.h:162
bool test_isApprox(const AnnoyingScalar &a, const AnnoyingScalar &b)
InverseReturnType transpose() const
static int g_test_level
Definition: main.h:168
#define CALL_SUBTEST_2(FUNC)
const PermutationType & colsPermutation() const
Definition: SparseQR.h:192
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy x
void setPivotThreshold(const RealScalar &threshold)
Definition: SparseQR.h:235
const Solve< SparseQR, Rhs > solve(const MatrixBase< Rhs > &B) const
Definition: SparseQR.h:246
void compute(const MatrixType &mat)
Definition: SparseQR.h:127


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:36:07