示例#1
0
 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;
 }
示例#2
0
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) ;
}