27 #ifndef G2O_LINEAR_SOLVER_CHOLMOD 28 #define G2O_LINEAR_SOLVER_CHOLMOD 58 dtype = CHOLMOD_DOUBLE;
65 delete[] (
int*)p; p = 0;
66 delete[] (
double*)x; x = 0;
67 delete[] (
int*)i; i = 0;
75 template <
typename MatrixType>
83 _blockOrdering =
false;
86 cholmod_start(&_cholmodCommon);
89 _cholmodCommon.nmethods = 1 ;
90 _cholmodCommon.method[0].ordering = CHOLMOD_AMD;
93 _cholmodCommon.supernodal = CHOLMOD_AUTO;
98 delete _cholmodSparse;
99 if (_cholmodFactor != 0) {
100 cholmod_free_factor(&_cholmodFactor, &_cholmodCommon);
103 cholmod_finish(&_cholmodCommon);
108 if (_cholmodFactor != 0) {
109 cholmod_free_factor(&_cholmodFactor, &_cholmodCommon);
118 fillCholmodExt(A, _cholmodFactor != 0);
120 if (_cholmodFactor == 0) {
121 computeSymbolicDecomposition(A);
122 assert(_cholmodFactor != 0 &&
"Symbolic cholesky failed");
127 cholmod_dense bcholmod;
128 bcholmod.nrow = bcholmod.d = _cholmodSparse->nrow;
131 bcholmod.xtype = CHOLMOD_REAL;
132 bcholmod.dtype = CHOLMOD_DOUBLE;
134 cholmod_factorize(_cholmodSparse, _cholmodFactor, &_cholmodCommon);
135 if (_cholmodCommon.status == CHOLMOD_NOT_POSDEF) {
137 std::cerr <<
"Cholesky failure, writing debug.txt (Hessian loadable by Octave)" << std::endl;
138 saveMatrix(
"debug.txt");
143 cholmod_dense* xcholmod = cholmod_solve(CHOLMOD_A, _cholmodFactor, &bcholmod, &_cholmodCommon);
144 memcpy(x, xcholmod->x,
sizeof(
double) * bcholmod.nrow);
145 cholmod_free_dense(&xcholmod, &_cholmodCommon);
150 globalStats->
choleskyNNZ =
static_cast<size_t>(_cholmodCommon.method[0].lnz);
159 fillCholmodExt(A, _cholmodFactor != 0);
161 if (_cholmodFactor == 0) {
162 computeSymbolicDecomposition(A);
163 assert(_cholmodFactor &&
"Symbolic cholesky failed");
167 blocks=
new double*[A.
rows()];
168 double **block=blocks;
171 *block =
new double [dim];
176 cholmod_factorize(_cholmodSparse, _cholmodFactor, &_cholmodCommon);
177 if (_cholmodCommon.status == CHOLMOD_NOT_POSDEF)
181 int change_status = cholmod_change_factor(CHOLMOD_REAL, 1, 0, 1, 1, _cholmodFactor, &_cholmodCommon);
182 if (! change_status) {
185 assert(_cholmodFactor->is_ll && !_cholmodFactor->is_super && _cholmodFactor->is_monotonic &&
"Cholesky factor has wrong format");
188 int* p = (
int*)_cholmodFactor->Perm;
189 VectorXI pinv; pinv.resize(_cholmodSparse->ncol);
190 for (
size_t i = 0; i < _cholmodSparse->ncol; ++i)
195 mcc.
setCholeskyFactor(_cholmodSparse->ncol, (
int*)_cholmodFactor->p, (
int*)_cholmodFactor->i,
196 (
double*)_cholmodFactor->x, pinv.data());
201 globalStats->
choleskyNNZ =
static_cast<size_t>(_cholmodCommon.method[_cholmodCommon.selected].lnz);
210 fillCholmodExt(A, _cholmodFactor != 0);
212 if (_cholmodFactor == 0) {
213 computeSymbolicDecomposition(A);
214 assert(_cholmodFactor &&
"Symbolic cholesky failed");
217 cholmod_factorize(_cholmodSparse, _cholmodFactor, &_cholmodCommon);
218 if (_cholmodCommon.status == CHOLMOD_NOT_POSDEF)
222 int change_status = cholmod_change_factor(CHOLMOD_REAL, 1, 0, 1, 1, _cholmodFactor, &_cholmodCommon);
223 if (! change_status) {
226 assert(_cholmodFactor->is_ll && !_cholmodFactor->is_super && _cholmodFactor->is_monotonic &&
"Cholesky factor has wrong format");
229 int* p = (
int*)_cholmodFactor->Perm;
230 VectorXI pinv; pinv.resize(_cholmodSparse->ncol);
231 for (
size_t i = 0; i < _cholmodSparse->ncol; ++i)
236 mcc.
setCholeskyFactor(_cholmodSparse->ncol, (
int*)_cholmodFactor->p, (
int*)_cholmodFactor->i,
237 (
double*)_cholmodFactor->x, pinv.data());
242 globalStats->
choleskyNNZ =
static_cast<size_t>(_cholmodCommon.method[_cholmodCommon.selected].lnz);
257 writeCCSMatrix(fileName, _cholmodSparse->nrow, _cholmodSparse->ncol, (
int*)_cholmodSparse->p, (
int*)_cholmodSparse->i, (
double*)_cholmodSparse->x,
true);
274 if (! _blockOrdering) {
276 _cholmodCommon.nmethods = 1;
277 _cholmodCommon.method[0].ordering = CHOLMOD_AMD;
278 _cholmodFactor = cholmod_analyze(_cholmodSparse, &_cholmodCommon);
284 if (_blockPermutation.size() == 0)
285 _blockPermutation.resize(_matrixStructure.
n);
286 if (_blockPermutation.size() < _matrixStructure.
n)
287 _blockPermutation.resize(2*_matrixStructure.
n);
290 cholmod_sparse auxCholmodSparse;
291 auxCholmodSparse.nzmax = _matrixStructure.
nzMax();
292 auxCholmodSparse.nrow = auxCholmodSparse.ncol = _matrixStructure.
n;
293 auxCholmodSparse.p = _matrixStructure.
Ap;
294 auxCholmodSparse.i = _matrixStructure.
Aii;
295 auxCholmodSparse.nz = 0;
296 auxCholmodSparse.x = 0;
297 auxCholmodSparse.z = 0;
298 auxCholmodSparse.stype = 1;
299 auxCholmodSparse.xtype = CHOLMOD_PATTERN;
300 auxCholmodSparse.itype = CHOLMOD_INT;
301 auxCholmodSparse.dtype = CHOLMOD_DOUBLE;
302 auxCholmodSparse.sorted = 1;
303 auxCholmodSparse.packed = 1;
304 int amdStatus = cholmod_amd(&auxCholmodSparse, NULL, 0, _blockPermutation.data(), &_cholmodCommon);
310 if (_scalarPermutation.size() == 0)
311 _scalarPermutation.resize(_cholmodSparse->ncol);
312 if (_scalarPermutation.size() < (int)_cholmodSparse->ncol)
313 _scalarPermutation.resize(2*_cholmodSparse->ncol);
314 size_t scalarIdx = 0;
315 for (
int i = 0; i < _matrixStructure.
n; ++i) {
316 const int& p = _blockPermutation(i);
319 for (
int j = 0; j < nCols; ++j)
320 _scalarPermutation(scalarIdx++) = base++;
322 assert(scalarIdx == _cholmodSparse->ncol);
325 _cholmodCommon.nmethods = 1 ;
326 _cholmodCommon.method[0].ordering = CHOLMOD_GIVEN;
327 _cholmodFactor = cholmod_analyze_p(_cholmodSparse, _scalarPermutation.data(), NULL, 0, &_cholmodCommon);
343 this->initMatrixStructure(A);
346 assert(m > 0 && n > 0 &&
"Hessian has 0 rows/cols");
351 delete[] (
int*)_cholmodSparse->p;
356 if (_cholmodSparse->nzmax < nzmax) {
358 _cholmodSparse->nzmax = _cholmodSparse->nzmax == 0 ? nzmax : 2 * nzmax;
359 delete[] (
double*)_cholmodSparse->x;
360 delete[] (
int*)_cholmodSparse->i;
361 _cholmodSparse->i =
new int[_cholmodSparse->nzmax];
362 _cholmodSparse->x =
new double[_cholmodSparse->nzmax];
365 _cholmodSparse->ncol = n;
366 _cholmodSparse->nrow = m;
369 this->_ccsMatrix->fillCCS((
double*)_cholmodSparse->x,
true);
371 this->_ccsMatrix->fillCCS((
int*)_cholmodSparse->p, (
int*)_cholmodSparse->i, (
double*)_cholmodSparse->x,
true);
const std::vector< int > & rowBlockIndices() const
indices of the row blocks
double get_monotonic_time()
statistics about the optimization
int rowsOfBlock(int r) const
how many rows does the block at block-row r has?
virtual bool solvePattern(SparseBlockMatrix< MatrixXD > &spinv, const std::vector< std::pair< int, int > > &blockIndices, const SparseBlockMatrix< MatrixType > &A)
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.
bool blockOrdering() const
do the AMD ordering on the blocks or on the scalar matrix
int rows() const
rows of the matrix
representing the structure of a matrix in column compressed structure (only the upper triangular part...
bool writeCCSMatrix(const string &filename, int rows, int cols, const int *Ap, const int *Ai, const double *Ax, bool upperTriangleSymmetric)
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
Our extension of the CHOLMOD matrix struct.
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
MatrixStructure _matrixStructure
void computeSymbolicDecomposition(const SparseBlockMatrix< MatrixType > &A)
void computeCovariance(double **covBlocks, const std::vector< int > &blockIndices)
bool solve(const SparseBlockMatrix< MatrixType > &A, double *x, double *b)
static G2OBatchStatistics * globalStats()
bool solveBlocks(double **&blocks, const SparseBlockMatrix< MatrixType > &A)
double timeNumericDecomposition
numeric decomposition (0 if not done)
virtual void setWriteDebug(bool b)
cholmod_factor * _cholmodFactor
int colBaseOfBlock(int c) const
where does the col at block-col r starts?
basic solver for Ax = b which has to reimplemented for different linear algebra libraries ...
virtual ~LinearSolverCholmod()
int * Aii
row indices of A, of size nz = Ap [n]
virtual bool saveMatrix(const std::string &fileName)
void fillCholmodExt(const SparseBlockMatrix< MatrixType > &A, bool onlyValues)
Solver with faster iterating structure for the linear matrix.
void setBlockOrdering(bool blockOrdering)
Eigen::Matrix< int, Eigen::Dynamic, 1, Eigen::ColMajor > VectorXI
virtual bool writeDebug() const
write a debug dump of the system matrix if it is not SPD in solve
int nzMax() const
max number of non-zeros blocks
cholmod_common _cholmodCommon
Sparse matrix which uses blocks.
CholmodExt * _cholmodSparse
VectorXI _scalarPermutation