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