Main Page | Class List | File List | Class Members | File Members

matrix_permutations.c

Go to the documentation of this file.
00001 // Permutations on matrices
00002 // Matrices are seen either as transformations (mtransformation) or as polyhedra (mpolyhedron)
00003 // B. Meister
00004 // C code
00005 
00006 #include <polylib/matrix_permutations.h>
00007 
00008 // utility function : bit count (i know, there are faster methods)
00009 unsigned int nb_bits(unsigned long long int x) {
00010   unsigned int i,n=0;
00011   unsigned long long int y=x;
00012   for (i=0; i< 64; i++) {
00013     n+=y%2;
00014     y>>=1;
00015   }
00016   return n;
00017 }
00018 
00019 
00020 // gives the inverse permutation vector of a permutation vector
00021 unsigned int * permutation_inverse(unsigned int * perm, unsigned int nb_elems) {
00022   int i;
00023   unsigned int * inv_perm = (unsigned int *)malloc(sizeof(unsigned int) * nb_elems);
00024   for (i=0; i< nb_elems; i++) inv_perm[perm[i]] = i;
00025   return inv_perm;
00026 }
00027   
00028 
00029 // Given a linear tranformation on initial variables, and a variable permutation, compute the tranformation for the permuted variables.
00030 // perm is a vector giving the new "position of the k^th variable, k \in [1..n]
00031 // we can call it a "permutation vector" if you wish
00032 // transf[x][y] -> permuted[permutation(x)][permutation(y)]
00033 Matrix * mtransformation_permute(Matrix * transf, unsigned int * permutation) {
00034   unsigned int i,j;
00035   // the transformation is supposed to be from Q^n to Q^n, so a square matrix.
00036   assert(transf->NbRows==transf->NbColumns);
00037   Matrix * permuted = Matrix_Alloc(transf->NbRows, transf->NbRows);
00038   for (i= 0; i< transf->NbRows; i++) {
00039     for (j= 0; j< transf->NbRows; j++) {
00040       value_assign(permuted->p[permutation[i]][permutation[j]], transf->p[i][j]);
00041     }
00042   }
00043   return permuted;
00044 }
00045 
00046 // permutes the variables of a matrix seen as a polyhedron
00047 Matrix * mpolyhedron_permute(Matrix * polyh, unsigned int * permutation) {
00048   unsigned int i,j;
00049   Matrix * permuted = Matrix_Alloc(polyh->NbRows, polyh->NbColumns);
00050   for (i= 0; i< polyh->NbRows; i++) {
00051     value_assign(permuted->p[i][0], polyh->p[i][0]);
00052     for (j= 1; j< polyh->NbColumns; j++) {
00053       value_assign(permuted->p[i][permutation[j-1]+1], polyh->p[i][j]);
00054     }
00055   }
00056   return permuted;
00057 }
00058 
00059 
00060 // find a valid permutation : for a set of m equations, find m variables that will be put at the beginning (to be eliminated)
00061 // it must be possible to eliminate these variables : the submatrix built with their columns must be full-rank.
00062 // brute force method, that tests all the combinations until finding one which works.
00063 // LIMITATIONS : up to x-1 variables, where the long long format is x-1 bits (often 64 in year 2005).
00064 unsigned int * find_a_permutation(Matrix * Eqs, unsigned int nb_parms) {
00065   unsigned int i, j, k;
00066   int nb_vars = Eqs->NbColumns-nb_parms-2;
00067   unsigned long long int combination;
00068   unsigned int * permutation = (unsigned int *)malloc(sizeof(unsigned int) * Eqs->NbColumns-1);
00069   int found = 0;
00070   Matrix * Square_Mat = Matrix_Alloc(Eqs->NbRows, Eqs->NbRows);
00071   Matrix * M, * H, * Q, *U;
00072 
00073   // generate all the combinations of Eqs->NbRows variables (-> bits to 1 in the word "combination") among nb_vars
00074   // WARNING : we assume here that we have not more than 64 variables...
00075   // you may convert it to use GNU MP to set it to an infinite number of bits
00076   for (combination = ((unsigned long long int) 1<<(Eqs->NbRows))-1; (combination < ((unsigned long long int) 1 << nb_vars)) ; combination ++) {
00077     if (nb_bits(combination) == Eqs->NbRows) {
00078       k=0;
00079       // 1- put the m colums in a square matrix
00080       for (j=0; j< nb_vars; j++) {
00081         if ((combination>>j)%2) {
00082           for (i=0; i< Eqs->NbRows; i++) {
00083             value_assign(Square_Mat->p[i][k], Eqs->p[i][j]);
00084           }
00085           k++;
00086         }
00087       }
00088       // 2- see if the matrix is full-row-rank
00089       right_hermite(Square_Mat, &Q, &H, &U);
00090       Matrix_Free(Q);
00091       Matrix_Free(U);
00092       // if it is full-row-rank, we have found a set of variables that can be eliminated. (to be prooved in order to be clean)
00093       if (H->p[Eqs->NbRows-1][Eqs->NbRows-1]!=0) {
00094         // 3- make the permutation matrix
00095         //  a- deal with the variables
00096         k=0;
00097         for (i=0; i< nb_vars; i++) {
00098           // if the variable has to be eliminated, put them at the beginning
00099           if (combination%2) {
00100             permutation[i] = k;
00101             k++;
00102           }
00103           // if not, put the variables at the end
00104           else permutation[i] = Eqs->NbRows+nb_parms+ i-k;
00105           combination>>=1;
00106         }
00107         //  b- deal with the parameters
00108         for (i=0; i< nb_parms; i++) {
00109           permutation[nb_vars+i] = Eqs->NbRows+i;
00110         }
00111         //  c- deal with the constant
00112         permutation[Eqs->NbColumns-2] = Eqs->NbColumns-2;
00113         // have a look at the permutation
00114         // printf(" Permutation : ");
00115         // for (i=0; i< Eqs->NbColumns-1; i++) printf("%u ", permutation[i]);
00116         // return it.
00117         return permutation;
00118       }
00119       Matrix_Free(H);
00120     }
00121   }
00122   // if no combination of variables allow an elimination, then return an error code.
00123   return NULL;
00124 }
00125 // find_a_permutation
00126 
00127 
00128 
00129 // compute the permutation of variables and parameters, according to some variables to keep.
00130 // put the variables not to be kept at the beginning, then the parameters and finally the variables to be kept.
00131 // strongly related to the function compress_to_full_dim2
00132 unsigned int * permutation_for_full_dim2(unsigned int * vars_to_keep, unsigned int nb_keep, unsigned int nb_vars_parms, unsigned int nb_parms) {
00133   unsigned int * permutation = (unsigned int*)malloc(sizeof(unsigned int) * nb_vars_parms+1);
00134   unsigned int i;
00135   int cur_keep =0, cur_go = 0; // current number of variables to eliminate and to keep
00136   for (i=0; i< nb_vars_parms - nb_parms; i++) {
00137     if (i==vars_to_keep[cur_keep]) {
00138       permutation[i] = nb_vars_parms-nb_keep+cur_keep;
00139       cur_keep++;
00140     }
00141     else {
00142       permutation[i] = cur_go;
00143       cur_go++;
00144     }
00145   }
00146   // parameters are just left-shifted
00147   for (i=0; i< nb_parms; i++)
00148     permutation[i+nb_vars_parms-nb_parms] = i+nb_vars_parms-nb_parms-nb_keep;
00149 
00150   // contants stay where they are
00151   permutation[nb_vars_parms] = nb_vars_parms;
00152   return permutation;
00153 } // permutation_for_full_dim2
00154 
00155 
00156 // END OF STUFF WITH PERMUTATIONS

Generated on Mon Sep 12 15:15:11 2005 for polylib by doxygen 1.3.5