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 #include <boost/serialization/nvp.hpp>
25 #include <cassert>
26 #include <stdexcept>
27 #include <array>
28 
29 namespace boost {
30 namespace serialization {
31 class access;
32 } /* namespace serialization */
33 } /* namespace boost */
34 
35 namespace gtsam {
36 
37  // Forward declarations
38  class VerticalBlockMatrix;
39 
51  class GTSAM_EXPORT SymmetricBlockMatrix
52  {
53  public:
57 
58  protected:
61 
63 
64  public:
67  blockStart_(0)
68  {
69  variableColOffsets_.push_back(0);
70  assertInvariants();
71  }
72 
74  template<typename CONTAINER>
75  SymmetricBlockMatrix(const CONTAINER& dimensions, bool appendOneDimension = false) :
76  blockStart_(0)
77  {
78  fillOffsets(dimensions.begin(), dimensions.end(), appendOneDimension);
79  matrix_.resize(variableColOffsets_.back(), variableColOffsets_.back());
80  assertInvariants();
81  }
82 
84  template<typename ITERATOR>
85  SymmetricBlockMatrix(ITERATOR firstBlockDim, ITERATOR lastBlockDim, bool appendOneDimension = false) :
86  blockStart_(0)
87  {
88  fillOffsets(firstBlockDim, lastBlockDim, appendOneDimension);
89  matrix_.resize(variableColOffsets_.back(), variableColOffsets_.back());
90  assertInvariants();
91  }
92 
94  template<typename CONTAINER>
95  SymmetricBlockMatrix(const CONTAINER& dimensions, const Matrix& matrix, bool appendOneDimension = false) :
96  blockStart_(0)
97  {
98  matrix_.resize(matrix.rows(), matrix.cols());
99  matrix_.triangularView<Eigen::Upper>() = matrix.triangularView<Eigen::Upper>();
100  fillOffsets(dimensions.begin(), dimensions.end(), appendOneDimension);
101  if(matrix_.rows() != matrix_.cols())
102  throw std::invalid_argument("Requested to create a SymmetricBlockMatrix from a non-square matrix.");
103  if(variableColOffsets_.back() != matrix_.cols())
104  throw std::invalid_argument("Requested to create a SymmetricBlockMatrix with dimensions that do not sum to the total size of the provided matrix.");
105  assertInvariants();
106  }
107 
111  static SymmetricBlockMatrix LikeActiveViewOf(const SymmetricBlockMatrix& other);
112 
116  static SymmetricBlockMatrix LikeActiveViewOf(const VerticalBlockMatrix& other);
117 
119  DenseIndex rows() const { assertInvariants(); return variableColOffsets_.back() - variableColOffsets_[blockStart_]; }
120 
122  DenseIndex cols() const { return rows(); }
123 
125  DenseIndex nBlocks() const { return nActualBlocks() - blockStart_; }
126 
129  return calcIndices(block, block, 1, 1)[2];
130  }
131 
134 
138 
141  return block_(J, J).selfadjointView<Eigen::Upper>();
142  }
143 
146  return block_(J, J).selfadjointView<Eigen::Upper>();
147  }
148 
151  return block_(J, J).diagonal();
152  }
153 
155  constBlock aboveDiagonalBlock(DenseIndex I, DenseIndex J) const {
156  assert(I < J);
157  return block_(I, J);
158  }
159 
162  DenseIndex I, DenseIndex J) const {
163  assert(J > I);
164  return block_(I, I, J - I, J - I).selfadjointView<Eigen::Upper>();
165  }
166 
169  DenseIndex J) const {
170  assert(J > I);
171  return block_(I, I, J - I, J - I).triangularView<Eigen::Upper>();
172  }
173 
175  constBlock aboveDiagonalRange(DenseIndex i_startBlock,
176  DenseIndex i_endBlock,
177  DenseIndex j_startBlock,
178  DenseIndex j_endBlock) const {
179  assert(i_startBlock < j_startBlock);
180  assert(i_endBlock <= j_startBlock);
181  return block_(i_startBlock, j_startBlock, i_endBlock - i_startBlock,
182  j_endBlock - j_startBlock);
183  }
184 
186  Block aboveDiagonalRange(DenseIndex i_startBlock, DenseIndex i_endBlock,
187  DenseIndex j_startBlock, DenseIndex j_endBlock) {
188  assert(i_startBlock < j_startBlock);
189  assert(i_endBlock <= j_startBlock);
190  return block_(i_startBlock, j_startBlock, i_endBlock - i_startBlock,
191  j_endBlock - j_startBlock);
192  }
193 
197 
199  template <typename XprType>
200  void setDiagonalBlock(DenseIndex I, const XprType& xpr) {
201  block_(I, I).triangularView<Eigen::Upper>() = xpr.template triangularView<Eigen::Upper>();
202  }
203 
205  template <typename XprType>
206  void setOffDiagonalBlock(DenseIndex I, DenseIndex J, const XprType& xpr) {
207  assert(I != J);
208  if (I < J) {
209  block_(I, J) = xpr;
210  } else {
211  block_(J, I) = xpr.transpose();
212  }
213  }
214 
216  template <typename XprType>
217  void updateDiagonalBlock(DenseIndex I, const XprType& xpr) {
218  // TODO(gareth): Eigen won't let us add triangular or self-adjoint views
219  // here, so we do it manually.
220  auto dest = block_(I, I);
221  assert(dest.rows() == xpr.rows());
222  assert(dest.cols() == xpr.cols());
223  for (DenseIndex col = 0; col < dest.cols(); ++col) {
224  for (DenseIndex row = 0; row <= col; ++row) {
225  dest(row, col) += xpr(row, col);
226  }
227  }
228  }
229 
232  template <typename XprType>
233  void updateOffDiagonalBlock(DenseIndex I, DenseIndex J, const XprType& xpr) {
234  assert(I != J);
235  if (I < J) {
236  block_(I, J).noalias() += xpr;
237  } else {
238  block_(J, I).noalias() += xpr.transpose();
239  }
240  }
241 
245 
248  return full().selfadjointView<Eigen::Upper>();
249  }
250 
253  return full().selfadjointView<Eigen::Upper>();
254  }
255 
257  template <typename XprType>
258  void setFullMatrix(const XprType& xpr) {
259  full().triangularView<Eigen::Upper>() = xpr.template triangularView<Eigen::Upper>();
260  }
261 
263  void setZero() {
264  full().triangularView<Eigen::Upper>().setZero();
265  }
266 
268  void negate() {
269  full().triangularView<Eigen::Upper>() *= -1.0;
270  }
271 
273  void invertInPlace() {
274  const auto identity = Matrix::Identity(rows(), rows());
275  full().triangularView<Eigen::Upper>() =
276  selfadjointView()
277  .llt()
278  .solve(identity)
279  .triangularView<Eigen::Upper>();
280  }
281 
283 
287  DenseIndex& blockStart() { return blockStart_; }
288 
291  DenseIndex blockStart() const { return blockStart_; }
292 
303  void choleskyPartial(DenseIndex nFrontals);
304 
311 
312  protected:
313 
316  return variableColOffsets_.size();
317  }
318 
321  return nOffsets() - 1;
322  }
323 
325  DenseIndex offset(DenseIndex block) const {
326  assert(block >= 0);
327  const DenseIndex actual_index = block + blockStart();
328  assert(actual_index < nOffsets());
329  return variableColOffsets_[actual_index];
330  }
331 
333  constBlock block_(DenseIndex iBlock, DenseIndex jBlock,
334  DenseIndex blockRows = 1, DenseIndex blockCols = 1) const {
335  const std::array<DenseIndex, 4> indices =
336  calcIndices(iBlock, jBlock, blockRows, blockCols);
337  return matrix_.block(indices[0], indices[1], indices[2], indices[3]);
338  }
339 
341  Block block_(DenseIndex iBlock, DenseIndex jBlock, DenseIndex blockRows = 1,
342  DenseIndex blockCols = 1) {
343  const std::array<DenseIndex, 4> indices =
344  calcIndices(iBlock, jBlock, blockRows, blockCols);
345  return matrix_.block(indices[0], indices[1], indices[2], indices[3]);
346  }
347 
349  constBlock full() const {
350  return block_(0, 0, nBlocks(), nBlocks());
351  }
352 
354  Block full() {
355  return block_(0, 0, nBlocks(), nBlocks());
356  }
357 
359  std::array<DenseIndex, 4> calcIndices(DenseIndex iBlock, DenseIndex jBlock,
360  DenseIndex blockRows,
361  DenseIndex blockCols) const {
362  assert(blockRows >= 0);
363  assert(blockCols >= 0);
364 
365  // adjust indices to account for start and size of blocks
366  const DenseIndex denseI = offset(iBlock);
367  const DenseIndex denseJ = offset(jBlock);
368  const DenseIndex denseRows = offset(iBlock + blockRows) - denseI;
369  const DenseIndex denseCols = offset(jBlock + blockCols) - denseJ;
370  return {{denseI, denseJ, denseRows, denseCols}};
371  }
372 
373  void assertInvariants() const
374  {
375  assert(matrix_.rows() == matrix_.cols());
376  assert(matrix_.cols() == variableColOffsets_.back());
377  assert(blockStart_ < (DenseIndex)variableColOffsets_.size());
378  }
379 
380  template<typename ITERATOR>
381  void fillOffsets(ITERATOR firstBlockDim, ITERATOR lastBlockDim, bool appendOneDimension)
382  {
383  variableColOffsets_.resize((lastBlockDim-firstBlockDim) + 1 + (appendOneDimension ? 1 : 0));
384  variableColOffsets_[0] = 0;
385  DenseIndex j=0;
386  for(ITERATOR dim=firstBlockDim; dim!=lastBlockDim; ++dim) {
387  variableColOffsets_[j+1] = variableColOffsets_[j] + *dim;
388  ++ j;
389  }
390  if(appendOneDimension)
391  {
392  variableColOffsets_[j+1] = variableColOffsets_[j] + 1;
393  ++ j;
394  }
395  }
396 
397  friend class VerticalBlockMatrix;
398  template<typename SymmetricBlockMatrixType> friend class SymmetricBlockMatrixBlockExpr;
399 
400  private:
402  friend class boost::serialization::access;
403  template<class ARCHIVE>
404  void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
405  // Fill in the lower triangle part of the matrix, so boost::serialization won't
406  // complain about uninitialized data with an input_stream_error exception
407  // http://www.boost.org/doc/libs/1_37_0/libs/serialization/doc/exceptions.html#stream_error
408  matrix_.triangularView<Eigen::Lower>() = matrix_.triangularView<Eigen::Upper>().transpose();
409  ar & BOOST_SERIALIZATION_NVP(matrix_);
410  ar & BOOST_SERIALIZATION_NVP(variableColOffsets_);
411  ar & BOOST_SERIALIZATION_NVP(blockStart_);
412  }
413  };
414 
416  class CholeskyFailed;
417 
418 }
Eigen::SelfAdjointView< constBlock, Eigen::Upper > selfadjointView() const
Get self adjoint view.
DenseIndex offset(DenseIndex block) const
Get an offset for a block index (in the active view).
Typedefs for easier changing of types.
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)
Eigen::Block< Matrix > Block
Block full()
Get the full matrix as a block.
Matrix matrix_
The full matrix.
Eigen::MatrixXd Matrix
Definition: base/Matrix.h:43
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.
constBlock full() const
Get the full matrix as a block.
vector< size_t > dimensions(L.begin(), L.end())
ptrdiff_t DenseIndex
The index type for Eigen objects.
Definition: types.h:67
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 invertInPlace()
Invert the entire active matrix in place.
void split(const G &g, const PredecessorMap< KEY > &tree, G &Ab1, G &Ab2)
Definition: graph-inl.h:255
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
Eigen::SelfAdjointView< constBlock, Eigen::Upper > diagonalBlock(DenseIndex J) const
Return the J&#39;th diagonal block as a self adjoint view.
m row(1)
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.
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.
void serialize(ARCHIVE &ar, const unsigned int)
Vector diagonal(DenseIndex J) const
Get the diagonal of the J&#39;th diagonal block.
void negate()
Negate the entire active matrix.
void updateDiagonalBlock(DenseIndex I, const XprType &xpr)
Increment the diagonal block by the values in xpr. Only reads the upper triangular part of xpr...
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 selfadjoint matrix from a triangular part of a dense matrix.
constBlock aboveDiagonalBlock(DenseIndex I, DenseIndex J) const
Get block above the diagonal (I, J).
static const Matrix I
Definition: lago.cpp:35
JacobiRotation< float > J
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. ...
Eigen::SelfAdjointView< Block, Eigen::Upper > selfadjointView()
Get self adjoint view.
bool choleskyPartial(Matrix &ABC, size_t nFrontal, size_t topleft)
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.
const mpreal dim(const mpreal &a, const mpreal &b, mp_rnd_t r=mpreal::get_default_rnd())
Definition: mpreal.h:2201
traits
Definition: chartTesting.h:28
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.
Expression of a fixed-size or dynamic-size block.
Definition: Block.h:103
DenseIndex nActualBlocks() const
Number of actual blocks in the full matrix.
void setZero()
Set the entire active matrix zero.
Eigen::Block< const Matrix > constBlock
DenseIndex cols() const
Column size.
Expression of a triangular part in a matrix.
Eigen::SelfAdjointView< constBlock, Eigen::Upper > selfadjointView(DenseIndex I, DenseIndex J) const
Return the square sub-matrix that contains blocks(i:j, i:j).
std::vector< T, typename internal::FastDefaultVectorAllocator< T >::type > FastVector
Definition: FastVector.h:34
m col(1)
SymmetricBlockMatrix()
Construct from an empty matrix (asserts that the matrix is empty)
void updateOffDiagonalBlock(DenseIndex I, DenseIndex J, const XprType &xpr)
Indicate Cholesky factorization failure.
DenseIndex getDim(DenseIndex block) const
Number of dimensions for variable on this diagonal block.
Eigen::SelfAdjointView< Block, Eigen::Upper > diagonalBlock(DenseIndex J)
Return the J&#39;th diagonal block as a self adjoint view.
DenseIndex nOffsets() const
Number of offsets in the full matrix.
Map< Matrix< T, Dynamic, Dynamic, ColMajor >, 0, OuterStride<> > matrix(T *data, int rows, int cols, int stride)
DenseIndex nBlocks() const
Block count.
SymmetricBlockMatrix(const CONTAINER &dimensions, bool appendOneDimension=false)
Construct from a container of the sizes of each block.
DenseIndex rows() const
Row size.
std::ptrdiff_t j
v setZero(3)


gtsam
Author(s):
autogenerated on Sat May 8 2021 02:45:07