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

matrix_addon.c

Go to the documentation of this file.
00001 // Polylib Matrix addons
00002 // Mainly deals with polyhedra represented as a matrix (implicit form)
00003 // B. Meister
00004 #include<polylib/polylib.h>
00005 #include <polylib/matrix_addon.h>
00006 
00007 // splits a matrix of constraints M into a matrix of equalities Eqs and a matrix of inequalities Ineqs
00008 // allocs the new matrices.
00009 void split_constraints(Matrix const * M, Matrix ** Eqs, Matrix **Ineqs) {
00010   unsigned int i, j, k_eq, k_ineq, nb_eqs=0;
00011 
00012   // 1- count the number of equations;
00013   for (i=0; i< M->NbRows; i++)     
00014     if (value_zero_p(M->p[i][0])) nb_eqs++;
00015 
00016   // 2- extract the two matrices of equations
00017   (*Eqs) = Matrix_Alloc(nb_eqs, M->NbColumns);
00018   (*Ineqs) = Matrix_Alloc(M->NbRows-nb_eqs, M->NbColumns);
00019 
00020   k_eq = k_ineq = 0;
00021   for(i=0; i< M->NbRows; i++) {
00022     if (value_zero_p(M->p[i][0])) 
00023       {
00024         for(j=0; j< M->NbColumns; j++)
00025           value_assign((*Eqs)->p[k_eq][j], M->p[i][j]);
00026         k_eq++;
00027       }
00028     else
00029        {
00030         for(j=0; j< M->NbColumns; j++)
00031           value_assign((*Ineqs)->p[k_ineq][j], M->p[i][j]);
00032         k_ineq++;
00033       }
00034   }
00035 }
00036 
00037 // returns the dim-dimensional identity matrix
00038 Matrix * Identity_Matrix(unsigned int dim) {
00039   Matrix * ret = Matrix_Alloc(dim, dim);
00040   unsigned int i,j;
00041   for (i=0; i< dim; i++) {
00042     for (j=0; j< dim; j++) {
00043       if (i==j) 
00044         { value_set_si(ret->p[i][j], 1); } 
00045       else value_set_si(ret->p[i][j], 0);
00046     }
00047   }
00048   return ret;
00049 } // Identity_Matrix
00050 
00051 // given a n x n integer transformation matrix transf, compute its inverse M/g, where M is a nxn integer matrix.
00052 // g is a common denominator for elements of (transf^{-1})
00053 void mtransformation_inverse(Matrix * transf, Matrix ** inverse, Value * g) {
00054   Value factor;
00055   unsigned int i,j;
00056 
00057   value_init(*g);
00058   value_set_si(*g,1);
00059 
00060   // a - compute the inverse as usual (n x (n+1) matrix)
00061   Matrix * tmp = Matrix_Copy(transf);
00062   Matrix * inv = Matrix_Alloc(transf->NbRows, transf->NbColumns+1);
00063   MatInverse(tmp, inv);
00064   Matrix_Free(tmp);
00065 
00066   // b - as it is rational, put it to the same denominator
00067   (*inverse) = Matrix_Alloc(transf->NbRows, transf->NbRows);
00068   for (i=0; i< inv->NbRows; i++) 
00069     Lcm3(*g, inv->p[i][inv->NbColumns-1],g);
00070   for (i=0; i< inv->NbRows; i++) {
00071     value_division(factor, *g, inv->p[i][inv->NbColumns-1]);
00072     for (j=0; j< (*inverse)->NbColumns; j++) value_multiply((*inverse)->p[i][j], inv->p[i][j],  factor);
00073   }
00074 
00075   // c- clean up
00076   value_clear(factor);
00077   Matrix_Free(inv);
00078 } // mtransformation_inverse
00079 
00080 
00081 // takes a transformation matrix, and expands it to a higher dimension with the identity matrix 
00082 // regardless of it homogeneousness
00083 Matrix * mtransformation_expand_left_to_dim(Matrix * M, int new_dim) {
00084   assert(new_dim>=M->NbColumns);
00085   assert(M->NbRows==M->NbColumns);
00086   Matrix * ret = Identity_Matrix(new_dim);
00087   int offset = new_dim-M->NbRows;
00088   unsigned int i,j;
00089   for (i=0; i< M->NbRows; i++)
00090     for (j=0; j< M->NbRows; j++)
00091       value_assign(ret->p[offset+i][offset+j], M->p[i][j]);
00092   return ret;
00093 } // mtransformation_expand_left_to_dim
00094 
00095 
00096 // simplify a matrix seen as a polyhedron, by dividing its rows by the gcd of their elements.
00097 void mpolyhedron_simplify(Matrix * polyh) {
00098   int i, j;
00099   Value cur_gcd;
00100   value_init(cur_gcd);
00101   for (i=0; i< polyh->NbRows; i++) {
00102     value_set_si(cur_gcd, 0);
00103     for (j=1; j< polyh->NbColumns; j++) Gcd(cur_gcd, polyh->p[i][j], &cur_gcd);
00104     printf(" gcd[%d] = ", i); value_print(stdout, VALUE_FMT, cur_gcd);printf("\n");
00105     for (j=1; j< polyh->NbColumns; j++) value_division(polyh->p[i][j], polyh->p[i][j], cur_gcd);
00106   }
00107   value_clear(cur_gcd);
00108 } // mpolyhedron_simplify
00109 
00110 
00111 // inflates a polyhedron (represented as a matrix) P, so that the apx of its Ehrhart Polynomial is an upper bound of the Ehrhart polynomial of P
00112 // WARNING: this inflation is supposed to be applied on full-dimensional polyhedra.
00113 void mpolyhedron_inflate(Matrix * polyh, unsigned int nb_parms) {
00114   unsigned int i,j;
00115   unsigned nb_vars = polyh->NbColumns-nb_parms-2;
00116   Value infl;
00117   value_init(infl);
00118   // substract the sum of the negative coefficients of each inequality
00119   for (i=0; i< polyh->NbRows; i++) {
00120     value_set_si(infl, 0);
00121     for (j=0; j< nb_vars; j++) {
00122       if (value_sign(polyh->p[i][j])<0)
00123         value_addto(infl, infl, polyh->p[i][j]);
00124     }
00125     // here, we substract a negative value
00126     value_subtract(polyh->p[i][polyh->NbColumns-1], polyh->p[i][polyh->NbColumns-1], infl);
00127   }
00128   value_clear(infl);
00129 } // mpolyhedron_inflate
00130 
00131 
00132 // deflates a polyhedron (represented as a matrix) P, so that the apx of its Ehrhart Polynomial is a lower bound of the Ehrhart polynomial of P
00133 // WARNING: this deflation is supposed to be applied on full-dimensional polyhedra.
00134 void mpolyhedron_deflate(Matrix * polyh, unsigned int nb_parms) {
00135   unsigned int i,j;
00136   unsigned nb_vars = polyh->NbColumns-nb_parms-2;
00137   Value defl;
00138   value_init(defl);
00139   // substract the sum of the negative coefficients of each inequality
00140   for (i=0; i< polyh->NbRows; i++) {
00141     value_set_si(defl, 0);
00142     for (j=0; j< nb_vars; j++) {
00143       if (value_sign(polyh->p[i][j])>0)
00144         value_addto(defl, defl, polyh->p[i][j]);
00145     }
00146     // here, we substract a negative value
00147     value_subtract(polyh->p[i][polyh->NbColumns-1], polyh->p[i][polyh->NbColumns-1], defl);
00148   }
00149   value_clear(defl);
00150 } // mpolyhedron_deflate
00151 
00152 
00153 // use an eliminator row to eliminate a variable in a victim row (without changing the sign of the victim row -> important if it is an inequality).
00154 void eliminate_var_with_constr(Matrix * Eliminator, unsigned int eliminator_row, Matrix * Victim, unsigned int victim_row, unsigned int var_to_elim) {
00155   Value cur_lcm, mul_a, mul_b, a, b, sb;
00156   Value tmp, tmp2;
00157   int k; 
00158   value_init(cur_lcm); value_init(mul_a); value_init(mul_b); value_init(a); value_init(b); value_init(sb);
00159   value_init(tmp); value_init(tmp2);
00160   // if the victim coefficient is not zero 
00161   if (value_notzero_p(Victim->p[victim_row][var_to_elim+1])) {
00162     value_assign(a, Eliminator->p[eliminator_row][var_to_elim+1]);
00163     value_assign(b, Victim->p[victim_row][var_to_elim+1]);
00164     Lcm3(a, b, &cur_lcm);
00165     // multiplication factor for the current constraint
00166     value_division(tmp, cur_lcm, b);
00167     value_absolute(mul_a, tmp); // IT HAS TO BE POSITIVE (otherwise you may modify the sign of your constraint)
00168     value_absolute(tmp, b);
00169     value_division(sb, tmp, b); // sb represents the sign of b
00170     // multiplication factor for the constraint to project
00171 #ifdef GNUMP
00172     mpz_divexact(tmp, cur_lcm, a);
00173     value_multiply(mul_b, tmp, sb);
00174 #else
00175     mul_b = cur_lcm / a * sb;
00176 #endif
00177 
00178     value_assign(Victim->p[victim_row][0], Victim->p[victim_row][0]);
00179     for (k=1; k<Victim->NbColumns; k++) {
00180       value_multiply(tmp, Victim->p[victim_row][k], mul_a);
00181       value_multiply(tmp2, Eliminator->p[eliminator_row][k], mul_b);
00182       value_subtract(Victim->p[victim_row][k], tmp, tmp2);
00183       // = Victim->p[victim_row][k] * mul_a -  Eliminator->p[eliminator_row][k] * mul_b;
00184     }
00185   }
00186   value_clear(cur_lcm); value_clear(mul_a); value_clear(mul_b); value_clear(a); value_clear(b); value_clear(sb);
00187   value_clear(tmp); value_clear(tmp2);
00188 }
00189 // eliminate_var_with_constr
00190 
00191 
00192 // STUFF WITH PARTIAL MAPPINGS (Mappings to a subset of the variables/parameters) : on the first or last variables/parameters
00193 
00194 // compress the last vars/pars of the polyhedron M expressed as a polylib matrix
00195 // - adresses the full-rank compressions only
00196 // - modfies M
00197 void mpolyhedron_compress_last_vars(Matrix * M, Matrix * compression) {
00198   unsigned int i, j, k;
00199   unsigned int offset = M->NbColumns - compression->NbRows; // the computations on M will begin on column "offset"
00200   Matrix * M_tmp = Matrix_Alloc(1, M->NbColumns);
00201   assert(compression->NbRows==compression->NbColumns);
00202   // basic matrix multiplication (using a temporary row instead of a whole temporary matrix), but with a column offset
00203   for(i=0; i< M->NbRows; i++) {
00204     for (j=0; j< compression->NbRows; j++) {
00205       value_set_si(M_tmp->p[0][j], 0);
00206       for (k=0; k< compression->NbRows; k++) {
00207         value_addmul(M_tmp->p[0][j], M->p[i][k+offset],compression->p[k][j] );
00208       }
00209     }
00210     for (j=0; j< compression->NbRows; j++) 
00211       value_assign(M->p[i][j+offset], M_tmp->p[0][j]);
00212   }
00213   Matrix_Free(M_tmp);
00214 } // mpolyhedron_compress_last_vars
00215 
00216 
00217 // use a set of m equalities Eqs to eliminate m variables in the polyhedron Ineqs represented as a matrix
00218 // eliminates the m first variables
00219 // - assumes that Eqs allow to eliminate the m equalities
00220 //  -modifies Eqs and Ineqs
00221 unsigned int mpolyhedron_eliminate_first_variables(Matrix * Eqs, Matrix * Ineqs) {
00222   unsigned int i, j, k;
00223   // eliminate one variable (index i) after each other
00224   for (i=0; i< Eqs->NbRows; i++) {
00225     // find j, the first (non-marked) row of Eqs with a non-zero coefficient
00226     for (j=0; j<Eqs->NbRows && (Eqs->p[j][i+1]==0 || ( !value_cmp_si(Eqs->p[j][0],2) )); j++);
00227     // if no row is found in Eqs that allows to eliminate variable i, return an error code (0)
00228     if (j==Eqs->NbRows) return 0;
00229     // else, eliminate variable i in Eqs and Ineqs with the j^th row of Eqs (and mark this row so we don't use it again for an elimination)
00230     for (k=j+1; k<Eqs->NbRows; k++)
00231       eliminate_var_with_constr(Eqs, j, Eqs, k, i);
00232     for (k=0; k< Ineqs->NbRows; k++)
00233       eliminate_var_with_constr(Eqs, j, Ineqs, k, i);
00234     // mark the row
00235     value_set_si(Eqs->p[j][0],2);
00236   }
00237   // un-mark all the rows
00238   for (i=0; i< Eqs->NbRows; i++) value_set_si(Eqs->p[i][0],0);
00239   return 1;
00240 }
00241 

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