Пример #1
0
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);
}
Пример #2
0
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
}
Пример #3
0
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 );
}
Пример #4
0
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) ;
}