//////////////////////////////////////////////////////////////////////////////// // 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; }
/** * 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 */