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

Generated on Mon Sep 12 14:48:29 2005 for polylib by doxygen 1.3.5