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

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