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

matrix_permutations.c

Go to the documentation of this file.
00001 /** 
00002  * $Id: matrix_permutations.c,v 1.8 2006/10/01 02:10:46 meister Exp $
00003  *
00004  * Permutations on matrices Matrices are seen either as transformations
00005  * (mtransformation) or as polyhedra (mpolyhedron)
00006  * @author B. Meister
00007  * LSIIT -ICPS 
00008  * UMR 7005 CNRS
00009  * Louis Pasteur University (ULP), Strasbourg, France 
00010  * 
00011  * Permutations are just indirection vectors: the k^th element of a permutation
00012  * vector is the position of the k^th variable in the permuted object.
00013  */
00014 
00015 #include <stdlib.h>
00016 #include <polylib/matrix_permutations.h>
00017 
00018 /** utility function : bit count (i know, there are faster methods) */
00019 unsigned int nb_bits(unsigned long long int x) {
00020   unsigned int i,n=0;
00021   unsigned long long int y=x;
00022   for (i=0; i< 64; i++) {
00023     n+=y%2;
00024     y>>=1;
00025   }
00026   return n;
00027 }
00028 
00029 
00030 /** Gives the inverse permutation vector of a permutation vector 
00031  * @param perm the permutation vector
00032  * @param 
00033 */
00034 unsigned int * permutation_inverse(unsigned int * perm, unsigned int nb_elems) {
00035   int i;
00036   unsigned int * inv_perm = (unsigned int *)malloc(sizeof(unsigned int) * nb_elems);
00037   for (i=0; i< nb_elems; i++) inv_perm[perm[i]] = i;
00038   return inv_perm;
00039 }
00040   
00041 
00042 /**
00043  * Given a linear tranformation on initial variables, and a variable
00044  * permutation, computes the tranformation for the permuted variables.  perm is
00045  * a vector giving the new "position of the k^th variable, k \in [1..n] we can
00046  * call it a "permutation vector" if you wish transf[x][y] ->
00047  * permuted[permutation(x)][permutation(y)]
00048  */
00049 Matrix * mtransformation_permute(Matrix * transf, unsigned int * permutation) {
00050   Matrix * permuted;
00051   unsigned int i,j;
00052   /* the transformation is supposed to be from Q^n to Q^n, so a square matrix. */
00053   assert(transf->NbRows==transf->NbColumns);
00054   permuted = Matrix_Alloc(transf->NbRows, transf->NbRows);
00055   for (i= 0; i< transf->NbRows; i++) {
00056     for (j= 0; j< transf->NbRows; j++) {
00057       value_assign(permuted->p[permutation[i]][permutation[j]], transf->p[i][j]);
00058     }
00059   }
00060   return permuted;
00061 }
00062 
00063 
00064 /** permutes the variables of the constraints of a polyhedron 
00065  * @param polyh the constraints of the polyhedron
00066  * @param permutation a permutation vector
00067 */
00068 Matrix * mpolyhedron_permute(Matrix * polyh, unsigned int * permutation) {
00069   unsigned int i,j;
00070   Matrix * permuted = Matrix_Alloc(polyh->NbRows, polyh->NbColumns);
00071   for (i= 0; i< polyh->NbRows; i++) {
00072     value_assign(permuted->p[i][0], polyh->p[i][0]);
00073     for (j= 1; j< polyh->NbColumns; j++) {
00074       value_assign(permuted->p[i][permutation[j-1]+1], polyh->p[i][j]);
00075     }
00076   }
00077   return permuted;
00078 }
00079 
00080 
00081 /** permutes the variables of the constraints of a polyhedron 
00082  * @param C the original set of constraints
00083  * @param perm a permutation vector
00084  * @param Cp (returned) the set of constraints whose variables are
00085  * permuted. Allocated if set to NULL, assumed to be already allocated if not.
00086  */
00087 void Constraints_permute(Matrix * C, unsigned int * perm, Matrix ** Cp) {
00088   unsigned int i,j;
00089   if ((*Cp)==NULL) {
00090     (*Cp) = Matrix_Alloc(C->NbRows, C->NbColumns);
00091   }
00092   else {
00093     assert((*Cp)->NbRows == C->NbRows && (*Cp)->NbColumns==C->NbColumns);
00094   }
00095   for (i= 0; i< C->NbRows; i++) {
00096     value_assign((*Cp)->p[i][0], C->p[i][0]);
00097     for (j= 1; j< C->NbColumns; j++) {
00098       value_assign((*Cp)->p[i][perm[j-1]+1], C->p[i][j]);
00099     }
00100   }
00101 } /* Constraints_permute */
00102 
00103 
00104 /** Given a set of <i>equalities</i>, find a set of variables that can be
00105  * eliminated using these equalities.  The variables that we agree to eliminate
00106  * are in a zone of contiguous variables (or parameters).  <p>
00107  * Notes: 
00108  <ul>
00109  <li>brute force, surely enhanceable algorithm</li>
00110  <li>limited number of variables in the zone: limit = bitwidth of long long
00111  </ul>
00112  * @param Eqs the matrix of equalities.
00113  * @param start the rank of the first variable (inclusive) of the zone in Eqs
00114  * @param end the rank of the last variable (inclusive) of the zone
00115  * return a bitfield where bits set to one define the variables to eliminate
00116 */
00117 unsigned long long int eliminable_vars(Matrix * Eqs, unsigned start, 
00118                                       unsigned end) {
00119   unsigned long long int combination;
00120   unsigned int i,j,k;
00121   Matrix * M, * H, * Q, *U;
00122   Matrix * Square_Mat, *Eqs2;
00123   unsigned nb_vars = end - start + 1 ;
00124   Polyhedron * OverConstrained;
00125 
00126   assert (start>0 && end < Eqs->NbColumns-1);
00127 
00128   /* if the affine hull is overconstrained, return 0 */
00129   if (Eqs->NbRows >nb_vars) {
00130     /* FIXME: there is a magic maximum number of rays here */
00131     Eqs2 = Matrix_Copy(Eqs);
00132     OverConstrained = Constraints2Polyhedron(Eqs2,
00133                                              Eqs->NbColumns*Eqs->NbColumns);
00134     Matrix_Free(Eqs2);
00135     if (emptyQ(OverConstrained)) {
00136       Polyhedron_Free(OverConstrained);
00137       return 0;
00138     }
00139     Polyhedron_Free(OverConstrained);
00140   }
00141 
00142   /* do not accept 0 = 0 equalities */
00143   for (i=0; i< Eqs->NbRows; i++) {
00144     assert (!Vector_IsZero(Eqs->p[i], Eqs->NbColumns));
00145   }
00146   
00147   Square_Mat= Matrix_Alloc(Eqs->NbRows, Eqs->NbRows);
00148   
00149   /* There are Eqs->NbRows variables to eliminate.
00150      Generate all the combinations of Eqs->NbRows variables (-> bits to 1 in
00151      the word "combination") among nb_vars WARNING : we assume here that we
00152      have not more than 64 variables.  You may convert it to use GNU MP to
00153      set it to an infinite number of bits 
00154   */
00155   for (combination = ((unsigned long long int) 1<<(Eqs->NbRows))-1;
00156        (combination < ((unsigned long long int) 1 << nb_vars)) ;
00157        combination++) {
00158     if (nb_bits(combination) == Eqs->NbRows) {
00159       k=0;
00160       /* 1- put the m colums in a square matrix */
00161       for (j=0; j< nb_vars; j++) {
00162         if ((combination>>j)%2) {
00163           for (i=0; i< Eqs->NbRows; i++) {
00164             value_assign(Square_Mat->p[i][k], Eqs->p[i][j+start]);
00165           }
00166           k++;
00167         }
00168       }
00169       /* 2- see if the matrix is full-row-rank */
00170       right_hermite(Square_Mat, &H, &Q, &U);
00171       Matrix_Free(Q);
00172       Matrix_Free(U);
00173 
00174       /* if it is full-row-rank, we have found a set of variables that can be
00175          eliminated. */
00176       if ( value_notzero_p((H->p[Eqs->NbRows-1][Eqs->NbRows-1])) ) {
00177         Matrix_Free(Square_Mat);
00178         Matrix_Free(H);
00179         return combination;
00180       }
00181       Matrix_Free(H);
00182     }
00183   }
00184   Matrix_Free(Square_Mat);
00185   return (unsigned long long int) 0;
00186 } /* eliminable_vars */
00187 
00188 
00189 
00190 /** 
00191  * finds a valid permutation : for a set of m equations, find m variables that
00192  * will be put at the beginning (to be eliminated). 
00193  * Note: inherits the limited the number of variables from
00194  * <i>eliminable_vars</i>
00195  */
00196 unsigned int * find_a_permutation(Matrix * Eqs, unsigned int nb_parms) {
00197   unsigned int i, j, k;
00198   int nb_vars = Eqs->NbColumns-nb_parms-2;
00199   unsigned long long int combination;
00200   unsigned int * permutation = (unsigned int *)malloc(sizeof(unsigned int) *
00201                                                       Eqs->NbColumns-1);
00202 
00203   /* 1- find a set of variables to eliminate */
00204   if ((combination = eliminable_vars(Eqs, 1, nb_vars)) == 0) {
00205     /* if it is impossible to eliminate enough variables, return error code */
00206     return NULL;
00207   }
00208 
00209   /* 2- make the permutation matrix
00210    *   a- deal with the variables */
00211   k=0;
00212   for (i=0; i< nb_vars; i++) {
00213     /* if the variable has to be eliminated, put them at the beginning */
00214     if (combination%2) {
00215       permutation[i] = k;
00216       k++;
00217     }
00218     /* if not, put the variables at the end */
00219     else permutation[i] = Eqs->NbRows+nb_parms+ i-k;
00220     combination>>=1;
00221   }
00222   /*  b- deal with the parameters */
00223   for (i=0; i< nb_parms; i++) {
00224     permutation[nb_vars+i] = Eqs->NbRows+i;
00225   }
00226   /*  c- deal with the constant */
00227   permutation[Eqs->NbColumns-2] = Eqs->NbColumns-2;
00228   
00229   return permutation;
00230 } /* find_a_permutation */
00231 
00232 
00233 
00234 /** computes the permutation of variables and parameters, according to some
00235  * variables to keep.  put the variables not to be kept at the beginning, then
00236  * the parameters and finally the variables to be kept.  strongly related to
00237  * the function compress_to_full_dim2
00238  */
00239 unsigned int * permutation_for_full_dim2(unsigned int * vars_to_keep, 
00240                                          unsigned int nb_keep, 
00241                                          unsigned int nb_vars_parms, 
00242                                          unsigned int nb_parms) {
00243   unsigned int * permutation = 
00244     (unsigned int*)malloc(sizeof(unsigned int) * nb_vars_parms+1);
00245   unsigned int i;
00246   int cur_keep =0, cur_go = 0;/*current number of variables to eliminate/keep*/
00247   for (i=0; i< nb_vars_parms - nb_parms; i++) {
00248     if (i==vars_to_keep[cur_keep]) {
00249       permutation[i] = nb_vars_parms-nb_keep+cur_keep;
00250       cur_keep++;
00251     }
00252     else {
00253       permutation[i] = cur_go;
00254       cur_go++;
00255     }
00256   }
00257   /* parameters are just left-shifted */
00258   for (i=0; i< nb_parms; i++)
00259     permutation[i+nb_vars_parms-nb_parms] = i+nb_vars_parms-nb_parms-nb_keep;
00260 
00261   /* contants stay where they are */
00262   permutation[nb_vars_parms] = nb_vars_parms;
00263   return permutation;
00264 } /* permutation_for_full_dim2 */

Generated on Mon Apr 23 19:23:52 2007 for polylib by doxygen 1.3.5