Beispiel #1
0
/* Orders rows and saves pointer to matrix.and model */
int
ClpCholeskyUfl::order(ClpInterior * model)
{
     int iRow;
     model_ = model;
     if (preOrder(false, true, doKKT_))
          return -1;
     permuteInverse_ = new int [numberRows_];
     permute_ = new int[numberRows_];
     double Control[AMD_CONTROL];
     double Info[AMD_INFO];

     amd_defaults(Control);
     //amd_control(Control);

     int returnCode = amd_order(numberRows_, choleskyStart_, choleskyRow_,
                                permute_, Control, Info);
     delete [] choleskyRow_;
     choleskyRow_ = NULL;
     delete [] choleskyStart_;
     choleskyStart_ = NULL;
     //amd_info(Info);

     if (returnCode != AMD_OK) {
          std::cout << "AMD ordering failed" << std::endl;
          return 1;
     }
     for (iRow = 0; iRow < numberRows_; iRow++) {
          permuteInverse_[permute_[iRow]] = iRow;
     }
     return 0;
}
Beispiel #2
0
void amd_order1(int n, int A_ptr[], int A_ind[], int P_per[])
{     /* approximate minimum degree ordering (AMD) */
      int k, ret;
      double Control[AMD_CONTROL], Info[AMD_INFO];
      /* get the default parameters */
      amd_defaults(Control);
#if 0
      /* and print them */
      amd_control(Control);
#endif
      /* 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 */
      ret = amd_order(n, &A_ptr[1], &A_ind[1], &P_per[1], Control, Info)
         ;
#if 0
      amd_info(Info);
#endif
      xassert(ret == AMD_OK || ret == AMD_OK_BUT_JUMBLED);
      /* retsore 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;
}
Beispiel #3
0
static scs_int _ldl_init(cs *A, scs_int P[], scs_float **info) {
  *info = (scs_float *)scs_malloc(AMD_INFO * sizeof(scs_float));
#ifdef DLONG
  return (amd_l_order(A->n, A->p, A->i, P, (scs_float *)SCS_NULL, *info));
#else
  return (amd_order(A->n, A->p, A->i, P, (scs_float *)SCS_NULL, *info));
#endif
}
Beispiel #4
0
Vec<unsigned> symamd(const Vec<Vec<unsigned> > &ind) {
    Vec<int> lines; lines.resize( ind.size() + 1 );
    Vec<int> indices;
    
    unsigned nb_ind = 0;
    for(unsigned i=0;i<ind.size();++i)
        nb_ind += ind[i].size();
    indices.reserve( nb_ind ); 
    
    lines[0] = 0;
    for(unsigned i=0;i<ind.size();++i) {
        for(unsigned j=0;j<ind[i].size();++j)
            indices.push_back( ind[i][j] );
        lines[i+1] = indices.size();
    }
    Vec<unsigned> P; P.resize( ind.size() );
    amd_order( ind.size(), lines.begin(), indices.begin(), (int *)P.begin(), (double *)NULL, (double *)NULL );
    return P;
}
Beispiel #5
0
int main (void)
#endif
{

    /* ---------------------------------------------------------------------- */
    /* local variables */
    /* ---------------------------------------------------------------------- */

#ifdef USE_AMD
    double Info [AMD_INFO] ;
#endif
    double r, rnorm, flops, maxrnorm = 0. ;
    double *Ax, *Lx, *B, *D, *X, *Y ;
    LDL_int matrix, *Ai, *Ap, *Li, *Lp, *P, *Pinv, *Perm, *PermInv, n, i, j, p,
	nz, *Flag, *Pattern, *Lnz, *Parent, trial, lnz, d, jumbled ;
    FILE *f ;
    char s [LEN] ;

    /* ---------------------------------------------------------------------- */
    /* check the error-checking routines with null matrices */
    /* ---------------------------------------------------------------------- */

    i = 1 ;
    n = -1 ;
    if (LDL_valid_perm (n, (LDL_int *) NULL, &i)
	|| !LDL_valid_perm (0, (LDL_int *) NULL, &i)
	|| LDL_valid_matrix (n, (LDL_int *) NULL, (LDL_int *) NULL)
	|| LDL_valid_matrix (0, &i, &i))
    {
	printf (PROGRAM ": ldl error-checking routine failed\n") ;
	EXIT_ERROR ;
    }

    /* ---------------------------------------------------------------------- */
    /* read in a factorize a set of matrices */
    /* ---------------------------------------------------------------------- */

    for (matrix = 1 ; matrix <= NMATRICES ; matrix++)
    {

	/* ------------------------------------------------------------------ */
	/* read in the matrix and the permutation */
	/* ------------------------------------------------------------------ */

	sprintf (s, "../Matrix/A%02d", (int) matrix) ;
	if ((f = fopen (s, "r")) == (FILE *) NULL)
	{
	    printf (PROGRAM ": could not open file: %s\n", s) ;
	    EXIT_ERROR ;
	}
	fgets (s, LEN, f) ;
	printf ("\n\n--------------------------------------------------------");
	printf ("\nInput matrix: %s", s) ;
	printf ("--------------------------------------------------------\n\n");
	fscanf (f, LDL_ID " " LDL_ID, &n, &jumbled) ;
	n = (n < 0) ? (0) : (n) ;
	ALLOC_MEMORY (P, LDL_int, n) ;
	ALLOC_MEMORY (Ap, LDL_int, n+1) ;
	for (j = 0 ; j <= n ; j++)
	{
	    fscanf (f, LDL_ID, &Ap [j]) ;
	}
	nz = Ap [n] ;
	ALLOC_MEMORY (Ai, LDL_int, nz) ;
	ALLOC_MEMORY (Ax, double, nz) ;
	for (p = 0 ; p < nz ; p++)
	{
	    fscanf (f, LDL_ID , &Ai [p]) ;
	}
	for (p = 0 ; p < nz ; p++)
	{
	    fscanf (f, "%lg", &Ax [p]) ;
	}
	for (j = 0 ; j < n  ; j++)
	{
	    fscanf (f, LDL_ID , &P  [j]) ;
	}
	fclose (f) ;

	/* ------------------------------------------------------------------ */
	/* check the matrix A and the permutation P */
	/* ------------------------------------------------------------------ */

	ALLOC_MEMORY (Flag, LDL_int, n) ;

	/* To test the error-checking routines, some of the input matrices
	 * are not valid.  So this error is expected to occur. */
	if (!LDL_valid_matrix (n, Ap, Ai) || !LDL_valid_perm (n, P, Flag))
	{
	    printf (PROGRAM ": invalid matrix and/or permutation\n") ;
	    FREE_MEMORY (P, LDL_int) ;
	    FREE_MEMORY (Ap, LDL_int) ;
	    FREE_MEMORY (Ai, LDL_int) ;
	    FREE_MEMORY (Ax, double) ;
	    FREE_MEMORY (Flag, LDL_int) ;
	    continue ;
	}

	/* ------------------------------------------------------------------ */
	/* get the AMD permutation, if available */
	/* ------------------------------------------------------------------ */

#ifdef USE_AMD

	/* recompute the permutation with AMD */
	/* Assume that AMD produces a valid permutation P. */

#ifdef LDL_LONG

	if (amd_l_order (n, Ap, Ai, P, (double *) NULL, Info) < AMD_OK)
	{
	    printf (PROGRAM ": call to AMD failed\n") ;
	    EXIT_ERROR ;
	}
	amd_l_control ((double *) NULL) ;
	amd_l_info (Info) ;

#else

	if (amd_order (n, Ap, Ai, P, (double *) NULL, Info) < AMD_OK)
	{
	    printf (PROGRAM ": call to AMD failed\n") ;
	    EXIT_ERROR ;
	}
	amd_control ((double *) NULL) ;
	amd_info (Info) ;

#endif
#endif

	/* ------------------------------------------------------------------ */
	/* allocate workspace and the first part of LDL factorization */
	/* ------------------------------------------------------------------ */

	ALLOC_MEMORY (Pinv, LDL_int, n) ;
	ALLOC_MEMORY (Y, double, n) ;
	ALLOC_MEMORY (Pattern, LDL_int, n) ;
	ALLOC_MEMORY (Lnz, LDL_int, n) ;
	ALLOC_MEMORY (Lp, LDL_int, n+1) ;
	ALLOC_MEMORY (Parent, LDL_int, n) ;
	ALLOC_MEMORY (D, double, n) ;
	ALLOC_MEMORY (B, double, n) ;
	ALLOC_MEMORY (X, double, n) ;

	/* ------------------------------------------------------------------ */
	/* factorize twice, with and without permutation */
	/* ------------------------------------------------------------------ */

	for (trial = 1 ; trial <= 2 ; trial++)
	{

	    if (trial == 1)
	    {
		printf ("Factorize PAP'=LDL' and solve Ax=b\n") ;
		Perm = P ;
		PermInv = Pinv ;
	    }
	    else
	    {
		printf ("Factorize A=LDL' and solve Ax=b\n") ;
		Perm = (LDL_int *) NULL ;
		PermInv = (LDL_int *) NULL ;
	    }

	    /* -------------------------------------------------------------- */
	    /* symbolic factorization to get Lp, Parent, Lnz, and Pinv */
	    /* -------------------------------------------------------------- */

	    LDL_symbolic (n, Ap, Ai, Lp, Parent, Lnz, Flag, Perm, PermInv) ;
	    lnz = Lp [n] ;

	    /* find # of nonzeros in L, and flop count for LDL_numeric */
	    flops = 0 ;
	    for (j = 0 ; j < n ; j++)
	    {
		flops += ((double) Lnz [j]) * (Lnz [j] + 2) ;
	    }
	    printf ("Nz in L: "LDL_ID"  Flop count: %g\n", lnz, flops) ;

	    /* -------------------------------------------------------------- */
	    /* allocate remainder of L, of size lnz */
	    /* -------------------------------------------------------------- */

	    ALLOC_MEMORY (Li, LDL_int, lnz) ;
	    ALLOC_MEMORY (Lx, double, lnz) ;

	    /* -------------------------------------------------------------- */
	    /* numeric factorization to get Li, Lx, and D */
	    /* -------------------------------------------------------------- */

	    d = LDL_numeric (n, Ap, Ai, Ax, Lp, Parent, Lnz, Li, Lx, D,
		Y, Flag, Pattern, Perm, PermInv) ;

	    /* -------------------------------------------------------------- */
	    /* solve, or report singular case */
	    /* -------------------------------------------------------------- */

	    if (d != n)
	    {
		printf ("Ax=b not solved since D("LDL_ID","LDL_ID") is zero.\n", d, d) ;
	    }
	    else
	    {
		/* construct the right-hand-side, B */
		for (i = 0 ; i < n ; i++)
		{
		    B [i] = 1 + ((double) i) / 100 ;
		}

		/* solve Ax=b */
		if (trial == 1)
		{
		    /* the factorization is LDL' = PAP' */
		    LDL_perm (n, Y, B, P) ;			/* y = Pb */
		    LDL_lsolve (n, Y, Lp, Li, Lx) ;		/* y = L\y */
		    LDL_dsolve (n, Y, D) ;			/* y = D\y */
		    LDL_ltsolve (n, Y, Lp, Li, Lx) ;		/* y = L'\y */
		    LDL_permt (n, X, Y, P) ;			/* x = P'y */
		}
		else
		{
		    /* the factorization is LDL' = A */
		    for (i = 0 ; i < n ; i++)			/* x = b */
		    {
			X [i] = B [i] ;
		    }
		    LDL_lsolve (n, X, Lp, Li, Lx) ;		/* x = L\x */
		    LDL_dsolve (n, X, D) ;			/* x = D\x */
		    LDL_ltsolve (n, X, Lp, Li, Lx) ;		/* x = L'\x */
		}

		/* compute the residual y = Ax-b */
		/* note that this code can tolerate a jumbled matrix */
		for (i = 0 ; i < n ; i++)
		{
		    Y [i] = -B [i] ;
		}
		for (j = 0 ; j < n ; j++)
		{
		    for (p = Ap [j] ; p < Ap [j+1] ; p++)
		    {
			Y [Ai [p]] += Ax [p] * X [j] ;
		    }
		}
		/* rnorm = norm (y, inf) */
		rnorm = 0 ;
		for (i = 0 ; i < n ; i++)
		{
		    r = (Y [i] > 0) ? (Y [i]) : (-Y [i]) ;
		    rnorm = (r > rnorm) ? (r) : (rnorm) ;
		}
		maxrnorm = (rnorm > maxrnorm) ? (rnorm) : (maxrnorm) ;
		printf ("relative maxnorm of residual: %g\n", rnorm) ;
	    }

	    /* -------------------------------------------------------------- */
	    /* free the size-lnz part of L */
	    /* -------------------------------------------------------------- */

	    FREE_MEMORY (Li, LDL_int) ;
	    FREE_MEMORY (Lx, double) ;

	}

	/* free everything */
	FREE_MEMORY (P, LDL_int) ;
	FREE_MEMORY (Ap, LDL_int) ;
	FREE_MEMORY (Ai, LDL_int) ;
	FREE_MEMORY (Ax, double) ;
	FREE_MEMORY (Pinv, LDL_int) ;
	FREE_MEMORY (Y, double) ;
	FREE_MEMORY (Flag, LDL_int) ;
	FREE_MEMORY (Pattern, LDL_int) ;
	FREE_MEMORY (Lnz, LDL_int) ;
	FREE_MEMORY (Lp, LDL_int) ;
	FREE_MEMORY (Parent, LDL_int) ;
	FREE_MEMORY (D, double) ;
	FREE_MEMORY (B, double) ;
	FREE_MEMORY (X, double) ;
    }

    printf ("\nLargest residual during all tests: %g\n", maxrnorm) ;
    if (maxrnorm < 1e-8)
    {
	printf ("\n" PROGRAM ": all tests passed\n") ;
	EXIT_OK ;
    }
    else
    {
	printf ("\n" PROGRAM ": one more tests failed (residual too high)\n") ;
	EXIT_ERROR ;
    }
}
CrsGraph_AMD::NewTypeRef
CrsGraph_AMD::
operator()( OriginalTypeRef orig )
{
  origObj_ = &orig;

  int n = orig.NumMyRows();
  int nnz = orig.NumMyNonzeros();

  //create std CRS format
  std::vector<int> ia(n+1,0);
  std::vector<int> ja(nnz);
  int cnt;
  for( int i = 0; i < n; ++i )
  {
    int * tmpP = &ja[ia[i]];
    orig.ExtractMyRowCopy( i, nnz-ia[i], cnt, tmpP );
    ia[i+1] = ia[i] + cnt;
  }

  //trim down to local only
  std::vector<int> iat(n+1);
  std::vector<int> jat(nnz);
  int loc = 0;
  for( int i = 0; i < n; ++i )
  {
    iat[i] = loc;
    for( int j = ia[i]; j < ia[i+1]; ++j )
    {
      if( ja[j] < n )
        jat[loc++] = ja[j];
      else
	break;
    }
  }
  iat[n] = loc;


  if( verbose_ )
  {
    std::cout << "Orig Graph\n";
    std::cout << orig << std::endl;
    std::cout << "-----------------------------------------\n";
    std::cout << "CRS Format Graph\n";
    std::cout << "-----------------------------------------\n";
    for( int i = 0; i < n; ++i )
    {
      std::cout << i << ": " << iat[i+1] << ": ";
      for( int j = iat[i]; j<iat[i+1]; ++j )
        std::cout << " " << jat[j];
      std::cout << std::endl;
    }
    std::cout << "-----------------------------------------\n";
  }

  std::vector<int> perm(n);
  std::vector<double> info(AMD_INFO);

  amd_order( n, &iat[0], &jat[0], &perm[0], NULL, &info[0] ); 

  if( info[AMD_STATUS] == AMD_INVALID )
    std::cout << "AMD ORDERING: Invalid!!!!\n";

  if( verbose_ )
  {
    std::cout << "-----------------------------------------\n";
    std::cout << "AMD Output\n";
    std::cout << "-----------------------------------------\n";
    std::cout << "STATUS: " << info[AMD_STATUS] << std::endl;
    std::cout << "SYMM: " << info[AMD_SYMMETRY] << std::endl;
    std::cout << "N: " << info[AMD_N] << std::endl;
    std::cout << "NZ: " << info[AMD_NZ] << std::endl;
    std::cout << "SYMM: " << info[AMD_SYMMETRY] << std::endl;
    std::cout << "NZDIAG: " << info[AMD_NZDIAG] << std::endl;
    std::cout << "NZ A+At: " << info[AMD_NZ_A_PLUS_AT] << std::endl;
    std::cout << "NDENSE: " << info[AMD_SYMMETRY] << std::endl;
    std::cout << "Perm\n";
    for( int i = 0; i<n; ++i )
      std::cout << perm[i] << std::endl;
    std::cout << "-----------------------------------------\n";
  }

  //Generate New Domain and Range Maps
  //for now, assume they start out as identical
  const Epetra_BlockMap & OldMap = orig.RowMap();
  int nG = orig.NumGlobalRows();

  std::vector<int> newElements( n );
  for( int i = 0; i < n; ++i )
    newElements[i] = OldMap.GID( perm[i] );

  NewMap_ = new Epetra_Map( nG, n, &newElements[0], OldMap.IndexBase(), OldMap.Comm() );

  if( verbose_ )
  {
    std::cout << "Old Map\n";
    std::cout << OldMap << std::endl;
    std::cout << "New Map\n";
    std::cout << *NewMap_ << std::endl;
  }

  //Generate New Graph
  NewGraph_ = new Epetra_CrsGraph( Copy, *NewMap_, 0 );
  Epetra_Import Importer( *NewMap_, OldMap );
  NewGraph_->Import( orig, Importer, Insert );
  NewGraph_->FillComplete();

  if( verbose_ )
  {
    std::cout << "New CrsGraph\n";
    std::cout << *NewGraph_ << std::endl;
  }

  newObj_ = NewGraph_;

  return *NewGraph_;
}
Beispiel #7
0
std::vector<int> cAMD_Interf::DoRank(bool show) 
{
   Im2D_Bits<1> aM(1,1);
   if (show)
      aM = Im2D_Bits<1>(mNb,mNb,0);

   std::vector<int> Ap,Ai,P;
   Ap.push_back(0);
   for (int aK=0 ; aK<mNb ; aK++)
   {
       std::vector<int> & aVK = mV[aK];
       std::sort(aVK.begin(),aVK.end());
       aVK.erase(std::unique(aVK.begin(),aVK.end()),aVK.end());

      for (int aI=0;aI<int(aVK.size()) ; aI++)
      {
          Ai.push_back(aVK[aI]);
          if (show)
          {
              aM.set(aK,aVK[aI],1);
          }
          // std::cout << " " << aVK[aI] ;
      }
      Ap.push_back(Ap.back()+aVK.size());
      P.push_back(0);
      // std::cout << "\n";

   }



   double Control [AMD_CONTROL] , Info [AMD_INFO] ;

   amd_defaults (Control) ;
   // amd_control  (Control) ;

   int result;
   result = amd_order(mNb,VData(Ap),VData(Ai), VData(P),Control,Info);

   ELISE_ASSERT(result==0,"amd_order");
   //std::cout << "RES = "  << result << "\n";

   std::vector<int> aRes(mNb,-1);
   for (int aK=0 ; aK<mNb ; aK++)
   {
       aRes[P[aK]] = aK;
   }
   if (show)
   {
      for (int aK=0 ; aK<mNb ; aK++)
      {
   
      }
      std::cout << "\n";
   }
    // result = amd_order (n, Ap, Ai, P, Control, Info) ;

   if (show)
   {
       Im2D_Bits<1> aM2(mNb,mNb);
       for (int aX=0 ; aX<mNb ; aX++)
       {
           for (int aY=0 ; aY<mNb ; aY++)
           {
                 aM2.set(aRes[aX],aRes[aY],aM.get(aX,aY));
                // aM2.set(aX,aY,aM.get(P[aX],P[aY]));
           }
       }
       ShowMat(aM);
       std::cout << "\n";
       ShowMat(aM2);
   }
   return aRes;
}
Beispiel #8
0
int amd_demo_1 (void)
{
    /* The symmetric can_24 Harwell/Boeing matrix, including upper and lower
     * triangular parts, and the diagonal entries.  Note that this matrix is
     * 0-based, with row and column indices in the range 0 to n-1. */
    int n = 24, nz,
    Ap [ ] = { 0, 9, 15, 21, 27, 33, 39, 48, 57, 61, 70, 76, 82, 88, 94, 100,
	106, 110, 119, 128, 137, 143, 152, 156, 160 },
    Ai [ ] = {
	/* column  0: */    0, 5, 6, 12, 13, 17, 18, 19, 21,
	/* column  1: */    1, 8, 9, 13, 14, 17,
	/* column  2: */    2, 6, 11, 20, 21, 22,
	/* column  3: */    3, 7, 10, 15, 18, 19,
	/* column  4: */    4, 7, 9, 14, 15, 16,
	/* column  5: */    0, 5, 6, 12, 13, 17,
	/* column  6: */    0, 2, 5, 6, 11, 12, 19, 21, 23,
	/* column  7: */    3, 4, 7, 9, 14, 15, 16, 17, 18,
	/* column  8: */    1, 8, 9, 14,
	/* column  9: */    1, 4, 7, 8, 9, 13, 14, 17, 18,
	/* column 10: */    3, 10, 18, 19, 20, 21,
	/* column 11: */    2, 6, 11, 12, 21, 23,
	/* column 12: */    0, 5, 6, 11, 12, 23,
	/* column 13: */    0, 1, 5, 9, 13, 17,
	/* column 14: */    1, 4, 7, 8, 9, 14,
	/* column 15: */    3, 4, 7, 15, 16, 18,
	/* column 16: */    4, 7, 15, 16,
	/* column 17: */    0, 1, 5, 7, 9, 13, 17, 18, 19,
	/* column 18: */    0, 3, 7, 9, 10, 15, 17, 18, 19,
	/* column 19: */    0, 3, 6, 10, 17, 18, 19, 20, 21,
	/* column 20: */    2, 10, 19, 20, 21, 22,
	/* column 21: */    0, 2, 6, 10, 11, 19, 20, 21, 22,
	/* column 22: */    2, 20, 21, 22,
	/* column 23: */    6, 11, 12, 23 } ;

    int P [24], Pinv [24], i, j, k, jnew, p, inew, result ;
    double Control [AMD_CONTROL], Info [AMD_INFO] ;
    char A [24][24] ;

    /* here is an example of how to use AMD_VERSION.  This code will work in
     * any version of AMD. */
#if defined(AMD_VERSION) && (AMD_VERSION >= AMD_VERSION_CODE(1,2))
    printf ("AMD version %d.%d, date: %s\n", AMD_MAIN_VERSION, AMD_SUB_VERSION,
	    AMD_DATE) ;
#else
    printf ("AMD version: 1.1 or earlier\n") ;
#endif

    printf ("AMD demo, with the 24-by-24 Harwell/Boeing matrix, can_24:\n") ;

    /* get the default parameters, and print them */
    amd_defaults (Control) ;
    amd_control  (Control) ;

    /* print the input matrix */
    nz = Ap [n] ;
    printf ("\nInput matrix:  %d-by-%d, with %d entries.\n"
	   "   Note that for a symmetric matrix such as this one, only the\n"
	   "   strictly lower or upper triangular parts would need to be\n"
	   "   passed to AMD, since AMD computes the ordering of A+A'.  The\n"
	   "   diagonal entries are also not needed, since AMD ignores them.\n"
	   , n, n, nz) ;
    for (j = 0 ; j < n ; j++)
    {
	printf ("\nColumn: %d, number of entries: %d, with row indices in"
		" Ai [%d ... %d]:\n    row indices:",
		j, Ap [j+1] - Ap [j], Ap [j], Ap [j+1]-1) ;
	for (p = Ap [j] ; p < Ap [j+1] ; p++)
	{
	    i = Ai [p] ;
	    printf (" %d", i) ;
	}
	printf ("\n") ;
    }

    /* print a character plot of the input matrix.  This is only reasonable
     * because the matrix is small. */
    printf ("\nPlot of input matrix pattern:\n") ;
    for (j = 0 ; j < n ; j++)
    {
	for (i = 0 ; i < n ; i++) A [i][j] = '.' ;
	for (p = Ap [j] ; p < Ap [j+1] ; p++)
	{
	    i = Ai [p] ;
	    A [i][j] = 'X' ;
	}
    }
    printf ("    ") ;
    for (j = 0 ; j < n ; j++) printf (" %1d", j % 10) ;
    printf ("\n") ;
    for (i = 0 ; i < n ; i++)
    {
	printf ("%2d: ", i) ;
	for (j = 0 ; j < n ; j++)
	{
	    printf (" %c", A [i][j]) ;
	}
	printf ("\n") ;
    }

    /* order the matrix */
    result = amd_order (n, Ap, Ai, P, Control, Info) ;
    printf ("return value from amd_order: %d (should be %d)\n",
	result, AMD_OK) ;

    /* print the statistics */
    amd_info (Info) ;

    if (result != AMD_OK)
    {
	printf ("AMD failed\n") ;
	ElEXIT (1,"AMD DEMO") ;
    }

    /* print the permutation vector, P, and compute the inverse permutation */
    printf ("Permutation vector:\n") ;
    for (k = 0 ; k < n ; k++)
    {
	/* row/column j is the kth row/column in the permuted matrix */
	j = P [k] ;
	Pinv [j] = k ;
	printf (" %2d", j) ;
    }
    printf ("\n\n") ;

    printf ("Inverse permutation vector:\n") ;
    for (j = 0 ; j < n ; j++)
    {
	k = Pinv [j] ;
	printf (" %2d", k) ;
    }
    printf ("\n\n") ;

    /* print a character plot of the permuted matrix. */
    printf ("\nPlot of permuted matrix pattern:\n") ;
    for (jnew = 0 ; jnew < n ; jnew++)
    {
	j = P [jnew] ;
	for (inew = 0 ; inew < n ; inew++) A [inew][jnew] = '.' ;
	for (p = Ap [j] ; p < Ap [j+1] ; p++)
	{
	    inew = Pinv [Ai [p]] ;
	    A [inew][jnew] = 'X' ;
	}
    }
    printf ("    ") ;
    for (j = 0 ; j < n ; j++) printf (" %1d", j % 10) ;
    printf ("\n") ;
    for (i = 0 ; i < n ; i++)
    {
	printf ("%2d: ", i) ;
	for (j = 0 ; j < n ; j++)
	{
	    printf (" %c", A [i][j]) ;
	}
	printf ("\n") ;
    }

    return (0) ;
}
Beispiel #9
0
 int order(int n, const int *Ap, const int *Ai, int *perm,
             double *control, double *info)
 {
     return (amd_order(n, Ap, Ai, perm, control, info));
 }
