g2o
Classes | Public Types | Public Member Functions | Protected Member Functions | Protected Attributes | List of all members
g2o::LinearSolverEigen< MatrixType > Class Template Reference

linear solver which uses the sparse Cholesky solver from Eigen More...

#include <linear_solver_eigen.h>

Inheritance diagram for g2o::LinearSolverEigen< MatrixType >:
Inheritance graph
[legend]
Collaboration diagram for g2o::LinearSolverEigen< MatrixType >:
Collaboration graph
[legend]

Classes

class  CholeskyDecomposition
 Sub-classing Eigen's SimplicialLDLT to perform ordering with a given ordering. More...
 

Public Types

typedef Eigen::SparseMatrix< double, Eigen::ColMajor > SparseMatrix
 
typedef Eigen::Triplet< double > Triplet
 
typedef Eigen::PermutationMatrix< Eigen::Dynamic, Eigen::Dynamic > PermutationMatrix
 

Public Member Functions

 LinearSolverEigen ()
 
virtual ~LinearSolverEigen ()
 
virtual bool init ()
 
bool solve (const SparseBlockMatrix< MatrixType > &A, double *x, double *b)
 
bool blockOrdering () const
 do the AMD ordering on the blocks or on the scalar matrix More...
 
void setBlockOrdering (bool blockOrdering)
 
virtual bool writeDebug () const
 write a debug dump of the system matrix if it is not SPD in solve More...
 
virtual void setWriteDebug (bool b)
 
- Public Member Functions inherited from g2o::LinearSolver< MatrixType >
 LinearSolver ()
 
virtual ~LinearSolver ()
 
virtual bool solveBlocks (double **&blocks, const SparseBlockMatrix< MatrixType > &A)
 
virtual bool solvePattern (SparseBlockMatrix< MatrixXD > &spinv, const std::vector< std::pair< int, int > > &blockIndices, const SparseBlockMatrix< MatrixType > &A)
 

Protected Member Functions

void computeSymbolicDecomposition (const SparseBlockMatrix< MatrixType > &A)
 
void fillSparseMatrix (const SparseBlockMatrix< MatrixType > &A, bool onlyValues)
 

Protected Attributes

bool _init
 
bool _blockOrdering
 
bool _writeDebug
 
SparseMatrix _sparseMatrix
 
CholeskyDecomposition _cholesky
 

Detailed Description

template<typename MatrixType>
class g2o::LinearSolverEigen< MatrixType >

linear solver which uses the sparse Cholesky solver from Eigen

Has no dependencies except Eigen. Hence, should compile almost everywhere without to much issues. Performance should be similar to CSparse, I guess.

Definition at line 49 of file linear_solver_eigen.h.

Member Typedef Documentation

template<typename MatrixType >
typedef Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic> g2o::LinearSolverEigen< MatrixType >::PermutationMatrix

Definition at line 54 of file linear_solver_eigen.h.

template<typename MatrixType >
typedef Eigen::SparseMatrix<double, Eigen::ColMajor> g2o::LinearSolverEigen< MatrixType >::SparseMatrix

Definition at line 52 of file linear_solver_eigen.h.

template<typename MatrixType >
typedef Eigen::Triplet<double> g2o::LinearSolverEigen< MatrixType >::Triplet

Definition at line 53 of file linear_solver_eigen.h.

Constructor & Destructor Documentation

template<typename MatrixType >
g2o::LinearSolverEigen< MatrixType >::LinearSolverEigen ( )
inline

Definition at line 76 of file linear_solver_eigen.h.

76  :
77  LinearSolver<MatrixType>(),
78  _init(true), _blockOrdering(false), _writeDebug(false)
79  {
80  }
template<typename MatrixType >
virtual g2o::LinearSolverEigen< MatrixType >::~LinearSolverEigen ( )
inlinevirtual

Definition at line 82 of file linear_solver_eigen.h.

83  {
84  }

Member Function Documentation

template<typename MatrixType >
bool g2o::LinearSolverEigen< MatrixType >::blockOrdering ( ) const
inline

