bool SparseOptimizerIncremental::computeCholeskyUpdate() { if (_cholmodFactor) { cholmod_free_factor(&_cholmodFactor, &_cholmodCommon); _cholmodFactor = 0; } const SparseBlockMatrix<MatrixXd>& A = _updateMat; size_t m = A.rows(); size_t n = A.cols(); if (_cholmodSparse->columnsAllocated < n) { //std::cerr << __PRETTY_FUNCTION__ << ": reallocating columns" << std::endl; _cholmodSparse->columnsAllocated = _cholmodSparse->columnsAllocated == 0 ? n : 2 * n; // pre-allocate more space if re-allocating delete[] (int*)_cholmodSparse->p; _cholmodSparse->p = new int[_cholmodSparse->columnsAllocated+1]; } size_t nzmax = A.nonZeros(); if (_cholmodSparse->nzmax < nzmax) { //std::cerr << __PRETTY_FUNCTION__ << ": reallocating row + values" << std::endl; _cholmodSparse->nzmax = _cholmodSparse->nzmax == 0 ? nzmax : 2 * nzmax; // pre-allocate more space if re-allocating delete[] (double*)_cholmodSparse->x; delete[] (int*)_cholmodSparse->i; _cholmodSparse->i = new int[_cholmodSparse->nzmax]; _cholmodSparse->x = new double[_cholmodSparse->nzmax]; } _cholmodSparse->ncol = n; _cholmodSparse->nrow = m; A.fillCCS((int*)_cholmodSparse->p, (int*)_cholmodSparse->i, (double*)_cholmodSparse->x, true); //writeCCSMatrix("updatesparse.txt", _cholmodSparse->nrow, _cholmodSparse->ncol, (int*)_cholmodSparse->p, (int*)_cholmodSparse->i, (double*)_cholmodSparse->x, true); _cholmodFactor = cholmod_analyze(_cholmodSparse, &_cholmodCommon); cholmod_factorize(_cholmodSparse, _cholmodFactor, &_cholmodCommon); #if 0 int* p = (int*)_cholmodFactor->Perm; for (int i = 0; i < (int)n; ++i) if (i != p[i]) cerr << "wrong permutation" << i << " -> " << p[i] << endl; #endif if (_cholmodCommon.status == CHOLMOD_NOT_POSDEF) { //std::cerr << "Cholesky failure, writing debug.txt (Hessian loadable by Octave)" << std::endl; //writeCCSMatrix("debug.txt", _cholmodSparse->nrow, _cholmodSparse->ncol, (int*)_cholmodSparse->p, (int*)_cholmodSparse->i, (double*)_cholmodSparse->x, true); return false; } // change to the specific format we need to have a pretty normal L int change_status = cholmod_change_factor(CHOLMOD_REAL, 1, 0, 1, 1, _cholmodFactor, &_cholmodCommon); if (! change_status) { return false; } return true; }
SEXP CHMfactor_to_sparse(SEXP x) { CHM_FR L = AS_CHM_FR(x), Lcp; CHM_SP Lm; R_CheckStack(); /* cholmod_factor_to_sparse changes its first argument. Make a copy */ Lcp = cholmod_copy_factor(L, &c); if (!(Lcp->is_ll)) if (!cholmod_change_factor(Lcp->xtype, 1, 0, 1, 1, Lcp, &c)) error(_("cholmod_change_factor failed with status %d"), c.status); Lm = cholmod_factor_to_sparse(Lcp, &c); cholmod_free_factor(&Lcp, &c); return chm_sparse_to_SEXP(Lm, 1/*do_free*/, -1/*uploT*/, 0/*Rkind*/, "N"/*non_unit*/, R_NilValue/*dimNames*/); }
/** * Update the numerical values in the factor f as A + mult * I, if A is * symmetric, otherwise AA' + mult * I * * @param f pointer to a CHM_FR object. f is updated upon return. * @param A pointer to a CHM_SP object, possibly symmetric * @param mult multiple of the identity to be added to A or AA' before * decomposing. * * \note: A and f must be compatible. There is no check on this * here. Incompatibility of A and f will cause the CHOLMOD functions * to take an error exit. * */ CHM_FR chm_factor_update(CHM_FR f, CHM_SP A, double mult) { int ll = f->is_ll; double mm[2] = {0, 0}; mm[0] = mult; // NB: Result depends if A is "dsC" or "dgC"; the latter case assumes we mean AA' !!! if (!cholmod_factorize_p(A, mm, (int*)NULL, 0 /*fsize*/, f, &c)) /* -> ./CHOLMOD/Cholesky/cholmod_factorize.c */ error(_("cholmod_factorize_p failed: status %d, minor %d of ncol %d"), c.status, f->minor, f->n); if (f->is_ll != ll) if(!cholmod_change_factor(f->xtype, ll, f->is_super, 1 /*to_packed*/, 1 /*to_monotonic*/, f, &c)) error(_("cholmod_change_factor failed")); return f; }