Example #1
0
static void taucs_ccs_genmmd(taucs_ccs_matrix * m, int **perm, int **invperm, char *which)
{
#ifndef TAUCS_CONFIG_GENMMD
	taucs_printf("taucs_ccs_genmmd: GENMMD routines not linked.\n");
	*perm = NULL;
	*invperm = NULL;
	return;
#else
	int n, maxint, delta, nofsub;
	int *xadj;
	int *adjncy;
	int *invp;
	int *prm;
	int *dhead;
	int *qsize;
	int *llist;
	int *marker;

	int *len;
	int *next;

	int nnz, i, j, ip;

	/*
	 * taucs_printf("taucs_ccs_genmmd: starting (%s)\n",which);
	 */

	if (!(m->flags & TAUCS_SYMMETRIC) && !(m->flags & TAUCS_HERMITIAN)) {
		taucs_printf("taucs_ccs_genmmd: GENMMD ordering only works on symmetric matrices.\n");
		*perm = NULL;
		*invperm = NULL;
		return;
	}
	/*
	 * this routine may actually work on UPPER as well 
	 */
	if (!(m->flags & TAUCS_LOWER)) {
		taucs_printf("taucs_ccs_genmmd: the lower part of the matrix must be represented.\n");
		*perm = NULL;
		*invperm = NULL;
		return;
	}

	*perm = NULL;
	*invperm = NULL;

	n = m->n;
	nnz = (m->colptr)[n];

	/*
	 * I copied the value of delta and the size of 
	 */
	/*
	 * from SuperLU. Sivan 
	 */

	delta = 1;					       /* DELTA is a parameter to allow the choice of nodes whose degree <= 
							        * min-degree + DELTA. */
	delta = 1;					       /* DELTA is a parameter to allow the choice of nodes whose degree <= 
							        * min-degree + DELTA. */
	/*
	 * maxint = 2147483648;
	 *//*
	 * 2**31-1, for 32-bit only! 
	 */
	maxint = 32000;

	assert(sizeof(int) == 4);
	maxint = 2147483647;				       /* 2**31-1, for 32-bit only! */

	xadj = (int *) taucs_malloc((n + 1) * sizeof(int));
	adjncy = (int *) taucs_malloc((2 * nnz - n) * sizeof(int));
	invp = (int *) taucs_malloc((n + 1) * sizeof(int));
	prm = (int *) taucs_malloc(n * sizeof(int));
	dhead = (int *) taucs_malloc((n + 1) * sizeof(int));
	qsize = (int *) taucs_malloc((n + 1) * sizeof(int));
	llist = (int *) taucs_malloc(n * sizeof(int));
	marker = (int *) taucs_malloc(n * sizeof(int));

	if (!xadj || !adjncy || !invp || !prm || !dhead || !qsize || !llist || !marker) {
		taucs_free(xadj);
		taucs_free(adjncy);
		taucs_free(invp);
		taucs_free(prm);
		taucs_free(dhead);
		taucs_free(qsize);
		taucs_free(llist);
		taucs_free(marker);
		return;
	}

	len = dhead;					       /* we reuse space */
	next = qsize;					       /* we reuse space */

	for (i = 0; i < n; i++)
		len[i] = 0;

	for (j = 0; j < n; j++) {
		for (ip = (m->colptr)[j]; ip < (m->colptr)[j + 1]; ip++) {
			/*
			 * i = (m->rowind)[ip] - (m->indshift);
			 */
			i = (m->rowind)[ip];
			if (i != j) {
				len[i]++;
				len[j]++;
			} else {
				/*
				 * len[i] ++;
				 */
			}
		}
	}

	xadj[0] = 1;
	for (i = 1; i <= n; i++)
		xadj[i] = xadj[i - 1] + len[i - 1];

	/*
	 * for (i=0; i<=n; i++) printf("xadj[%d]=%d\n",i,xadj[i]);
	 */

	/*
	 * use degree as a temporary 
	 */

	for (i = 0; i < n; i++)
		next[i] = xadj[i] - 1;

	for (j = 0; j < n; j++) {
		for (ip = (m->colptr)[j]; ip < (m->colptr)[j + 1]; ip++) {
			/*
			 * i = (m->rowind)[ip] - (m->indshift);
			 */
			i = (m->rowind)[ip];
			assert(next[i] < 2 * nnz - n);
			assert(next[j] < 2 * nnz - n);
			if (i != j) {
				adjncy[next[i]] = j + 1;
				adjncy[next[j]] = i + 1;
				next[i]++;
				next[j]++;
			} else {
				/*
				 * adjncy[ next[i] ] = j+1; next[i] ++; 
				 */
			}
		}
	}

	/*
	 * for (j=0; j<n; j++) { qsort(adjncy + (xadj[j] - 1), xadj[j+1] - xadj[j], sizeof(int), compare_ints); printf("+++ %d:
	 * ",j+1); for (ip=xadj[j]-1; ip<xadj[j+1]-1;ip++) printf("%d ",adjncy[ip]); printf("\n"); } 
	 */

	/*
	 * taucs_printf("taucs_ccs_genmmd: calling genmmd, matrix is %dx%d, nnz=%d\n", n,n,nnz); 
	 */

	genmmd_(&n, xadj, adjncy, invp, prm, &delta, dhead, qsize, llist, marker, &maxint, &nofsub);

	/*
	 * taucs_printf("taucs_ccs_genmmd: genmmd returned.\n");
	 */

	/*
	 * { FILE* f; f=fopen("p.ijv","w"); for (i=0; i<n; i++) fprintf(f,"%d %d\n",prm[i],invp[i]); fclose(f); } 
	 */

	taucs_free(marker);
	taucs_free(llist);
	taucs_free(qsize);
	taucs_free(dhead);
	taucs_free(xadj);
	taucs_free(adjncy);

	for (i = 0; i < n; i++)
		prm[i]--;
	for (i = 0; i < n; i++)
		invp[prm[i]] = i;

	*perm = prm;
	*invperm = invp;
#endif
}
Example #2
0
void
get_perm_c(int ispec, SuperMatrix *A, int *perm_c)
/*
 * Purpose
 * =======
 *
 * GET_PERM_C obtains a permutation matrix Pc, by applying the multiple
 * minimum degree ordering code by Joseph Liu to matrix A'*A or A+A'.
 * or using approximate minimum degree column ordering by Davis et. al.
 * The LU factorization of A*Pc tends to have less fill than the LU 
 * factorization of A.
 *
 * Arguments
 * =========
 *
 * ispec   (input) int
 *         Specifies the type of column ordering to reduce fill:
 *         = 1: minimum degree on the structure of A^T * A
 *         = 2: minimum degree on the structure of A^T + A
 *         = 3: approximate minimum degree for unsymmetric matrices
 *         If ispec == 0, the natural ordering (i.e., Pc = I) is returned.
 * 
 * A       (input) SuperMatrix*
 *         Matrix A in A*X=B, of dimension (A->nrow, A->ncol). The number
 *         of the linear equations is A->nrow. Currently, the type of A 
 *         can be: Stype = NC; Dtype = _D; Mtype = GE. In the future,
 *         more general A can be handled.
 *
 * perm_c  (output) int*
 *	   Column permutation vector of size A->ncol, which defines the 
 *         permutation matrix Pc; perm_c[i] = j means column i of A is 
 *         in position j in A*Pc.
 *
 */
{
    NCformat *Astore = A->Store;
    int m, n, bnz = 0, *b_colptr, i;
    int delta, maxint, nofsub, *invp;
    int *b_rowind, *dhead, *qsize, *llist, *marker;
    double t, SuperLU_timer_();
    
    m = A->nrow;
    n = A->ncol;

    t = SuperLU_timer_();
    switch ( ispec ) {
        case 0: /* Natural ordering */
	      for (i = 0; i < n; ++i) perm_c[i] = i;
#if ( PRNTlevel>=1 )
	      printf("Use natural column ordering.\n");
#endif
	      return;
        case 1: /* Minimum degree ordering on A'*A */
	      getata(m, n, Astore->nnz, Astore->colptr, Astore->rowind,
		     &bnz, &b_colptr, &b_rowind);
#if ( PRNTlevel>=1 )
	      printf("Use minimum degree ordering on A'*A.\n");
#endif
	      t = SuperLU_timer_() - t;
	      /*printf("Form A'*A time = %8.3f\n", t);*/
	      break;
        case 2: /* Minimum degree ordering on A'+A */
	      if ( m != n ) ABORT("Matrix is not square");
	      at_plus_a(n, Astore->nnz, Astore->colptr, Astore->rowind,
			&bnz, &b_colptr, &b_rowind);
#if ( PRNTlevel>=1 )
	      printf("Use minimum degree ordering on A'+A.\n");
#endif
	      t = SuperLU_timer_() - t;
	      /*printf("Form A'+A time = %8.3f\n", t);*/
	      break;
        case 3: /* Approximate minimum degree column ordering. */
	      get_colamd(m, n, Astore->nnz, Astore->colptr, Astore->rowind,
			 perm_c);
#if ( PRNTlevel>=1 )
	      printf(".. Use approximate minimum degree column ordering.\n");
#endif
	      return; 
        default:
	      ABORT("Invalid ISPEC");
    }

    if ( bnz != 0 ) {
	t = SuperLU_timer_();

	/* Initialize and allocate storage for GENMMD. */
	delta = 1; /* DELTA is a parameter to allow the choice of nodes
		      whose degree <= min-degree + DELTA. */
	maxint = 2147483647; /* 2**31 - 1 */
	invp = (int *) SUPERLU_MALLOC((n+delta)*sizeof(int));
	if ( !invp ) ABORT("SUPERLU_MALLOC fails for invp.");
	dhead = (int *) SUPERLU_MALLOC((n+delta)*sizeof(int));
	if ( !dhead ) ABORT("SUPERLU_MALLOC fails for dhead.");
	qsize = (int *) SUPERLU_MALLOC((n+delta)*sizeof(int));
	if ( !qsize ) ABORT("SUPERLU_MALLOC fails for qsize.");
	llist = (int *) SUPERLU_MALLOC(n*sizeof(int));
	if ( !llist ) ABORT("SUPERLU_MALLOC fails for llist.");
	marker = (int *) SUPERLU_MALLOC(n*sizeof(int));
	if ( !marker ) ABORT("SUPERLU_MALLOC fails for marker.");

	/* Transform adjacency list into 1-based indexing required by GENMMD.*/
	for (i = 0; i <= n; ++i) ++b_colptr[i];
	for (i = 0; i < bnz; ++i) ++b_rowind[i];
	
	genmmd_(&n, b_colptr, b_rowind, perm_c, invp, &delta, dhead, 
		qsize, llist, marker, &maxint, &nofsub);

	/* Transform perm_c into 0-based indexing. */
	for (i = 0; i < n; ++i) --perm_c[i];

	SUPERLU_FREE(invp);
	SUPERLU_FREE(dhead);
	SUPERLU_FREE(qsize);
	SUPERLU_FREE(llist);
	SUPERLU_FREE(marker);
	SUPERLU_FREE(b_rowind);

	t = SuperLU_timer_() - t;
	/*  printf("call GENMMD time = %8.3f\n", t);*/

    } else { /* Empty adjacency structure */
	for (i = 0; i < n; ++i) perm_c[i] = i;
    }

    SUPERLU_FREE(b_colptr);
}