do the AMD ordering on the blocks or on the scalar matrix

Definition at line 125 of file linear_solver_eigen.h.

References g2o::LinearSolverEigen< MatrixType >::_blockOrdering.

Referenced by g2o::LinearSolverEigen< MatrixType >::setBlockOrdering().

template<typename MatrixType >
void g2o::LinearSolverEigen< MatrixType >::computeSymbolicDecomposition ( const SparseBlockMatrix< MatrixType > &  A)
inlineprotected

compute the symbolic decompostion of the matrix only once. Since A has the same pattern in all the iterations, we only compute the fill-in reducing ordering once and re-use for all the following iterations.

Definition at line 145 of file linear_solver_eigen.h.

References g2o::LinearSolverEigen< MatrixType >::CholeskyDecomposition::analyzePatternWithPermutation(), g2o::SparseBlockMatrix< MatrixType >::blockCols(), g2o::SparseBlockMatrix< MatrixType >::colBaseOfBlock(), g2o::SparseBlockMatrix< MatrixType >::cols(), g2o::SparseBlockMatrix< MatrixType >::colsOfBlock(), g2o::get_monotonic_time(), g2o::G2OBatchStatistics::globalStats(), g2o::SparseBlockMatrix< MatrixType >::rows(), and g2o::G2OBatchStatistics::timeSymbolicDecomposition.

Referenced by g2o::LinearSolverEigen< MatrixType >::solve().

146  {
147  double t=get_monotonic_time();
148  if (! _blockOrdering) {
149  _cholesky.analyzePattern(_sparseMatrix);
150  } else {
151  // block ordering with the Eigen Interface
152  // This is really ugly currently, as it calls internal functions from Eigen
153  // and modifies the SparseMatrix class
154  Eigen::PermutationMatrix<Eigen::Dynamic,Eigen::Dynamic> blockP;
155  {
156  // prepare a block structure matrix for calling AMD
157  std::vector<Triplet> triplets;
158  for (size_t c = 0; c < A.blockCols().size(); ++c){
159  const typename SparseBlockMatrix<MatrixType>::IntBlockMap& column = A.blockCols()[c];
160  for (typename SparseBlockMatrix<MatrixType>::IntBlockMap::const_iterator it = column.begin(); it != column.end(); ++it) {
161  const int& r = it->first;
162  if (r > static_cast<int>(c)) // only upper triangle
163  break;
164  triplets.push_back(Triplet(r, c, 0.));
165  }
166  }
167 
168  // call the AMD ordering on the block matrix.
169  // Relies on Eigen's internal stuff, probably bad idea
170  SparseMatrix auxBlockMatrix(A.blockCols().size(), A.blockCols().size());
171  auxBlockMatrix.setFromTriplets(triplets.begin(), triplets.end());
172  typename CholeskyDecomposition::CholMatrixType C;
173  C = auxBlockMatrix.selfadjointView<Eigen::Upper>();
174  Eigen::internal::minimum_degree_ordering(C, blockP);
175  }
176 
177  int rows = A.rows();
178  assert(rows == A.cols() && "Matrix A is not square");
179 
180  // Adapt the block permutation to the scalar matrix
181  PermutationMatrix scalarP;
182  scalarP.resize(rows);
183  int scalarIdx = 0;
184  for (int i = 0; i < blockP.size(); ++i) {
185  const int& p = blockP.indices()(i);
186  int base = A.colBaseOfBlock(p);
187  int nCols = A.colsOfBlock(p);
188  for (int j = 0; j < nCols; ++j)
189  scalarP.indices()(scalarIdx++) = base++;
190  }
191  assert(scalarIdx == rows && "did not completely fill the permutation matrix");
192  // analyze with the scalar permutation
194 
195  }
196  G2OBatchStatistics* globalStats = G2OBatchStatistics::globalStats();
197  if (globalStats)
198  globalStats->timeSymbolicDecomposition = get_monotonic_time() - t;
199  }
double get_monotonic_time()
Definition: timeutil.cpp:113
Eigen::SparseMatrix< double, Eigen::ColMajor > SparseMatrix
Eigen::Triplet< double > Triplet
Eigen::PermutationMatrix< Eigen::Dynamic, Eigen::Dynamic > PermutationMatrix
static G2OBatchStatistics * globalStats()
Definition: batch_stats.h:73
std::map< int, SparseMatrixBlock * > IntBlockMap
CholeskyDecomposition _cholesky
void analyzePatternWithPermutation(SparseMatrix &a, const PermutationMatrix &permutation)
template<typename MatrixType >
void g2o::LinearSolverEigen< MatrixType >::fillSparseMatrix ( const SparseBlockMatrix< MatrixType > &  A,
bool  onlyValues 
)
inlineprotected

