int main (void) { /* ====================================================================== */ /* input matrix A definition */ /* ====================================================================== */ int A [ALEN] = { 0, 1, 4, /* row indices of nonzeros in column 0 */ 2, 4, /* row indices of nonzeros in column 1 */ 0, 1, 2, 3, /* row indices of nonzeros in column 2 */ 1, 3} ; /* row indices of nonzeros in column 3 */ int p [ ] = { 0, /* column 0 is in A [0..2] */ 3, /* column 1 is in A [3..4] */ 5, /* column 2 is in A [5..8] */ 9, /* column 3 is in A [9..10] */ A_NNZ} ; /* number of nonzeros in A */ /* ====================================================================== */ /* input matrix B definition */ /* ====================================================================== */ int B [ ] = { /* Note: only strictly lower triangular part */ /* is included, since symamd ignores the */ /* diagonal and upper triangular part of B. */ 1, /* row indices of nonzeros in column 0 */ 2, 3, /* row indices of nonzeros in column 1 */ /* row indices of nonzeros in column 2 (none) */ 4 /* row indices of nonzeros in column 3 */ } ; /* row indices of nonzeros in column 4 (none) */ int q [ ] = { 0, /* column 0 is in B [0] */ 1, /* column 1 is in B [1..2] */ 3, /* column 2 is empty */ 3, /* column 3 is in B [3] */ 4, /* column 4 is empty */ B_NNZ} ; /* number of nonzeros in strictly lower B */ /* ====================================================================== */ /* other variable definitions */ /* ====================================================================== */ int perm [B_N+1] ; /* note the size is N+1 */ int stats [CCOLAMD_STATS] ; /* for ccolamd and csymamd output statistics */ int row, col, pp, length, ok ; /* ====================================================================== */ /* dump the input matrix A */ /* ====================================================================== */ printf ("ccolamd %d-by-%d input matrix:\n", A_NROW, A_NCOL) ; for (col = 0 ; col < A_NCOL ; col++) { length = p [col+1] - p [col] ; printf ("Column %d, with %d entries:\n", col, length) ; for (pp = p [col] ; pp < p [col+1] ; pp++) { row = A [pp] ; printf (" row %d\n", row) ; } } /* ====================================================================== */ /* order the matrix. Note that this destroys A and overwrites p */ /* ====================================================================== */ ok = ccolamd (A_NROW, A_NCOL, ALEN, A, p, (double *) NULL, stats, NULL) ; ccolamd_report (stats) ; if (!ok) { printf ("ccolamd error!\n") ; exit (1) ; } /* ====================================================================== */ /* print the column ordering */ /* ====================================================================== */ printf ("ccolamd column ordering:\n") ; printf ("1st column: %d\n", p [0]) ; printf ("2nd column: %d\n", p [1]) ; printf ("3rd column: %d\n", p [2]) ; printf ("4th column: %d\n", p [3]) ; /* ====================================================================== */ /* dump the strictly lower triangular part of symmetric input matrix B */ /* ====================================================================== */ printf ("\n\ncsymamd %d-by-%d input matrix:\n", B_N, B_N) ; printf ("Entries in strictly lower triangular part:\n") ; for (col = 0 ; col < B_N ; col++) { length = q [col+1] - q [col] ; printf ("Column %d, with %d entries:\n", col, length) ; for (pp = q [col] ; pp < q [col+1] ; pp++) { row = B [pp] ; printf (" row %d\n", row) ; } } /* ====================================================================== */ /* order the matrix B. Note that this does not modify B or q. */ /* ====================================================================== */ ok = csymamd (B_N, B, q, perm, (double *) NULL, stats, &calloc, &free, NULL, -1) ; csymamd_report (stats) ; if (!ok) { printf ("csymamd error!\n") ; exit (1) ; } /* ====================================================================== */ /* print the symmetric ordering */ /* ====================================================================== */ printf ("csymamd column ordering:\n") ; printf ("1st row/column: %d\n", perm [0]) ; printf ("2nd row/column: %d\n", perm [1]) ; printf ("3rd row/column: %d\n", perm [2]) ; printf ("4th row/column: %d\n", perm [3]) ; printf ("5th row/column: %d\n", perm [4]) ; return (0) ; }
static int ccolamd_interface ( cholmod_sparse *A, size_t alen, Int *Perm, Int *Cmember, Int *fset, Int fsize, cholmod_sparse *C, cholmod_common *Common ) { double knobs [CCOLAMD_KNOBS] ; Int *Cp = NULL ; Int ok, k, nrow, ncol, stats [CCOLAMD_STATS] ; nrow = A->nrow ; ncol = A->ncol ; /* ---------------------------------------------------------------------- */ /* copy (and transpose) the input matrix A into the ccolamd workspace */ /* ---------------------------------------------------------------------- */ /* C = A (:,f)', which also packs A if needed. */ /* workspace: Iwork (nrow if no fset; MAX (nrow,ncol) if fset non-NULL) */ ok = CHOLMOD(transpose_unsym) (A, 0, NULL, fset, fsize, C, Common) ; /* ---------------------------------------------------------------------- */ /* order the matrix (destroys the contents of C->i and C->p) */ /* ---------------------------------------------------------------------- */ /* get parameters */ #ifdef LONG ccolamd_l_set_defaults (knobs) ; #else ccolamd_set_defaults (knobs) ; #endif if (Common->current < 0 || Common->current >= CHOLMOD_MAXMETHODS) { /* this is the CHOLMOD default, not the CCOLAMD default */ knobs [CCOLAMD_DENSE_ROW] = -1 ; } else { /* get the knobs from the Common parameters */ knobs [CCOLAMD_DENSE_COL] =Common->method[Common->current].prune_dense ; knobs [CCOLAMD_DENSE_ROW] =Common->method[Common->current].prune_dense2; knobs [CCOLAMD_AGGRESSIVE]=Common->method[Common->current].aggressive ; knobs [CCOLAMD_LU] =Common->method[Common->current].order_for_lu; } if (ok) { #ifdef LONG ccolamd_l (ncol, nrow, alen, C->i, C->p, knobs, stats, Cmember) ; #else ccolamd (ncol, nrow, alen, C->i, C->p, knobs, stats, Cmember) ; #endif ok = stats [CCOLAMD_STATUS] ; ok = (ok == CCOLAMD_OK || ok == CCOLAMD_OK_BUT_JUMBLED) ; /* permutation returned in C->p, if the ordering succeeded */ Cp = C->p ; for (k = 0 ; k < nrow ; k++) { Perm [k] = Cp [k] ; } } return (ok) ; }
/* ************************************************************************* */ Ordering Ordering::ColamdConstrained(const VariableIndex& variableIndex, std::vector<int>& cmember) { gttic(Ordering_COLAMDConstrained); gttic(Prepare); const size_t nEntries = variableIndex.nEntries(), nFactors = variableIndex.nFactors(), nVars = variableIndex.size(); // Convert to compressed column major format colamd wants it in (== MATLAB format!) const size_t Alen = ccolamd_recommended((int) nEntries, (int) nFactors, (int) nVars); /* colamd arg 3: size of the array A */ vector<int> A = vector<int>(Alen); /* colamd arg 4: row indices of A, of size Alen */ vector<int> p = vector<int>(nVars + 1); /* colamd arg 5: column pointers of A, of size n_col+1 */ // Fill in input data for COLAMD p[0] = 0; int count = 0; vector<Key> keys(nVars); // Array to store the keys in the order we add them so we can retrieve them in permuted order size_t index = 0; for (auto key_factors: variableIndex) { // Arrange factor indices into COLAMD format const VariableIndex::Factors& column = key_factors.second; for(size_t factorIndex: column) { A[count++] = (int) factorIndex; // copy sparse column } p[index + 1] = count; // column j (base 1) goes from A[j-1] to A[j]-1 // Store key in array and increment index keys[index] = key_factors.first; ++index; } assert((size_t)count == variableIndex.nEntries()); //double* knobs = NULL; /* colamd arg 6: parameters (uses defaults if NULL) */ double knobs[CCOLAMD_KNOBS]; ccolamd_set_defaults(knobs); knobs[CCOLAMD_DENSE_ROW] = -1; knobs[CCOLAMD_DENSE_COL] = -1; int stats[CCOLAMD_STATS]; /* colamd arg 7: colamd output statistics and error codes */ gttoc(Prepare); // call colamd, result will be in p /* returns (1) if successful, (0) otherwise*/ if (nVars > 0) { gttic(ccolamd); int rv = ccolamd((int) nFactors, (int) nVars, (int) Alen, &A[0], &p[0], knobs, stats, &cmember[0]); if (rv != 1) throw runtime_error( (boost::format("ccolamd failed with return value %1%") % rv).str()); } // ccolamd_report(stats); // Convert elimination ordering in p to an ordering gttic(Fill_Ordering); Ordering result; result.resize(nVars); for (size_t j = 0; j < nVars; ++j) result[j] = keys[p[j]]; gttoc(Fill_Ordering); return result; }