Beispiel #10
0
int main (int argc, char **argv)
{
    int i, j, k, n, nz, *Ap, *Ai, *Ti, *Tj, status, *Pamd, nrow, ncol, rhs ;
    double *Ax, *b, *x, Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], aij,
	*Tx, *r, amd_Control [AMD_CONTROL], amd_Info [AMD_INFO], tamd [2],
	stats [2], droptol ;
    void *Symbolic, *Numeric ;
    FILE *f, *f2 ;
    char s [SMAX] ;

    /* ---------------------------------------------------------------------- */
    /* set controls */
    /* ---------------------------------------------------------------------- */

    printf ("\n===========================================================\n"
	    "=== UMFPACK v%d.%d.%d ========================================\n"
	    "===========================================================\n",
	    UMFPACK_MAIN_VERSION, UMFPACK_SUB_VERSION, UMFPACK_SUBSUB_VERSION) ;

    umfpack_di_defaults (Control) ;
    Control [UMFPACK_PRL] = 3 ;
    Control [UMFPACK_BLOCK_SIZE] = 32 ;

    f = fopen ("tmp/control.umf4", "r") ;
    if (f != (FILE *) NULL)
    {
	printf ("Reading control file tmp/control.umf4\n") ;
	for (i = 0 ; i < UMFPACK_CONTROL ; i++)
	{
	    fscanf (f, "%lg\n", & Control [i]) ;
	}
	fclose (f) ;
    }

    if (argc > 1)
    {
	char *t = argv [1] ;

	/* get the strategy */
	if (t [0] == 'u')
	{
	    Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_UNSYMMETRIC ;
	}
	else if (t [0] == 'a')
	{
	    Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_AUTO ;
	}
	else if (t [0] == 's')
	{
	    Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_SYMMETRIC ;
	}
	else if (t [0] == '2')
	{
	    printf ("unrecognized strategy: %s\n", argv [1]) ;
	}
	else if (t [0] == 'U')
	{
	    Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_UNSYMMETRIC ;
	    Control [UMFPACK_SCALE] = UMFPACK_SCALE_MAX ;
	}
	else if (t [0] == 'A')
	{
	    Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_AUTO ;
	    Control [UMFPACK_SCALE] = UMFPACK_SCALE_MAX ;
	}
	else if (t [0] == 'S')
	{
	    Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_SYMMETRIC ;
	    Control [UMFPACK_SCALE] = UMFPACK_SCALE_MAX ;
	}
	else if (t [0] == 'T')
	{
	    printf ("unrecognized strategy: %s\n", argv [1]) ;
	}
	else
	{
	    printf ("unrecognized strategy: %s\n", argv [1]) ;
	}

	if (t [1] == 'n')
	{
	    /* no aggressive absorption */
	    Control [UMFPACK_AGGRESSIVE] = FALSE ;
	}
    }

    if (argc > 2)
    {
	/* get the drop tolerance */
	sscanf (argv [2], "%lg", &droptol) ;
	printf ("droptol %g\n", droptol) ;
	Control [UMFPACK_DROPTOL] = droptol ;
    }

    umfpack_di_report_control (Control) ;

    /* ---------------------------------------------------------------------- */
    /* open the matrix file (tmp/A) */
    /* ---------------------------------------------------------------------- */

    printf ("File: tmp/A\n") ;
    f = fopen ("tmp/A", "r") ;
    if (!f)
    {
	printf ("Unable to open file\n") ;
	exit (1) ;
    }

    /* ---------------------------------------------------------------------- */
    /* get n and nz */
    /* ---------------------------------------------------------------------- */

    printf ("File: tmp/Asize\n") ;
    f2 = fopen ("tmp/Asize", "r") ;
    if (f2)
    {
	fscanf (f2, "%d %d %d\n", &nrow, &ncol, &nz) ;
	fclose (f2) ;
    }
    else
    {
	nrow = 1 ;
	ncol = 1 ;
    }
    nz = 0 ;
    while (fgets (s, SMAX, f) != (char *) NULL)
    {
	sscanf (s, "%d %d %lg", &i, &j, &aij) ;
#ifdef ZERO_BASED
	/* matrix is zero based */
	i++ ;
	j++ ;
#endif
	nrow = MAX (nrow, i) ;
	ncol = MAX (ncol, j) ;
	nz++ ;
    }
    fclose (f) ;
    n = MAX (nrow, ncol) ;

    printf ("n %d nrow %d ncol %d nz %d\n", n, nrow, ncol, nz) ;

    /* ---------------------------------------------------------------------- */
    /* allocate space for the input triplet form */
    /* ---------------------------------------------------------------------- */

    Ti = (int *) malloc (nz * sizeof (int)) ;
    Tj = (int *) malloc (nz * sizeof (int)) ;
    Tx = (double *) malloc (nz * sizeof (double)) ;
    if (!Ti || !Tj || !Tx)
    {
	printf ("out of memory for input matrix\n") ;
	exit (1) ;
    }

    /* ---------------------------------------------------------------------- */
    /* read in the triplet form */
    /* ---------------------------------------------------------------------- */

    f2 = fopen ("tmp/A", "r") ;
    if (!f2)
    {
	printf ("Unable to open file\n") ;
	exit (1) ;
    }

    k = 0 ;
    while (fgets (s, SMAX, f2) != (char *) NULL)
    {
	sscanf (s, "%d %d %lg", &i, &j, &aij) ;
#ifndef ZERO_BASED
	i-- ;	/* convert to 0-based */
	j-- ;
#endif
	if (k >= nz)
	{
	    printf ("Error!  Matrix size is wrong\n") ;
	    exit (1) ;
	}
	Ti [k] = i ;
	Tj [k] = j ;
	Tx [k] = aij ;
	k++ ;
    }
    fclose (f2) ;

    (void) umfpack_di_report_triplet (nrow, ncol, nz, Ti, Tj, Tx, Control) ;

    /* ---------------------------------------------------------------------- */
    /* convert to column form */
    /* ---------------------------------------------------------------------- */

    /* convert to column form */
    Ap = (int *) malloc ((n+1) * sizeof (int)) ;
    Ai = (int *) malloc (nz * sizeof (int)) ;
    Ax = (double *) malloc (nz * sizeof (double)) ;
    b = (double *) malloc (n * sizeof (double)) ;
    r = (double *) malloc (n * sizeof (double)) ;
    x = (double *) malloc (n * sizeof (double)) ;

    if (!Ap || !Ai || !Ax || !b || !r)
    {
	printf ("out of memory") ;
	exit (1) ;
    }

    umfpack_tic (stats) ;
    status = umfpack_di_triplet_to_col (nrow, ncol, nz, Ti, Tj, Tx, Ap, Ai, Ax,
	(int *) NULL) ;
    umfpack_toc (stats) ;
    printf ("triplet-to-col time: wall %g cpu %g\n", stats [0], stats [1]) ;
    if (status != UMFPACK_OK)
    {
	umfpack_di_report_status (Control, status) ;
	printf ("umfpack_di_triplet_to_col failed") ;
	exit (1) ;
    }

    /* print the column-form of A */
    (void) umfpack_di_report_matrix (nrow, ncol, Ap, Ai, Ax, 1, Control) ;

    /* b = A * xtrue */
    rhs = FALSE ;
    if (nrow == ncol)
    {
	f = fopen ("tmp/b", "r") ;
	if (f != (FILE *) NULL)
	{
	    printf ("Reading tmp/b\n") ;
	    rhs = TRUE ;
	    for (i = 0 ; i < n ; i++)
	    {
		fscanf (f, "%lg\n", &b [i]) ;
	    }
	    fclose (f) ;
	}
	else
	{
	    Atimesx (n, Ap, Ai, Ax, b, FALSE) ;
	}
    }

    /* ---------------------------------------------------------------------- */
    /* free the triplet form */
    /* ---------------------------------------------------------------------- */

    free (Ti) ;
    free (Tj) ;
    free (Tx) ;

    /* ---------------------------------------------------------------------- */
    /* symbolic factorization */
    /* ---------------------------------------------------------------------- */

    status = umfpack_di_symbolic (nrow, ncol, Ap, Ai, Ax, &Symbolic,
	    Control, Info) ;

    umfpack_di_report_info (Control, Info) ;
    if (status != UMFPACK_OK)
    {
	umfpack_di_report_status (Control, status) ;
	printf ("umfpack_di_symbolic failed") ;
	exit (1) ;
    }

    /* print the symbolic factorization */
    (void) umfpack_di_report_symbolic (Symbolic, Control) ;

    /* ---------------------------------------------------------------------- */
    /* numeric factorization */
    /* ---------------------------------------------------------------------- */

    status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, Control, Info);
    if (status < UMFPACK_OK)
    {
	umfpack_di_report_info (Control, Info) ;
	umfpack_di_report_status (Control, status) ;
	fprintf (stderr, "umfpack_di_numeric failed: %d\n", status) ;
	printf ("umfpack_di_numeric failed\n") ;
	exit (1) ;
    }

    /* print the numeric factorization */
    (void) umfpack_di_report_numeric (Numeric, Control) ;

    /* ---------------------------------------------------------------------- */
    /* solve Ax=b */
    /* ---------------------------------------------------------------------- */

    if (nrow == ncol && status == UMFPACK_OK)
    {
	status = umfpack_di_solve (UMFPACK_A, Ap, Ai, Ax, x, b, Numeric,
		Control, Info) ;

	umfpack_di_report_info (Control, Info) ;
	umfpack_di_report_status (Control, status) ;
	if (status < UMFPACK_OK)
	{
	    printf ("umfpack_di_solve failed\n") ;
	    exit (1) ;
	}
	(void) umfpack_di_report_vector (n, x, Control) ;
	printf ("relative maxnorm of residual, ||Ax-b||/||b||: %g\n",
	    resid (n, Ap, Ai, Ax, x, r, b, FALSE)) ;
	if (!rhs)
	{
	    printf ("relative maxnorm of error, ||x-xtrue||/||xtrue||: %g\n\n",
		err (n, x)) ;
	}

	f = fopen ("tmp/x", "w") ;
	if (f != (FILE *) NULL)
	{
	    printf ("Writing tmp/x\n") ;
	    for (i = 0 ; i < n ; i++)
	    {
		fprintf (f, "%30.20e\n", x [i]) ;
	    }
	    fclose (f) ;
	}
	else
	{
	    printf ("Unable to write output x!\n") ;
	    exit (1) ;
	}

	f = fopen ("tmp/info.umf4", "w") ;
	if (f != (FILE *) NULL)
	{
	    printf ("Writing tmp/info.umf4\n") ;
	    for (i = 0 ; i < UMFPACK_INFO ; i++)
	    {
		fprintf (f, "%30.20e\n", Info [i]) ;
	    }
	    fclose (f) ;
	}
	else
	{
	    printf ("Unable to write output info!\n") ;
	    exit (1) ;
	}
    }
    else
    {
	/* don't solve, just report the results */
	umfpack_di_report_info (Control, Info) ;
	umfpack_di_report_status (Control, status) ;
    }

    /* ---------------------------------------------------------------------- */
    /* free the Symbolic and Numeric factorization */
    /* ---------------------------------------------------------------------- */

    umfpack_di_free_symbolic (&Symbolic) ;
    umfpack_di_free_numeric (&Numeric) ;

    printf ("umf4 done, strategy: %g\n", Control [UMFPACK_STRATEGY]) ;

    /* ---------------------------------------------------------------------- */
    /* test just AMD ordering (not part of UMFPACK, but a separate test) */
    /* ---------------------------------------------------------------------- */

    /* first make the matrix square */
    if (ncol < n)
    {
	for (j = ncol+1 ; j <= n ; j++)
	{
	    Ap [j] = Ap [ncol] ;
	}
    }

    printf (
	"\n\n===========================================================\n"
	"=== AMD ===================================================\n"
	"===========================================================\n") ;
    printf ("\n\n------- Now trying the AMD ordering.  This not part of\n"
	"the UMFPACK analysis or factorization, above, but a separate\n"
	"test of just the AMD ordering routine.\n") ;
	Pamd = (int *) malloc (n * sizeof (int)) ;
    if (!Pamd)
    {
	printf ("out of memory\n") ;
	exit (1) ;
    }
    amd_defaults (amd_Control) ;
    amd_control (amd_Control) ;
    umfpack_tic (tamd) ;
    status = amd_order (n, Ap, Ai, Pamd, amd_Control, amd_Info) ;
    umfpack_toc (tamd) ;
    printf ("AMD ordering time: cpu %10.2f wall %10.2f\n",
	tamd [1], tamd [0]) ;
    if (status != AMD_OK)
    {
	printf ("amd failed: %d\n", status) ;
	exit (1) ;
    }
    amd_info (amd_Info) ;
    free (Pamd) ;
    printf ("AMD test done\n") ;

    free (Ap) ;
    free (Ai) ;
    free (Ax) ;
    free (b) ;
    free (r) ;
    free (x) ;

    return (0) ;
}
Beispiel #11
0
void amd(csc *A, int *p){
    amd_order(A->n, A->Ap, A->Ai, p, (double*)NULL, (double*)NULL);
}
int main (int argc, char **argv)
{
    /* The symmetric can_24 Harwell/Boeing matrix (jumbled, and not symmetric).
     * Since AMD operates on A+A', only A(i,j) or A(j,i) need to be specified,
     * or both.  The diagonal entries are optional (some are missing).
     * There are many duplicate entries, which must be removed. */
    int n = 24, nz,
    Ap [ ] = { 0, 9, 14, 20, 28, 33, 37, 44, 53, 58, 63, 63, 66, 69, 72, 75,
	      78, 82, 86, 91, 97, 101, 112, 112, 116 },
    Ai [ ] = {
	/* column  0: */    0, 17, 18, 21, 5, 12, 5, 0, 13,
	/* column  1: */    14, 1, 8, 13, 17,
	/* column  2: */    2, 20, 11, 6, 11, 22,
	/* column  3: */    3, 3, 10, 7, 18, 18, 15, 19,
	/* column  4: */    7, 9, 15, 14, 16,
	/* column  5: */    5, 13, 6, 17,
	/* column  6: */    5, 0, 11, 6, 12, 6, 23,
	/* column  7: */    3, 4, 9, 7, 14, 16, 15, 17, 18,
	/* column  8: */    1, 9, 14, 14, 14,
	/* column  9: */    7, 13, 8, 1, 17,
	/* column 10: */
	/* column 11: */    2, 12, 23,
	/* column 12: */    5, 11, 12,
	/* column 13: */    0, 13, 17,
	/* column 14: */    1, 9, 14,
	/* column 15: */    3, 15, 16,
	/* column 16: */    16, 4, 4, 15,
	/* column 17: */    13, 17, 19, 17,
	/* column 18: */    15, 17, 19, 9, 10,
	/* column 19: */    17, 19, 20, 0, 6, 10,
	/* column 20: */    22, 10, 20, 21,
	/* column 21: */    6, 2, 10, 19, 20, 11, 21, 22, 22, 22, 22,
	/* column 22: */
	/* column 23: */    12, 11, 12, 23 } ;

    int Rp [25], Ri [116] ;
    int P [24], Pinv [24], i, j, k, jnew, p, inew, result ;
    double Control [AMD_CONTROL], Info [AMD_INFO] ;
    char A [24][24] ;

    printf ("AMD demo, with a jumbled version of the 24-by-24\n") ;
    printf ("Harwell/Boeing matrix, can_24:\n") ;

    /* get the default parameters, and print them */
    amd_defaults (Control) ;
    amd_control  (Control) ;

    /* print the input matrix */
    nz = Ap [n] ;
    printf ("\nJumbled input matrix:  %d-by-%d, with %d entries.\n"
	   "   Note that for a symmetric matrix such as this one, only the\n"
	   "   strictly lower or upper triangular parts would need to be\n"
	   "   passed to AMD, since AMD computes the ordering of A+A'.  The\n"
	   "   diagonal entries are also not needed, since AMD ignores them.\n"
	   "   This version of the matrix has jumbled columns and duplicate\n"
	   "   row indices, and must be fixed by amd_preprocess prior to\n"
	   "   ordering it with amd_order.\n" , n, n, nz) ;
    for (j = 0 ; j < n ; j++)
    {
	printf ("\nColumn: %d, number of entries: %d, with row indices in"
		" Ai [%d ... %d]:\n    row indices:",
		j, Ap [j+1] - Ap [j], Ap [j], Ap [j+1]-1) ;
	for (p = Ap [j] ; p < Ap [j+1] ; p++)
	{
	    i = Ai [p] ;
	    printf (" %d", i) ;
	}
	printf ("\n") ;
    }

    /* print a character plot of the input matrix.  This is only reasonable
     * because the matrix is small. */
    printf ("\nPlot of (jumbled) input matrix pattern:\n") ;
    for (j = 0 ; j < n ; j++)
    {
	for (i = 0 ; i < n ; i++) A [i][j] = '.' ;
	for (p = Ap [j] ; p < Ap [j+1] ; p++)
	{
	    i = Ai [p] ;
	    A [i][j] = 'X' ;
	}
    }
    printf ("    ") ;
    for (j = 0 ; j < n ; j++) printf (" %1d", j % 10) ;
    printf ("\n") ;
    for (i = 0 ; i < n ; i++)
    {
	printf ("%2d: ", i) ;
	for (j = 0 ; j < n ; j++)
	{
	    printf (" %c", A [i][j]) ;
	}
	printf ("\n") ;
    }

    /* sort, remove duplicates, and transpose A to get R */
    result = amd_preprocess (n, Ap, Ai, Rp, Ri) ;
    printf ("return value from amd_preprocess: %d (should be %d)\n",
	result, AMD_OK) ;

    if (result != AMD_OK)
    {
	printf ("AMD failed\n") ;
	exit (1) ;
    }

    /* print the sorted/transposed matrix R */
    printf ("\nThe column-oriented form of the sorted/transposed matrix R:\n");
    for (j = 0 ; j < n ; j++)
    {
	printf ("\nColumn: %d, number of entries: %d, with row indices in"
		" Ri [%d ... %d]:\n    row indices:",
		j, Rp [j+1] - Rp [j], Rp [j], Rp [j+1]-1) ;
	for (p = Rp [j] ; p < Rp [j+1] ; p++)
	{
	    i = Ri [p] ;
	    printf (" %d", i) ;
	}
	printf ("\n") ;
    }

    /* print a character plot of the matrix R. */
    printf ("\nPlot of the sorted/transposed matrix R:\n") ;
    for (j = 0 ; j < n ; j++)
    {
	for (i = 0 ; i < n ; i++) A [i][j] = '.' ;
	for (p = Rp [j] ; p < Rp [j+1] ; p++)
	{
	    i = Ri [p] ;
	    A [i][j] = 'X' ;
	}
    }
    printf ("    ") ;
    for (j = 0 ; j < n ; j++) printf (" %1d", j % 10) ;
    printf (" \n") ;
    for (i = 0 ; i < n ; i++)
    {
	printf ("%2d: ", i) ;
	for (j = 0 ; j < n ; j++)
	{
	    printf (" %c", A [i][j]) ;
	}
	printf (" \n") ;
    }

    /* print a character plot of the matrix R+R'. */
    printf ("\nPlot of symmetric matrix to be ordered by amd_order:\n") ;
    for (j = 0 ; j < n ; j++)
    {
	for (i = 0 ; i < n ; i++) A [i][j] = '.' ;
    }
    for (j = 0 ; j < n ; j++)
    {
	A [j][j] = 'X' ;
	for (p = Rp [j] ; p < Rp [j+1] ; p++)
	{
	    i = Ri [p] ;
	    A [i][j] = 'X' ;
	    A [j][i] = 'X' ;
	}
    }
    printf ("    ") ;
    for (j = 0 ; j < n ; j++) printf (" %1d", j % 10) ;
    printf ("\n") ;
    for (i = 0 ; i < n ; i++)
    {
	printf ("%2d: ", i) ;
	for (j = 0 ; j < n ; j++)
	{
	    printf (" %c", A [i][j]) ;
	}
	printf ("\n") ;
    }

    /* order the matrix */
    result = amd_order (n, Rp, Ri, P, Control, Info) ;
    printf ("return value from amd_order: %d (should be %d)\n",
	result, AMD_OK) ;

    /* print the statistics */
    amd_info (Info) ;

    if (result != AMD_OK)
    {
	printf ("AMD failed\n") ;
	exit (1) ;
    }

    /* print the permutation vector, P, and compute the inverse permutation */
    printf ("Permutation vector:\n") ;
    for (k = 0 ; k < n ; k++)
    {
	/* row/column j is the kth row/column in the permuted matrix */
	j = P [k] ;
	Pinv [j] = k ;
	printf (" %2d", j) ;
    }
    printf ("\n\n") ;

    printf ("Inverse permutation vector:\n") ;
    for (j = 0 ; j < n ; j++)
    {
	k = Pinv [j] ;
	printf (" %2d", k) ;
    }
    printf ("\n\n") ;

    /* print a character plot of the permuted matrix. */
    printf ("\nPlot of (symmetrized) permuted matrix pattern:\n") ;
    for (j = 0 ; j < n ; j++)
    {
	for (i = 0 ; i < n ; i++) A [i][j] = '.' ;
    }
    for (jnew = 0 ; jnew < n ; jnew++)
    {
	j = P [jnew] ;
	A [jnew][jnew] = 'X' ;
	for (p = Rp [j] ; p < Rp [j+1] ; p++)
	{
	    inew = Pinv [Ri [p]] ;
	    A [inew][jnew] = 'X' ;
	    A [jnew][inew] = 'X' ;
	}
    }
    printf ("    ") ;
    for (j = 0 ; j < n ; j++) printf (" %1d", j % 10) ;
    printf ("\n") ;
    for (i = 0 ; i < n ; i++)
    {
	printf ("%2d: ", i) ;
	for (j = 0 ; j < n ; j++)
	{
	    printf (" %c", A [i][j]) ;
	}
	printf ("\n") ;
    }

    return (0) ;
}
Beispiel #13
0
static int set_defaults(double *control)
{
    int_t pos=0;
    int param_id;
    PyObject *param, *key, *value;
#if PY_MAJOR_VERSION < 3
    char *keystr; 
#endif
    char err_str[100];

    amd_defaults(control);

    if (!(param = PyObject_GetAttrString(amd_module, "options")) ||
        !PyDict_Check(param)){
        PyErr_SetString(PyExc_AttributeError, "missing amd.options"
            "dictionary");
        return 0;
    }
    while (PyDict_Next(param, &pos, &key, &value))
#if PY_MAJOR_VERSION >= 3
        if ((PyUnicode_Check(key)) && 
            get_param_idx(_PyUnicode_AsString(key),&param_id)) {
            if (!PyLong_Check(value) && !PyFloat_Check(value)){
                sprintf(err_str, "invalid value for AMD parameter: %-.20s",
                    _PyUnicode_AsString(key));
#else
        if ((keystr = PyString_AsString(key)) && get_param_idx(keystr,
            &param_id)) {
            if (!PyInt_Check(value) && !PyFloat_Check(value)){
                sprintf(err_str, "invalid value for AMD parameter: "
                    "%-.20s", keystr);
#endif
                PyErr_SetString(PyExc_ValueError, err_str);
                Py_DECREF(param);
                return 0;
            }
            control[param_id] = PyFloat_AsDouble(value);
        }
    Py_DECREF(param);
    return 1;
}


static char doc_order[] =
    "Computes the approximate minimum degree ordering of a square "
    "matrix.\n\n"
    "p = order(A, uplo='L')\n\n"
    "PURPOSE\n"
    "Computes a permutation p that reduces fill-in in the Cholesky\n"
    "factorization of A[p,p].\n\n"
    "ARGUMENTS\n"
    "A         square sparse matrix\n\n"
    "uplo      'L' or 'U'.  If uplo is 'L', the lower triangular part\n"
    "          of A is used and the upper triangular is ignored.  If\n"
    "          uplo is 'U', the upper triangular part is used and the\n"
    "          lower triangular part is ignored.\n\n"
    "p         'i' matrix of length equal to the order of A";


static PyObject* order_c(PyObject *self, PyObject *args, PyObject *kwrds)
{
    spmatrix *A;
    matrix *perm;
#if PY_MAJOR_VERSION >= 3
    int uplo_ = 'L';
#endif
    char uplo = 'L';
    int j, k, n, nnz, alloc=0, info;
    int_t *rowind=NULL, *colptr=NULL;
    double control[AMD_CONTROL];
    char *kwlist[] = {"A", "uplo", NULL};

#if PY_MAJOR_VERSION >= 3
    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|C", kwlist, &A,
        &uplo_)) return NULL;
    uplo = (char) uplo_;
#else
    if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|c", kwlist, &A,
        &uplo)) return NULL;