Definition at line 201 of file linear_solver_eigen.h.

References g2o::SparseBlockMatrix< MatrixType >::blockCols(), g2o::SparseBlockMatrix< MatrixType >::colBaseOfBlock(), g2o::SparseBlockMatrix< MatrixType >::fillCCS(), g2o::SparseBlockMatrix< MatrixType >::nonZeros(), and g2o::SparseBlockMatrix< MatrixType >::rowBaseOfBlock().

Referenced by g2o::LinearSolverEigen< MatrixType >::solve().

202  {
203  if (onlyValues) {
204  A.fillCCS(_sparseMatrix.valuePtr(), true);
205  } else {
206 
207  // create from triplet structure
208  std::vector<Triplet> triplets;
209  triplets.reserve(A.nonZeros());
210  for (size_t c = 0; c < A.blockCols().size(); ++c) {
211  int colBaseOfBlock = A.colBaseOfBlock(c);
212  const typename SparseBlockMatrix<MatrixType>::IntBlockMap& column = A.blockCols()[c];
213  for (typename SparseBlockMatrix<MatrixType>::IntBlockMap::const_iterator it = column.begin(); it != column.end(); ++it) {
214  int rowBaseOfBlock = A.rowBaseOfBlock(it->first);
215  const MatrixType& m = *(it->second);
216  for (int cc = 0; cc < m.cols(); ++cc) {
217  int aux_c = colBaseOfBlock + cc;
218  for (int rr = 0; rr < m.rows(); ++rr) {
219  int aux_r = rowBaseOfBlock + rr;
220  if (aux_r > aux_c)
221  break;
222  triplets.push_back(Triplet(aux_r, aux_c, m(rr, cc)));
223  }
224  }
225  }
226  }
227  _sparseMatrix.setFromTriplets(triplets.begin(), triplets.end());
228 
229  }
230  }
Eigen::Triplet< double > Triplet
std::map< int, SparseMatrixBlock * > IntBlockMap
template<typename MatrixType >
virtual bool g2o::LinearSolverEigen< MatrixType >::init ( )
inlinevirtual

init for operating on matrices with a different non-zero pattern like before

Implements g2o::LinearSolver< MatrixType >.

Definition at line 86 of file linear_solver_eigen.h.

References g2o::LinearSolverEigen< MatrixType >::_init.

87  {
88  _init = true;
89  return true;
90  }
template<typename MatrixType >
void g2o::LinearSolverEigen< MatrixType >::setBlockOrdering ( bool  blockOrdering)
inline

Definition at line 126 of file linear_solver_eigen.h.

References g2o::LinearSolverEigen< MatrixType >::_blockOrdering, and g2o::LinearSolverEigen< MatrixType >::blockOrdering().

bool blockOrdering() const
do the AMD ordering on the blocks or on the scalar matrix
template<typename MatrixType >
virtual void g2o::LinearSolverEigen< MatrixType >::setWriteDebug ( bool  b)
inlinevirtual
template<typename MatrixType >
bool g2o::LinearSolverEigen< MatrixType >::solve ( const SparseBlockMatrix< MatrixType > &  A,
double *  x,
double *  b 
)
inlinevirtual

