NDEVR
API Documentation
linear_solver_eigen.h
1// g2o - General Graph Optimization
2// Copyright (C) 2011 R. Kuemmerle, G. Grisetti, W. Burgard
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright notice,
10// this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the distribution.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
18// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27#ifndef G2O_LINEAR_SOLVER_EIGEN_H
28#define G2O_LINEAR_SOLVER_EIGEN_H
29
30#include <Eigen/Sparse>
31#include <Eigen/SparseCholesky>
32
33#include "linear_solver.h"
34
35#include "eigen_types.h"
36
37namespace NDEVR {
38
45 template <typename MatrixType>
47 {
48 public:
50 typedef Eigen::SparseMatrix<g_type, Eigen::ColMajor> SparseMatrix;
51 typedef Eigen::Triplet<g_type> Triplet;
52 typedef Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic, int> PermutationMatrix;
56 class CholeskyDecomposition : public Eigen::SimplicialLDLT<SparseMatrix, Eigen::Upper>
57 {
58 public:
60 CholeskyDecomposition() : Eigen::SimplicialLDLT<SparseMatrix, Eigen::Upper>() {}
61 using Eigen::SimplicialLDLT< SparseMatrix, Eigen::Upper>::analyzePattern_preordered;
62
67 {
68 m_Pinv = permutation;
69 m_P = permutation.inverse();
70 int size = cast<int>(a.cols());
71 SparseMatrix ap(size, size);
72 ap.selfadjointView<Eigen::Upper>() = a.selfadjointView<UpLo>().twistedBy(m_P);
73 analyzePattern_preordered(ap, true);
74 }
75 };
76
77 public:
80 : _init(true)
81 , _blockOrdering(false)
82 {
83 }
84
86 {
87 }
88
91 virtual bool init()
92 {
93 _init = true;
94 return true;
95 }
96
102 bool solve(const SparseBlockMatrix<MatrixType>& A, g_type* x, g_type* b)
103 {
104 if (_init)
105 _sparseMatrix.resize(A.rows(), A.cols());
106 fillSparseMatrix(A, !_init);
107 if (_init) // compute the symbolic composition once
109 _init = false;
110
111 _cholesky.factorize(_sparseMatrix);
112 if (_cholesky.info() != Eigen::Success) { // the matrix is not positive definite
113 return false;
114 }
115
116 // Solving the system
117 Eigen::VectorX<g_type>::MapType xx(x, _sparseMatrix.cols());
118 Eigen::VectorX<g_type>::ConstMapType bb(b, _sparseMatrix.cols());
119 xx = _cholesky.solve(bb);
120
121 return true;
122 }
123
125 bool blockOrdering() const { return _blockOrdering; }
126 void setBlockOrdering(bool blockOrdering) { _blockOrdering = blockOrdering; }
127
128
129 protected:
130 bool _init;
134
142 {
143 if (!_blockOrdering) {
144 _cholesky.analyzePattern(_sparseMatrix);
145 }
146 else {
147 // block ordering with the Eigen Interface
148 // This is really ugly currently, as it calls internal functions from Eigen
149 // and modifies the SparseMatrix class
150 Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic> blockP;
151 {
152 // prepare a block structure matrix for calling AMD
153 std::vector<Triplet> triplets;
154 for (uint04 c = 0; c < A.blockCols().size(); ++c) {
155 const typename SparseBlockMatrix<MatrixType>::IntBlockMap& column = A.blockCols()[c];
156 for (typename SparseBlockMatrix<MatrixType>::IntBlockMap::const_iterator it = column.begin(); it != column.end(); ++it) {
157 const int& r = it->first;
158 if (r > static_cast<int>(c)) // only upper triangle
159 break;
160 triplets.push_back(Triplet(r, c, 0.));
161 }
162 }
163
164 // call the AMD ordering on the block matrix.
165 // Relies on Eigen's internal stuff, probably bad idea
166 SparseMatrix auxBlockMatrix(A.blockCols().size(), A.blockCols().size());
167 auxBlockMatrix.setFromTriplets(triplets.begin(), triplets.end());
168 typename CholeskyDecomposition::CholMatrixType C;
169 C = auxBlockMatrix.selfadjointView<Eigen::Upper>();
170 Eigen::internal::minimum_degree_ordering(C, blockP);
171 }
172
173 int rows = A.rows();
174 assert(rows == A.cols() && "Matrix A is not square");
175
176 // Adapt the block permutation to the scalar matrix
177 PermutationMatrix scalarP;
178 scalarP.resize(rows);
179 int scalarIdx = 0;
180 for (int i = 0; i < blockP.size(); ++i) {
181 const int& p = blockP.indices()(i);
182 int base = A.colBaseOfBlock(p);
183 int nCols = A.colsOfBlock(p);
184 for (int j = 0; j < nCols; ++j)
185 scalarP.indices()(scalarIdx++) = base++;
186 }
187 assert(scalarIdx == rows && "did not completely fill the permutation matrix");
188 // analyze with the scalar permutation
189 _cholesky.analyzePatternWithPermutation(_sparseMatrix, scalarP);
190
191 }
192 }
193
194 void fillSparseMatrix(const SparseBlockMatrix<MatrixType>& A, bool onlyValues)
195 {
196 if (onlyValues)
197 {
198 A.fillCCS(_sparseMatrix.valuePtr(), true);
199 }
200 else
201 {
202
203 // create from triplet structure
204 std::vector<Triplet> triplets;
205 triplets.reserve(A.nonZeros());
206 for (uint04 c = 0; c < A.blockCols().size(); ++c) {
207 int colBaseOfBlock = A.colBaseOfBlock(c);
208 const typename SparseBlockMatrix<MatrixType>::IntBlockMap& column = A.blockCols()[c];
209 for (typename SparseBlockMatrix<MatrixType>::IntBlockMap::const_iterator it = column.begin(); it != column.end(); ++it) {
210 int rowBaseOfBlock = A.rowBaseOfBlock(it->first);
211 const MatrixType& m = it->second;
212 for (int cc = 0; cc < m.cols(); ++cc) {
213 int aux_c = colBaseOfBlock + cc;
214 for (int rr = 0; rr < m.rows(); ++rr) {
215 int aux_r = rowBaseOfBlock + rr;
216 if (aux_r > aux_c)
217 break;
218 triplets.push_back(Triplet(aux_r, aux_c, m(rr, cc)));
219 }
220 }
221 }
222 }
223 _sparseMatrix.setFromTriplets(triplets.begin(), triplets.end());
224
225 }
226 }
227 };
228
229} // end namespace
230
231#endif
Sub-classing Eigen's SimplicialLDLT to perform ordering with a given ordering.
void analyzePatternWithPermutation(SparseMatrix &a, const PermutationMatrix &permutation)
Analyzes the sparsity pattern with a user-provided permutation.
linear solver which uses the sparse Cholesky solver from Eigen
Eigen::PermutationMatrix< Eigen::Dynamic, Eigen::Dynamic, int > PermutationMatrix
Permutation matrix type.
void computeSymbolicDecomposition(const SparseBlockMatrix< MatrixType > &A)
compute the symbolic decompostion of the matrix only once.
bool _init
Whether the symbolic decomposition needs to be (re)computed.
LinearSolverEigen()
Default constructor.
CholeskyDecomposition _cholesky
The Cholesky decomposition.
SparseMatrix _sparseMatrix
The Eigen sparse matrix representation.
Eigen::Triplet< g_type > Triplet
Triplet type for sparse matrix construction.
virtual bool init()
Resets the solver for a new factorization.
Eigen::SparseMatrix< g_type, Eigen::ColMajor > SparseMatrix
Column-major Eigen sparse matrix type.
SparseOptimizer optimizer
The sparse optimizer instance.
bool blockOrdering() const
do the AMD ordering on the blocks or on the scalar matrix
bool solve(const SparseBlockMatrix< MatrixType > &A, g_type *x, g_type *b)
Solves the linear system Ax = b using sparse Cholesky decomposition.
bool _blockOrdering
Whether to use block-level AMD ordering.
Sparse matrix which uses blocks.
Sparse optimizer that manages active vertices and edges for graph-based optimization.
Convenience typedefs for commonly used Eigen vector, matrix, and transform types.
The primary namespace for the NDEVR SDK.
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
constexpr t_to cast(const Angle< t_from > &value)
Casts an Angle from one backing type to another.
Definition Angle.h:408