Esempio n. 1
0
void amdtest (cholmod_sparse *A)
{
    double Control [AMD_CONTROL], Info [AMD_INFO], alpha ;
    Int *P, *Cp, *Ci, *Sp, *Si, *Bp, *Bi, *Ep, *Ei, *Fp, *Fi,
	*Len, *Nv, *Next, *Head, *Elen, *Deg, *Wi, *W, *Flag ;
    cholmod_sparse *C, *B, *S, *E, *F ;
    Int i, j, n, nrow, ncol, ok, cnz, bnz, p, trial, sorted ;

    /* ---------------------------------------------------------------------- */
    /* get inputs */
    /* ---------------------------------------------------------------------- */

    printf ("\nAMD test\n") ;

    if (A == NULL)
    {
	return ;
    }

    if (A->stype)
    {
	B = CHOLMOD(copy) (A, 0, 0, cm) ;
    }
    else
    {
	B = CHOLMOD(aat) (A, NULL, 0, 0, cm) ;
    }

    if (A->nrow != A->ncol)
    {
	F = CHOLMOD(copy_sparse) (B, cm) ;
	OK (F->nrow == F->ncol) ;
	CHOLMOD(sort) (F, cm) ;
    }
    else
    {
	/* A is square and unsymmetric, and may have entries in A+A' that
	 * are not in A */
	F = CHOLMOD(copy_sparse) (A, cm) ;
	CHOLMOD(sort) (F, cm) ;
    }

    C = CHOLMOD(copy_sparse) (B, cm) ;

    nrow = C->nrow ;
    ncol = C->ncol ;
    n = nrow ;
    OK (nrow == ncol) ;

    Cp = C->p ;
    Ci = C->i ;

    Bp = B->p ;
    Bi = B->i ;

    /* ---------------------------------------------------------------------- */
    /* S = sorted form of B, using AMD_preprocess */
    /* ---------------------------------------------------------------------- */

    cnz = CHOLMOD(nnz) (C, cm) ;
    S = CHOLMOD(allocate_sparse) (n, n, cnz, TRUE, TRUE, 0, CHOLMOD_PATTERN,
	    cm);
    Sp = S->p ;
    Si = S->i ;

    W = CHOLMOD(malloc) (n, sizeof (Int), cm) ;
    Flag = CHOLMOD(malloc) (n, sizeof (Int), cm) ;
    AMD_preprocess (n, Bp, Bi, Sp, Si, W, Flag) ;

    /* ---------------------------------------------------------------------- */
    /* allocate workspace for amd */
    /* ---------------------------------------------------------------------- */

    P = CHOLMOD(malloc) (n+1, sizeof (Int), cm) ;

    Len  = CHOLMOD(malloc) (n, sizeof (Int), cm) ;
    Nv   = CHOLMOD(malloc) (n, sizeof (Int), cm) ;
    Next = CHOLMOD(malloc) (n, sizeof (Int), cm) ;
    Head = CHOLMOD(malloc) (n+1, sizeof (Int), cm) ;
    Elen = CHOLMOD(malloc) (n, sizeof (Int), cm) ;
    Deg  = CHOLMOD(malloc) (n, sizeof (Int), cm) ;
    Wi   = CHOLMOD(malloc) (n, sizeof (Int), cm) ;

    /* ---------------------------------------------------------------------- */

    for (sorted = 0 ; sorted <= 1 ; sorted++)
    {

	if (sorted) CHOLMOD(sort) (C, cm) ;

	Cp = C->p ;
	Ci = C->i ;

	/* ------------------------------------------------------------------ */
	/* order C with AMD_order */
	/* ------------------------------------------------------------------ */

	AMD_defaults (Control) ;
	AMD_defaults (NULL) ;
	AMD_control (Control) ;
	AMD_control (NULL) ;
	AMD_info (NULL) ;

	ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
	printf ("amd return value: "ID"\n", ok) ;
	AMD_info (Info) ;
	OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	OK (CHOLMOD(print_perm) (P, n, n, "AMD permutation", cm)) ;

	/* no dense rows/cols */
	alpha = Control [AMD_DENSE] ;
	Control [AMD_DENSE] = -1 ;
	AMD_control (Control) ;
	ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
	printf ("amd return value: "ID"\n", ok) ;
	AMD_info (Info) ;
	OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	OK (CHOLMOD(print_perm) (P, n, n, "AMD permutation (alpha=-1)", cm)) ;

	/* many dense rows/cols */
	Control [AMD_DENSE] = 0 ;
	AMD_control (Control) ;
	ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
	printf ("amd return value: "ID"\n", ok) ;
	AMD_info (Info) ;
	OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	OK (CHOLMOD(print_perm) (P, n, n, "AMD permutation (alpha=0)", cm)) ;
	Control [AMD_DENSE] = alpha ;

	/* no aggressive absorption */
	Control [AMD_AGGRESSIVE] = FALSE ;
	AMD_control (Control) ;
	ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
	printf ("amd return value: "ID"\n", ok) ;
	AMD_info (Info) ;
	OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	OK (CHOLMOD(print_perm) (P, n, n, "AMD permutation (no agg) ", cm)) ;
	Control [AMD_AGGRESSIVE] = TRUE ;

	/* ------------------------------------------------------------------ */
	/* order F with AMD_order */
	/* ------------------------------------------------------------------ */

	Fp = F->p ;
	Fi = F->i ;
	ok = AMD_order (n, Fp, Fi, P, Control, Info) ;
	printf ("amd return value: "ID"\n", ok) ;
	AMD_info (Info) ;
	OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	OK (CHOLMOD(print_perm) (P, n, n, "F: AMD permutation", cm)) ;

	/* ------------------------------------------------------------------ */
	/* order S with AMD_order */
	/* ------------------------------------------------------------------ */

	ok = AMD_order (n, Sp, Si, P, Control, Info) ;
	printf ("amd return value: "ID"\n", ok) ;
	AMD_info (Info) ;
	OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	OK (CHOLMOD(print_perm) (P, n, n, "AMD permutation", cm)) ;

	/* ------------------------------------------------------------------ */
	/* order E with AMD_2, which destroys its contents */
	/* ------------------------------------------------------------------ */

	E = CHOLMOD(copy) (B, 0, -1, cm) ;	/* remove diagonal entries */
	bnz = CHOLMOD(nnz) (E, cm) ;

	/* add the bare minimum extra space to E */
	ok = CHOLMOD(reallocate_sparse) (bnz + n, E, cm) ;
	OK (ok) ;
	Ep = E->p ;
	Ei = E->i ;

	for (j = 0 ; j < n ; j++)
	{
	    Len [j] = Ep [j+1] - Ep [j] ;
	}

	printf ("calling AMD_2:\n") ;
	if (n > 0)
	{
	    AMD_2 (n, Ep, Ei, Len, E->nzmax, Ep [n], Nv, Next, P, Head, Elen,
		Deg, Wi, Control, Info) ;
	    AMD_info (Info) ;
	    OK (CHOLMOD(print_perm) (P, n, n, "AMD2 permutation", cm)) ;
	}

	/* ------------------------------------------------------------------ */
	/* error tests */
	/* ------------------------------------------------------------------ */

	ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
	OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	ok = AMD_order (-1, Cp, Ci, P, Control, Info) ;
	OK (ok == AMD_INVALID);
	ok = AMD_order (0, Cp, Ci, P, Control, Info) ;
	OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	ok = AMD_order (n, NULL, Ci, P, Control, Info) ;
	OK (ok == AMD_INVALID);
	ok = AMD_order (n, Cp, NULL, P, Control, Info) ;
	OK (ok == AMD_INVALID);
	ok = AMD_order (n, Cp, Ci, NULL, Control, Info) ;
	OK (ok == AMD_INVALID);

	if (n > 0)
	{
	    printf ("AMD error tests:\n") ;

	    p = Cp [n] ;
	    Cp [n] = -1 ;
	    ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
	    OK (ok == AMD_INVALID) ;

	    if (Size_max/2 == Int_max)
	    {
		Cp [n] = Int_max ;
		ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
		printf ("AMD status is "ID"\n", ok) ;
		OK (ok == AMD_OUT_OF_MEMORY) ;
	    }

	    Cp [n] = p ;
	    ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
	    OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	    if (Cp [n] > 0)
	    {
		printf ("Mangle column zero:\n") ;
		i = Ci [0] ;
		Ci [0] = -1 ;
		ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
		AMD_info (Info) ;
		OK (ok == AMD_INVALID) ;
		Ci [0] = i ;
	    }
	}

	ok = AMD_valid (n, n, Sp, Si) ;
	OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	ok = AMD_valid (-1, n, Sp, Si) ;	    OK (ok == AMD_INVALID) ;
	ok = AMD_valid (n, -1, Sp, Si) ;	    OK (ok == AMD_INVALID) ;
	ok = AMD_valid (n, n, NULL, Si) ;	    OK (ok == AMD_INVALID) ;
	ok = AMD_valid (n, n, Sp, NULL) ;	    OK (ok == AMD_INVALID) ;

	if (n > 0 && Sp [n] > 0)
	{

	    p = Sp [n] ;
	    Sp [n] = -1 ;
	    ok = AMD_valid (n, n, Sp, Si) ; OK (ok == AMD_INVALID) ;
	    Sp [n] = p ;

	    p = Sp [0] ;
	    Sp [0] = -1 ;
	    ok = AMD_valid (n, n, Sp, Si) ; OK (ok == AMD_INVALID) ;
	    Sp [0] = p ;

	    p = Sp [1] ;
	    Sp [1] = -1 ;
	    ok = AMD_valid (n, n, Sp, Si) ; OK (ok == AMD_INVALID) ;
	    Sp [1] = p ;

	    i = Si [0] ;
	    Si [0] = -1 ;
	    ok = AMD_valid (n, n, Sp, Si) ; OK (ok == AMD_INVALID) ;
	    Si [0] = i ;

	}

	ok = AMD_valid (n, n, Sp, Si) ;
	OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	AMD_preprocess (n, Bp, Bi, Sp, Si, W, Flag) ;
	ok = AMD_valid (n, n, Sp, Si) ;
	OK (ok == AMD_OK) ;

	if (n > 0 && Bp [n] > 0)
	{

	    p = Bp [n] ;
	    Bp [n] = -1 ;
	    ok = AMD_valid (n, n, Bp, Bi) ;	    OK (ok == AMD_INVALID) ;
	    Bp [n] = p ;


	    p = Bp [1] ;
	    Bp [1] = -1 ;
	    ok = AMD_valid (n, n, Bp, Bi) ;	    OK (ok == AMD_INVALID) ;
	    Bp [1] = p ;

	    i = Bi [0] ;
	    Bi [0] = -1 ;
	    ok = AMD_valid (n, n, Bp, Bi) ;	    OK (ok == AMD_INVALID) ;
	    Bi [0] = i ;
	}

	AMD_preprocess (n, Bp, Bi, Sp, Si, W, Flag) ;

	Info [AMD_STATUS] = 777 ;
	AMD_info (Info) ;

	/* ------------------------------------------------------------------ */
	/* memory tests */
	/* ------------------------------------------------------------------ */

	if (n > 0)
	{
	    amd_malloc = cm->malloc_memory ;
	    amd_free = cm->free_memory ;
	    ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
	    OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;

	    test_memory_handler ( ) ;
	    amd_malloc = cm->malloc_memory ;
	    amd_free = cm->free_memory ;
	    for (trial = 0 ; trial < 6 ; trial++)
	    {
		my_tries = trial ;
		printf ("AMD memory trial "ID"\n", trial) ;
		ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
		AMD_info (Info) ;
		OK (ok == AMD_OUT_OF_MEMORY
		    || (sorted ? (ok == AMD_OK) : (ok >= AMD_OK))) ;
	    }
	    normal_memory_handler ( ) ;
	    OK (CHOLMOD(print_perm) (P, n, n, "AMD2 permutation", cm)) ;

	    amd_malloc = cm->malloc_memory ;
	    amd_free = cm->free_memory ;
	}

	CHOLMOD(free_sparse) (&E, cm) ;
    }

    /* ---------------------------------------------------------------------- */
    /* free everything */
    /* ---------------------------------------------------------------------- */

    CHOLMOD(free) (n, sizeof (Int), Len,  cm) ;
    CHOLMOD(free) (n, sizeof (Int), Nv,   cm) ;
    CHOLMOD(free) (n, sizeof (Int), Next, cm) ;
    CHOLMOD(free) (n+1, sizeof (Int), Head, cm) ;
    CHOLMOD(free) (n, sizeof (Int), Elen, cm) ;
    CHOLMOD(free) (n, sizeof (Int), Deg,  cm) ;
    CHOLMOD(free) (n, sizeof (Int), Wi,   cm) ;

    CHOLMOD(free) (n+1, sizeof (Int), P, cm) ;

    CHOLMOD(free) (n, sizeof (Int), W, cm) ;
    CHOLMOD(free) (n, sizeof (Int), Flag, cm) ;

    CHOLMOD(free_sparse) (&S, cm) ;
    CHOLMOD(free_sparse) (&B, cm) ;
    CHOLMOD(free_sparse) (&C, cm) ;
    CHOLMOD(free_sparse) (&F, cm) ;
}
Esempio n. 2
0
GLOBAL Int AMD_order
(
    Int n,
    const Int Ap [ ],
    const Int Ai [ ],
    Int P [ ],
    double Control [ ],
    double Info [ ]
)
{
    Int *Len, *S, nz, i, *Pinv, info, status, *Rp, *Ri, *Cp, *Ci, ok ;
    size_t nzaat, slen ;
    double mem = 0 ;

#ifndef NDEBUG
    AMD_debug_init ("amd") ;
#endif

    /* clear the Info array, if it exists */
    info = Info != (double *) NULL ;
    if (info)
    {
	for (i = 0 ; i < AMD_INFO ; i++)
	{
	    Info [i] = EMPTY ;
	}
	Info [AMD_N] = n ;
	Info [AMD_STATUS] = AMD_OK ;
    }

    /* make sure inputs exist and n is >= 0 */
    if (Ai == (Int *) NULL || Ap == (Int *) NULL || P == (Int *) NULL || n < 0)
    {
	if (info) Info [AMD_STATUS] = AMD_INVALID ;
	return (AMD_INVALID) ;	    /* arguments are invalid */
    }

    if (n == 0)
    {
	return (AMD_OK) ;	    /* n is 0 so there's nothing to do */
    }

    nz = Ap [n] ;
    if (info)
    {
	Info [AMD_NZ] = nz ;
    }
    if (nz < 0)
    {
	if (info) Info [AMD_STATUS] = AMD_INVALID ;
	return (AMD_INVALID) ;
    }

    /* check if n or nz will cause size_t overflow */
    if (((size_t) n) >= SIZE_T_MAX / sizeof (Int)
     || ((size_t) nz) >= SIZE_T_MAX / sizeof (Int))
    {
	if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;
	return (AMD_OUT_OF_MEMORY) ;	    /* problem too large */
    }

    /* check the input matrix:	AMD_OK, AMD_INVALID, or AMD_OK_BUT_JUMBLED */
    status = AMD_valid (n, n, Ap, Ai) ;

    if (status == AMD_INVALID)
    {
	if (info) Info [AMD_STATUS] = AMD_INVALID ;
	return (AMD_INVALID) ;	    /* matrix is invalid */
    }

    /* allocate two size-n integer workspaces */
    Len = (Int*)amd_malloc (n * sizeof (Int)) ;
    Pinv = (Int*)amd_malloc (n * sizeof (Int)) ;
    mem += n ;
    mem += n ;
    if (!Len || !Pinv)
    {
	/* :: out of memory :: */
	amd_free (Len) ;
	amd_free (Pinv) ;
	if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;
	return (AMD_OUT_OF_MEMORY) ;
    }

    if (status == AMD_OK_BUT_JUMBLED)
    {
	/* sort the input matrix and remove duplicate entries */
	AMD_DEBUG1 (("Matrix is jumbled\n")) ;
	Rp = (Int*)amd_malloc ((n+1) * sizeof (Int)) ;
	Ri = (Int*)amd_malloc (MAX (nz,1) * sizeof (Int)) ;
	mem += (n+1) ;
	mem += MAX (nz,1) ;
	if (!Rp || !Ri)
	{
	    /* :: out of memory :: */
	    amd_free (Rp) ;
	    amd_free (Ri) ;
	    amd_free (Len) ;
	    amd_free (Pinv) ;
	    if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;
	    return (AMD_OUT_OF_MEMORY) ;
	}
	/* use Len and Pinv as workspace to create R = A' */
	AMD_preprocess (n, Ap, Ai, Rp, Ri, Len, Pinv) ;
	Cp = Rp ;
	Ci = Ri ;
    }
    else
    {
	/* order the input matrix as-is.  No need to compute R = A' first */
	Rp = NULL ;
	Ri = NULL ;
	Cp = (Int *) Ap ;
	Ci = (Int *) Ai ;
    }

    /* --------------------------------------------------------------------- */
    /* determine the symmetry and count off-diagonal nonzeros in A+A' */
    /* --------------------------------------------------------------------- */

    nzaat = AMD_aat (n, Cp, Ci, Len, P, Info) ;
    AMD_DEBUG1 (("nzaat: %g\n", (double) nzaat)) ;
    ASSERT ((MAX (nz-n, 0) <= nzaat) && (nzaat <= 2 * (size_t) nz)) ;

    /* --------------------------------------------------------------------- */
    /* allocate workspace for matrix, elbow room, and 6 size-n vectors */
    /* --------------------------------------------------------------------- */

    S = NULL ;
    slen = nzaat ;			/* space for matrix */
    ok = ((slen + nzaat/5) >= slen) ;	/* check for size_t overflow */
    slen += nzaat/5 ;			/* add elbow room */
    for (i = 0 ; ok && i < 7 ; i++)
    {
	ok = ((slen + n) > slen) ;	/* check for size_t overflow */
	slen += n ;			/* size-n elbow room, 6 size-n work */
    }
    mem += slen ;
    ok = ok && (slen < SIZE_T_MAX / sizeof (Int)) ; /* check for overflow */
    ok = ok && (slen < Int_MAX) ;	/* S[i] for Int i must be OK */
    if (ok)
    {
	S = (Int*)amd_malloc (slen * sizeof (Int)) ;
    }
    AMD_DEBUG1 (("slen %g\n", (double) slen)) ;
    if (!S)
    {
	/* :: out of memory :: (or problem too large) */
	amd_free (Rp) ;
	amd_free (Ri) ;
	amd_free (Len) ;
	amd_free (Pinv) ;
	if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;
	return (AMD_OUT_OF_MEMORY) ;
    }
    if (info)
    {
	/* memory usage, in bytes. */
	Info [AMD_MEMORY] = mem * sizeof (Int) ;
    }

    /* --------------------------------------------------------------------- */
    /* order the matrix */
    /* --------------------------------------------------------------------- */

    AMD_1 (n, Cp, Ci, P, Pinv, Len, slen, S, Control, Info) ;

    /* --------------------------------------------------------------------- */
    /* free the workspace */
    /* --------------------------------------------------------------------- */

    amd_free (Rp) ;
    amd_free (Ri) ;
    amd_free (Len) ;
    amd_free (Pinv) ;
    amd_free (S) ;
    if (info) Info [AMD_STATUS] = status ;
    return (status) ;	    /* successful ordering */
}