void get_colamd( const int m, /* number of rows in matrix A. */ const int n, /* number of columns in matrix A. */ const int nnz,/* number of nonzeros in matrix A. */ int *colptr, /* column pointer of size n+1 for matrix A. */ int *rowind, /* row indices of size nz for matrix A. */ int *perm_c /* out - the column permutation vector. */ ) { int Alen, *A, i, info, *p; double knobs[COLAMD_KNOBS]; int stats[COLAMD_STATS]; Alen = colamd_recommended(nnz, m, n); colamd_set_defaults(knobs); if (!(A = (int *) SUPERLU_MALLOC(Alen * sizeof(int))) ) ABORT("Malloc fails for A[]"); if (!(p = (int *) SUPERLU_MALLOC((n+1) * sizeof(int))) ) ABORT("Malloc fails for p[]"); for (i = 0; i <= n; ++i) p[i] = colptr[i]; for (i = 0; i < nnz; ++i) A[i] = rowind[i]; info = colamd(m, n, Alen, A, p, knobs, stats); if ( info == FALSE ) ABORT("COLAMD failed"); for (i = 0; i < n; ++i) perm_c[p[i]] = i; SUPERLU_FREE(A); SUPERLU_FREE(p); }
static void taucs_ccs_colamd(taucs_ccs_matrix * m, int **perm, int **invperm, char *which) { #ifndef TAUCS_CONFIG_COLAMD taucs_printf("taucs_ccs_colamd: COLAMD routines not linked.\n"); *perm = NULL; *invperm = NULL; return; #else double knobs[COLAMD_KNOBS]; int Alen; int *A; int *p; int *ip; int k, nnz; int i; if (m->flags & TAUCS_SYMMETRIC || m->flags & TAUCS_HERMITIAN) { taucs_printf("taucs_ccs_colamd: not applicable for symmetric or hermitian matrices\n"); return; } taucs_printf("taucs_ccs_colamd: starting\n"); *perm = NULL; *invperm = NULL; nnz = (m->colptr)[m->n]; p = (int *) taucs_malloc((m->n + 1) * sizeof(int)); ip = (int *) taucs_malloc((m->n + 1) * sizeof(int)); assert(p && ip); Alen = colamd_recommended(nnz, m->m, m->n); A = taucs_malloc(Alen * sizeof(int)); assert(A); assert(A); colamd_set_defaults(knobs); for (i = 0; i <= m->n; i++) p[i] = (m->colptr)[i]; for (k = 0; k < nnz; k++) A[k] = (m->rowind)[k]; taucs_printf("oocsp_ccs_colamd: calling colamd matrix is %dx%d, nnz=%d\n", m->m, m->n, nnz); if (!colamd(m->m, m->n, Alen, A, p, knobs)) { taucs_printf("oocsp_ccs_colamd: colamd failed\n"); taucs_free(A); taucs_free(p); return; } taucs_printf("oocsp_ccs_colamd: colamd returned\n"); taucs_free(A); *perm = p; *invperm = ip; for (i = 0; i < m->n; i++) (*invperm)[(*perm)[i]] = i; #endif }
int __WINAPI getMDO(lprec *lp, MYBOOL *usedpos, int *colorder, int *size, MYBOOL symmetric) { int error = FALSE; int nrows = lp->rows+1, ncols = colorder[0]; int i, j, kk, n; int *col_end, *row_map = NULL; int Bnz, Blen, *Brows = NULL; int stats[COLAMD_STATS]; double knobs[COLAMD_KNOBS]; /* Tally the non-zero counts of the unused columns/rows of the basis matrix and store corresponding "net" starting positions */ allocINT(lp, &col_end, ncols+1, FALSE); n = prepareMDO(lp, usedpos, colorder, col_end, NULL); Bnz = col_end[ncols]; /* Check that we have unused basic columns, otherwise skip analysis */ if(ncols == 0 || Bnz == 0) goto Transfer; /* Get net number of rows and fill mapper */ allocINT(lp, &row_map, nrows, FALSE); nrows = 0; for(i = 0; i <= lp->rows; i++) { row_map[i] = i-nrows; /* Increment eliminated row counter if necessary */ if(!includeMDO(usedpos, i)) nrows++; } nrows = lp->rows+1 - nrows; /* Store row indeces of non-zero values in the basic columns */ Blen = colamd_recommended(Bnz, nrows, ncols); allocINT(lp, &Brows, Blen, FALSE); prepareMDO(lp, usedpos, colorder, Brows, row_map); #ifdef Paranoia verifyMDO(lp, col_end, Brows, nrows, ncols); #endif /* Compute the MDO */ #if 1 colamd_set_defaults(knobs); knobs [COLAMD_DENSE_ROW] = 0.2+0.2 ; /* default changed for UMFPACK */ knobs [COLAMD_DENSE_COL] = knobs [COLAMD_DENSE_ROW]; if(symmetric && (nrows == ncols)) { MEMCOPY(colorder, Brows, ncols + 1); error = !symamd(nrows, colorder, col_end, Brows, knobs, stats, mdo_calloc, mdo_free); } else error = !colamd(nrows, ncols, Blen, Brows, col_end, knobs, stats); #else if(symmetric && (nrows == ncols)) { MEMCOPY(colorder, Brows, ncols + 1); error = !symamd(nrows, colorder, col_end, Brows, knobs, stats, mdo_calloc, mdo_free); } else error = !colamd(nrows, ncols, Blen, Brows, col_end, (double *) NULL, stats); #endif /* Transfer the estimated optimal ordering, adjusting for index offsets */ Transfer: if(error) error = stats[COLAMD_STATUS]; else { MEMCOPY(Brows, colorder, ncols + 1); for(j = 0; j < ncols; j++) { kk = col_end[j]; n = Brows[kk+1]; colorder[j+1] = n; } } /* Free temporary vectors */ FREE(col_end); if(row_map != NULL) FREE(row_map); if(Brows != NULL) FREE(Brows); if(size != NULL) *size = ncols; return( error ); }
int CHOLMOD(colamd) ( /* ---- input ---- */ cholmod_sparse *A, /* matrix to order */ Int *fset, /* subset of 0:(A->ncol)-1 */ size_t fsize, /* size of fset */ int postorder, /* if TRUE, follow with a coletree postorder */ /* ---- output --- */ Int *Perm, /* size A->nrow, output permutation */ /* --------------- */ cholmod_common *Common ) { double knobs [COLAMD_KNOBS] ; cholmod_sparse *C ; Int *NewPerm, *Parent, *Post, *Work2n ; Int k, nrow, ncol ; size_t s, alen ; int ok = TRUE ; /* ---------------------------------------------------------------------- */ /* check inputs */ /* ---------------------------------------------------------------------- */ RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; RETURN_IF_NULL (Perm, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; if (A->stype != 0) { ERROR (CHOLMOD_INVALID, "matrix must be unsymmetric") ; return (FALSE) ; } Common->status = CHOLMOD_OK ; /* ---------------------------------------------------------------------- */ /* get inputs */ /* ---------------------------------------------------------------------- */ nrow = A->nrow ; ncol = A->ncol ; /* ---------------------------------------------------------------------- */ /* allocate workspace */ /* ---------------------------------------------------------------------- */ /* Note: this is less than the space used in cholmod_analyze, so if * cholmod_colamd is being called by that routine, no space will be * allocated. */ /* s = 4*nrow + ncol */ s = CHOLMOD(mult_size_t) (nrow, 4, &ok) ; s = CHOLMOD(add_size_t) (s, ncol, &ok) ; #ifdef LONG alen = colamd_l_recommended (A->nzmax, ncol, nrow) ; colamd_l_set_defaults (knobs) ; #else alen = colamd_recommended (A->nzmax, ncol, nrow) ; colamd_set_defaults (knobs) ; #endif if (!ok || alen == 0) { ERROR (CHOLMOD_TOO_LARGE, "matrix invalid or too large") ; return (FALSE) ; } CHOLMOD(allocate_work) (0, s, 0, Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; } /* ---------------------------------------------------------------------- */ /* allocate COLAMD workspace */ /* ---------------------------------------------------------------------- */ /* colamd_printf is only available in colamd v2.4 or later */ colamd_printf = Common->print_function ; C = CHOLMOD(allocate_sparse) (ncol, nrow, alen, TRUE, TRUE, 0, CHOLMOD_PATTERN, Common) ; /* ---------------------------------------------------------------------- */ /* copy (and transpose) the input matrix A into the colamd workspace */ /* ---------------------------------------------------------------------- */ /* C = A (:,f)', which also packs A if needed. */ /* workspace: Iwork (nrow if no fset; MAX (nrow,ncol) if fset) */ 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 */ if (Common->current < 0 || Common->current >= CHOLMOD_MAXMETHODS) { /* this is the CHOLMOD default, not the COLAMD default */ knobs [COLAMD_DENSE_ROW] = -1 ; } else { /* get the knobs from the Common parameters */ knobs [COLAMD_DENSE_COL] = Common->method[Common->current].prune_dense ; knobs [COLAMD_DENSE_ROW] = Common->method[Common->current].prune_dense2; knobs [COLAMD_AGGRESSIVE] = Common->method[Common->current].aggressive ; } if (ok) { Int *Cp ; Int stats [COLAMD_STATS] ; Cp = C->p ; #ifdef LONG colamd_l (ncol, nrow, alen, C->i, Cp, knobs, stats) ; #else colamd (ncol, nrow, alen, C->i, Cp, knobs, stats) ; #endif ok = stats [COLAMD_STATUS] ; ok = (ok == COLAMD_OK || ok == COLAMD_OK_BUT_JUMBLED) ; /* permutation returned in C->p, if the ordering succeeded */ for (k = 0 ; k < nrow ; k++) { Perm [k] = Cp [k] ; } } CHOLMOD(free_sparse) (&C, Common) ; /* ---------------------------------------------------------------------- */ /* column etree postordering */ /* ---------------------------------------------------------------------- */ if (postorder) { /* use the last 2*n space in Iwork for Parent and Post */ Work2n = Common->Iwork ; Work2n += 2*((size_t) nrow) + ncol ; Parent = Work2n ; /* size nrow (i/i/l) */ Post = Work2n + nrow ; /* size nrow (i/i/l) */ /* workspace: Iwork (2*nrow+ncol), Flag (nrow), Head (nrow+1) */ ok = ok && CHOLMOD(analyze_ordering) (A, CHOLMOD_COLAMD, Perm, fset, fsize, Parent, Post, NULL, NULL, NULL, Common) ; /* combine the colamd permutation with its postordering */ if (ok) { NewPerm = Common->Iwork ; /* size nrow (i/i/l) */ for (k = 0 ; k < nrow ; k++) { NewPerm [k] = Perm [Post [k]] ; } for (k = 0 ; k < nrow ; k++) { Perm [k] = NewPerm [k] ; } } } return (ok) ; }