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

polyparam.c

Go to the documentation of this file.
00001 /***********************************************************************/
00002 /*                Parametrized polyhedra V4.20                         */
00003 /*                copyright 1995-2000 Vincent Loechner                 */
00004 /*                copyright 1996-1997, Doran Wilde                     */
00005 /*       Permission is granted to copy, use, and distribute            */
00006 /*       for any commercial or noncommercial purpose under the terms   */
00007 /*       of the GNU General Public license, version 2, June 1991       */
00008 /*       (see file : LICENSING).                                       */
00009 /***********************************************************************/
00010 
00011 /********************* -----------USER #DEFS-------- ***********************/
00012 /* These are mainly for debug purposes. You shouldn't need to change       */
00013 /* anything for daily usage...                                             */
00014 /***************************************************************************/
00015 
00016 /* you may define each macro independently */
00017 /* #define DEBUGPP      */
00018 /* #define DEBUGPP3     */              /* initialization of domain, context, ... */
00019 /* #define DEBUGPP31    */              /* even more init-domains */
00020 /* #define DEBUGPP32    */              /* even even more... (Elim_Columns) */
00021 /* #define DEBUGPP4     */              /* m-faces scan */
00022 /* #define DEBUGPP41    */              /* inverse Di in scan */
00023 /* #define DEBUGPP5     */              /* Compute_PDomains */
00024 /********************* ---------END USER #DEFS------ ***********************/
00025 
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <assert.h>
00030 #ifdef DEBUGPP
00031 #include <time.h>
00032 #endif
00033 
00034 #include <polylib/polylib.h>
00035 
00036 static void traite_m_face(Polyhedron *, unsigned int *, unsigned int *);
00037 static void scan_m_face(int,int,Polyhedron *,unsigned int *);
00038 
00039 /*
00040  * Return the intersection of two polyhedral domains 'Pol1' and 'Pol2' such 
00041  * that if the intersection is a polyhedron of lower dimension (a degenerate
00042  * polyhedron) than the operands, it is discarded from the resulting polyhedra
00043  * list. 
00044  */
00045 Polyhedron *PDomainIntersection(Polyhedron *Pol1,Polyhedron *Pol2,unsigned NbMaxRays) {
00046         
00047   Polyhedron *p1, *p2, *p3, *d;
00048   
00049   if (!Pol1 || !Pol2) return (Polyhedron*) 0;
00050   if((Pol1->Dimension != Pol2->Dimension) || (Pol1->NbEq != Pol2->NbEq)) {
00051     fprintf(stderr,
00052             "? PDomainIntersection: operation on different dimensions\n");
00053     return (Polyhedron*) 0;
00054   }
00055   
00056   POL_ENSURE_FACETS(Pol1);
00057   POL_ENSURE_VERTICES(Pol1);
00058   POL_ENSURE_FACETS(Pol2);
00059   POL_ENSURE_VERTICES(Pol2);
00060  
00061   d = (Polyhedron *)0;
00062   for (p1=Pol1; p1; p1=p1->next) {
00063     for (p2=Pol2; p2; p2=p2->next) {
00064       p3 = AddConstraints(p2->Constraint[0],
00065                           p2->NbConstraints,p1,NbMaxRays);
00066       if (!p3) continue;
00067       
00068       /* If the new polyhedron 'p3' has lower dimension, discard it */
00069       if (p3->NbEq!=Pol1->NbEq)
00070         Polyhedron_Free(p3) ;
00071       
00072       /* Otherwise add it to the new polyhderal domain 'd'. */
00073       else
00074         d = AddPolyToDomain(p3,d);
00075     }
00076   }
00077   return d;
00078 } /* PDomainIntersection */
00079 
00080 /* 
00081  * Given polyhderal domains 'Pol1' and 'Pol2', return the difference of the 
00082  * two domains with a modification that the resulting polyhedra in the new 
00083  * domain don't have a 1 unit space around cut and the degenerate results
00084  * (of smaller dimension) are discarded. 
00085  */
00086 Polyhedron *PDomainDifference(Polyhedron *Pol1,Polyhedron *Pol2,unsigned NbMaxRays) {
00087   
00088   Polyhedron *p1, *p2, *p3, *d;
00089   int i;
00090   
00091   if (!Pol1 || !Pol2)
00092     return (Polyhedron*) 0;
00093   if((Pol1->Dimension != Pol2->Dimension) || (Pol1->NbEq != Pol2->NbEq)) {
00094     fprintf(stderr,
00095             "? PDomainDifference: operation on different dimensions\n");
00096     return (Polyhedron*) 0;
00097   }
00098 
00099   POL_ENSURE_FACETS(Pol1);
00100   POL_ENSURE_VERTICES(Pol1);
00101   POL_ENSURE_FACETS(Pol2);
00102   POL_ENSURE_VERTICES(Pol2);
00103  
00104   d = (Polyhedron *)0;
00105   for (p2=Pol2; p2; p2=p2->next) {
00106     for (p1=Pol1; p1; p1=p1->next) {
00107       for (i=0; i<p2->NbConstraints; i++) {
00108         
00109         /* Add the constraint (-p2->Constraint[i]) >= 0 in 'p1' */
00110         p3 = SubConstraint(p2->Constraint[i],p1,NbMaxRays,2);
00111         if (!p3) continue;
00112         
00113         /* If the new polyhedron 'p3' is empty or is a polyhedron of lower */
00114         /* dimension, discard it.                                          */
00115         if (emptyQ(p3) || p3->NbEq!=Pol1->NbEq)
00116           Polyhedron_Free(p3);
00117         
00118         /* Otherwise add 'p3' to the new polyhderal domain 'd' */
00119         else
00120           d = AddPolyToDomain(p3,d);
00121       }
00122     }
00123     if (p2 != Pol2)
00124         Domain_Free(Pol1);
00125     Pol1 = d;
00126     d = (Polyhedron *)0;
00127   }
00128   return Pol1;
00129 } /* PDomainDifference */
00130 
00131 /* 
00132  * Return 1 if matrix 'Mat' is full column ranked, otherwise return 0. 
00133  */  
00134 static int TestRank(Matrix *Mat) {
00135   
00136   int i,j,k;
00137   Value m1,m2,m3,gcd,tmp;
00138 
00139   /* Initialize all the 'Value' variables */
00140   value_init(m1); value_init(m2); 
00141   value_init(m3); value_init(gcd); value_init(tmp);
00142   
00143   for(k=0;k<Mat->NbColumns;++k) {
00144     
00145     /* If the digonal entry (k,k) is zero, search down the column(k) */
00146     /* starting from row(k) to find a non-zero entry                 */
00147     if(value_zero_p(Mat->p[k][k])) {
00148       for(j=k+1;j<Mat->NbRows;++j) {
00149         
00150         /* If a non-zero entry (j,k) is found */
00151         if(value_notzero_p(Mat->p[j][k])) {
00152           
00153           /* Exchange row(k) and row(j) */
00154           for(i=k;i<Mat->NbColumns;++i) {
00155             value_assign(tmp,Mat->p[j][i]);
00156             value_assign(Mat->p[j][i],Mat->p[k][i]);
00157             value_assign(Mat->p[k][i],tmp);
00158           }
00159           break;
00160         }
00161       }
00162       
00163       /* If no non-zero entry is found then the matrix 'Mat' is not full */
00164       /* ranked. Return zero.                                            */
00165       if(j>=Mat->NbRows) {
00166         
00167         /* Clear all the 'Value' variables */
00168         value_clear(m1); value_clear(m2); 
00169         value_clear(m3); value_clear(gcd); value_clear(tmp);
00170         return 0;
00171       } 
00172     }
00173     
00174     /* Now Mat[k][k] is the pivot element */
00175     for(j=k+1;j<Mat->NbRows;++j) {
00176       
00177       /* Make every other entry (below row(k)) in column(k) zero */
00178       value_gcd(gcd, Mat->p[j][k], Mat->p[k][k]);
00179       for(i=k+1;i<Mat->NbColumns;++i) {
00180         
00181         /* pour tous les indices i > k */
00182         value_multiply(m1,Mat->p[j][i],Mat->p[k][k]);
00183         value_multiply(m2,Mat->p[j][k],Mat->p[k][i]);
00184         value_subtract(m3,m1,m2);
00185         value_division(Mat->p[j][i],m3,gcd);
00186       }
00187     }   
00188   }
00189 
00190   /* Clear all the 'Value' variables */
00191   value_clear(m1); value_clear(m2); 
00192   value_clear(m3); value_clear(gcd); value_clear(tmp);
00193   
00194   /* The matrix 'Mat' is full ranked, return 1 */
00195   return 1;
00196 } /* TestRank */
00197 
00198 /*
00199  * The Saturation matrix is defined to be an integer (int type) matrix. It is
00200  * a boolean matrix which has a row for every constraint and a column for 
00201  * every line or ray. The bits in the binary format of each integer in the 
00202  * saturation matrix stores the information whether the corresponding constr-
00203  * aint is saturated by ray(line) or not. 
00204  */
00205 typedef struct {
00206   unsigned int NbRows;
00207   unsigned int NbColumns;
00208   unsigned int **p;
00209   unsigned int *p_init;
00210 } SatMatrix; 
00211 
00212 static SatMatrix *SMAlloc(int rows,int cols) {
00213 
00214   unsigned int **q, *p;
00215   int i;
00216 
00217   SatMatrix *result = (SatMatrix *)malloc(sizeof(SatMatrix));
00218   assert (result != NULL);
00219 
00220   result->NbRows = rows;
00221   result->NbColumns = cols;
00222   result->p = q = (unsigned int **)malloc(rows * sizeof(unsigned int *));
00223   assert (result->p != NULL);  
00224   result->p_init = p = (unsigned int *)malloc(rows * cols * sizeof(unsigned int));
00225   assert (result->p_init != NULL);  
00226   
00227   for (i=0;i<rows;i++) {
00228     *q++ = p;
00229     p += cols;
00230   }
00231   
00232   return result;
00233 } /* SMAlloc */
00234 
00235 static void SMPrint (SatMatrix *matrix) {
00236   
00237   unsigned int *p;
00238   int i, j;
00239   unsigned NbRows, NbColumns;
00240   
00241   fprintf(stderr,"%d %d\n",NbRows=matrix->NbRows, NbColumns=matrix->NbColumns);
00242   for (i=0;i<NbRows;i++) {
00243     p = *(matrix->p+i);
00244     for (j=0;j<NbColumns;j++)
00245       fprintf(stderr, " %10X ", *p++);
00246     fprintf(stderr, "\n");
00247   }  
00248 } /* SMPrint */
00249 
00250 
00251 static void SMFree (SatMatrix *matrix) {
00252   
00253   free ((char *) matrix->p_init);
00254   free ((char *) matrix->p);
00255   free ((char *) matrix);
00256   return;
00257 } /* SMFree */
00258 
00259 /* -------------------------------------------------------------------------
00260  * Shared Global Variables:
00261  * Used by procedures: Find_m_face, scan_m_face, Poly2Sat, traite_m_face,
00262  *                     count_sat 
00263  * -------------------------------------------------------------------------
00264  */
00265 static int m;                   /* number of parameters */
00266 static int m_dim;               /* dimension of m-face */
00267 static int n;                   /* dimension (not including parameters) */
00268 static int ws;                  /* Working Space size */
00269 static int nr;                  /* (NbRays-1)/32 + 1 */
00270 
00271 static Polyhedron *CEqualities;/* Equalities in the context */
00272 static SatMatrix   *Sat;       /* Saturation Matrix (row=constraint, col=ray)*/
00273 static unsigned int *egalite;  /* Bool vector marking constraints in m-face  */
00274 static Matrix *Xi, *Pi;        /* Xi and Pi */
00275 static Matrix *PiTest;         /* Matrix used to test if Pi is full ranked? */
00276 static Matrix *CTest;
00277 static Matrix *PiInv;          /* Matrix inverse Pi, with the last col of   */
00278                                /* each line = denominator of the line       */
00279 static Matrix *RaysDi;         /* Constraint matrix for computing Di */
00280 
00281 static int KD;                   /* Flag : keep the full domains in memory ? */
00282                                  /* 1 = yes; 0 = no, keep constraints only   */
00283 
00284 static int nbPV;                  /* The number of parameterized vertices */
00285 static Param_Vertices *PV_Result; /* List of parameterized vertices */
00286 static Param_Domain *PDomains;    /* List of domains. */
00287 
00288 #ifdef DEBUGPP
00289 static int nbfaces;
00290 #endif
00291 
00292 /*
00293  * Add the constraints from the context polyhedron 'CEqualities' to the 
00294  * constraints of polyhedra in the polyhedral domain 'D' and return the new
00295  * polyhedral domain. Polyhedral domain 'D' is subsequently deleted from memory
00296  */
00297 static Polyhedron *Add_CEqualities(Polyhedron *D) {
00298   
00299   Polyhedron *d,*r,*tmp;
00300 
00301   if(!CEqualities)
00302     return D;
00303   else {
00304     if(!D || emptyQ(D)) {
00305       if(D)
00306         Domain_Free(D);
00307       return(Polyhedron_Copy(CEqualities));
00308     }
00309     r = AddConstraints(D->Constraint[0],D->NbConstraints,
00310                        CEqualities,ws);
00311     tmp = r;
00312     for(d=D->next;d;d=d->next) {
00313       tmp->next = AddConstraints(d->Constraint[0],d->NbConstraints,
00314                                  CEqualities,ws);
00315       tmp = tmp->next;
00316     }
00317     Domain_Free(D);
00318     return(r);
00319   }
00320 } /* Add_CEqualities */
00321 
00322 #define INT_BITS (sizeof(unsigned) * 8)
00323 
00324 unsigned int *int_array2bit_vector(unsigned int *array, int n)
00325 {
00326   int i, ix;
00327   unsigned bx;
00328   int words = (n+INT_BITS-1)/INT_BITS;
00329   unsigned int *bv = (unsigned int *)calloc(words, sizeof(unsigned));
00330   assert(bv);
00331   for (i = 0, ix = 0, bx = MSB; i < n; ++i) {
00332     if (array[i])
00333       bv[ix] |= bx;
00334     NEXT(ix, bx);
00335   }
00336   return bv;
00337 }
00338 
00339 /*----------------------------------------------------------------------*/
00340 /* traite_m_face                                                        */
00341 /*       Given an m-face, compute the parameterized vertex              */
00342 /* D       - The entire domain                                          */
00343 /* mf      - Bit vector marking the lines/rays in the m-face            */
00344 /* egalite - boolean vector marking saturated constraints in m-face     */
00345 /*----------------------------------------------------------------------*/
00346 static void traite_m_face(Polyhedron *D, unsigned int *mf,
00347                           unsigned int *egalite)
00348 {
00349   Matrix *Si;                           /* Solution */
00350   Polyhedron *PDi;                      /* polyhedron Di */
00351   Param_Vertices *PV;
00352   int j,k,c,r;
00353   unsigned kx, bx;
00354 
00355 #ifdef DEBUGPP
00356   ++nbfaces;
00357 #endif
00358   
00359   /* Extract  Xi, Pi, and RaysDi from D */
00360   RaysDi->NbRows = 0;
00361   for(k=0,c=0,kx=0,bx=MSB;k<D->NbRays;++k) {
00362     if(mf[kx]&bx) {      /* this ray is in the current m-face */      
00363       if(c<m+1) {       
00364         int i;
00365         
00366         /* tester si cette nouvelle colonne est lin. indep. des autres */
00367         /* i.e. si gauss ne donne pas de '0' sur la colonne Pi */
00368         /* jusqu'a l'indice 'c'                                */
00369         
00370         /* construit PiTest */
00371         for(j=0;j<m+1;++j) {
00372           for(i=0;i<c;++i)
00373             
00374             /* les c premieres colonnes */
00375             value_assign(PiTest->p[j][i],Pi->p[j][i]);
00376           
00377           /* la nouvelle */
00378           value_assign(PiTest->p[j][c],D->Ray[k][j+1+n]);
00379         }
00380         PiTest->NbColumns = c+1;
00381         r = TestRank(PiTest);
00382         if(r /* TestRank(PiTest) */) {
00383                                 
00384           /* Ok, c'est lin. indep. */
00385           for (j=0;j<n;j++)
00386             value_assign(Xi->p[j][c],D->Ray[k][j+1]);   /* Xi */
00387           for (j=0;j<m;j++)
00388             value_assign(Pi->p[j][c],D->Ray[k][j+1+n]); /* Pi */
00389           value_assign(Xi->p[n][c],D->Ray[k][n+m+1]);   /* const */
00390           value_assign(Pi->p[m][c],D->Ray[k][n+m+1]);   /* const */
00391           c++;
00392         }
00393       }
00394       
00395       /* Status bit */
00396       value_assign(RaysDi->p[RaysDi->NbRows][0],D->Ray[k][0]);     
00397       Vector_Copy(&D->Ray[k][n+1],&RaysDi->p[RaysDi->NbRows][1],(m+1));
00398       ++RaysDi->NbRows;
00399     }
00400     NEXT(kx,bx);
00401   }
00402   
00403 #ifdef DEBUGPP41
00404   fprintf(stderr, "\nRaysDi=\n");
00405   Matrix_Print(stderr,P_VALUE_FMT,RaysDi);
00406   if(c < m+1)
00407     fprintf(stderr, "Invalid ");
00408   fprintf(stderr, "Pi=\n");
00409   Matrix_Print(stderr,P_VALUE_FMT,Pi);
00410 #endif
00411   
00412 #ifdef DEBUGPP4
00413   if(c < m+1)
00414     fprintf(stderr,"Eliminated because of no vertex\n");
00415 #endif
00416 
00417   if(c < m+1)   
00418     return;
00419 
00420   /* RaysDi->numColumns = m+2; */  /* stays the same */
00421 
00422   /*    Xi->NbColumns = m+1;*/  /* VIN100: stays the same. was 'c'! */
00423   /*    Xi->NbRows = n+1; */    /* stays the same */
00424   /*    Pi->NbColumns = m+1;*/  /* VIN100: stays the same. was 'c'! */
00425   /*    Pi->NbRows = m+1; */            /* stays the same */
00426   
00427 #ifdef DEBUGPP4
00428   fprintf(stderr,"Xi = ");
00429   Matrix_Print(stderr,P_VALUE_FMT,Xi);
00430   fprintf(stderr,"Pi = ");
00431   Matrix_Print(stderr,P_VALUE_FMT,Pi);
00432 #endif
00433   
00434   /* (Right) invert Pi if POSSIBLE, if not then next m-face */
00435   /* Pi is destroyed                                        */
00436   if(!MatInverse(Pi,PiInv)) {
00437     
00438 #ifdef DEBUGPP4
00439     fprintf(stderr, "Eliminated because of no inverse Pi\n");
00440 #endif
00441     
00442     return;
00443   }
00444   
00445 #ifdef DEBUGPP4
00446   fprintf(stderr,"FACE GENERATED!\n");
00447   fprintf(stderr,"PiInv = ");
00448   Matrix_Print(stderr,P_VALUE_FMT,PiInv);
00449 #endif
00450   
00451   /* Compute  Si (now called Ti in the paper) */
00452   Si = Matrix_Alloc(Xi->NbRows,PiInv->NbColumns);
00453   rat_prodmat(Si,Xi,PiInv);
00454   
00455 #ifdef DEBUGPP4
00456   fprintf(stderr,"Si = ");
00457   Matrix_Print(stderr,P_VALUE_FMT,Si);
00458 #endif
00459   
00460   Si->NbRows--;      /* throw out the last row = 0 ... 0 1 */
00461   
00462   /* Copy all of that into the PV structure */
00463   PV = (Param_Vertices *) malloc(sizeof(Param_Vertices));
00464   PV->next = PV_Result;
00465   PV->Vertex = Si;
00466   PV->Domain = NULL;
00467   PV->Facets = int_array2bit_vector(egalite, D->NbConstraints);
00468   PV_Result = PV;
00469   nbPV++;         /* increment vertex count */
00470   
00471   /* Ok... now compute the parameter domain */
00472   PDi = Rays2Polyhedron(RaysDi,ws);
00473   
00474 #ifdef DEBUGPP3
00475   fprintf(stderr,"RaysDi = ");
00476   Matrix_Print(stderr,P_VALUE_FMT,RaysDi);
00477   fprintf(stderr,"PDi = ");
00478   Polyhedron_Print(stderr,P_VALUE_FMT,PDi);
00479 #endif
00480   
00481   if(KD==0) {
00482     
00483     /* Add the equalities again to the domain */
00484     PDi = Add_CEqualities(PDi);
00485     PV->Domain = Polyhedron2Constraints(PDi);
00486     Polyhedron_Free(PDi);
00487   }
00488   else {
00489     Param_Domain *PD;
00490     PD = (Param_Domain *) malloc(sizeof(Param_Domain));
00491     PD->Domain = PDi;
00492     PD->F = NULL;
00493     PD->next = PDomains;
00494     PDomains = PD;
00495   }
00496   return;
00497 } /* traite_m_face */
00498 
00499 /*----------------------------------------------------------------------*/
00500 /* count_sat                                                            */
00501 /*      count the number of saturated rays in the bit vector mf         */
00502 /*      Uses nr from global area                                        */
00503 /*----------------------------------------------------------------------*/
00504 int cntbit[256] = {                             /* counts for 8 bits */
00505 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
00506 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
00507 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
00508 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00509 
00510 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
00511 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00512 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00513 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
00514 
00515 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
00516 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00517 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00518 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
00519 
00520 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00521 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
00522 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
00523 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 };
00524 
00525 static int count_sat (unsigned int *mf) {
00526   
00527   register unsigned int i, tmp, cnt=0;
00528   
00529   for (i=0; i<nr; i++) {
00530     tmp = mf[i];
00531     cnt = cnt
00532       + cntbit[ tmp & 0xff ]
00533       + cntbit[ (tmp>>8) & 0xff ]
00534       + cntbit[ (tmp>>16) & 0xff ]
00535       + cntbit[ (tmp>>24) & 0xff ]
00536       ;
00537   }
00538   return cnt;
00539 } /* count_sat */
00540 
00541 /* Returns true if all bits in part are also set in bv */
00542 static int bit_vector_includes(unsigned int *bv, int len, unsigned int *part)
00543 {
00544   int j;
00545 
00546   for (j = 0; j < len; j++) {
00547 #ifdef DEBUGPP4
00548     fprintf(stderr, "mf=%08X Sat=%08X &=%08X\n",
00549                     part[j],bv[j], (part[j] & bv[j]));
00550 #endif
00551     if ((part[j] & bv[j]) != part[j])
00552       return 0;
00553   }
00554   return 1;
00555 }
00556 
00557 /*----------------------------------------------------------------------*/
00558 /* let D + E + L be the dimension of the polyhedron                     */
00559 /* D = Dimension of polytope (ray space)                                */
00560 /* L = Dimension of Lineality space (number of lines, bid)              */
00561 /* E = Dimension of Affine hull (number of equations)                   */
00562 /* n = number of data indices                                           */
00563 /* m = number of parameters                                             */
00564 /* full domain:                                                         */
00565 /*     n + m = D + E + L                                                */
00566 /* projected domains:                                                   */
00567 /*     m = D_m + E_m + L_m                                              */
00568 /*     n = D_n + E_n + L_n                                              */
00569 /* What dimension M-face, when projected onto parameter space,          */
00570 /* will give an L_m-face?                                               */
00571 /* What are the conditions?                                             */
00572 /*   - at least one vertex                                              */
00573 /*   - number of rays >= D_m+1 after removal of redundants              */
00574 /*                                                                      */
00575 /* dim of face    nb saturated constraints   nb saturated lines,rays    */
00576 /* -----------    ------------------------   -----------------------    */
00577 /* (0+L)-face     all E eqns + >=D ineq      all L lines + 1 ray        */
00578 /* (M+L)-face     all E eqns + >=(D-M) ineq  all L lines + >=(M+1) rays */
00579 /* (D+L)-face     all E eqns + 0 ineq        all L lines + >=(D+1) rays */
00580 /*----------------------------------------------------------------------*/
00581 /*----------------------------------------------------------------------*/
00582 /* scan_m_face                                                          */
00583 /*      pos : the next candidate constraint position                    */
00584 /*    nb_un : number of saturated constraints needed to finish a face   */
00585 /*        D : the source polyhedron (context included )                 */
00586 /*       mf : bit-array marking rays which are saturated so far         */
00587 /* From Global area:                                                    */
00588 /* ----------------                                                     */
00589 /*        n : number of data indices                                    */
00590 /*        m : number of parameters                                      */
00591 /*  egalite : boolean vector marking saturated constraints in m-face    */
00592 /*      Sat : Saturation Matrix (row=constraints, col=rays)             */
00593 /*       ws : working space size                                        */
00594 /*       nr : (NbRays-1)/32 + 1                                         */
00595 /*                                                                      */
00596 /* Recursive function to find the rays and vertices of each m-face      */
00597 /*----------------------------------------------------------------------*/
00598 static void scan_m_face(int pos,int nb_un,Polyhedron *D,unsigned int *mf) {
00599   /* pos   - the next candidate constraint position */
00600   /* nb_un - the number of constraints needed to finish a face */
00601   /* D     - the source polyhedron */
00602   /* mf    - (bit vector) marks rays that are saturated so far */
00603 
00604   unsigned int *new_mf;
00605 
00606 #ifdef DEBUGPP4
00607   fprintf(stderr,"Start scan_m_face(pos=%d, nb_un=%d, n=%d, m=%d\n",
00608           pos,nb_un,n,m);
00609   fprintf(stderr,"mf = ");
00610   {
00611     int i;
00612     for(i=0;i<nr;i++)
00613       fprintf(stderr,"%08X", mf[i]);
00614     fprintf(stderr,"\nequality = [");
00615     for(i=0;i<D->NbConstraints;i++)
00616       fprintf(stderr," %1d",egalite[i]);
00617     fprintf(stderr,"]\n");
00618   }
00619 #endif
00620 
00621   if(nb_un == 0) {      /* Base case */   
00622     int i;
00623     
00624     /*********** ELIMINATION OF REDUNDANT FACES ***********/
00625     /* if all these vertices also verify a previous constraint */
00626     /* which is NOT already selected, we eliminate this face */
00627     /* This keeps the lexicographically greatest selection */
00628         for(i=0;i<pos-1;i++)
00629         {
00630                 if(egalite[i])
00631                         continue;       /* already selected */
00632       
00633                 /* if Sat[i] & mf == mf then it's redundant */
00634 #ifdef DEBUGPP4
00635                 fprintf(stderr, "Sat[%d]\n", i);
00636 #endif
00637                 if (bit_vector_includes(Sat->p[i], nr, mf)) {
00638 #ifdef DEBUGPP4
00639                   fprintf(stderr, "Redundant with constraint %d\n", i);
00640 #endif
00641                   return;       /* it is redundant */
00642                 }
00643         }
00644     /********* END OF ELIMINATION OF DEGENERATE FACES *********/    
00645     /* Now check for other constraints that are verified */
00646     for (i = pos; i < D->NbConstraints; ++i) {
00647       if (bit_vector_includes(Sat->p[i], nr, mf))
00648         egalite[i] = 1;
00649     }
00650     /* if we haven't found a constraint verified by all */
00651     /* the rays, its OK, it's a new face. */
00652     traite_m_face(D, mf, egalite);
00653     for (i = pos; i < D->NbConstraints; ++i)
00654       egalite[i] = 0;
00655     return;
00656   }
00657 
00658   /* See if there are enough constraints left to finish */
00659   if((pos+nb_un)>D->NbConstraints) return;
00660   
00661   /* Recurring part of the procedure */
00662   /* Add the pos'th constraint, compute new saturation vector */
00663   {     
00664     int k;
00665     new_mf  = (unsigned int *)malloc(nr*sizeof(unsigned int));
00666     for (k=0; k<nr; k++)
00667       new_mf[k] = mf[k] & Sat->p[pos][k];
00668   }
00669 #ifdef DEBUGPP4
00670 fprintf(stderr,"new_mf = ");
00671  { 
00672    int i;
00673    for(i=0;i<nr;i++) {
00674      fprintf(stderr,"%08X", new_mf[i]);
00675    }
00676    fprintf(stderr,"\ncount(new_mf) = %d\n",count_sat(new_mf));
00677  }
00678 #endif
00679 
00680   {
00681         int c;
00682         c = count_sat(new_mf);
00683         /* optimization : at least m_dim+1 rays must be saturated to add this constraint */
00684         if (c>m_dim )
00685         {
00686                 int redundant = 0;
00687 
00688                 egalite[pos]=1;         /* Try it with the pos-th constraint */
00689 
00690                 /* If this constraint does not change anything,
00691                  * it is redundant with respect to the selected
00692                  * equalities and the remaining inequalities.
00693                  * Check whether it is redundant with respect
00694                  * to just the selected equalities.
00695                  */
00696                 if( c==count_sat(mf) ) {
00697                     int i, c, j;
00698 
00699                     for (i = 0, c = 0; i < D->NbConstraints; ++i) {
00700                         if (egalite[i] == 0 || egalite[i] == -1)
00701                             continue;
00702                         for (j = 0; j < D->Dimension+1; ++j)
00703                             value_assign(CTest->p[j][c], 
00704                                          D->Constraint[i][j+1]);
00705                         ++c;
00706                     }
00707                     CTest->NbColumns = c;
00708 #ifdef DEBUGPP41
00709                     Matrix_Print(stderr,P_VALUE_FMT,CTest);
00710 #endif
00711                     redundant = !TestRank(CTest);
00712                 }
00713 
00714                 /* Do not decrement nb_un if equality is redundant. */
00715                 if( redundant )
00716                 {
00717                    egalite[pos]=-1;     /* Don't use in further redundance test
00718                                          */
00719                    scan_m_face(pos+1,nb_un,D,new_mf);
00720                 }
00721                 else
00722                 {
00723                    scan_m_face(pos+1,nb_un-1,D,new_mf);
00724                 }
00725         }
00726   }
00727  free(new_mf);
00728  egalite[pos]=0;                /* Try it without the pos-th constraint */
00729  if ((pos+nb_un)>=D->NbConstraints) return;
00730  scan_m_face(pos+1,nb_un,D,mf);
00731  return;
00732 } /* scan_m_face */
00733 
00734 /*
00735  * Create a saturation matrix with rows correspond to the constraints and 
00736  * columns correspond to the rays of the polyhedron 'Pol'. Global variable 
00737  * 'nr' is set in the function.             
00738  */
00739 static SatMatrix *Poly2Sat(Polyhedron *Pol,unsigned int **L) { 
00740   
00741   SatMatrix *Sat;
00742   int i, j, k, kx;
00743   unsigned int *Temp;
00744   Value *p1, *p2, p3,tmp;
00745   unsigned Dimension, NbRay, NbCon, bx;
00746   
00747   /* Initialize all the 'Value' variables */
00748   value_init(p3); value_init(tmp);
00749   
00750   NbRay = Pol->NbRays;
00751   NbCon = Pol->NbConstraints;
00752   Dimension = Pol->Dimension+1;                /* Homogeneous Dimension */
00753   
00754   /* Build the Sat matrix */
00755   nr      = (NbRay - 1)/(sizeof(int)*8) + 1;   /* Set globally */
00756   Sat     = SMAlloc(NbCon,nr);
00757   Temp     = (unsigned int *)malloc(nr*sizeof(unsigned int));
00758   memset(Sat->p_init,0,nr*NbCon*sizeof(int));
00759   memset(Temp,0,nr*sizeof(unsigned int));
00760   kx=0; bx=MSB;
00761   for (k=0; k<NbRay; k++) { 
00762     for (i=0; i<NbCon; i++) {
00763       p1 = &Pol->Constraint[i][1];
00764       p2 = &Pol->Ray[k][1];
00765       value_set_si(p3,0);
00766       for (j=0;j<Dimension;j++) {
00767         value_multiply(tmp,*p1,*p2);
00768         value_addto(p3,p3,tmp);
00769         p1++; p2++;
00770       }
00771       if (value_zero_p(p3))
00772         Sat->p[i][kx]|=bx;
00773     }
00774     Temp[kx] |= bx;
00775     NEXT(kx, bx);
00776   }
00777   
00778   /* Set 'L' to an array containing ones in every bit position of its */
00779   /* elements.                                                        */
00780   *L = Temp;
00781   
00782   /* Clear all the 'Value' variables */
00783   value_clear(p3); value_clear(tmp);
00784   
00785   return Sat;
00786 } /* Poly2Sat */
00787 
00788 /*
00789  * Create a parametrized polyhedron with zero parameters. This function was 
00790  * first written by Xavier Redon, and was later modified by others.
00791  */
00792 Param_Polyhedron *GenParamPolyhedron(Polyhedron *Pol, Matrix *Rays)
00793 {
00794   Param_Polyhedron *result;
00795   int nbRows, nbColumns;
00796   int i, size, rays;
00797   
00798   nbRows=Pol->NbRays;
00799   nbColumns=Pol->Dimension+2;
00800   
00801   /* Count the number of rays */
00802   for(i=0, rays=0; i<nbRows; i++)
00803     if(value_notone_p(Pol->Ray[i][0]) ||
00804        value_zero_p(Pol->Ray[i][nbColumns-1]))
00805       ++rays;
00806   
00807   /* Initialize the result */
00808   result=(Param_Polyhedron *)malloc(sizeof(Param_Polyhedron));
00809   result->nbV=nbRows-rays;
00810   result->V=NULL;
00811   result->Constraints = Polyhedron2Constraints(Pol);
00812   result->Rays = Rays;
00813   
00814   /* Build the parametric vertices */
00815   for(i=0;i<nbRows;i++) {
00816     Matrix *vertex;
00817     Param_Vertices *paramVertex;
00818     int j;
00819 
00820     if (value_notone_p(Pol->Ray[i][0]) ||
00821         value_zero_p(Pol->Ray[i][nbColumns-1]))
00822       continue;
00823 
00824     vertex=Matrix_Alloc(nbColumns-2,2);
00825     for(j=1;j<nbColumns-1;j++) {
00826       value_assign(vertex->p[j-1][0],Pol->Ray[i][j]);
00827       value_assign(vertex->p[j-1][1],Pol->Ray[i][nbColumns-1]);
00828     }
00829     paramVertex=(Param_Vertices *)malloc(sizeof(Param_Vertices));
00830     paramVertex->Vertex=vertex;
00831     
00832     /* There is one validity domain : universe of dimension 0 */
00833     paramVertex->Domain=Matrix_Alloc(1,2);
00834     value_set_si(paramVertex->Domain->p[0][0],1);
00835     value_set_si(paramVertex->Domain->p[0][1],1);    
00836     paramVertex->Facets = NULL;
00837     paramVertex->next=result->V;
00838     result->V=paramVertex;
00839   }
00840   
00841   /* Build the parametric domains (only one here) */
00842   if (nbRows > 1)
00843     size=(nbRows-1)/(8*sizeof(int))+1;
00844   else
00845     size = 1;
00846   result->D=(Param_Domain *)malloc(sizeof(Param_Domain));
00847   result->D->next=NULL;
00848   result->D->Domain=Universe_Polyhedron(0);
00849   result->D->F=(unsigned int *)malloc(size*sizeof(int));
00850   memset(&result->D->F[0],0xFF,size*sizeof(int));
00851   
00852   return result;
00853 } /* GenParamPolyhedron */
00854 
00855 
00856 /*----------------------------------------------------------------------*/
00857 /* PreElim_Columns                                                      */
00858 /* function being called before Elim_Columns                            */
00859 /* Equalities in E are analysed to initialize ref and p.                */
00860 /* These two vectors are used to construct the new constraint matrix    */
00861 /* PreElim_Columns returns the transformation matrix to re-convert the  */
00862 /* resulting domains in the same format (by adding empty columns)       */
00863 /* in the parameter space                                               */
00864 /*----------------------------------------------------------------------*/
00865 Matrix *PreElim_Columns(Polyhedron *E,int *p,int *ref,int m) {
00866         
00867   int i,j,l;
00868   Matrix *T;
00869   
00870   /* find which columns to eliminate */
00871   /* p contains, for each line in E, the column to eliminate */
00872   /* (i.e. the corresponding parameter index to eliminate) */
00873   /* 0 <= i <= E->NbEq, and  1 <= p[i] <= E->Dimension */
00874   memset(p,0,sizeof(int)*(E->NbEq));
00875 
00876 #ifdef DEBUGPP32
00877   fprintf(stderr,"\n\nPreElim_Columns starting\n");
00878   fprintf(stderr,"E =\n");
00879   Polyhedron_Print(stderr,P_VALUE_FMT,E);
00880 #endif
00881   
00882   for(l=0;l<E->NbEq;++l) {
00883     if(value_notzero_p(E->Constraint[l][0])) {
00884       fprintf(stderr,"Internal error: Elim_Columns (polyparam.c), expecting equalities first in E.\n");
00885       free(p);
00886       return(NULL);
00887     }
00888     for(i=1;value_zero_p(E->Constraint[l][i]);++i) {
00889       if(i==E->Dimension+1) {
00890         fprintf(stderr,"Internal error: Elim_Columns (polyparam.c), expecting non-empty constraint in E.\n");
00891         free(p);
00892         return( NULL );
00893       }
00894     }
00895     p[l] = i;
00896     
00897 #ifdef DEBUGPP32
00898     fprintf(stderr,"p[%d] = %d,",l,p[l]);
00899 #endif
00900   }
00901 
00902   /* Reference vector: column ref[i] in A corresponds to column i in M */
00903   for(i=0;i<E->Dimension+2-E->NbEq;++i) {
00904     ref[i]=i;
00905     for(j=0;j<E->NbEq;++j)
00906       if(p[j]<=ref[i])
00907         ref[i]++;
00908     
00909 #ifdef DEBUGPP32
00910     fprintf(stderr,"ref[%d] = %d,",i,ref[i]);
00911 #endif
00912   }
00913   
00914   /* Size of T : phdim-nbEq * phdim */
00915   T = Matrix_Alloc(m+1-E->NbEq,m+1);
00916   for(i=0;i<T->NbColumns;i++)
00917     for(j=0;j<T->NbRows;j++)
00918       if(ref[E->Dimension-m+j+1] == E->Dimension-m+i+1)
00919         value_set_si(T->p[j][i],1);
00920       else
00921         value_set_si(T->p[j][i],0);
00922   
00923 #ifdef DEBUGPP32
00924   fprintf(stderr,"\nTransMatrix =\n");
00925   Matrix_Print(stderr,P_VALUE_FMT,T);
00926 #endif
00927   
00928   return(T);
00929 
00930 } /* PreElim_Columns */
00931 
00932 /*----------------------------------------------------------------------*/
00933 /* Elim_Columns                                                         */
00934 /* Eliminate columns from A, using the equalities in E.                 */
00935 /* ref and p are precalculated by PreElim_Columns, using E;             */
00936 /* these two vectors are used to construct the new constraint matrix    */
00937 /*----------------------------------------------------------------------*/
00938 Polyhedron *Elim_Columns(Polyhedron *A,Polyhedron *E,int *p,int *ref) {
00939   
00940   int i,l,c;
00941   Matrix *M, *C;
00942   Polyhedron *R;
00943   Value tmp1,tmp2;
00944   
00945   /* Initialize all the 'Value' variables */
00946   value_init(tmp1); value_init(tmp2);
00947   
00948 #ifdef DEBUGPP32
00949   fprintf(stderr,"\nElim_Columns starting\n");
00950   fprintf(stderr,"A =\n" );
00951   Polyhedron_Print(stderr,P_VALUE_FMT,A);
00952 #endif
00953   
00954   /* Builds M = constraint matrix of A, useless columns zeroed */
00955   M = Polyhedron2Constraints(A);
00956   for(l=0;l<E->NbEq;++l) {    
00957     for(c=0;c<M->NbRows;++c) {
00958       if(value_notzero_p(M->p[c][p[l]])) {
00959         
00960         /* A parameter to eliminate here ! */
00961         for(i=1;i<M->NbColumns;++i) {
00962           value_multiply(tmp1,M->p[c][i],E->Constraint[l][p[l]]);
00963           value_multiply(tmp2,E->Constraint[l][i],M->p[c][p[l]]);
00964           value_subtract(M->p[c][i],tmp1,tmp2);
00965         }
00966       }
00967     }
00968   } 
00969   
00970 #ifdef DEBUGPP32
00971   fprintf(stderr,"\nElim_Columns after zeroing columns of A.\n");
00972   fprintf(stderr,"M =\n");
00973   Matrix_Print(stderr,P_VALUE_FMT,M);
00974 #endif
00975   
00976   /* Builds C = constraint matrix, useless columns eliminated */
00977   C = Matrix_Alloc(M->NbRows,M->NbColumns - E->NbEq);
00978   for(l=0;l<C->NbRows;++l)
00979     for(c=0;c<C->NbColumns;++c) {
00980       value_assign(C->p[l][c],M->p[l][ref[c]]);
00981     }
00982     
00983 #ifdef DEBUGPP32
00984   fprintf(stderr,"\nElim_Columns after eliminating columns of A.\n");
00985   fprintf(stderr,"C =\n");
00986   Matrix_Print(stderr,P_VALUE_FMT,C);
00987 #endif
00988     
00989   R = Constraints2Polyhedron(C,ws);
00990   Matrix_Free(C);
00991   Matrix_Free(M);
00992   value_clear(tmp1); value_clear(tmp2);
00993   return(R);
00994 } /* Elim_Columns */
00995 
00996 
00997 static Polyhedron *Recession_Cone(Polyhedron *P, unsigned nvar, unsigned MaxRays)
00998 {
00999     int i;
01000     Matrix *M = Matrix_Alloc(P->NbConstraints, 1 + nvar + 1);
01001     Polyhedron *R;
01002     for (i = 0; i < P->NbConstraints; ++i)
01003         Vector_Copy(P->Constraint[i], M->p[i], 1+nvar);
01004     R = Constraints2Polyhedron(M, MaxRays);
01005     Matrix_Free(M);
01006     return R;
01007 }
01008 
01009 /* Compute lines/unidirectional rays of the (non parametric) polyhedron */
01010 /* Input :
01011  *   D1 : combined polyhedron,
01012  * Output :
01013  *   Rays : non parametric ray matrix
01014  *   return value : number of lines
01015  */
01016 static int ComputeNPLinesRays(int n, Polyhedron *D1, Matrix **Rays)
01017 {
01018   int i, j, nbr, dimfaces;
01019   Polyhedron *RC;  /* Recession Cone */
01020 
01021   RC = Recession_Cone(D1, n, ws);
01022 
01023   /* get the rays/lines from RC */
01024   nbr = 0;
01025   for (i = 0; i < RC->NbRays ;i++)
01026     if (value_zero_p(RC->Ray[i][n+1]))
01027       nbr++;
01028   *Rays=Matrix_Alloc(nbr, n+2);
01029   for (i = 0, j = 0; j < nbr ;i++)
01030     if (value_zero_p(RC->Ray[i][n+1]))
01031       Vector_Copy(RC->Ray[i], (*Rays)->p[j++], n+2);
01032 
01033   dimfaces = RC->NbBid;
01034   Polyhedron_Free(RC);
01035 
01036 #ifdef DEBUGPP31
01037   fprintf(stderr, "Rays = ");
01038   Matrix_Print(stderr, P_VALUE_FMT, *Rays);
01039   fprintf(stderr, "dimfaces = %d\n", dimfaces);
01040 #endif
01041 
01042   return dimfaces;
01043 }
01044 
01045 /* 
01046  * Given a polyhedron 'Di' in combined data and parameter space and a context 
01047  * polyhedron 'C' representing the constraints on the parameter space, create
01048  * a list of parameterized vertices and assign values to global variables: 
01049  * m,n,ws,Sat,egalite,mf,Xi,Pi,PiInv,RaysDi,CEqualities. 
01050  */
01051 Param_Polyhedron *Find_m_faces(Polyhedron **Di,Polyhedron *C,int keep_dom,int working_space,Polyhedron **CEq,Matrix **CT) {     
01052   
01053   unsigned int *mf;
01054   int i, j, dimfaces;
01055   Polyhedron *D=*Di,
01056              *C1,         /* true context */
01057              *D1;         /* the combined polyhedron, including context C */
01058   Matrix *Rays,           /* lines/rays (non parametric) */
01059          *M;
01060   Param_Polyhedron *res;
01061   int *p, *ref;
01062 
01063   CEqualities = NULL;
01064 
01065   if(CT) {
01066     *CEq = NULL;
01067     *CT = NULL;
01068   }
01069   
01070   if(!D || !C) 
01071     return (Param_Polyhedron *) 0;
01072 
01073   ws = working_space;
01074   m = C->Dimension;
01075   n = D->Dimension - m;
01076   if(n<0) {
01077     fprintf(stderr,
01078             "Find_m_faces: ?%d parameters of a %d-polyhedron !\n",m,n);
01079     return (Param_Polyhedron *) 0;
01080   }
01081   if (m==0)
01082     return GenParamPolyhedron(D,Matrix_Alloc(0,2));
01083   
01084   /* Add constraints from Context to D -> result in D1 */
01085   C1 = align_context(C,D->Dimension,ws);
01086 
01087 #ifdef DEBUGPP31
01088   fprintf(stderr,"m = %d\n",m);
01089   fprintf(stderr, "D = ");
01090   Polyhedron_Print(stderr,P_VALUE_FMT,D);
01091   fprintf(stderr,"C1 = ");
01092   Polyhedron_Print(stderr,P_VALUE_FMT,C1);
01093 #endif
01094   
01095   D1 = DomainIntersection(D,C1,ws);
01096 
01097 #ifdef DEBUGPP31
01098   fprintf(stderr,"D1 = ");
01099   Polyhedron_Print(stderr,P_VALUE_FMT,D1);
01100 #endif
01101   
01102   Domain_Free(C1);
01103 
01104   if (!D1)
01105     return(NULL);
01106   if (emptyQ(D1)) {
01107     Polyhedron_Free(D1);
01108     return(NULL);
01109   }
01110   
01111   /* Compute the true context C1 */
01112   /* M : lines in the direction of the first n indices (index space) */
01113   M   = Matrix_Alloc(n, D1->Dimension+2);
01114   for (i=0; i<n; i++)
01115     value_set_si(M->p[i][i+1],1);
01116   C1 = DomainAddRays(D1,M,ws);
01117   Matrix_Free(M);
01118   
01119 #ifdef DEBUGPP31
01120   fprintf(stderr,"True context C1 = ");
01121   Polyhedron_Print(stderr,P_VALUE_FMT,C1);
01122 #endif
01123 
01124   dimfaces = ComputeNPLinesRays(n, D1, &Rays);
01125 
01126   /* CEqualities contains the constraints (to be added again later) */
01127   /* *CT is the transformation matrix to add the removed parameters */
01128   if(!CT) {
01129     if (C1->NbEq == 0) {
01130       Polyhedron_Free(C1);
01131       C1 = NULL;
01132     } else {
01133       Polyhedron *CEq1, /* CEqualities, in homogeneous dim */
01134                  *D2;   /* D1, (temporary) simplified */
01135       
01136       /* Remove equalities from true context C1 and from D1             */     
01137       /* Compute CEqualities = matrix of equalities in C1, projected in */
01138       /* the parameter space                                            */
01139       M = Matrix_Alloc(C1->NbEq,m+2);
01140       for(j=0,i=0;i<C1->NbEq;++i,++j) {
01141         while(value_notzero_p(C1->Constraint[j][0]))
01142           ++j;
01143         value_assign(M->p[i][0],C1->Constraint[j][0]);
01144         Vector_Copy(&C1->Constraint[j][D->Dimension-m+1],&M->p[i][1],(m+1));
01145       }
01146       CEqualities = Constraints2Polyhedron(M,ws);
01147       Matrix_Free(M);
01148       CEq1 = align_context(CEqualities,D->Dimension,ws);
01149 
01150       /* Simplify D1 and C1 (remove the equalities) */
01151       D2 = DomainSimplify(D1,CEq1,ws);
01152       Polyhedron_Free(D1);
01153       Polyhedron_Free(C1);
01154       Polyhedron_Free(CEq1);
01155       D1 = D2;
01156       C1 = NULL;
01157     }
01158   }
01159   else { /* if( CT  ) */
01160     Polyhedron *CEq1,   /* CEqualities */
01161                *D2;     /* D1, (temporary) simplified */
01162 
01163     /* Suppress all useless constraints in parameter domain */
01164     /* when CT is not NULL (ehrhart) */
01165     /* Vin100, march 01 */
01166     CEq1 = C1;
01167     M = Matrix_Alloc(C1->NbConstraints,m+2);
01168     for(i=0;i<C1->NbConstraints;++i) {
01169       value_assign(M->p[i][0],C1->Constraint[i][0]);
01170       Vector_Copy(&C1->Constraint[i][D->Dimension-m+1],&M->p[i][1],(m+1));
01171     }
01172     CEqualities = Constraints2Polyhedron( M, ws );
01173     Matrix_Free(M);
01174 
01175     D2 = DomainSimplify(D1,CEq1,ws);
01176     Polyhedron_Free(D1);
01177     D1 = D2;
01178     C1 = Universe_Polyhedron(D2->Dimension);
01179     
01180     /* if CT is not NULL, the constraints are eliminated                */
01181     /* *CT will contain the transformation matrix to come back to the   */
01182     /* original dimension (for a polyhedron, in the parameter space)    */
01183     if( CEq1->NbEq )
01184     {
01185       m -= CEq1->NbEq;
01186       p = (int *)malloc(sizeof(int)*(CEq1->NbEq));
01187     }
01188     else
01189       p = NULL;
01190     ref = (int*) malloc(sizeof(int)*
01191                         (CEq1->Dimension+2-CEq1->NbEq));
01192     *CT = PreElim_Columns(CEq1,p,ref,CEqualities->Dimension);
01193     D2 = Elim_Columns(D1,CEq1,p,ref);
01194     if (p)
01195       free(p);
01196     free(ref);
01197     
01198 #ifdef DEBUGPP3
01199     fprintf(stderr,"D2\t Dim = %3d\tNbEq = %3d\tLines = %3d\n",
01200             D2->Dimension,D2->NbEq,D2->NbBid);
01201     C2 = Elim_Columns(C1,CEq1,p,ref);
01202     fprintf(stderr,"C2\t Dim = %3d\tNbEq = %3d\tLines = %3d\n",
01203             C2->Dimension,C2->NbEq,C2->NbBid);
01204     Polyhedron_Free(C2);
01205 #endif
01206     
01207     Polyhedron_Free(D1);
01208     Polyhedron_Free(C1);
01209     D1 = D2;
01210     C1 = NULL;
01211     *CEq = CEqualities;
01212     
01213 #ifdef DEBUGPP3
01214     fprintf(stderr,"Polyhedron CEq = ");
01215     Polyhedron_Print(stderr,P_VALUE_FMT,*CEq);
01216     fprintf(stderr,"Matrix CT = ");
01217     Matrix_Print(stderr,P_VALUE_FMT,*CT);
01218 #endif
01219     
01220     Polyhedron_Free(CEq1);
01221     CEqualities = NULL; /* don't simplify ! */
01222 
01223     /* m changed !!! */
01224     if(m==0) {
01225       /* return the new D1 too */
01226       *Di = D1;
01227 
01228       return GenParamPolyhedron(D1, Rays);
01229     }
01230   }
01231 
01232 #ifdef DEBUGPP3
01233   fprintf(stderr,"Polyhedron D1 (D AND C) = ");
01234   Polyhedron_Print(stderr,P_VALUE_FMT, D1);
01235   fprintf(stderr,"Polyhedron CEqualities = ");
01236   if(CEqualities) Polyhedron_Print(stderr,P_VALUE_FMT, CEqualities);
01237   else fprintf(stderr,"NULL\n");
01238 #endif
01239   
01240   KD = keep_dom;
01241   PDomains = NULL;
01242   PV_Result = NULL;
01243   nbPV = 0;
01244   
01245   if (emptyQ(D1)) {
01246     Polyhedron_Free(D1);
01247     Matrix_Free(Rays);
01248     return NULL;
01249   }
01250   
01251   /* mf : a bit array indicating which rays are part of the m-face */
01252   /* Poly2Sat initializes mf to all ones */
01253   /* set global variable nr to size (number of words) of mf */
01254   Sat = Poly2Sat(D1,&mf);
01255 
01256 #ifdef DEBUGPP4
01257     fprintf(stderr,"Sat = ");
01258     SMPrint(Sat);
01259 
01260   fprintf(stderr,"mf = ");
01261   for (i=0; i<nr; i++)
01262     fprintf(stderr,"%08X", mf[i]);
01263   fprintf(stderr, "\n");
01264 #endif
01265   
01266   /* A boolean array saying which constraints are part of the m-face */
01267   egalite = (unsigned int *)malloc(sizeof(int)*D1->NbConstraints);
01268   memset(egalite,0, sizeof(int)*D1->NbConstraints);
01269 
01270   for (i=0; i<D1->NbEq; i++)
01271     egalite[i] = 1;
01272 
01273   Xi     = Matrix_Alloc(n+1,m+1);
01274   Pi     = Matrix_Alloc(m+1,m+1);
01275   PiTest = Matrix_Alloc(m+1,m+1);
01276   CTest  = Matrix_Alloc(D->Dimension+1,D->NbConstraints);
01277   PiInv  = Matrix_Alloc(m+1,m+2);
01278   RaysDi = Matrix_Alloc(D1->NbRays,m+2);
01279   m_dim = m;
01280 
01281   /* m_dim has to be increased by the dimension of the smallest faces
01282    * of the (non parametric) polyhedron
01283    */
01284   m_dim += dimfaces;
01285 
01286   /* if the smallest face is of smaller dimension than m_dim,
01287    * then increase m_dim (I think this should never happen --Vincent)
01288    */
01289 #ifdef DEBUGPP3
01290   if (m_dim < D1->NbBid)
01291      fprintf(stderr, "m_dim (%d) < D1->NbBid (%d)\n", m_dim, D1->NbBid );
01292 #endif
01293   if (m_dim < D1->NbBid)
01294       m_dim = D1->NbBid;
01295 
01296 #ifdef DEBUGPP
01297   nbfaces=0;
01298 #endif
01299 #ifdef DEBUGPP3
01300   fprintf(stderr, "m_dim = %d\n", m_dim);
01301   fprintf(stderr,
01302           "Target: find faces that saturate %d constraints and %d rays/lines\n",
01303           D1->Dimension - m_dim,m_dim+1);
01304 #endif
01305         
01306   /* D1->NbEq constraints already saturated ! */
01307   scan_m_face(D1->NbEq,(D1->Dimension - m_dim - D1->NbEq),D1,mf);
01308 
01309   /* pos, number of constraints needed     */
01310 
01311 #ifdef DEBUGPP
01312   fprintf( stderr, "Number of m-faces: %d\n", nbfaces );
01313 #endif
01314   
01315   Matrix_Free(RaysDi);
01316   Matrix_Free(PiInv);
01317   Matrix_Free(PiTest);
01318   Matrix_Free(CTest);
01319   Matrix_Free(Pi);
01320   Matrix_Free(Xi);
01321   free(egalite);
01322   free(mf);
01323   SMFree(Sat);
01324   
01325   /*    if(CEqualities && keep_dom==0) {
01326            Domain_Free(CEqualities);
01327         }
01328   */
01329 
01330   res = (Param_Polyhedron *) malloc (sizeof(Param_Polyhedron));
01331   res->nbV = nbPV;
01332   res->V = PV_Result;
01333   res->D = PDomains;
01334   res->Constraints = Polyhedron2Constraints(D1);
01335   res->Rays = Rays;
01336 
01337   if(CT)                /* return the new D1 too ! */
01338     *Di = D1;
01339   else
01340     Domain_Free(D1);
01341 
01342   return(res);
01343 } /* Find_m_faces */
01344 
01345 /*
01346  * Given parametric domain 'PD' and number of parametric vertices 'nb_domains',
01347  * find the vertices that belong to distinct sub-domains. 
01348  */
01349 void Compute_PDomains(Param_Domain *PD,int nb_domains,int working_space) {
01350   
01351   unsigned bx;
01352   int i, ix, nv;
01353   Polyhedron *dx, *d1, *d2;
01354   Param_Domain *p1, *p2, *p2prev, *PDNew;
01355   
01356   if (nb_domains==0) {
01357     
01358 #ifdef DEBUGPP5
01359     fprintf(stderr,"No domains\n");
01360 #endif
01361     
01362     return;
01363   }
01364 
01365   /* Already filled out by GenParamPolyhedron */
01366   if (!PD->next && PD->F)
01367     return;
01368 
01369    /* Initialization */
01370    nv = (nb_domains - 1)/(8*sizeof(int)) + 1;
01371 
01372 #ifdef DEBUGPP5
01373    fprintf(stderr,"nv = %d\n",nv);
01374 #endif
01375 
01376    for(p1=PD,i=0,ix=0,bx=MSB;p1;p1=p1->next,i++) {
01377      
01378      /* Assign a bit array 'p1->F' of suitable size to include the vertices */
01379      p1->F = (unsigned *) malloc (nv * sizeof(unsigned));
01380      
01381      /* Set the bit array to zeros */
01382      memset(p1->F,0,nv * sizeof(unsigned));
01383      p1->F[ix] |= bx;      /* Set i'th bit to one */
01384      NEXT(ix, bx);
01385    }
01386 
01387 #ifdef DEBUGPP5
01388    fprintf(stderr,"nb of vertices=%d\n",i);
01389 #endif
01390 
01391    /* Walk the PD list with two pointers */
01392    ix = 0; bx=MSB;
01393    for (p1=PD;p1;p1=p1->next) {
01394      for (p2prev=p1,p2=p1->next;p2;p2prev=p2,p2=p2->next) {
01395         
01396        /* Find intersection */
01397        dx = PDomainIntersection(p1->Domain,p2->Domain,working_space);
01398        
01399        if (!dx || emptyQ(dx)) {
01400          
01401 #ifdef DEBUGPP5
01402          fprintf( stderr, "Empty dx (p1 inter p2). Continuing\n");
01403 #endif
01404          if(dx)
01405            Domain_Free(dx);
01406          continue;
01407        }
01408 
01409 #ifdef DEBUGPP5      
01410        fprintf(stderr,"Begin PDomainDifference\n");
01411        fprintf(stderr, "p1=");
01412        Polyhedron_Print(stderr,P_VALUE_FMT,p1->Domain);
01413        fprintf(stderr,"p2=");
01414        Polyhedron_Print(stderr,P_VALUE_FMT,p2->Domain);
01415 #endif
01416        d1 = PDomainDifference(p1->Domain,p2->Domain,working_space);
01417        d2 = PDomainDifference(p2->Domain,p1->Domain,working_space);       
01418 
01419 #ifdef DEBUGPP5       
01420        fprintf(stderr,"p1\\p2=");
01421        Polyhedron_Print(stderr,P_VALUE_FMT,d1);
01422        fprintf(stderr,"p2\\p1=");
01423        Polyhedron_Print(stderr,P_VALUE_FMT,d2);
01424        fprintf(stderr,"END PDomainDifference\n\n");       
01425 #endif
01426        if (!d1 || emptyQ(d1) || d1->NbEq!=0) {
01427 
01428 #ifdef DEBUGPP5
01429          fprintf(stderr,"Empty d1\n");
01430 #endif
01431          if (d1) 
01432            Domain_Free(d1);
01433          Domain_Free(dx);
01434          
01435          if (!d2 || emptyQ(d2) || d2->NbEq!=0) {
01436            
01437 #ifdef DEBUGPP5
01438            fprintf( stderr, "Empty d2 (deleting)\n");
01439 #endif
01440            /* dx = p1->Domain = p2->Domain */
01441            if (d2) Domain_Free(d2);
01442            
01443            /* Update p1 */
01444            for (i=0;i<nv;i++)
01445              p1->F[i] |= p2->F[i];
01446            
01447            /* Delete p2 */
01448            p2prev->next = p2->next;
01449            Domain_Free(p2->Domain);
01450            free(p2->F);
01451            free(p2);
01452            p2 = p2prev;
01453          }
01454          else {  /* d2 is not empty --> dx==p1->domain */
01455            
01456 #ifdef DEBUGPP5
01457            fprintf( stderr, "p2 replaced by d2\n");
01458 #endif
01459            /* Update p1 */
01460            for(i=0;i<nv;i++)
01461              p1->F[i] |= p2->F[i];
01462            
01463            /* Replace p2 with d2 */
01464            Domain_Free( p2->Domain );
01465            p2->Domain = d2;
01466          }
01467        }
01468        else { /* d1 is not empty */         
01469          if (!d2 || emptyQ(d2) || d2->NbEq!=0) {
01470            
01471 #ifdef DEBUGPP5
01472            fprintf( stderr, "p1 replaced by d1\n");
01473 #endif
01474            if (d2) Domain_Free(d2);
01475            
01476            /* dx = p2->domain */
01477            Domain_Free(dx);
01478            
01479            /* Update p2 */
01480            for(i=0;i<nv;i++)
01481              p2->F[i] |= p1->F[i];
01482 
01483            /* Replace p1 with d1 */
01484            Domain_Free(p1->Domain);
01485            p1->Domain = d1;
01486          }
01487          else { /*d2 is not empty-->d1,d2,dx are distinct */
01488            
01489 #ifdef DEBUGPP5
01490            fprintf(stderr,"Non-empty d1 and d2\nNew node created\n");
01491 #endif
01492            /* Create a new node for dx */
01493            PDNew = (Param_Domain *) malloc( sizeof(Param_Domain) );
01494            PDNew->F = (unsigned int *)malloc( nv*sizeof(int) );
01495            memset(PDNew->F,0,nv*sizeof(int));
01496            PDNew->Domain = dx;
01497            
01498            for (i=0;i<nv;i++)
01499              PDNew->F[i] = p1->F[i] | p2->F[i];
01500            
01501            /* Replace p1 with d1 */
01502            Domain_Free( p1->Domain );
01503            p1->Domain = d1;
01504            
01505            /* Replace p2 with d2 */
01506            Domain_Free( p2->Domain );
01507            p2->Domain = d2;
01508            
01509            /* Insert new node after p1 */
01510            PDNew->next = p1->next;
01511            p1->next = PDNew;
01512          }
01513        }
01514      }  /* end of p2 scan */
01515      if (p1->Domain->next) {
01516         Polyhedron *C = DomainConvex(p1->Domain, working_space);
01517         Domain_Free(p1->Domain);
01518         p1->Domain = C;
01519      }
01520    } /* end of p1 scan */
01521 } /* Compute_PDomains */
01522                                         
01523 /* 
01524  * Given a polyhedron 'Din' in combined data and parametre space, a context
01525  * polyhedron 'Cin' representing the constraints on the parameter space and 
01526  * a working space size 'working_space', return a parametric polyhedron with
01527  * a list of parametric vertices and their defining domains. 
01528  */
01529 Param_Polyhedron *Polyhedron2Param_Vertices(Polyhedron *Din,Polyhedron *Cin,int working_space) {
01530   
01531   Param_Polyhedron *result;
01532   
01533   POL_ENSURE_FACETS(Din);
01534   POL_ENSURE_VERTICES(Din);
01535   POL_ENSURE_FACETS(Cin);
01536   POL_ENSURE_VERTICES(Cin);
01537  
01538 #ifdef DEBUGPP
01539   fprintf(stderr,"Polyhedron2Param_Vertices algorithm starting at : %.2fs\n",
01540           (float)clock()/CLOCKS_PER_SEC);
01541 #endif
01542   
01543   /***************** Scan the m-faces ****************/
01544   result = Find_m_faces(&Din,Cin,0,working_space,NULL,NULL);
01545   
01546 #ifdef DEBUGPP
01547   fprintf(stderr, "nb of points : %d\n",result->nbV);
01548 #endif
01549   
01550 #ifdef DEBUGPP
01551   fprintf(stderr, "end main loop : %.2fs\n", (float)clock()/CLOCKS_PER_SEC);
01552 #endif
01553   
01554   return(result);
01555 } /* Polyhedron2Param_Vertices */
01556 
01557 /*
01558  * Free the memory allocated to a list of parametrized vertices  
01559  */
01560 void Param_Vertices_Free(Param_Vertices *PV) {
01561   
01562   Param_Vertices *next_pv;
01563   
01564   while(PV) {
01565     next_pv = PV->next;
01566     if (PV->Vertex) Matrix_Free(PV->Vertex);
01567     if (PV->Domain) Matrix_Free(PV->Domain);
01568     if (PV->Facets) free(PV->Facets);
01569     free(PV);  
01570     PV = next_pv;
01571   }
01572 } /* Param_Vertices_Free */
01573 
01574 /*
01575  * Print a list of parametrized vertices *
01576  */
01577 void Print_Vertex(FILE *DST, Matrix *V, const char **param_names)
01578 {
01579   int l, v;
01580   int first;
01581   Value gcd,tmp;
01582   
01583   value_init(gcd); value_init(tmp);
01584   
01585   fprintf(DST, "[" );
01586   for(l=0;l<V->NbRows;++l){
01587     
01588     /* Variables */
01589     first=1;
01590     fprintf(DST, " " );
01591     for(v=0;v < V->NbColumns-2;++v) {
01592       if(value_notzero_p(V->p[l][v])) {
01593         value_gcd(gcd, V->p[l][v], V->p[l][V->NbColumns-1]);
01594         value_divexact(tmp, V->p[l][v], gcd);
01595         if(value_posz_p(tmp)) {
01596           if(!first) 
01597             fprintf(DST, "+");
01598           if(value_notone_p(tmp)) { 
01599             value_print(DST,VALUE_FMT,tmp);
01600           }  
01601         }
01602         else { /* V->p[l][v]/gcd<0 */
01603           if(value_mone_p(tmp))
01604             fprintf(DST, "-" );
01605           else {
01606             value_print(DST,VALUE_FMT,tmp);
01607           }
01608         }
01609         value_divexact(tmp, V->p[l][V->NbColumns-1], gcd);
01610         if(value_notone_p(tmp)) {
01611           fprintf(DST, "%s/", param_names[v]);
01612           value_print(DST,VALUE_FMT,tmp);
01613         }
01614         else
01615           fprintf(DST, "%s", param_names[v]);
01616         first=0;
01617       }
01618     }
01619 
01620     /* Constant */
01621     if(value_notzero_p(V->p[l][v]) || first) {
01622       if(value_posz_p(V->p[l][v]) && !first)
01623         fprintf(DST,"+");
01624         value_gcd(gcd, V->p[l][v], V->p[l][V->NbColumns-1]);
01625         value_divexact(tmp, V->p[l][v], gcd);
01626       value_print(DST,VALUE_FMT,tmp);
01627         value_divexact(tmp, V->p[l][V->NbColumns-1], gcd);
01628       if(value_notone_p(tmp)) {
01629         fprintf(DST,"/");
01630         value_print(DST,VALUE_FMT,tmp);
01631         fprintf(DST," ");
01632       }
01633     }
01634     if (l<V->NbRows-1) 
01635       fprintf(DST, ", ");
01636   }
01637   fprintf(DST, " ]");
01638   value_clear(gcd); value_clear(tmp);
01639   return;
01640 } /* Print_Vertex */
01641 
01642 /*----------------------------------------------------------------------*/
01643 /* VertexCT                                                             */
01644 /* convert a paramvertex from reduced space to normal m-space           */
01645 /*----------------------------------------------------------------------*/
01646 Matrix *VertexCT(Matrix *V,Matrix *CT) {
01647   
01648   Matrix *Vt;
01649   int i,j,k;
01650   
01651   if(CT) {
01652     
01653     /* Have to transform the vertices to original dimension */
01654     Vt = Matrix_Alloc(V->NbRows,CT->NbColumns+1);
01655     for(i=0;i<V->NbRows;++i) {
01656       value_assign(Vt->p[i][CT->NbColumns],V->p[i][V->NbColumns-1]);
01657       for(j=0;j<CT->NbColumns;j++) {
01658         for(k=0;k<CT->NbRows;k++)
01659           if(value_notzero_p(CT->p[k][j]))
01660             break;
01661         if(k<CT->NbRows)
01662           value_assign(Vt->p[i][j],V->p[i][k]);
01663         else
01664           value_set_si(Vt->p[i][j],0);
01665       }
01666     }
01667     return(Vt);
01668   }
01669   else
01670     return(NULL);
01671 } /* VertexCT */
01672 
01673 /*
01674  * Print the validity Domain 'D' of a parametric polyhedron 
01675  */ 
01676 void Print_Domain(FILE *DST, Polyhedron *D, const char **pname)
01677 {
01678   int l, v;
01679   int first;
01680   
01681   POL_ENSURE_FACETS(D);
01682   POL_ENSURE_VERTICES(D);
01683  
01684   for(l=0;l<D->NbConstraints;++l) {
01685     fprintf(DST, "         ");
01686     first = 1;
01687     for(v=1;v<=D->Dimension;++v) {
01688       if(value_notzero_p(D->Constraint[l][v])) {
01689         if(value_one_p(D->Constraint[l][v])) {
01690           if(first)
01691             fprintf(DST, "%s ", pname[v-1]);
01692           else
01693             fprintf(DST, "+ %s ", pname[v-1] );
01694         }
01695         else if(value_mone_p(D->Constraint[l][v]))
01696           fprintf(DST, "- %s ", pname[v-1] );
01697         else {
01698           if(value_pos_p(D->Constraint[l][v]) && !first )
01699             fprintf(DST, "+ " );
01700           value_print(DST,VALUE_FMT,D->Constraint[l][v]);
01701           fprintf(DST,"%s ",pname[v-1]);
01702         }
01703         first = 0;
01704       }
01705     }
01706     if(value_notzero_p(D->Constraint[l][v])) {
01707       if(value_pos_p(D->Constraint[l][v]) && !first)
01708         fprintf(DST,"+");
01709       fprintf(DST," ");
01710       value_print(DST,VALUE_FMT,D->Constraint[l][v]);
01711     }
01712     fprintf(DST,(value_notzero_p(D->Constraint[l][0])) ?" >= 0":" = 0");
01713     fprintf(DST, "\n" );
01714   }
01715   fprintf(DST, "\n");
01716 
01717         if( D->next )
01718         {
01719                 fprintf( DST, "UNION\n" );
01720                 Print_Domain( DST, D->next, pname );
01721         }
01722   return;
01723 } /* Print_Domain */
01724 
01725 /* 
01726  * Given a list of parametrized vertices and an array of parameter names, Print
01727  * a list of parametrized vertices in a comprehensible format. 
01728  */
01729 void Param_Vertices_Print(FILE *DST, Param_Vertices *PV, const char **param_names)
01730 {
01731   Polyhedron *poly;
01732   
01733   while(PV) {
01734     fprintf(DST, "Vertex :\n" );
01735     Print_Vertex(DST,PV->Vertex,param_names);
01736     
01737     /* Pour le domaine : */
01738     fprintf(DST, "   If :\n" );
01739     poly = Constraints2Polyhedron(PV->Domain,200);
01740     Print_Domain(DST,poly,param_names);
01741     Domain_Free(poly);   
01742     PV = PV->next;
01743   }
01744   return;
01745 } /* Param_Vertices_Print */
01746 
01747 /* 
01748  * Given a polyhedron 'Din' in combined data and parametre space, a context
01749  * polyhedron 'Cin' representing the constraints on the parameter space and 
01750  * a working space size 'working_space', return a parametric polyhedron with
01751  * a list of distinct validity domains and a complete list of valid vertices 
01752  * associated to each validity domain. 
01753  */
01754 Param_Polyhedron *Polyhedron2Param_Domain(Polyhedron *Din,Polyhedron *Cin,int working_space) {
01755                 
01756   Param_Polyhedron *result;
01757   Param_Domain *D;
01758 
01759   POL_ENSURE_FACETS(Din);
01760   POL_ENSURE_VERTICES(Din);
01761   POL_ENSURE_FACETS(Cin);
01762   POL_ENSURE_VERTICES(Cin);
01763 
01764   if (emptyQ(Din) || emptyQ(Cin))
01765     return NULL;
01766  
01767 #ifdef DEBUGPP
01768   fprintf(stderr,"Polyhedron2Param_Polyhedron algorithm starting at : %.2fs\n",
01769           (float)clock()/CLOCKS_PER_SEC);
01770 #endif
01771   
01772   /* Find the m-faces, keeping the corresponding domains */
01773   /* in the linked list PDomains */
01774   result = Find_m_faces(&Din,Cin,1,working_space,NULL,NULL);
01775   
01776 #ifdef DEBUGPP
01777   if(result) fprintf(stderr, "Number of vertices : %d\n",result->nbV);
01778   fprintf(stderr,"Vertices found at : %.2fs\n",(float)clock()/CLOCKS_PER_SEC);
01779 #endif
01780   
01781   /* Processing of PVResult and PDomains */
01782   if(result && Cin->Dimension>0)                /* at least 1 parameter */
01783     Compute_PDomains(result->D,result->nbV,working_space);
01784   if(result && CEqualities)
01785     for(D=result->D;D;D=D->next)
01786       D->Domain = Add_CEqualities(D->Domain);
01787   Polyhedron_Free(CEqualities); 
01788   
01789 #ifdef DEBUGPP
01790   fprintf(stderr, "domains found at : %.2fs\n", (float)clock()/CLOCKS_PER_SEC);
01791 #endif
01792 
01793   return(result);
01794 } /* Polyhedon2Param_Domain */
01795 
01796 /*
01797  *
01798  */
01799 Param_Polyhedron *Polyhedron2Param_SimplifiedDomain(Polyhedron **Din,Polyhedron *Cin,int working_space,Polyhedron **CEq,Matrix **CT) {
01800                                                      
01801   Param_Polyhedron *result;
01802 
01803   assert(CEq != NULL);
01804   assert(CT != NULL);
01805 
01806   POL_ENSURE_FACETS(*Din);
01807   POL_ENSURE_VERTICES(*Din);
01808   POL_ENSURE_FACETS(Cin);
01809   POL_ENSURE_VERTICES(Cin);
01810  
01811 #ifdef DEBUGPP
01812   fprintf(stderr,"Polyhedron2Param_Polyhedron algorithm starting at : %.2fs\n",
01813           (float)clock()/CLOCKS_PER_SEC);
01814 #endif
01815   
01816   /* Find the m-faces, keeping the corresponding domains */
01817   /* in the linked list PDomains */
01818   result = Find_m_faces(Din,Cin,1,working_space,CEq,CT);
01819   
01820 #ifdef DEBUGPP
01821   if(result) fprintf(stderr, "Number of vertices : %d\n",result->nbV);
01822   fprintf(stderr,"Vertices found at : %.2fs\n",(float)clock()/CLOCKS_PER_SEC);
01823 #endif
01824 
01825   /* Processing of PVResult and PDomains */
01826   if(result && Cin->Dimension>0)                /* at least 1 parameter */
01827     Compute_PDomains(result->D,result->nbV,working_space);
01828   
01829   /* Removed this, Vin100, March 01 */
01830   /*    if(result && CEqualities )
01831         for(D=result->D;D;D=D->next)
01832         D->Domain = Add_CEqualities(D->Domain);
01833   */
01834   
01835 #ifdef DEBUGPP
01836   fprintf(stderr, "domains found at : %.2fs\n", (float)clock()/CLOCKS_PER_SEC);
01837 #endif
01838   
01839   return(result);
01840 } /* Polyhedron2Param_SimplifiedDomain */
01841 
01842 /*
01843  * Free the memory allocated to a list of validity domain of a parametrized 
01844  * polyhedron.
01845  */
01846 void Param_Domain_Free(Param_Domain *PD) {
01847         
01848   Param_Domain *next_pd;
01849   
01850   while(PD) {
01851     free(PD->F);
01852     Domain_Free(PD->Domain);
01853     next_pd = PD->next;
01854     free(PD);
01855     PD = next_pd;
01856   }
01857   return;
01858 } /* Param_Domain_Free */
01859 
01860 /*
01861  * Free the memory allocated to a parametric polyhedron 'P' 
01862  */
01863 void Param_Polyhedron_Free(Param_Polyhedron *P) {
01864   
01865   if (!P) return;
01866   Param_Vertices_Free(P->V);
01867   Param_Domain_Free(P->D);
01868   if (P->Constraints)
01869     Matrix_Free(P->Constraints);
01870   if (P->Rays)
01871     Matrix_Free(P->Rays);
01872   free(P);
01873   return;
01874 } /* Param_Polyhedron_Free */
01875 
01876 /*
01877  * Scales the parametric polyhedron such that all vertices are integer.
01878  */
01879 void Param_Polyhedron_Scale_Integer(Param_Polyhedron *PP, Polyhedron **P,
01880                                     Value *det, unsigned MaxRays)
01881 {
01882   int i;
01883   int nb_param, nb_vars;
01884   Vector *denoms;
01885   Param_Vertices *V;
01886   Value global_var_lcm;
01887   Matrix *expansion;
01888 
01889   value_set_si(*det, 1);
01890   if (!PP->nbV)
01891     return;
01892 
01893   nb_param = PP->D->Domain->Dimension;
01894   nb_vars = PP->V->Vertex->NbRows;
01895 
01896   /* Scan the vertices and make an orthogonal expansion of the variable
01897      space */
01898   /* a- prepare the array of common denominators */
01899   denoms = Vector_Alloc(nb_vars);
01900   value_init(global_var_lcm);
01901 
01902   /* b- scan the vertices and compute the variables' global lcms */
01903   for (V = PP->V; V; V = V->next)
01904     for (i = 0; i < nb_vars; i++)
01905       value_lcm(denoms->p[i], denoms->p[i], V->Vertex->p[i][nb_param+1]);
01906 
01907   value_set_si(global_var_lcm, 1);
01908   for (i = 0; i < nb_vars; i++) {
01909     value_multiply(*det, *det, denoms->p[i]);
01910     value_lcm(global_var_lcm, global_var_lcm, denoms->p[i]);
01911   }
01912 
01913   /* scale vertices */
01914   for (V = PP->V; V; V = V->next)
01915     for (i = 0; i < nb_vars; i++) {
01916       Vector_Scale(V->Vertex->p[i], V->Vertex->p[i], denoms->p[i], nb_param+1);
01917       Vector_Normalize(V->Vertex->p[i], nb_param+2);
01918     }
01919 
01920   /* the expansion can be actually writen as global_var_lcm.L^{-1} */
01921   /* this is equivalent to multiply the rows of P by denoms_det */
01922   for (i = 0; i < nb_vars; i++)
01923     value_division(denoms->p[i], global_var_lcm, denoms->p[i]);
01924 
01925   /* OPT : we could use a vector instead of a diagonal matrix here (c- and d-).*/
01926   /* c- make the quick expansion matrix */
01927   expansion = Matrix_Alloc(nb_vars+nb_param+1, nb_vars+nb_param+1);
01928   for (i = 0; i < nb_vars; i++)
01929     value_assign(expansion->p[i][i], denoms->p[i]);
01930   for (i = nb_vars; i < nb_vars+nb_param+1; i++)
01931     value_assign(expansion->p[i][i], global_var_lcm);
01932 
01933   /* d- apply the variable expansion to the polyhedron */
01934   if (P)
01935     *P = Polyhedron_Preimage(*P, expansion, MaxRays);
01936 
01937   Matrix_Free(expansion);
01938   value_clear(global_var_lcm);
01939   Vector_Free(denoms);
01940 }

Generated on Thu Sep 4 15:28:58 2008 for polylib by doxygen 1.3.5