void symamd_ord(int n, int A_ptr[], int A_ind[], int P_per[]) { /* approximate minimum degree ordering (SYMAMD) */ int k, ok; int stats[COLAMD_STATS]; /* make all indices 0-based */ for (k = 1; k < A_ptr[n+1]; k++) A_ind[k]--; for (k = 1; k <= n+1; k++) A_ptr[k]--; /* call the ordering routine */ ok = symamd(n, &A_ind[1], &A_ptr[1], &P_per[1], NULL, stats, allocate, release); #if 0 symamd_report(stats); #endif xassert(ok); /* restore 1-based indices */ for (k = 1; k <= n+1; k++) A_ptr[k]++; for (k = 1; k < A_ptr[n+1]; k++) A_ind[k]++; /* patch up permutation matrix */ memset(&P_per[n+1], 0, n * sizeof(int)); for (k = 1; k <= n; k++) { P_per[k]++; xassert(1 <= P_per[k] && P_per[k] <= n); xassert(P_per[n+P_per[k]] == 0); P_per[n+P_per[k]] = k; } return; }
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 ); }