#endif
    if (!set_defaults(control)) return NULL;
    if (!SpMatrix_Check(A) || SP_NROWS(A) != SP_NCOLS(A)){
        PyErr_SetString(PyExc_TypeError, "A must be a square sparse "
            "matrix");
        return NULL;
    }
    if (uplo != 'U' && uplo != 'L') err_char("uplo", "'L', 'U'");
    if (!(perm = (matrix *) Matrix_New((int)SP_NROWS(A),1,INT)))
        return PyErr_NoMemory();
    n = SP_NROWS(A);
    for (nnz=0, j=0; j<n; j++) {
        if (uplo == 'L'){
            for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] && SP_ROW(A)[k]<j; k++);
            nnz += SP_COL(A)[j+1] - k;
        }
        else {
            for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] && SP_ROW(A)[k] <= j;
                k++);
            nnz += k - SP_COL(A)[j];
        }
    }
    if (nnz == SP_NNZ(A)){
        colptr = (int_t *) SP_COL(A);
        rowind = (int_t *) SP_ROW(A);
    }
    else {
        alloc = 1;
        colptr = (int_t *) calloc(n+1, sizeof(int_t));
        rowind = (int_t *) calloc(nnz, sizeof(int_t));
        if (!colptr || !rowind) {
            Py_XDECREF(perm);  free(colptr);  free(rowind);
            return PyErr_NoMemory();
        }
        colptr[0] = 0;
        for (j=0; j<n; j++) {
            if (uplo == 'L'){
                for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] && SP_ROW(A)[k] < j; 
                    k++);
                nnz = SP_COL(A)[j+1] - k;
                colptr[j+1] = colptr[j] + nnz;
                memcpy(rowind + colptr[j], (int_t *) SP_ROW(A) + k,
                    nnz*sizeof(int_t));
            }
            else {
                for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] && SP_ROW(A)[k] <= j;
                    k++);
                nnz = k - SP_COL(A)[j];
                colptr[j+1] = colptr[j] + nnz;
                memcpy(rowind + colptr[j], (int_t *) (SP_ROW(A) +
                    SP_COL(A)[j]), nnz*sizeof(int_t));
            }
        }
    }
    info = amd_order(n, colptr, rowind, MAT_BUFI(perm), control, NULL);
    if (alloc){
        free(colptr);
        free(rowind);
    }
    switch (info) {
        case AMD_OUT_OF_MEMORY:
            Py_XDECREF(perm);
            return PyErr_NoMemory();

        case AMD_INVALID:
            Py_XDECREF(perm);
            return Py_BuildValue("");

        case AMD_OK:
            return (PyObject *) perm;
    }
    return Py_BuildValue("");
}

static PyMethodDef amd_functions[] = {
    {"order", (PyCFunction) order_c, METH_VARARGS|METH_KEYWORDS, doc_order},
    {NULL}  /* Sentinel */
};

#if PY_MAJOR_VERSION >= 3

static PyModuleDef amd_module_def = {
    PyModuleDef_HEAD_INIT,
    "amd",
    amd__doc__,
    -1,
    amd_functions,
    NULL, NULL, NULL, NULL
};

PyMODINIT_FUNC PyInit_amd(void)
{
    if (!(amd_module = PyModule_Create(&amd_module_def))) return NULL;
    PyModule_AddObject(amd_module, "options", PyDict_New());
    if (import_cvxopt() < 0) return NULL;
    return amd_module;
}

#else
PyMODINIT_FUNC initamd(void)
{
    amd_module = Py_InitModule3("cvxopt.amd", amd_functions, amd__doc__);
    PyModule_AddObject(amd_module, "options", PyDict_New());
    if (import_cvxopt() < 0) return;
}