Assumes that A is the same matrix for several calls. Among other assumptions, the non-zero pattern does not change! If the matrix changes call init() before. solve system Ax = b, x and b have to allocated beforehand!!

Implements g2o::LinearSolver< MatrixType >.

Definition at line 92 of file linear_solver_eigen.h.

References g2o::LinearSolverEigen< MatrixType >::_cholesky, g2o::LinearSolverEigen< MatrixType >::_init, g2o::LinearSolverEigen< MatrixType >::_sparseMatrix, g2o::LinearSolverEigen< MatrixType >::_writeDebug, g2o::G2OBatchStatistics::choleskyNNZ, g2o::SparseBlockMatrix< MatrixType >::cols(), g2o::LinearSolverEigen< MatrixType >::computeSymbolicDecomposition(), g2o::LinearSolverEigen< MatrixType >::fillSparseMatrix(), g2o::get_monotonic_time(), g2o::G2OBatchStatistics::globalStats(), g2o::SparseBlockMatrix< MatrixType >::rows(), g2o::G2OBatchStatistics::timeNumericDecomposition, and g2o::SparseBlockMatrix< MatrixType >::writeOctave().

93  {
94  if (_init)
95  _sparseMatrix.resize(A.rows(), A.cols());
97  if (_init) // compute the symbolic composition once
99  _init = false;
100 
101  double t=get_monotonic_time();
102  _cholesky.factorize(_sparseMatrix);
103  if (_cholesky.info() != Eigen::Success) { // the matrix is not positive definite
104  if (_writeDebug) {
105  std::cerr << "Cholesky failure, writing debug.txt (Hessian loadable by Octave)" << std::endl;
106  A.writeOctave("debug.txt");
107  }
108  return false;
109  }
110 
111  // Solving the system
112  VectorXD::MapType xx(x, _sparseMatrix.cols());
113  VectorXD::ConstMapType bb(b, _sparseMatrix.cols());
114  xx = _cholesky.solve(bb);
115  G2OBatchStatistics* globalStats = G2OBatchStatistics::globalStats();
116  if (globalStats) {
117  globalStats->timeNumericDecomposition = get_monotonic_time() - t;
118  globalStats->choleskyNNZ = _cholesky.matrixL().nestedExpression().nonZeros() + _sparseMatrix.cols(); // the elements of D
119  }
120 
121  return true;
122  }
double get_monotonic_time()
Definition: timeutil.cpp:113
void computeSymbolicDecomposition(const SparseBlockMatrix< MatrixType > &A)
static G2OBatchStatistics * globalStats()
Definition: batch_stats.h:73
void fillSparseMatrix(const SparseBlockMatrix< MatrixType > &A, bool onlyValues)
CholeskyDecomposition _cholesky
template<typename MatrixType >
virtual bool g2o::LinearSolverEigen< MatrixType >::writeDebug ( ) const
inlinevirtual

write a debug dump of the system matrix if it is not SPD in solve

Reimplemented from g2o::LinearSolver< MatrixType >.

Definition at line 129 of file linear_solver_eigen.h.

References g2o::LinearSolverEigen< MatrixType >::_writeDebug.

Member Data Documentation

template<typename MatrixType >
bool g2o::LinearSolverEigen< MatrixType >::_blockOrdering
protected
template<typename MatrixType >
CholeskyDecomposition g2o::LinearSolverEigen< MatrixType >::_cholesky
protected

Definition at line 137 of file linear_solver_eigen.h.

Referenced by g2o::LinearSolverEigen< MatrixType >::solve().

template<typename MatrixType >
bool g2o::LinearSolverEigen< MatrixType >::_init
protected
template<typename MatrixType >
SparseMatrix g2o::LinearSolverEigen< MatrixType >::_sparseMatrix
protected

Definition at line 136 of file linear_solver_eigen.h.

Referenced by g2o::LinearSolverEigen< MatrixType >::solve().

template<typename MatrixType >
bool g2o::LinearSolverEigen< MatrixType >::_writeDebug
protected

The documentation for this class was generated from the following file: