MRPT  2.0.0
CSparseMatrix_unittest.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2020, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include <CTraitsTest.h>
11 #include <gtest/gtest.h>
13 #include <mrpt/random.h>
14 #include <Eigen/Dense>
15 
16 using namespace mrpt;
17 using namespace mrpt::math;
18 using namespace std;
19 
20 template class mrpt::CTraitsTest<mrpt::math::CSparseMatrix>;
21 
23  size_t N, size_t M, size_t nEntries, CSparseMatrix& MAT)
24 {
25  MAT.clear();
26 
27  MAT.setRowCount(N);
28  MAT.setColCount(M);
29 
30  for (size_t i = 0; i < nEntries; i++)
31  {
32  MAT.insert_entry(
33  mrpt::random::getRandomGenerator().drawUniform32bit() % N,
34  mrpt::random::getRandomGenerator().drawUniform32bit() % M,
35  mrpt::random::getRandomGenerator().drawGaussian1D(0, 1));
36  }
37 
38  // Return already compressed:
39  MAT.compressFromTriplet();
40 }
41 
42 void do_test_init_to_unit(size_t N)
43 {
44  CMatrixDouble dense1;
45  dense1.setIdentity(N);
46 
47  CSparseMatrix SM(dense1);
48 
49  CMatrixDouble dense_out;
50  SM.get_dense(dense_out);
51 
52  EXPECT_TRUE(dense_out == dense1) << "Failed with N=" << N << "\n";
53 }
54 
55 TEST(SparseMatrix, InitFromDenseUnit)
56 {
60 }
61 
62 void do_test_init_random(size_t N)
63 {
64  CMatrixDouble dense1(N, N);
66  CSparseMatrix SM(dense1);
67  CMatrixDouble dense_out;
68  SM.get_dense(dense_out);
69  EXPECT_TRUE(dense_out == dense1) << "Failed with N=" << N << "\n";
70 }
71 
72 TEST(SparseMatrix, InitFromDenseRandom)
73 {
77 }
78 
79 TEST(SparseMatrix, InitFromTriplet)
80 {
81  CSparseMatrix SM;
82  CMatrixDouble D(10, 20);
83 
84  SM.insert_entry(2, 2, 4.0);
85  D(2, 2) = 4.0;
86  SM.insert_entry(6, 8, -2.0);
87  D(6, 8) = -2.0;
88 
89  SM.setRowCount(10);
90  SM.setColCount(20);
91 
92  CMatrixDouble dense_out1;
93  SM.get_dense(dense_out1);
94 
96 
97  CMatrixDouble dense_out2;
98  SM.get_dense(dense_out2);
99 
100  EXPECT_TRUE(dense_out1 == dense_out2);
101 }
102 
103 TEST(SparseMatrix, InitFromSparse)
104 {
105  CMatrixDouble D(4, 5);
107  D(1, 2) = 2.0;
108  S(1, 2) = 2.0;
109 
110  D(3, 1) = -7.0;
111  S(3, 1) = -7.0;
112 
113  CSparseMatrix SM(S);
114  CMatrixDouble dense_out;
115  SM.get_dense(dense_out);
116  EXPECT_TRUE(dense_out == D) << "Dense: \n"
117  << D << "Sparse:\n"
118  << dense_out << endl;
119 }
120 
121 TEST(SparseMatrix, InitFromRandom)
122 {
123  CSparseMatrix SM;
124  generateRandomSparseMatrix(100, 100, 25, SM);
125  generateRandomSparseMatrix(20, 10, 15, SM);
126 }
127 
128 using TMatrixSMOperator = void (*)(
129  const CSparseMatrix& M1, const CSparseMatrix& M2, CSparseMatrix& res);
130 using TMatrixDenseOperator = void (*)(
131  const CMatrixDouble& M1, const CMatrixDouble& M2, CMatrixDouble& res);
132 
134  size_t nRows1, size_t nCols1, size_t nNonZeros1, size_t nRows2,
135  size_t nCols2, size_t nNonZeros2, TMatrixSMOperator op1,
137 {
138  CSparseMatrix SM1, SM2;
139  generateRandomSparseMatrix(nRows1, nCols1, nNonZeros1, SM1);
140  generateRandomSparseMatrix(nRows2, nCols2, nNonZeros2, SM2);
141 
142  CSparseMatrix SM_res;
143  (*op1)(SM1, SM2, SM_res);
144 
145  // Check:
146  CMatrixDouble D1, D2, Dres;
147  SM1.get_dense(D1);
148  SM2.get_dense(D2);
149  SM_res.get_dense(Dres);
150 
151  CMatrixDouble RES;
152  (*op2)(D1, D2, RES);
153 
154  const double err = (RES - Dres).array().abs().maxCoeff();
155 
156  EXPECT_TRUE(err < 1e-10) << "M1:\n"
157  << D1 << "M2:\n"
158  << D2 << "Real op result:\n"
159  << RES << "SM result:\n"
160  << Dres << "ERR:\n"
161  << (RES - Dres);
162 }
163 
165  const CSparseMatrix& M1, const CSparseMatrix& M2, CSparseMatrix& res)
166 {
167  res = M1 + M2;
168 }
170  const CMatrixDouble& M1, const CMatrixDouble& M2, CMatrixDouble& res)
171 {
172  res = M1 + M2;
173 }
174 
175 TEST(SparseMatrix, Op_Add)
176 {
177  do_matrix_op_test(1, 1, 0, 1, 1, 0, &op_sparse_add, &op_dense_add);
178  do_matrix_op_test(1, 1, 1, 1, 1, 1, &op_sparse_add, &op_dense_add);
179  do_matrix_op_test(2, 2, 1, 2, 2, 1, &op_sparse_add, &op_dense_add);
180  do_matrix_op_test(10, 20, 33, 10, 20, 33, &op_sparse_add, &op_dense_add);
181  do_matrix_op_test(11, 21, 34, 11, 21, 34, &op_sparse_add, &op_dense_add);
182 }
183 
185  const CSparseMatrix& M1, const CSparseMatrix& M2, CSparseMatrix& res)
186 {
187  res = M1 * M2;
188 }
190  const CMatrixDouble& M1, const CMatrixDouble& M2, CMatrixDouble& res)
191 {
192  if (M1.isSquare() && M2.isSquare())
193  res = M1 * M2;
194  else
195  res = M1.asEigen() * M2.asEigen();
196 }
197 
198 TEST(SparseMatrix, Op_Multiply_AB)
199 {
201  1, 1, 0, 1, 1, 0, &op_sparse_multiply_AB, &op_dense_multiply_AB);
203  1, 1, 1, 1, 1, 1, &op_sparse_multiply_AB, &op_dense_multiply_AB);
205  2, 2, 1, 2, 2, 1, &op_sparse_multiply_AB, &op_dense_multiply_AB);
207  10, 20, 33, 20, 15, 33, &op_sparse_multiply_AB, &op_dense_multiply_AB);
209  8, 34, 100, 34, 3, 100, &op_sparse_multiply_AB, &op_dense_multiply_AB);
210 }
211 
212 TEST(SparseMatrix, CholeskyDecomp)
213 {
214  CSparseMatrix SM(10, 10);
215  const auto COV1 = mrpt::random::getRandomGenerator()
217  const auto COV2 = mrpt::random::getRandomGenerator()
219 
220  SM.insert_submatrix(0, 0, COV1);
221  SM.insert_submatrix(6, 6, COV2);
222  SM.compressFromTriplet();
223 
225 
226  const CMatrixDouble L = Chol.get_L(); // lower triangle
227 
228  // Compare with the dense matrix implementation:
229  CMatrixDouble D;
230  SM.get_dense(D);
231 
232  CMatrixDouble Ud; // Upper triangle
233  D.chol(Ud);
234 
235  const double err = (Ud.transpose() - L.asEigen()).array().abs().mean();
236  EXPECT_TRUE(err < 1e-8);
237 }
Scalar maxCoeff() const
Maximum value in the matrix/vector.
MATRIX drawDefinitePositiveMatrix(const size_t dim, const double std_scale=1.0, const double diagonal_epsilon=1e-8)
Generates a random definite-positive matrix of the given size, using the formula C = v*v^t + epsilon*...
void setColCount(const size_t nCols)
EXPECT_TRUE(mrpt::system::fileExists(ini_fil))
void do_matrix_op_test(size_t nRows1, size_t nCols1, size_t nNonZeros1, size_t nRows2, size_t nCols2, size_t nNonZeros2, TMatrixSMOperator op1, TMatrixDenseOperator op2)
bool chol(Derived &U) const
Cholesky M=UT * U decomposition for symmetric matrix (upper-half of the matrix is actually ignored...
void drawGaussian1DMatrix(MAT &matrix, const double mean=0, const double std=1)
Fills the given matrix with independent, 1D-normally distributed samples.
Auxiliary class to hold the results of a Cholesky factorization of a sparse matrix.
bool isSquare() const
returns true if matrix is NxN
A sparse matrix structure, wrapping T.
Definition: CSparseMatrix.h:98
STL namespace.
void compressFromTriplet()
ONLY for TRIPLET matrices: convert the matrix in a column-compressed form.
void(*)(const CMatrixDouble &M1, const CMatrixDouble &M2, CMatrixDouble &res) TMatrixDenseOperator
void op_dense_multiply_AB(const CMatrixDouble &M1, const CMatrixDouble &M2, CMatrixDouble &res)
void insert_entry(const size_t row, const size_t col, const double val)
@ Access the matrix, get, set elements, etc.
A sparse matrix container (with cells of any type), with iterators.
CMatrixDouble get_L() const
Return the L matrix (L*L&#39; = M), as a dense matrix.
void get_dense(CMatrixDouble &outMat) const
Return a dense representation of the sparse matrix.
This base provides a set of functions for maths stuff.
void op_sparse_multiply_AB(const CSparseMatrix &M1, const CSparseMatrix &M2, CSparseMatrix &res)
void do_test_init_to_unit(size_t N)
TEST(SparseMatrix, InitFromDenseUnit)
void do_test_init_random(size_t N)
void setRowCount(const size_t nRows)
Change the number of rows in the matrix (can&#39;t be lower than current size)
void clear(const size_t nRows=1, const size_t nCols=1)
Erase all previous contents and leave the matrix as a "triplet" ROWS x COLS matrix without any nonzer...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void op_dense_add(const CMatrixDouble &M1, const CMatrixDouble &M2, CMatrixDouble &res)
void insert_submatrix(const size_t row, const size_t col, const MATRIX &M)
ONLY for TRIPLET matrices: insert a given matrix (in any of the MRPT formats) at a given location of ...
CRandomGenerator & getRandomGenerator()
A static instance of a CRandomGenerator class, for use in single-thread applications.
EIGEN_MAP asEigen()
Get as an Eigen-compatible Eigen::Map object.
void op_sparse_add(const CSparseMatrix &M1, const CSparseMatrix &M2, CSparseMatrix &res)
void(*)(const CSparseMatrix &M1, const CSparseMatrix &M2, CSparseMatrix &res) TMatrixSMOperator
void generateRandomSparseMatrix(size_t N, size_t M, size_t nEntries, CSparseMatrix &MAT)



Page generated by Doxygen 1.8.14 for MRPT 2.0.0 Git: b38439d21 Tue Mar 31 19:58:06 2020 +0200 at miƩ abr 1 00:50:30 CEST 2020