コード例 #1
0
ファイル: hessenberg_orthog.c プロジェクト: ffavaro/uQuad2
////////////////////////////////////////////////////////////////////////////////
//  int Hessenberg_Form_Orthogonal(double *A, double *U, int n)               //
//                                                                            //
//  Description:                                                              //
//     This program transforms the square matrix A to a similar matrix in     //
//     Hessenberg form by a multiplying A on the right and left by a sequence //
//     of Householder transformations.                                        //
//     Def:  Two matrices A and B are said to be orthogonally similar if there//
//           exists an orthogonal matrix U such that A U = U B.               //
//     Def   A Hessenberg matrix is the sum of an upper triangular matrix and //
//           a matrix all of whose components are 0 except possibly on its    //
//           subdiagonal.  A Hessenberg matrix is sometimes said to be almost //
//           upper triangular.                                                //
//     Def:  A Householder transformation is an orthogonal transformation of  //
//           the form Q = I - 2 uu'/u'u, where u is a n x 1 column matrix and //
//           ' denotes the transpose.                                         //
//     Thm:  If Q is a Householder transformation then Q' = Q  and  Q' Q = I, //
//           i.e. Q is a symmetric involution.                                //
//     The algorithm proceeds by successivly selecting columns j = 0,...,n-3  //
//     and then calculating the Householder transformation Q which annihilates//
//     the components below the subdiagonal for that column and leaves the    //
//     previously selected columns invariant.  The algorithm then updates     //
//     the matrix A, in place, by premultiplication by Q followed by          //
//     postmultiplication by Q.                                               //
//     If the j-th column of A is (a[0],...,a[n-1]), then  choose u' =        //
//     (u[0],...,u[n-1]) by u[0] = 0, ... , u[j] = 0, u[j+2] = a[j+2],...,    //
//     u[n-1] = a[n-1].  The remaining component u[j+1] = a[j+1] - s, where   //
//     s^2 = a[j+1]^2 + ... + a[n-1]^2, and the choice of sign for s,         //
//     sign(s) = -sign(a[j+1]) maximizes the number of significant bits for   //
//     u[j+1].                                                                //
//                                                                            //
//     Remark:  If H = U' A U, where U is orthogonal, and if v is an eigen-   //
//     vector of H with eigenvalue x, then A U v = U H v = x U v, so that     //
//     U v is an eigenvector of A with corresponding eigenvalue x.            //
//                                                                            //
//  Arguments:                                                                //
//     double *A   Pointer to the first element of the matrix A[n][n].        //
//                 The original matrix A is replaced with the orthogonally    //
//                 similar matrix in Hessenberg form.                         //
//     double *U   Pointer to the first element of the matrix U[n][n].  The   //
//                 orthogonal matrix which transforms the input matrix to     //
//                 an orthogonally similar matrix in Hessenberg form.         //
//     int     n   The number of rows or columns of the matrix A.             //
//                                                                            //
//  Return Values:                                                            //
//     0  Success                                                             //
//    -1  Failure - Unable to allocate space for working storage.             //
//                                                                            //
//  Example:                                                                  //
//     #define N                                                              //
//     double A[N][N], U[N][N];                                               //
//                                                                            //
//     (your code to create the matrix A)                                     //
//     Hessenberg_Form_Orthogonal(&A[0][0], (double*) U, N);                  //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//                                                                            //
int Hessenberg_Form_Orthogonal(double *A, double *U, int n)
{
   int i, k, col;
   double *u;
   double *p_row, *psubdiag;
   double *pA, *pU;
   double sss;                             // signed sqrt of sum of squares
   double scale;
   double innerproduct;

         // n x n matrices for which n <= 2 are already in Hessenberg form

   Identity_Matrix(U, n);
   if (n <= 2) return 0;

         // Reserve auxillary storage, if unavailable, return an error

   u = (double *) malloc(n * sizeof(double));
   if (u == NULL) return -1;

           // For each column use a Householder transformation 
           //   to zero all entries below the subdiagonal.

   for (psubdiag = A + n, col = 0; col < (n - 2); psubdiag += (n+1), col++) {

          // Calculate the signed square root of the sum of squares of the
          // elements below the diagonal.

      for (pA = psubdiag, sss = 0.0, i = col + 1; i < n; pA += n, i++)
         sss += *pA * *pA;
      if (sss == 0.0) continue;
      sss = sqrt(sss);
      if ( *psubdiag >= 0.0 ) sss = -sss;

          // Calculate the Householder transformation Q = I - 2uu'/u'u.

      u[col + 1] = *psubdiag - sss;
      *psubdiag = sss; 
      for (pA = psubdiag + n, i = col + 2; i < n; pA += n, i++) {
         u[i] = *pA;
         *pA = 0.0;
      }

                    // Premultiply A by Q
   
      scale = -1.0 / (sss * u[col+1]);
      for (p_row = psubdiag - col, i = col + 1; i < n; i++) {
         pA = A + n * (col + 1) + i;
         for (innerproduct = 0.0, k = col + 1; k < n; pA += n, k++) 
            innerproduct += u[k] * *pA;
         innerproduct *= scale;
         for (pA = p_row + i, k = col + 1; k < n; pA += n, k++) 
            *pA -= u[k] * innerproduct;
      }
        
                    // Postmultiply QA by Q

      for (p_row = A, i = 0; i < n; p_row += n, i++) {
         for (innerproduct = 0.0, k = col + 1; k < n; k++) 
            innerproduct += u[k] * *(p_row + k);
         innerproduct *= scale;
         for (k = col + 1; k < n; k++) 
            *(p_row + k) -= u[k] * innerproduct;
      }
        
                    // Postmultiply U by (I - 2uu')

      for (i = 0, pU = U; i < n; pU += n, i++) {
         for (innerproduct = 0.0, k = col + 1; k < n; k++) 
            innerproduct += u[k] * *(pU + k);
         innerproduct *= scale;
         for (k = col + 1; k < n; k++) 
            *(pU + k) -= u[k] * innerproduct;
      }

   }

   free(u);

   return 0;
}
コード例 #2
0
/**
 * Given a matrix with m parameterized equations, compress the nb_parms
 * parameters and n-m variables so that m variables are integer, and transform
 * the variable space into a n-m space by eliminating the m variables (using
 * the equalities) the variables to be eliminated are chosen automatically by
 * the function.
 * <b>Deprecated.</b> Try to use Constraints_fullDimensionize instead.
 * @param M the constraints 
 * @param the number of parameters
 * @param validityLattice the the integer lattice underlying the integer
 * solutions.
*/
Matrix * full_dimensionize(Matrix const * M, int nbParms, 
			   Matrix ** validityLattice) {
  Matrix * Eqs, * Ineqs;
  Matrix * permutedEqs, * permutedIneqs;
  Matrix * Full_Dim;
  Matrix * WVL; /* The Whole Validity Lattice (vars+parms) */
  unsigned int i,j;
  int nbElimVars;
  unsigned int * permutation, * permutationInv;
  /* 0- Split the equalities and inequalities from each other */
  split_constraints(M, &Eqs, &Ineqs);

  /* 1- if the polyhedron is already full-dimensional, return it */
  if (Eqs->NbRows==0) {
    Matrix_Free(Eqs);
    (*validityLattice) = Identity_Matrix(nbParms+1);
    return Ineqs;
  }
  nbElimVars = Eqs->NbRows;

  /* 2- put the vars to be eliminated at the first positions, 
     and compress the other vars/parms
     -> [ variables to eliminate / parameters / variables to keep ] */
  permutation = find_a_permutation(Eqs, nbParms);
  if (dbgCompParm) {
    printf("Permuting the vars/parms this way: [ ");
    for (i=0; i< Eqs->NbColumns; i++) {
      printf("%d ", permutation[i]);
    }
    printf("]\n");
  }
  permutedEqs = mpolyhedron_permute(Eqs, permutation);
  WVL = compress_parms(permutedEqs, Eqs->NbColumns-2-Eqs->NbRows);
  if (dbgCompParm) {
    printf("Whole validity lattice: ");
    show_matrix(WVL);
  }
  mpolyhedron_compress_last_vars(permutedEqs, WVL);
  permutedIneqs = mpolyhedron_permute(Ineqs, permutation);
  if (dbgCompParm) {
    show_matrix(permutedEqs);
  }
  Matrix_Free(Eqs);
  Matrix_Free(Ineqs);
  mpolyhedron_compress_last_vars(permutedIneqs, WVL);
  if (dbgCompParm) {
    printf("After compression: ");
    show_matrix(permutedIneqs);
  }
  /* 3- eliminate the first variables */
  if (!mpolyhedron_eliminate_first_variables(permutedEqs, permutedIneqs)) {
    fprintf(stderr,"full-dimensionize > variable elimination failed. \n"); 
    return NULL;
  }
  if (dbgCompParm) {
    printf("After elimination of the variables: ");
    show_matrix(permutedIneqs);
  }

  /* 4- get rid of the first (zero) columns, 
     which are now useless, and put the parameters back at the end */
  Full_Dim = Matrix_Alloc(permutedIneqs->NbRows,
			  permutedIneqs->NbColumns-nbElimVars);
  for (i=0; i< permutedIneqs->NbRows; i++) {
    value_set_si(Full_Dim->p[i][0], 1);
    for (j=0; j< nbParms; j++) 
      value_assign(Full_Dim->p[i][j+Full_Dim->NbColumns-nbParms-1], 
		   permutedIneqs->p[i][j+nbElimVars+1]);
    for (j=0; j< permutedIneqs->NbColumns-nbParms-2-nbElimVars; j++) 
      value_assign(Full_Dim->p[i][j+1], 
		   permutedIneqs->p[i][nbElimVars+nbParms+j+1]);
    value_assign(Full_Dim->p[i][Full_Dim->NbColumns-1], 
		 permutedIneqs->p[i][permutedIneqs->NbColumns-1]);
  }
  Matrix_Free(permutedIneqs);
  
  /* 5- Keep only the the validity lattice restricted to the parameters */
  *validityLattice = Matrix_Alloc(nbParms+1, nbParms+1);
  for (i=0; i< nbParms; i++) {
    for (j=0; j< nbParms; j++)
      value_assign((*validityLattice)->p[i][j], 
		   WVL->p[i][j]);
    value_assign((*validityLattice)->p[i][nbParms], 
		 WVL->p[i][WVL->NbColumns-1]);
  }
  for (j=0; j< nbParms; j++) 
    value_set_si((*validityLattice)->p[nbParms][j], 0);
  value_assign((*validityLattice)->p[nbParms][nbParms], 
	       WVL->p[WVL->NbColumns-1][WVL->NbColumns-1]);

  /* 6- Clean up */
  Matrix_Free(WVL);
  return Full_Dim;
} /* full_dimensionize */