void evaluateSPQRSolver(const Eigen::MatrixXd& A, const Eigen::VectorXd& b, const Eigen::VectorXd& x) { cholmod_common cholmod; cholmod_l_start(&cholmod); cholmod_sparse* A_CS = aslam::calibration::eigenDenseToCholmodSparseCopy(A, &cholmod); cholmod_dense b_CD; aslam::calibration::eigenDenseToCholmodDenseView(b, &b_CD); Eigen::VectorXd x_est; // const double before = aslam::calibration::Timestamp::now(); SuiteSparseQR_factorization<double>* factor = SuiteSparseQR_factorize<double>( SPQR_ORDERING_BEST, SPQR_DEFAULT_TOL, A_CS, &cholmod); cholmod_dense* Qtb = SuiteSparseQR_qmult<double>(SPQR_QTX, factor, &b_CD, &cholmod); cholmod_dense* x_est_cd = SuiteSparseQR_solve<double>(SPQR_RETX_EQUALS_B, factor, Qtb, &cholmod); cholmod_l_free_dense(&Qtb, &cholmod); aslam::calibration::cholmodDenseToEigenDenseCopy(x_est_cd, x_est); cholmod_l_free_dense(&x_est_cd, &cholmod); // std::cout << "estimated rank: " << factor->rank << std::endl; // std::cout << "estimated rank deficiency: " << A.cols() - factor->rank // << std::endl; SuiteSparseQR_free(&factor, &cholmod); // const double after = aslam::calibration::Timestamp::now(); // const double error = (b - A * x_est).norm(); // std::cout << std::fixed << std::setprecision(18) << "error: " << error // << " est_diff: " << (x - x_est).norm() << " time: " << after - before // << std::endl; cholmod_l_free_sparse(&A_CS, &cholmod); cholmod_l_finish(&cholmod); }
void Cholmod<I>::free(spqr_factor* factor) { if (factor) SuiteSparseQR_free(&factor, &_cholmod); }
int main (int argc, char **argv) { cholmod_common Common, *cc ; cholmod_sparse *A ; cholmod_dense *X, *B ; int mtype ; Long m, n ; // start CHOLMOD cc = &Common ; cholmod_l_start (cc) ; // A = mread (stdin) ; read in the sparse matrix A A = (cholmod_sparse *) cholmod_l_read_matrix (stdin, 1, &mtype, cc) ; if (mtype != CHOLMOD_SPARSE) { printf ("input matrix must be sparse\n") ; exit (1) ; } // [m n] = size (A) ; m = A->nrow ; n = A->ncol ; printf ("Matrix %6ld-by-%-6ld nnz: %6ld\n", m, n, cholmod_l_nnz (A, cc)) ; // B = ones (m,1), a dense right-hand-side of the same type as A B = cholmod_l_ones (m, 1, A->xtype, cc) ; // X = A\B ; with default ordering and default column 2-norm tolerance if (A->xtype == CHOLMOD_REAL) { // A, X, and B are all real X = SuiteSparseQR <double> (SPQR_ORDERING_DEFAULT, SPQR_DEFAULT_TOL, A, B, cc) ; } else { // A, X, and B are all complex X = SuiteSparseQR < std::complex<double> > (SPQR_ORDERING_DEFAULT, SPQR_DEFAULT_TOL, A, B, cc) ; } check_residual (A, X, B, cc) ; cholmod_l_free_dense (&X, cc) ; // ------------------------------------------------------------------------- // factorizing once then solving twice with different right-hand-sides // ------------------------------------------------------------------------- // Just the real case. Complex case is essentially identical if (A->xtype == CHOLMOD_REAL) { SuiteSparseQR_factorization <double> *QR ; cholmod_dense *Y ; Long i ; double *Bx ; // factorize once QR = SuiteSparseQR_factorize <double> (SPQR_ORDERING_DEFAULT, SPQR_DEFAULT_TOL, A, cc) ; // solve Ax=b, using the same B as before // Y = Q'*B Y = SuiteSparseQR_qmult (SPQR_QTX, QR, B, cc) ; // X = R\(E*Y) X = SuiteSparseQR_solve (SPQR_RETX_EQUALS_B, QR, Y, cc) ; // check the results check_residual (A, X, B, cc) ; // free X and Y cholmod_l_free_dense (&Y, cc) ; cholmod_l_free_dense (&X, cc) ; // repeat with a different B Bx = (double *) (B->x) ; for (i = 0 ; i < m ; i++) { Bx [i] = i ; } // Y = Q'*B Y = SuiteSparseQR_qmult (SPQR_QTX, QR, B, cc) ; // X = R\(E*Y) X = SuiteSparseQR_solve (SPQR_RETX_EQUALS_B, QR, Y, cc) ; // check the results check_residual (A, X, B, cc) ; // free X and Y cholmod_l_free_dense (&Y, cc) ; cholmod_l_free_dense (&X, cc) ; // free QR SuiteSparseQR_free (&QR, cc) ; } // ------------------------------------------------------------------------- // free everything that remains // ------------------------------------------------------------------------- cholmod_l_free_sparse (&A, cc) ; cholmod_l_free_dense (&B, cc) ; cholmod_l_finish (cc) ; return (0) ; }