27 #ifndef G2O_LINEAR_SOLVERCSPARSE_H 28 #define G2O_LINEAR_SOLVERCSPARSE_H 70 template <
typename MatrixType>
77 _symbolicDecomposition = 0;
78 _csWorkspaceSize = -1;
82 _blockOrdering =
true;
88 if (_symbolicDecomposition) {
89 cs_sfree(_symbolicDecomposition);
90 _symbolicDecomposition = 0;
92 delete[] _csWorkspace; _csWorkspace = 0;
93 delete[] _csIntWorkspace; _csIntWorkspace = 0;
99 if (_symbolicDecomposition) {
100 cs_sfree(_symbolicDecomposition);
101 _symbolicDecomposition = 0;
108 fillCSparse(A, _symbolicDecomposition != 0);
110 if (_symbolicDecomposition == 0) {
111 computeSymbolicDecomposition(A);
114 if (_csWorkspaceSize < _ccsA->n) {
115 _csWorkspaceSize = 2 * _ccsA->n;
116 delete[] _csWorkspace;
117 _csWorkspace =
new double[_csWorkspaceSize];
118 delete[] _csIntWorkspace;
119 _csIntWorkspace =
new int[2*_csWorkspaceSize];
125 memcpy(x, b, _ccsA->n *
sizeof(
double));
129 std::cerr <<
"Cholesky failure, writing debug.txt (Hessian loadable by Octave)" << std::endl;
138 globalStats->
choleskyNNZ =
static_cast<size_t>(_symbolicDecomposition->lnz);
145 fillCSparse(A, _symbolicDecomposition != 0);
147 if (_symbolicDecomposition == 0) {
148 computeSymbolicDecomposition(A);
149 assert(_symbolicDecomposition &&
"Symbolic cholesky failed");
152 if (_csWorkspaceSize < _ccsA->n) {
153 _csWorkspaceSize = 2 * _ccsA->n;
154 delete[] _csWorkspace;
155 _csWorkspace =
new double[_csWorkspaceSize];
156 delete[] _csIntWorkspace;
157 _csIntWorkspace =
new int[2*_csWorkspaceSize];
161 blocks=
new double*[A.
rows()];
162 double **block=blocks;
165 *block =
new double [dim];
172 if (numericCholesky) {
174 mcc.
setCholeskyFactor(_ccsA->n, numericCholesky->L->p, numericCholesky->L->i, numericCholesky->L->x, _symbolicDecomposition->pinv);
176 cs_nfree(numericCholesky);
179 std::cerr <<
"inverse fail (numeric decomposition)" << std::endl;
184 globalStats->
choleskyNNZ =
static_cast<size_t>(_symbolicDecomposition->lnz);
191 fillCSparse(A, _symbolicDecomposition != 0);
193 if (_symbolicDecomposition == 0) {
194 computeSymbolicDecomposition(A);
195 assert(_symbolicDecomposition &&
"Symbolic cholesky failed");
198 if (_csWorkspaceSize < _ccsA->n) {
199 _csWorkspaceSize = 2 * _ccsA->n;
200 delete[] _csWorkspace;
201 _csWorkspace =
new double[_csWorkspaceSize];
202 delete[] _csIntWorkspace;
203 _csIntWorkspace =
new int[2*_csWorkspaceSize];
209 if (numericCholesky) {
211 mcc.
setCholeskyFactor(_ccsA->n, numericCholesky->L->p, numericCholesky->L->i, numericCholesky->L->x, _symbolicDecomposition->pinv);
213 cs_nfree(numericCholesky);
216 std::cerr <<
"inverse fail (numeric decomposition)" << std::endl;
221 globalStats->
choleskyNNZ =
static_cast<size_t>(_symbolicDecomposition->lnz);
249 if (! _blockOrdering) {
250 _symbolicDecomposition = cs_schol (1, _ccsA) ;
256 auxBlock.nzmax = _matrixStructure.
nzMax();
257 auxBlock.m = auxBlock.n = _matrixStructure.
n;
258 auxBlock.p = _matrixStructure.
Ap;
259 auxBlock.i = _matrixStructure.
Aii;
264 const int& n = _ccsA->n;
265 int* P = cs_amd(1, &auxBlock);
268 if (_scalarPermutation.size() == 0)
269 _scalarPermutation.resize(n);
270 if (_scalarPermutation.size() < n)
271 _scalarPermutation.resize(2*n);
272 size_t scalarIdx = 0;
273 for (
int i = 0; i < _matrixStructure.
n; ++i) {
277 for (
int j = 0; j < nCols; ++j)
278 _scalarPermutation(scalarIdx++) = base++;
280 assert((
int)scalarIdx == n);
284 _symbolicDecomposition = (css*) cs_calloc(1,
sizeof(css));
285 _symbolicDecomposition->pinv = cs_pinv(_scalarPermutation.data(), n);
286 cs* C = cs_symperm(_ccsA, _symbolicDecomposition->pinv, 0);
287 _symbolicDecomposition->parent = cs_etree(C, 0);
288 int* post = cs_post(_symbolicDecomposition->parent, n);
289 int* c = cs_counts(C, _symbolicDecomposition->parent, post, 0);
292 _symbolicDecomposition->cp = (
int*) cs_malloc(n+1,
sizeof(
int));
293 _symbolicDecomposition->unz = _symbolicDecomposition->lnz = cs_cumsum(_symbolicDecomposition->cp, c, n);
295 if (_symbolicDecomposition->lnz < 0) {
296 cs_sfree(_symbolicDecomposition);
297 _symbolicDecomposition = 0;
313 this->initMatrixStructure(A);
316 assert(m > 0 && n > 0 &&
"Hessian has 0 rows/cols");
326 if (_ccsA->nzmax < nzmax) {
327 _ccsA->nzmax = _ccsA->nzmax == 0 ? nzmax : 2 * nzmax;
330 _ccsA->i =
new int[_ccsA->nzmax];
331 _ccsA->x =
new double[_ccsA->nzmax];
338 this->_ccsMatrix->fillCCS(_ccsA->x,
true);
340 int nz = this->_ccsMatrix->fillCCS(_ccsA->p, _ccsA->i, _ccsA->x,
true); (void) nz;
341 assert(nz <= _ccsA->nzmax);
const std::vector< int > & rowBlockIndices() const
indices of the row blocks
double get_monotonic_time()
virtual void setWriteDebug(bool b)
statistics about the optimization
int rowsOfBlock(int r) const
how many rows does the block at block-row r has?
void setCholeskyFactor(int n, int *Lp, int *Li, double *Lx, int *permInv)
int cols() const
columns of the matrix
int * Ap
column pointers for A, of size n+1
computing the marginal covariance given a cholesky factor (lower triangle of the factor) ...
int n
A is m-by-n. n must be >= 0.
int rows() const
rows of the matrix
bool blockOrdering() const
do the AMD ordering on the blocks or on the scalar matrix
representing the structure of a matrix in column compressed structure (only the upper triangular part...
void fillCSparse(const SparseBlockMatrix< MatrixType > &A, bool onlyValues)
int colsOfBlock(int c) const
how many cols does the block at block-col c has?
size_t nonZeros() const
number of non-zero elements
void fillBlockStructure(MatrixStructure &ms) const
exports the non zero blocks in the structure matrix ms
size_t choleskyNNZ
number of non-zeros in the cholesky factor
utility functions for handling time related stuff
int cs_cholsolsymb(const cs *A, double *b, const css *S, double *x, int *work)
void setBlockOrdering(bool blockOrdering)
#define G2O_SOLVER_CSPARSE_API
VectorXI _scalarPermutation
linear solver which uses CSparse
Our C++ version of the csparse struct.
void computeCovariance(double **covBlocks, const std::vector< int > &blockIndices)
static G2OBatchStatistics * globalStats()
double timeNumericDecomposition
numeric decomposition (0 if not done)
int colBaseOfBlock(int c) const
where does the col at block-col r starts?
int * Aii
row indices of A, of size nz = Ap [n]
bool solve(const SparseBlockMatrix< MatrixType > &A, double *x, double *b)
virtual ~LinearSolverCSparse()
void computeSymbolicDecomposition(const SparseBlockMatrix< MatrixType > &A)
Solver with faster iterating structure for the linear matrix.
css * _symbolicDecomposition
MatrixStructure _matrixStructure
Eigen::Matrix< int, Eigen::Dynamic, 1, Eigen::ColMajor > VectorXI
double timeSymbolicDecomposition
symbolic decomposition (0 if not done)
csn * cs_chol_workspace(const cs *A, const css *S, int *cin, double *xin)
virtual bool solvePattern(SparseBlockMatrix< MatrixXD > &spinv, const std::vector< std::pair< int, int > > &blockIndices, const SparseBlockMatrix< MatrixType > &A)
int nzMax() const
max number of non-zeros blocks
virtual bool writeDebug() const
write a debug dump of the system matrix if it is not SPD in solve
bool solveBlocks(double **&blocks, const SparseBlockMatrix< MatrixType > &A)
bool writeCs2Octave(const char *filename, const cs *A, bool upperTriangular)
Sparse matrix which uses blocks.