SymmetricBlockMatrix.h
Go to the documentation of this file.
1 /* ----------------------------------------------------------------------------
2 
3 * GTSAM Copyright 2010, Georgia Tech Research Corporation,
4 * Atlanta, Georgia 30332-0415
5 * All Rights Reserved
6 * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
7 
8 * See LICENSE for the license information
9 
10 * -------------------------------------------------------------------------- */
11 
18 #pragma once
19 
20 #include <gtsam/base/FastVector.h>
21 #include <gtsam/base/Matrix.h>
22 #include <gtsam/base/types.h>
23 #include <gtsam/dllexport.h>
24 #ifdef GTSAM_ENABLE_BOOST_SERIALIZATION
25 #include <boost/serialization/nvp.hpp>
26 #endif
27 #include <cassert>
28 #include <stdexcept>
29 #include <array>
30 
31 namespace boost {
32 namespace serialization {
33 class access;
34 } /* namespace serialization */
35 } /* namespace boost */
36 
37 namespace gtsam {
38 
39  // Forward declarations
40  class VerticalBlockMatrix;
41 
53  class GTSAM_EXPORT SymmetricBlockMatrix
54  {
55  public:
59 
60  protected:
63 
65 
66  public:
69 
71  template<typename CONTAINER>
72  SymmetricBlockMatrix(const CONTAINER& dimensions, bool appendOneDimension = false) :
73  blockStart_(0)
74  {
75  fillOffsets(dimensions.begin(), dimensions.end(), appendOneDimension);
76  matrix_.resize(variableColOffsets_.back(), variableColOffsets_.back());
77  assertInvariants();
78  }
79 
81  template<typename ITERATOR>
82  SymmetricBlockMatrix(ITERATOR firstBlockDim, ITERATOR lastBlockDim, bool appendOneDimension = false) :
83  blockStart_(0)
84  {
85  fillOffsets(firstBlockDim, lastBlockDim, appendOneDimension);
86  matrix_.resize(variableColOffsets_.back(), variableColOffsets_.back());
87  assertInvariants();
88  }
89 
91  template<typename CONTAINER>
92  SymmetricBlockMatrix(const CONTAINER& dimensions, const Matrix& matrix, bool appendOneDimension = false) :
93  blockStart_(0)
94  {
95  matrix_.resize(matrix.rows(), matrix.cols());
96  matrix_.triangularView<Eigen::Upper>() = matrix.triangularView<Eigen::Upper>();
97  fillOffsets(dimensions.begin(), dimensions.end(), appendOneDimension);
98  if(matrix_.rows() != matrix_.cols())
99  throw std::invalid_argument("Requested to create a SymmetricBlockMatrix from a non-square matrix.");
100  if(variableColOffsets_.back() != matrix_.cols())
101  throw std::invalid_argument("Requested to create a SymmetricBlockMatrix with dimensions that do not sum to the total size of the provided matrix.");
102  assertInvariants();
103  }
104 
108  static SymmetricBlockMatrix LikeActiveViewOf(const SymmetricBlockMatrix& other);
109 
113  static SymmetricBlockMatrix LikeActiveViewOf(const VerticalBlockMatrix& other);
114 
116  DenseIndex rows() const { assertInvariants(); return variableColOffsets_.back() - variableColOffsets_[blockStart_]; }
117 
119  DenseIndex cols() const { return rows(); }
120 
122  DenseIndex nBlocks() const { return nActualBlocks() - blockStart_; }
123 
126  return calcIndices(block, block, 1, 1)[2];
127  }
128 
131 
135 
138  return block_(J, J).selfadjointView<Eigen::Upper>();
139  }
140 
143  return block_(J, J).selfadjointView<Eigen::Upper>();
144  }
145 
148  return block_(J, J).diagonal();
149  }
150 
152  constBlock aboveDiagonalBlock(DenseIndex I, DenseIndex J) const {
153  assert(I < J);
154  return block_(I, J);
155  }
156 
159  DenseIndex I, DenseIndex J) const {
160  assert(J > I);
161  return block_(I, I, J - I, J - I).selfadjointView<Eigen::Upper>();
162  }
163 
166  DenseIndex J) const {
167  assert(J > I);
168  return block_(I, I, J - I, J - I).triangularView<Eigen::Upper>();
169  }
170 
172  constBlock aboveDiagonalRange(DenseIndex i_startBlock,
173  DenseIndex i_endBlock,
174  DenseIndex j_startBlock,
175  DenseIndex j_endBlock) const {
176  assert(i_startBlock < j_startBlock);
177  assert(i_endBlock <= j_startBlock);
178  return block_(i_startBlock, j_startBlock, i_endBlock - i_startBlock,
179  j_endBlock - j_startBlock);
180  }
181 
183  Block aboveDiagonalRange(DenseIndex i_startBlock, DenseIndex i_endBlock,
184  DenseIndex j_startBlock, DenseIndex j_endBlock) {
185  assert(i_startBlock < j_startBlock);
186  assert(i_endBlock <= j_startBlock);
187  return block_(i_startBlock, j_startBlock, i_endBlock - i_startBlock,
188  j_endBlock - j_startBlock);
189  }
190 
194 
196  template <typename XprType>
197  void setDiagonalBlock(DenseIndex I, const XprType& xpr) {
198  block_(I, I).triangularView<Eigen::Upper>() = xpr.template triangularView<Eigen::Upper>();
199  }
200 
202  template <typename XprType>
204  assert(I != J);
205  if (I < J) {
206  block_(I, J) = xpr;
207  } else {
208  block_(J, I) = xpr.transpose();
209  }
210  }
211 
213  template <typename XprType>
214  void updateDiagonalBlock(DenseIndex I, const XprType& xpr) {
215  // TODO(gareth): Eigen won't let us add triangular or self-adjoint views
216  // here, so we do it manually.
217  auto dest = block_(I, I);
218  assert(dest.rows() == xpr.rows());
219  assert(dest.cols() == xpr.cols());
220  for (DenseIndex col = 0; col < dest.cols(); ++col) {
221  for (DenseIndex row = 0; row <= col; ++row) {
222  dest(row, col) += xpr(row, col);
223  }
224  }
225  }
226 
229  template <typename XprType>
231  assert(I != J);
232  if (I < J) {
233  block_(I, J).noalias() += xpr;
234  } else {
235  block_(J, I).noalias() += xpr.transpose();
236  }
237  }
238 
242 
245  return full().selfadjointView<Eigen::Upper>();
246  }
247 
250  return full().selfadjointView<Eigen::Upper>();
251  }
252 
254  template <typename XprType>
255  void setFullMatrix(const XprType& xpr) {
256  full().triangularView<Eigen::Upper>() = xpr.template triangularView<Eigen::Upper>();
257  }
258 
260  void setZero() {
261  full().triangularView<Eigen::Upper>().setZero();
262  }
263 
265  void negate();
266 
268  void invertInPlace();
269 
271 
275  DenseIndex& blockStart() { return blockStart_; }
276 
279  DenseIndex blockStart() const { return blockStart_; }
280 
291  void choleskyPartial(DenseIndex nFrontals);
292 
299 
300  protected:
301 
304  return variableColOffsets_.size();
305  }
306 
309  return nOffsets() - 1;
310  }
311 
313  DenseIndex offset(DenseIndex block) const {
314  assert(block >= 0);
315  const DenseIndex actual_index = block + blockStart();
316  assert(actual_index < nOffsets());
317  return variableColOffsets_[actual_index];
318  }
319 
321  constBlock block_(DenseIndex iBlock, DenseIndex jBlock,
322  DenseIndex blockRows = 1, DenseIndex blockCols = 1) const {
323  const std::array<DenseIndex, 4> indices =
324  calcIndices(iBlock, jBlock, blockRows, blockCols);
325  return matrix_.block(indices[0], indices[1], indices[2], indices[3]);
326  }
327 
329  Block block_(DenseIndex iBlock, DenseIndex jBlock, DenseIndex blockRows = 1,
330  DenseIndex blockCols = 1) {
331  const std::array<DenseIndex, 4> indices =
332  calcIndices(iBlock, jBlock, blockRows, blockCols);
333  return matrix_.block(indices[0], indices[1], indices[2], indices[3]);
334  }
335 
337  constBlock full() const {
338  return block_(0, 0, nBlocks(), nBlocks());
339  }
340 
342  Block full() {
343  return block_(0, 0, nBlocks(), nBlocks());
344  }
345 
347  std::array<DenseIndex, 4> calcIndices(DenseIndex iBlock, DenseIndex jBlock,
348  DenseIndex blockRows,
349  DenseIndex blockCols) const {
350  assert(blockRows >= 0);
351  assert(blockCols >= 0);
352 
353  // adjust indices to account for start and size of blocks
354  const DenseIndex denseI = offset(iBlock);
355  const DenseIndex denseJ = offset(jBlock);
356  const DenseIndex denseRows = offset(iBlock + blockRows) - denseI;
357  const DenseIndex denseCols = offset(jBlock + blockCols) - denseJ;
358  return {{denseI, denseJ, denseRows, denseCols}};
359  }
360 
361  void assertInvariants() const
362  {
363  assert(matrix_.rows() == matrix_.cols());
364  assert(matrix_.cols() == variableColOffsets_.back());
365  assert(blockStart_ < (DenseIndex)variableColOffsets_.size());
366  }
367 
368  template<typename ITERATOR>
369  void fillOffsets(ITERATOR firstBlockDim, ITERATOR lastBlockDim, bool appendOneDimension)
370  {
371  variableColOffsets_.resize((lastBlockDim-firstBlockDim) + 1 + (appendOneDimension ? 1 : 0));
372  variableColOffsets_[0] = 0;
373  DenseIndex j=0;
374  for(ITERATOR dim=firstBlockDim; dim!=lastBlockDim; ++dim) {
375  variableColOffsets_[j+1] = variableColOffsets_[j] + *dim;
376  ++ j;
377  }
378  if(appendOneDimension)
379  {
380  variableColOffsets_[j+1] = variableColOffsets_[j] + 1;
381  ++ j;
382  }
383  }
384 
385  friend class VerticalBlockMatrix;
386  template<typename SymmetricBlockMatrixType> friend class SymmetricBlockMatrixBlockExpr;
387 
388  private:
389 #ifdef GTSAM_ENABLE_BOOST_SERIALIZATION
390 
391  friend class boost::serialization::access;
392  template<class ARCHIVE>
393  void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
394  // Fill in the lower triangle part of the matrix, so boost::serialization won't
395  // complain about uninitialized data with an input_stream_error exception
396  // http://www.boost.org/doc/libs/1_37_0/libs/serialization/doc/exceptions.html#stream_error
397  matrix_.triangularView<Eigen::Lower>() = matrix_.triangularView<Eigen::Upper>().transpose();
398  ar & BOOST_SERIALIZATION_NVP(matrix_);
399  ar & BOOST_SERIALIZATION_NVP(variableColOffsets_);
400  ar & BOOST_SERIALIZATION_NVP(blockStart_);
401  }
402 #endif
403  };
404 
406  class CholeskyFailed;
407 
408 }
#define I
Definition: main.h:112
Typedefs for easier changing of types.
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT
constBlock full() const
Get the full matrix as a block.
m m block(1, 0, 2, 2)<< 4
void fillOffsets(ITERATOR firstBlockDim, ITERATOR lastBlockDim, bool appendOneDimension)
void setOffDiagonalBlock(DenseIndex I, DenseIndex J, const XprType &xpr)
Set an off-diagonal block. Only the upper triangular portion of xpr is evaluated. ...
FastVector< DenseIndex > variableColOffsets_
the starting columns of each block (0-based)
std::string serialize(const T &input)
serializes to a string
Eigen::Block< Matrix > Block
constBlock aboveDiagonalRange(DenseIndex i_startBlock, DenseIndex i_endBlock, DenseIndex j_startBlock, DenseIndex j_endBlock) const
Get a range [i,j) from the matrix. Indices are in block units.
Block full()
Get the full matrix as a block.
Matrix matrix_
The full matrix.
std::vector< T, typename internal::FastDefaultVectorAllocator< T >::type > FastVector
Definition: FastVector.h:34
Eigen::MatrixXd Matrix
Definition: base/Matrix.h:39
DenseIndex blockStart_
Changes apparent matrix view, see main class comment.
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 y set format x g set format y g set format x2 g set format y2 g set format z g set angles radians set nogrid set key title set key left top Right noreverse box linetype linewidth samplen spacing width set nolabel set noarrow set nologscale set logscale x set set pointsize set encoding default set nopolar set noparametric set set set set surface set nocontour set clabel set mapping cartesian set nohidden3d set cntrparam order set cntrparam linear set cntrparam levels auto set cntrparam points set size set set xzeroaxis lt lw set x2zeroaxis lt lw set yzeroaxis lt lw set y2zeroaxis lt lw set tics in set ticslevel set tics set mxtics default set mytics default set mx2tics default set my2tics default set xtics border mirror norotate autofreq set ytics border mirror norotate autofreq set ztics border nomirror norotate autofreq set nox2tics set noy2tics set timestamp bottom norotate offset
Block block_(DenseIndex iBlock, DenseIndex jBlock, DenseIndex blockRows=1, DenseIndex blockCols=1)
Get an arbitrary block from the matrix. Indices are in block units.
DenseIndex nActualBlocks() const
Number of actual blocks in the full matrix.
Eigen::SelfAdjointView< constBlock, Eigen::Upper > diagonalBlock(DenseIndex J) const
Return the J&#39;th diagonal block as a self adjoint view.
ptrdiff_t DenseIndex
The index type for Eigen objects.
Definition: types.h:108
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT
SymmetricBlockMatrix(ITERATOR firstBlockDim, ITERATOR lastBlockDim, bool appendOneDimension=false)
Construct from iterator over the sizes of each vertical block.
SymmetricBlockMatrix(const CONTAINER &dimensions, const Matrix &matrix, bool appendOneDimension=false)
Construct from a container of the sizes of each vertical block and a pre-prepared matrix...
void split(const G &g, const PredecessorMap< KEY > &tree, G &Ab1, G &Ab2)
Definition: graph-inl.h:245
Generic expression where a coefficient-wise binary operator is applied to two expressions.
Definition: CwiseBinaryOp.h:77
Eigen::SelfAdjointView< constBlock, Eigen::Upper > selfadjointView(DenseIndex I, DenseIndex J) const
Return the square sub-matrix that contains blocks(i:j, i:j).
DenseIndex nBlocks() const
Block count.
DenseIndex rows() const
Row size.
void setDiagonalBlock(DenseIndex I, const XprType &xpr)
Set a diagonal block. Only the upper triangular portion of xpr is evaluated.
Eigen::VectorXd Vector
Definition: Vector.h:38
m row(1)
DenseIndex cols() const
Column size.
Block aboveDiagonalRange(DenseIndex i_startBlock, DenseIndex i_endBlock, DenseIndex j_startBlock, DenseIndex j_endBlock)
Get a range [i,j) from the matrix. Indices are in block units.
DenseIndex nOffsets() const
Number of offsets in the full matrix.
Eigen::TriangularView< constBlock, Eigen::Upper > triangularView(DenseIndex I, DenseIndex J) const
Return the square sub-matrix that contains blocks(i:j, i:j) as a triangular view. ...
void updateDiagonalBlock(DenseIndex I, const XprType &xpr)
Increment the diagonal block by the values in xpr. Only reads the upper triangular part of xpr...
Expression of a selfadjoint matrix from a triangular part of a dense matrix.
JacobiRotation< float > J
Eigen::SelfAdjointView< Block, Eigen::Upper > selfadjointView()
Get self adjoint view.
void setFullMatrix(const XprType &xpr)
Set the entire active matrix. Only reads the upper triangular part of xpr.
A thin wrapper around std::vector that uses a custom allocator.
traits
Definition: chartTesting.h:28
bool choleskyPartial(Matrix &ABC, size_t nFrontal, size_t topleft)
Expression of a fixed-size or dynamic-size block.
Definition: Block.h:103
DenseIndex offset(DenseIndex block) const
Get an offset for a block index (in the active view).
Eigen::SelfAdjointView< constBlock, Eigen::Upper > selfadjointView() const
Get self adjoint view.
void setZero()
Set the entire active matrix zero.
Eigen::Block< const Matrix > constBlock
std::array< DenseIndex, 4 > calcIndices(DenseIndex iBlock, DenseIndex jBlock, DenseIndex blockRows, DenseIndex blockCols) const
Compute the indices into the underlying matrix for a given block.
Expression of a triangular part in a matrix.
m col(1)
Vector diagonal(DenseIndex J) const
Get the diagonal of the J&#39;th diagonal block.
void updateOffDiagonalBlock(DenseIndex I, DenseIndex J, const XprType &xpr)
Indicate Cholesky factorization failure.
Eigen::SelfAdjointView< Block, Eigen::Upper > diagonalBlock(DenseIndex J)
Return the J&#39;th diagonal block as a self adjoint view.
DenseIndex getDim(DenseIndex block) const
Number of dimensions for variable on this diagonal block.
Map< Matrix< T, Dynamic, Dynamic, ColMajor >, 0, OuterStride<> > matrix(T *data, int rows, int cols, int stride)
const std::vector< size_t > dimensions
SymmetricBlockMatrix(const CONTAINER &dimensions, bool appendOneDimension=false)
Construct from a container of the sizes of each block.
constBlock aboveDiagonalBlock(DenseIndex I, DenseIndex J) const
Get block above the diagonal (I, J).
constBlock block_(DenseIndex iBlock, DenseIndex jBlock, DenseIndex blockRows=1, DenseIndex blockCols=1) const
Get an arbitrary block from the matrix. Indices are in block units.
std::ptrdiff_t j
v setZero(3)


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