cholmod_dense* Cholmod<I>::solve(cholmod_sparse* A, spqr_factor* L, cholmod_dense* b, double tol, bool norm, double normTol) { cholmod_sparse* qrJ = cholmod_l_transpose(A, 1, &_cholmod); cholmod_dense* scaling = NULL; if (norm) { scaling = CholmodIndexTraits<index_t>::allocate_dense(qrJ->ncol, 1, qrJ->ncol, CHOLMOD_REAL, &_cholmod); double* values = reinterpret_cast<double*>(scaling->x); for (size_t i = 0; i < qrJ->ncol; ++i) { const double normCol = colNorm(qrJ, i); if (normCol < normTol) values[i] = 0.0; else values[i] = 1.0 / normCol; } SM_ASSERT_TRUE(Exception, scale(scaling, CHOLMOD_COL, qrJ), "Scaling failed"); } cholmod_dense* res = NULL; if (factorize(qrJ, L, tol)) { cholmod_dense* qrY = SuiteSparseQR_qmult(SPQR_QTX, L, b, &_cholmod); res = SuiteSparseQR_solve(SPQR_RETX_EQUALS_B, L, qrY, &_cholmod); CholmodIndexTraits<index_t>::free_dense(&qrY, &_cholmod); } if (norm) { const double* svalues = reinterpret_cast<const double*>(scaling->x); double* rvalues = reinterpret_cast<double*>(res->x); for (size_t i = 0; i < qrJ->ncol; ++i) rvalues[i] = svalues[i] * rvalues[i]; CholmodIndexTraits<index_t>::free_dense(&scaling, &_cholmod); } CholmodIndexTraits<index_t>::free_sparse(&qrJ, &_cholmod); return res; }
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) ; }