Main MRPT website > C++ reference for MRPT 1.9.9
MatrixBlockSparseCols.h
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #ifndef _mrpt_math_MatrixBlockSparseCols_H
11 #define _mrpt_math_MatrixBlockSparseCols_H
12 
14 #include <mrpt/math/CMatrixTemplateNumeric.h> // For mrpt::math::CMatrixDouble
15 
16 namespace mrpt
17 {
18 namespace math
19 {
20 /** A templated column-indexed efficient storage of block-sparse Jacobian or
21  * Hessian matrices, together with other arbitrary information.
22  * Columns are stored in a non-associative container, but the contents of each
23  * column are kept within an std::map<> indexed by row.
24  * All submatrix blocks have the same size, which allows dense storage of them
25  * in fixed-size matrices, avoiding costly memory allocations.
26  *
27  * \tparam NROWS Rows in each elementary matrix.
28  * \tparam NCOLS Cols in each elementary matrix.
29  * \tparam INFO Type of the extra data fields within each block
30  * \tparam HAS_REMAP Is true, an inverse mapping between column indices and
31  * "user IDs" is kept.
32  * \tparam INDEX_REMAP_MAP_IMPL Ignore if HAS_REMAP=false. Defaults to
33  * "mrpt::utils::map_as_vector<size_t,size_t>" for amortized O(1). Can be set to
34  * "std::map<size_t,size_t>" in very sparse systems to save memory at the cost
35  * of a O(log N) access time when using the remap indices.
36  *
37  * \ingroup mrpt_math_grp
38  */
39 template <typename Scalar, int NROWS, int NCOLS, typename INFO, bool HAS_REMAP,
40  typename INDEX_REMAP_MAP_IMPL =
41  mrpt::utils::map_as_vector<size_t, size_t>>
43 {
44  using matrix_t = Eigen::Matrix<Scalar, NROWS, NCOLS>;
45  using symbolic_t = INFO;
46 
47  struct TEntry
48  {
49  /** Numeric matrix */
51  /** Extra symbolic info */
53  };
54 
55  /** Each compressed sparse column */
57 
58  private:
59  /** -> cols[i]: i'th column.
60  * -> Each column is a map [row] -> TEntry
61  */
62  std::deque<col_t> cols;
63  /** "remapped index" is the index of some global variable, interpreted by
64  * the external user of this class. */
65  // map<size_t,size_t> col_inverse_remapped_indices;
66  mrpt::utils::map_as_vector<size_t, size_t> col_inverse_remapped_indices;
67  std::vector<size_t> col_remapped_indices;
68 
69  public:
70  inline MatrixBlockSparseCols() : cols(0) {}
71  inline col_t& getCol(const size_t idx) { return cols[idx]; }
72  inline const col_t& getCol(const size_t idx) const { return cols[idx]; }
73  inline const mrpt::utils::map_as_vector<size_t, size_t>&
75  {
76  if (!HAS_REMAP) assert(false);
78  }
79  inline const std::vector<size_t>& getColRemappedIndices() const
80  {
81  if (!HAS_REMAP) assert(false);
82  return col_remapped_indices;
83  }
84 
85  /** Append one column, returning a ref to the new col_t data */
86  inline col_t& appendCol(const size_t remapIndex)
87  {
88  const size_t idx = cols.size();
89  cols.push_back(col_t());
90 
91  if (HAS_REMAP)
92  {
93  col_remapped_indices.resize(idx + 1);
94  col_remapped_indices[idx] = remapIndex;
95 
96  col_inverse_remapped_indices[remapIndex] = idx;
97  }
98 
99  return *cols.rbegin();
100  }
101 
102  /** Change the number of columns (keep old contents) */
103  inline void setColCount(const size_t nCols) { cols.resize(nCols); }
104  /** Get current number of cols. \sa findCurrentNumberOfRows */
105  inline size_t cols() const { return cols.size(); }
106  /** Clear all the entries in each column (do not change the number of
107  * columns, though!) \sa getColCount */
108  inline void clearColEntries()
109  {
110  for (size_t i = 0; i < cols.size(); i++) cols[i].clear();
111  }
112 
113  /** Clear all the entries in each column (do not change the number of
114  * columns, though!) \sa getColCount */
115  inline void clearAll()
116  {
117  cols.clear();
118  if (HAS_REMAP)
119  {
120  col_remapped_indices.clear();
122  }
123  }
124 
125  /** Builds a dense representation of the matrix and saves to a text file. */
127  const std::string& filename, const bool force_symmetry = false,
128  const bool is_col_compressed = true) const
129  {
131  getAsDense(D, force_symmetry, is_col_compressed);
132  return D.saveToTextFile(filename);
133  }
134 
135  /** Builds a dense representation of the matrix and saves to a text file.
136  * \param is_col_compressed true: interpret this object as compressed by
137  * cols; false: compressed by rows
138  */
140  mrpt::math::CMatrixDouble& D, const bool force_symmetry = false,
141  const bool is_col_compressed = true) const
142  {
143  const size_t nCols = cols.size();
144  const size_t nRows = findCurrentNumberOfRows();
145 
146  if (is_col_compressed)
147  D.setSize(nRows * NROWS, nCols * NCOLS);
148  else
149  D.setSize(nCols * NROWS, nRows * NCOLS);
150 
151  for (size_t j = 0; j < nCols; j++)
152  {
153  for (typename col_t::const_iterator itRow = cols[j].begin();
154  itRow != cols[j].end(); ++itRow)
155  {
156  const size_t row = itRow->first;
157  const size_t row_idx =
158  is_col_compressed ? row * NROWS : j * NROWS;
159  const size_t col_idx =
160  is_col_compressed ? j * NCOLS : row * NCOLS;
161  D.block(row_idx, col_idx, NROWS, NCOLS) = itRow->second.num;
162  if (force_symmetry && row_idx != col_idx)
163  D.block(col_idx, row_idx, NCOLS, NROWS) =
164  itRow->second.num.transpose();
165  }
166  }
167  }
168 
169  /** Goes over all the columns and keep the largest column length. \sa
170  * cols() */
171  size_t findCurrentNumberOfRows() const
172  {
173  size_t nRows = 0;
174  const size_t nCols = cols.size();
175  for (size_t j = 0; j < nCols; j++)
176  for (typename col_t::const_iterator itRow = cols[j].begin();
177  itRow != cols[j].end(); ++itRow)
178  mrpt::keep_max(nRows, itRow->first);
179  return nRows +
180  1; // nRows was the max. row index, now it's the row count.
181  }
182 
183  /** Builds a binary matrix with 1s where an elementary matrix is stored, 0s
184  * elsewhere. */
185  template <class MATRIX>
186  void getBinaryBlocksRepresentation(MATRIX& out) const
187  {
188  const size_t nCols = cols.size();
189  const size_t nRows = findCurrentNumberOfRows();
190  out.zeros(nRows, nCols);
191  for (size_t j = 0; j < nCols; j++)
192  for (typename col_t::const_iterator itRow = cols[j].begin();
193  itRow != cols[j].end(); ++itRow)
194  {
195  const size_t row = itRow->first;
196  out(row, j) = 1;
197  }
198  }
199 
200  /** Clear the current contents of this objects and replicates the sparse
201  * structure and numerical values of \a o */
204  {
205  const size_t nC = o.cols.size();
206  if (cols.size() != nC)
207  {
208  // Just create an empty structure with the numerical matrices:
209  cols.resize(nC);
210  for (size_t i = 0; i < nC; i++)
211  {
212  cols[i].clear();
213  for (typename col_t::const_iterator it = o.cols[i].begin();
214  it != o.cols[i].end(); ++it)
215  cols[i][it->first].num = it->second.num;
216  }
217  }
218  else
219  {
220  // It might be that we're overwriting an existing data structure:
221  for (size_t i = 0; i < nC; i++)
222  {
223  // ASSERTMSG_(cols[i].size()>=o.cols[i].size(),
224  // "copyNumericalValuesFrom() invoked on dissimilar structures")
225  typename col_t::iterator it_dst = cols[i].begin();
226  typename col_t::const_iterator it_src = o.cols[i].begin();
227  while (it_src != o.cols[i].end())
228  {
229  if (it_dst->first < it_src->first)
230  {
231  it_dst->second.num.setZero();
232  it_dst++;
233  }
234  else if (it_dst->first > it_src->first)
235  {
236  cols[i][it_src->first].num = it_src->second.num;
237  it_src++;
238  }
239  else
240  {
241  it_dst->second.num = it_src->second.num;
242  ++it_dst;
243  ++it_src;
244  }
245  }
246  }
247  }
248  } // end copyNumericalValuesFrom()
249 
250 }; // end of MatrixBlockSparseCols
251 
252 } // end NS
253 } // end NS
254 
255 #endif //_mrpt_math_MatrixBlockSparseCols_H
Scalar * iterator
Definition: eigen_plugins.h:26
void getAsDense(mrpt::math::CMatrixDouble &D, const bool force_symmetry=false, const bool is_col_compressed=true) const
Builds a dense representation of the matrix and saves to a text file.
double Scalar
Definition: KmUtils.h:44
symbolic_t sym
Extra symbolic info.
void getBinaryBlocksRepresentation(MATRIX &out) const
Builds a binary matrix with 1s where an elementary matrix is stored, 0s elsewhere.
const col_t & getCol(const size_t idx) const
EIGEN_STRONG_INLINE iterator begin()
Definition: eigen_plugins.h:29
col_t & appendCol(const size_t remapIndex)
Append one column, returning a ref to the new col_t data.
std::map< KEY, VALUE, std::less< KEY >, mrpt::aligned_allocator_cpp11< std::pair< const KEY, VALUE > >> aligned_std_map
mrpt::aligned_std_map< size_t, TEntry > col_t
Each compressed sparse column.
matrix_t num
Numeric matrix.
void saveToTextFileAsDense(const std::string &filename, const bool force_symmetry=false, const bool is_col_compressed=true) const
Builds a dense representation of the matrix and saves to a text file.
void keep_max(T &var, const K test_val)
If the second argument is above the first one, set the first argument to this higher value...
void setColCount(const size_t nCols)
Change the number of columns (keep old contents)
size_t cols() const
Get current number of cols.
GLsizei const GLchar ** string
Definition: glext.h:4101
std::deque< col_t > cols
-> cols[i]: i&#39;th column.
A templated column-indexed efficient storage of block-sparse Jacobian or Hessian matrices, together with other arbitrary information.
size_t findCurrentNumberOfRows() const
Goes over all the columns and keep the largest column length.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void clearColEntries()
Clear all the entries in each column (do not change the number of columns, though!) ...
const std::vector< size_t > & getColRemappedIndices() const
const mrpt::utils::map_as_vector< size_t, size_t > & getColInverseRemappedIndices() const
GLenum GLenum GLvoid * row
Definition: glext.h:3576
void clearAll()
Clear all the entries in each column (do not change the number of columns, though!) ...
void copyNumericalValuesFrom(const MatrixBlockSparseCols< Scalar, NROWS, NCOLS, INFO, HAS_REMAP > &o)
Clear the current contents of this objects and replicates the sparse structure and numerical values o...
std::vector< size_t > col_remapped_indices
void clear()
Clear the contents of this container.
Definition: ts_hash_map.h:188
const Scalar * const_iterator
Definition: eigen_plugins.h:27
mrpt::utils::map_as_vector< size_t, size_t > col_inverse_remapped_indices
"remapped index" is the index of some global variable, interpreted by the external user of this class...
Eigen::Matrix< Scalar, NROWS, NCOLS > matrix_t



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ad3a9d8ae Tue May 1 23:10:22 2018 -0700 at lun oct 28 00:14:14 CET 2019