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

Zpolyhedron.c

Go to the documentation of this file.
00001 #include <polylib/polylib.h> 
00002 #include <stdlib.h>
00003 
00004 static ZPolyhedron * ZPolyhedronIntersection(ZPolyhedron *, ZPolyhedron *);
00005 static ZPolyhedron *ZPolyhedron_Copy(ZPolyhedron *A);
00006 static void ZPolyhedron_Free(ZPolyhedron *Zpol);
00007 static ZPolyhedron * ZPolyhedronDifference(ZPolyhedron *, ZPolyhedron *);
00008 static ZPolyhedron * ZPolyhedronImage(ZPolyhedron *, Matrix *);
00009 static ZPolyhedron * ZPolyhedronPreimage(ZPolyhedron *, Matrix *);
00010 static ZPolyhedron *AddZPolytoZDomain(ZPolyhedron *A, ZPolyhedron *Head);
00011 static void ZPolyhedronPrint(FILE *fp, const char *format, ZPolyhedron *A);
00012 
00013 typedef struct forsimplify {
00014   Polyhedron *Pol;
00015   LatticeUnion *LatUni;
00016   struct forsimplify *next;
00017 } ForSimplify;
00018 
00019 
00020 /* 
00021  * Returns True if 'Zpol' is empty, otherwise returns False 
00022  */
00023 Bool isEmptyZPolyhedron (ZPolyhedron *Zpol) {
00024   
00025   if(Zpol == NULL)
00026     return True;
00027   if((isEmptyLattice (Zpol->Lat)) || (emptyQ(Zpol->P)))
00028     return True;
00029   return False;
00030 } /* isEmptyZPolyhedron */
00031 
00032 /*
00033  * Given Lattice 'Lat' and a Polyhderon 'Poly', allocate space, and return
00034  * the Z-polyhderon corresponding to the image of the polyhderon 'Poly' by the 
00035  * lattice 'Lat'. If the input lattice 'Lat' is not integeral, it integralises 
00036  * it, i.e. the lattice of the Z-polyhderon returned is integeral. 
00037  */ 
00038 ZPolyhedron *ZPolyhedron_Alloc(Lattice *Lat, Polyhedron *Poly) {
00039   
00040   ZPolyhedron *A;
00041   
00042   POL_ENSURE_FACETS(Poly);
00043   POL_ENSURE_VERTICES(Poly);
00044 
00045   if(Lat->NbRows != Poly->Dimension+1) {
00046     fprintf(stderr,"\nInZPolyAlloc - The Lattice  and the Polyhedron");
00047     fprintf(stderr," are not compatible to form a ZPolyhedra\n");
00048     return NULL;
00049   }  
00050   if((!(isEmptyLattice(Lat))) && (!isfulldim (Lat))) {
00051     fprintf(stderr,"\nZPolAlloc: Lattice not Full Dimensional\n");
00052     return NULL;
00053   }
00054   A = (ZPolyhedron *)malloc(sizeof(ZPolyhedron));
00055   if (!A) {
00056     fprintf(stderr,"ZPolAlloc : Out of Memory\n");
00057     return NULL;
00058   } 
00059   A->next = NULL;
00060   A->P = Domain_Copy(Poly);
00061   A->Lat = Matrix_Copy(Lat);
00062   
00063   if(IsLattice(Lat) == False) {
00064     ZPolyhedron *Res;
00065     
00066     Res = IntegraliseLattice (A);
00067     ZPolyhedron_Free (A);
00068     return Res;
00069   }
00070   return A;
00071 } /* ZPolyhedron_Alloc */
00072 
00073 /*
00074  * Free the memory used by the Z-domain 'Head' 
00075  */
00076 void ZDomain_Free (ZPolyhedron *Head) {
00077   
00078   if (Head == NULL)
00079     return;
00080   if (Head->next != NULL)
00081     ZDomain_Free(Head->next);  
00082   ZPolyhedron_Free(Head);
00083 } /* ZDomain_Free */
00084 
00085 /*
00086  * Free the memory used by the Z-polyhderon 'Zpol' 
00087  */
00088 static void ZPolyhedron_Free (ZPolyhedron *Zpol) {
00089   
00090   if (Zpol == NULL)
00091     return;
00092   Matrix_Free((Matrix *) Zpol->Lat);
00093   Domain_Free(Zpol->P);
00094   free(Zpol);
00095   return;
00096 } /* ZPolyhderon_Free */
00097 
00098 /*
00099  * Return a copy of the Z-domain 'Head' 
00100  */ 
00101 ZPolyhedron *ZDomain_Copy(ZPolyhedron *Head) {
00102   
00103   ZPolyhedron *Zpol;
00104   Zpol = ZPolyhedron_Copy(Head);
00105   
00106   if (Head->next != NULL)
00107     Zpol->next = ZDomain_Copy(Head->next);
00108   return Zpol;
00109 } /* ZDomain_Copy */
00110 
00111 /*
00112  * Return a copy of the Z-polyhderon 'A' 
00113  */
00114 static ZPolyhedron *ZPolyhedron_Copy(ZPolyhedron *A) {
00115 
00116   ZPolyhedron *Zpol;
00117   
00118   Zpol = ZPolyhedron_Alloc(A->Lat, A->P);
00119   return Zpol;
00120 } /* ZPolyhderon_Copy */
00121 
00122 /* 
00123  * Add the ZPolyhedron 'Zpol' to the Z-domain 'Result' and return a pointer 
00124  * to the new Z-domain. 
00125  */
00126 static ZPolyhedron *AddZPoly2ZDomain(ZPolyhedron *Zpol, ZPolyhedron *Result) {
00127  
00128   ZPolyhedron *A;
00129   
00130   if (isEmptyZPolyhedron(Zpol))
00131     return Result;
00132   A = ZPolyhedron_Copy(Zpol);
00133   A->next = NULL;
00134   
00135   if (isEmptyZPolyhedron (Result)) {
00136     ZDomain_Free (Result);
00137     return A;
00138   }
00139   A->next = Result;  
00140   return A;
00141 } /* AddZPoly2ZDomain */
00142   
00143 /*
00144  * Given a Z-polyhderon 'A' and a Z-domain 'Head', return a new Z-domain with 
00145  * 'A' added to it. If the new Z-polyhedron 'A', is already included in the 
00146  * Z-domain 'Head', it is not added in the list. Othewise, the function checks 
00147  * if the new Z-polyhedron 'A' to be added to the Z-domain 'Head' has a common
00148  * lattice with some other Z-polyhderon already present in the Z-domain. If it 
00149  * is so, it takes the union of the underlying polyhdera; domains and returns. 
00150  * The function tries to make sure that the added Z-polyhedron 'A' is in the 
00151  * canonical form.
00152  */
00153 static ZPolyhedron *AddZPolytoZDomain(ZPolyhedron *A, ZPolyhedron *Head) {
00154   
00155   ZPolyhedron *Zpol, *temp, *temp1;
00156   Polyhedron *i;
00157   Bool Added;  
00158   
00159   if ((A == NULL) || (isEmptyZPolyhedron(A)))
00160     return Head;
00161   
00162   /* For each "underlying" Pol, find the Cnf and add Zpol in Cnf*/  
00163   for(i=A->P; i!= NULL; i=i->next) {
00164     ZPolyhedron *Z, *Z1;
00165     Polyhedron *Image;
00166     Matrix *H, *U;
00167     Lattice *Lat ;
00168     
00169     Added = False;    
00170     Image = Domain_Copy(i);
00171     Domain_Free(Image->next);
00172     Image->next = NULL;
00173     Z1 = ZPolyhedron_Alloc(A->Lat,Image);
00174     Domain_Free(Image);
00175     CanonicalForm(Z1,&Z,&H); 
00176     ZDomain_Free(Z1);
00177     Lat = (Lattice *)Matrix_Alloc(H->NbRows,Z->Lat->NbColumns);
00178     Matrix_Product(H,Z->Lat,(Matrix *)Lat);
00179     Matrix_Free(H);    
00180     AffineHermite(Lat,(Lattice **)&H,&U);
00181     Image = DomainImage(Z->P,U,MAXNOOFRAYS);
00182     ZDomain_Free(Z);
00183       
00184     Zpol=ZPolyhedron_Alloc((Lattice *)H,Image);     
00185     Domain_Free(Image);
00186     Matrix_Free((Matrix *)Lat);
00187     Matrix_Free(H);
00188     Matrix_Free(U);
00189     
00190     if ((Head == NULL) || (isEmptyZPolyhedron (Head))) {
00191       Head = Zpol;
00192       continue;
00193     }     
00194     temp1 = temp = Head;
00195     
00196     /* Check if the curr pol is included in the zpol or vice versa. */    
00197     for(; temp != NULL; temp = temp->next) {
00198       if (ZPolyhedronIncludes(Zpol, temp) == True) {
00199         ZPolyhedron_Free (Zpol);
00200         Added = True; 
00201         break;
00202       }
00203       else if (ZPolyhedronIncludes(temp, Zpol) == True) {
00204         if (temp == Head) {
00205           Zpol->next = temp->next;
00206           Head = Zpol;
00207           ZPolyhedron_Free (temp);
00208           Added = True;
00209           break;
00210         }       
00211         temp1->next = Zpol;
00212         Zpol->next = temp->next;
00213         ZPolyhedron_Free (temp);
00214         Added = True;
00215         break ;
00216       }
00217       temp1 = temp ;
00218     }
00219     if(Added == True)
00220       continue ; 
00221     for(temp = Head; temp != NULL; temp = temp->next) {
00222       if(sameLattice(temp->Lat, Zpol->Lat) == True) {
00223         Polyhedron *Union;
00224         
00225         Union = DomainUnion (temp->P,Zpol->P,MAXNOOFRAYS);
00226         if (!Union)
00227           fprintf (stderr,"\n In AddZPolytoZDomain: Out of memory\n");
00228         else {
00229           Domain_Free(temp->P);
00230           temp->P = Union;
00231           Added = True;
00232           ZPolyhedron_Free(Zpol);
00233         }
00234         break ; 
00235       }
00236       temp1 = temp;
00237     }
00238     if (Added == False) 
00239       temp1->next = Zpol;
00240   }
00241   return Head ;  
00242 } /* AddZPolytoZDomain */
00243 
00244 /*
00245  * Return the empty Z-polyhedron of dimension 'dimension' 
00246  */
00247 ZPolyhedron *EmptyZPolyhedron(int dimension) {
00248 
00249   ZPolyhedron *Zpol;
00250   Lattice *E ;
00251   Polyhedron *P; 
00252   
00253 #ifdef DOMDEBUG
00254   FILE *fp;
00255   fp = fopen ("_debug", "a");
00256   fprintf (fp, "\nEntered EMPTYZPOLYHEDRON\n");
00257   fclose (fp);
00258 #endif
00259 
00260   E = EmptyLattice(dimension+1);
00261   P = Empty_Polyhedron(dimension);
00262   Zpol = ZPolyhedron_Alloc(E,P);
00263   Matrix_Free((Matrix *) E);
00264   Domain_Free(P);
00265   return Zpol;
00266 } /* EmptyZPolyhedron */
00267 
00268 /* 
00269  * Given Z-domains 'A' and 'B', return True if A is included in 'B', otherwise
00270  * return False.
00271  */
00272 Bool ZDomainIncludes(ZPolyhedron *A, ZPolyhedron *B) {
00273   
00274   ZPolyhedron *Diff;
00275   Bool ret = False;
00276   
00277   Diff = ZDomainDifference(A,B);
00278   if (isEmptyZPolyhedron(Diff))
00279     ret = True;
00280   
00281   ZDomain_Free(Diff);
00282   return ret;
00283 } /* ZDomainIncludes */
00284 
00285 /* 
00286  * Given Z-polyhedra 'A' and 'B', return True if 'A' is included in 'B', 
00287  * otherwise return False 
00288  */
00289 Bool ZPolyhedronIncludes(ZPolyhedron *A, ZPolyhedron *B) {
00290 
00291   Polyhedron *Diff = NULL ;
00292   Bool retval = False;
00293 
00294 #ifdef DOMDEBUG
00295   FILE *fp;
00296   fp = fopen("_debug","a");
00297   fprintf(fp,"\nEntered ZPOLYHEDRONINCLUDES\n");
00298   fclose(fp);
00299 #endif
00300   
00301   if (LatticeIncludes(A->Lat, B->Lat) == True) {
00302     Polyhedron *ImageA, *ImageB ;
00303     
00304     ImageA = DomainImage(A->P,A->Lat,MAXNOOFRAYS);
00305     ImageB = DomainImage(B->P,B->Lat,MAXNOOFRAYS);
00306       
00307     Diff = DomainDifference(ImageA, ImageB, MAXNOOFRAYS);
00308     if(emptyQ (Diff))
00309       retval = True ;
00310     
00311     Domain_Free (ImageA);
00312     Domain_Free (ImageB);
00313     Domain_Free (Diff);
00314   }  
00315   return retval;
00316 } /* ZPolyhedronIncludes */ 
00317 
00318 /*
00319  * Print the contents of a Z-domain 'A' 
00320  */
00321 void ZDomainPrint(FILE *fp, const char *format, ZPolyhedron *A)
00322 {
00323 #ifdef DOMDEBUG
00324   FILE *fp1;
00325   fp1 = fopen("_debug", "a");
00326   fprintf(fp1,"\nEntered ZDOMAINPRINT\n");
00327   fclose(fp1);
00328 #endif
00329   
00330   ZPolyhedronPrint(fp,format,A);
00331   if (A->next != NULL) {
00332     fprintf(fp,"\nUNIONED with\n");
00333     ZDomainPrint(fp,format,A->next);
00334   }
00335   return;
00336 } /* ZDomainPrint */  
00337 
00338 /*
00339  * Print the contents of a ZPolyhderon 'A'
00340  */
00341 static void ZPolyhedronPrint (FILE *fp, const char *format, ZPolyhedron *A)
00342 {
00343   if (A == NULL)
00344     return ;
00345   fprintf(fp,"\nZPOLYHEDRON: Dimension %d \n",A->Lat->NbRows-1);
00346   fprintf(fp, "\nLATTICE: \n");
00347   Matrix_Print(fp,format,(Matrix *)A->Lat);
00348   Polyhedron_Print(fp,format,A->P);  
00349   return;
00350 } /* ZPolyhedronPrint */
00351 
00352 /*
00353  * Return the Z-domain union of the Z-domain 'A' and 'B'. The dimensions of the
00354  * Z-domains 'A' and 'B' must be equal. All the Z-polyhedra of the resulting 
00355  * union are expected to be in Canonical forms.
00356  */
00357 ZPolyhedron *ZDomainUnion (ZPolyhedron *A, ZPolyhedron *B) {
00358   
00359   ZPolyhedron *Result = NULL, *temp;
00360   
00361 #ifdef DOMDEBUG
00362   FILE *fp;
00363   fp = fopen("_debug", "a");
00364   fprintf(fp,"\nEntered ZDOMAINUNION\n");
00365   fclose(fp);
00366 #endif
00367 
00368   for(temp = A; temp != NULL; temp = temp->next)
00369     Result = AddZPolytoZDomain(temp, Result); 
00370   for(temp = B; temp != NULL; temp = temp->next )
00371     Result = AddZPolytoZDomain(temp, Result);
00372   return Result;
00373 } /* ZDomainUnion */
00374 
00375 /* 
00376  * Return the Z-domain intersection of the Z-domains 'A' and 'B'.The dimensions
00377  * of domains 'A' and 'B' must be equal. 
00378  */
00379 ZPolyhedron *ZDomainIntersection (ZPolyhedron *A, ZPolyhedron *B) {
00380   
00381   ZPolyhedron *Result = NULL, *tempA = NULL, *tempB = NULL;
00382 
00383 #ifdef DOMDEBUG
00384   FILE *fp;
00385   fp = fopen("_debug", "a");
00386   fprintf(fp,"\nEntered ZDOMAININTERSECTION\n");
00387   fclose(fp);
00388 #endif  
00389   
00390   for(tempA = A; tempA != NULL; tempA = tempA->next)
00391     for(tempB = B; tempB != NULL; tempB = tempB->next) {
00392       ZPolyhedron *Zpol;
00393       Zpol = ZPolyhedronIntersection(tempA, tempB);
00394       Result = AddZPolytoZDomain(Zpol, Result );
00395       ZPolyhedron_Free (Zpol);
00396     }
00397   if (Result == NULL)
00398     return EmptyZPolyhedron (A->Lat->NbRows-1);
00399   return Result;
00400 } /* ZDomainIntersection */
00401 
00402 /*
00403  * Return the Z-domain difference of the domains 'A' and 'B'. The dimensions of
00404  * the Z-domains 'A' and 'B' must be equal. Note that the difference of two 
00405  * Z-polyhedra is a Union of Z-polyhedra. The algorithms is as given below :-
00406  * Algorithm: (Given Z-domains A and B)
00407  *           Result <-- NULL
00408  *           for every Z-polyhderon Zpoly of A {
00409  *               temp <-- Zpoly;
00410  *               for every Z-polyhderon Z1 of B
00411  *                  temp = temp - Z1;
00412  *               }
00413  *           Add temp to Result;
00414  *           return;
00415  */
00416 ZPolyhedron *ZDomainDifference(ZPolyhedron  *A, ZPolyhedron *B) {
00417   
00418   ZPolyhedron *Result = NULL, *tempA = NULL, *tempB = NULL;
00419   ZPolyhedron *templist, *res, *i, *j;
00420 
00421 #ifdef DOMDEBUG
00422   FILE *fp;
00423   fp = fopen("_debug", "a");
00424   fprintf(fp,"\nEntered ZDOMAINDIFFERENCE\n");
00425   fclose(fp);
00426 #endif
00427   
00428   if (A->Lat->NbRows != B->Lat->NbRows) {
00429     fprintf(stderr, "In ZDomainDifference : the input ZDomains ");
00430     fprintf(stderr, "do not have compatible dimensions\n");
00431     fprintf(stderr, "ZDomainDifference not performed\n");
00432     return NULL;
00433   }
00434   
00435   for(tempA = A; tempA != NULL; tempA = tempA->next) {
00436     ZPolyhedron *temp = NULL;
00437     temp = ZPolyhedron_Copy(tempA);
00438     
00439     for(tempB = B; tempB != NULL; tempB = tempB->next) {
00440       templist = NULL; res = NULL;
00441       for(i = temp; i != NULL; i = i->next) {
00442         res = ZPolyhedronDifference(i,tempB);
00443         for (j = res; j != NULL; j = j->next )
00444           templist = AddZPoly2ZDomain(j,templist);
00445         ZDomain_Free(res);
00446       }
00447       ZDomain_Free (temp);
00448       temp = NULL; 
00449       for(i = templist; i != NULL; i = i->next)
00450         temp = AddZPoly2ZDomain(i, temp);
00451       ZDomain_Free (templist);
00452     }
00453     for(i = temp; i != NULL; i = i->next)
00454       Result = AddZPolytoZDomain(i, Result);
00455     ZDomain_Free(temp);    
00456   }
00457   if (Result==NULL)
00458     return (EmptyZPolyhedron(A->Lat->NbRows-1));
00459   return Result;
00460 } /* ZDomainDifference */
00461 
00462 /*
00463  * Return the image of the Z-domain 'A' under the invertible, affine, rational
00464  * transformation function 'Func'. The matrix representing the function 'Func'
00465  * must be non-singular and the number of rows of the function must be equal
00466  * to the number of rows in the matrix representing the lattice of 'A'. 
00467  * Note:: Image((Z1 U Z2),F) = Image(Z1,F) U Image(Z2 U F).
00468  */
00469 ZPolyhedron *ZDomainImage (ZPolyhedron *A, Matrix *Func) {
00470 
00471   ZPolyhedron *Result = NULL, *temp;
00472 
00473 #ifdef DOMDEBUG
00474   FILE *fp;
00475   fp = fopen ("_debug", "a");
00476   fprintf (fp, "\nEntered ZDOMAINIMAGE\n");
00477   fclose (fp);
00478 #endif  
00479   
00480   for(temp = A; temp != NULL; temp = temp->next) {
00481     ZPolyhedron *Zpol;
00482     Zpol =  ZPolyhedronImage (temp, Func);
00483     Result = AddZPolytoZDomain (Zpol, Result);
00484     ZPolyhedron_Free (Zpol);
00485   }  
00486   if(Result == NULL)
00487     return EmptyZPolyhedron(A->Lat->NbRows-1);  
00488   return Result;
00489 } /* ZDomainImage */ 
00490 
00491 /*
00492  * Return the preimage of the Z-domain 'A' under the invertible, affine, ratio-
00493  * nal transformation 'Func'. The number of rows of the matrix representing 
00494  * the function 'Func' must be equal to the number of rows of the matrix repr-
00495  * senting the lattice of 'A'.  
00496  */
00497 ZPolyhedron *ZDomainPreimage (ZPolyhedron *A, Matrix *Func) {
00498 
00499   ZPolyhedron *Result = NULL, *temp ;
00500   
00501 #ifdef DOMDEBUG
00502   FILE *fp;
00503   fp = fopen("_debug", "a");
00504   fprintf(fp,"\nEntered ZDOMAINPREIMAGE\n");
00505   fclose(fp);
00506 #endif
00507   
00508   if (A->Lat->NbRows != Func->NbRows) {
00509     fprintf(stderr,"\nError : In ZDomainPreimage, ");
00510     fprintf(stderr,"Incompatible dimensions of ZPolyhedron ");
00511     fprintf(stderr,"and the Function \n");
00512     return(EmptyZPolyhedron(Func->NbColumns-1)); 
00513   }  
00514   for(temp = A; temp != NULL; temp = temp->next) {       
00515     ZPolyhedron *Zpol;
00516     Zpol = ZPolyhedronPreimage(temp, Func);
00517     Result = AddZPolytoZDomain(Zpol, Result);
00518     ZPolyhedron_Free(Zpol);
00519   }  
00520   if (Result == NULL)
00521     return(EmptyZPolyhedron(Func->NbColumns-1));
00522   return Result;   
00523 } /* ZDomainPreimage */ 
00524 
00525 /*
00526  * Return the Z-polyhedron intersection of the Z-polyhedra 'A' and 'B'. 
00527  * Note: If Z1 = L1 (intersect) P1 and Z2 = L2 (intersect) P2, then 
00528  *     Z1 (intersect) Z2 = (L1 (intersect) L2) (intersect) (P1 (intersect) P2) 
00529  */
00530 static ZPolyhedron *ZPolyhedronIntersection(ZPolyhedron *A, ZPolyhedron *B) {
00531   
00532   ZPolyhedron *Result = NULL;
00533   Lattice *LInter;
00534   Polyhedron *PInter, *ImageA, *ImageB, *PreImage;
00535   
00536 #ifdef DOMDEBUG
00537   FILE *fp;
00538   fp = fopen("_debug","a");
00539   fprintf(fp,"\nEntered ZPOLYHEDRONINTERSECTION\n");
00540   fclose(fp);
00541 #endif  
00542   
00543   LInter = LatticeIntersection(A->Lat,B->Lat);
00544   if(isEmptyLattice(LInter) == True) {
00545     ZPolyhedron_Free (Result);
00546     Matrix_Free(LInter);
00547     return (EmptyZPolyhedron(A->Lat->NbRows-1));
00548   }  
00549   ImageA = DomainImage(A->P,A->Lat,MAXNOOFRAYS);
00550   ImageB = DomainImage(B->P,B->Lat,MAXNOOFRAYS);
00551   PInter = DomainIntersection(ImageA,ImageB,MAXNOOFRAYS); 
00552   if (emptyQ(PInter))
00553     Result = EmptyZPolyhedron(LInter->NbRows-1);
00554   else { 
00555     PreImage = DomainPreimage(PInter,(Matrix *)LInter,MAXNOOFRAYS);
00556     Result = ZPolyhedron_Alloc(LInter, PreImage);    
00557     Domain_Free (PreImage);
00558   }  
00559   Matrix_Free(LInter);
00560   Domain_Free(PInter); 
00561   Domain_Free(ImageA);
00562   Domain_Free(ImageB);  
00563   return Result ;
00564 } /* ZPolyhedronIntersection */ 
00565 
00566 /* 
00567  * Return the difference of the two Z-polyhedra 'A' and 'B'. Below is the 
00568  * procedure to find the difference of 'A' and 'B' :-
00569  * Procedure: 
00570  *     Let A = L1 (intersect) P1' and B = L2 (intersect) P2' where 
00571  *     (P1' = DomImage(P1,L1) and P2' = DomImage(P2,L2)). Then 
00572  *     A-B = L1 (intersect) (P1'-P2') Union 
00573  *           (L1-L2) (intersect) (P1' (intersect) P2')
00574  */ 
00575 static ZPolyhedron *ZPolyhedronDifference(ZPolyhedron *A, ZPolyhedron *B) {
00576   
00577   ZPolyhedron *Result = NULL ;
00578   LatticeUnion *LatDiff, *temp;
00579   Polyhedron *DomDiff, *DomInter, *PreImage, *ImageA, *ImageB;
00580   Bool flag = False;
00581 
00582 #ifdef DOMDEBUG
00583   FILE *fp;
00584   fp = fopen("_debug", "a");
00585   fprintf(fp,"\nEntered ZPOLYHEDRONDIFFERENCE\n");
00586   fclose(fp);
00587 #endif
00588 
00589   if(isEmptyZPolyhedron (A))
00590     return NULL;
00591   if(isEmptyZPolyhedron (B)) {
00592     Result = ZDomain_Copy (A);
00593     return Result;
00594   }  
00595   ImageA = DomainImage(A->P,(Matrix *)A->Lat,MAXNOOFRAYS);
00596   ImageB = DomainImage(B->P,(Matrix *)B->Lat,MAXNOOFRAYS);  
00597   DomDiff = DomainDifference(ImageA,ImageB,MAXNOOFRAYS);
00598   if (emptyQ (DomDiff))
00599     flag = True;
00600   else {
00601     ZPolyhedron *Z;
00602     PreImage = DomainPreimage(DomDiff,A->Lat,MAXNOOFRAYS);
00603     Z = ZPolyhedron_Alloc(A->Lat,PreImage);    
00604     Result = AddZPolytoZDomain(Z,Result);
00605   }  
00606   if (flag == True)  /* DomDiff = NULL; DomInter = A */
00607     DomInter = Domain_Copy(ImageA);
00608   else {
00609     DomInter = DomainIntersection(ImageA,ImageB,MAXNOOFRAYS);
00610     if (emptyQ(DomInter)) {
00611       if (flag == True)
00612         return (EmptyZPolyhedron(A->Lat->NbRows-1));
00613       else
00614         return Result;
00615     }
00616   }  
00617   LatDiff = LatticeDifference(A->Lat, B->Lat);
00618   if(LatDiff == NULL)
00619     if(flag == True )
00620       return(EmptyZPolyhedron (A->Lat->NbRows-1));
00621   
00622   while (LatDiff != NULL) {
00623     ZPolyhedron *tempZ = NULL;
00624     
00625     PreImage = DomainPreimage(DomInter, LatDiff->M, MAXNOOFRAYS);    
00626     tempZ = ZPolyhedron_Alloc(LatDiff->M, PreImage);
00627     Domain_Free(PreImage);
00628     Result = AddZPoly2ZDomain(tempZ,Result);
00629     ZPolyhedron_Free(tempZ);
00630     temp = LatDiff;
00631     LatDiff = LatDiff->next;  
00632     Matrix_Free ((Matrix *) temp->M);
00633     free (temp);
00634   }  
00635   Domain_Free (DomInter);
00636   Domain_Free (DomDiff);
00637   return Result;
00638 } /* ZPolyhedronDifference */ 
00639 
00640 /*
00641  * Return the image of the Z-polyhedron 'ZPol' under the invertible, affine, 
00642  * rational transformation function 'Func'. The matrix representing the funct-
00643  * ion must be non-singular and the number of rows of the function must be 
00644  * equal to the number of rows in the matrix representing the lattice of 'ZPol'
00645  * Algorithm: 
00646  *         1)  Let ZPol = L (intersect) Q
00647  *         2)  L1 = LatticeImage(L,F)
00648  *         3)  Q1 = DomainImage(Q,F)
00649  *         4)  Z1 = L1(Inverse(L1)*Q1)
00650  *         5)  Return Z1
00651  */
00652 static ZPolyhedron *ZPolyhedronImage(ZPolyhedron *ZPol,Matrix *Func) {
00653  
00654   ZPolyhedron *Result = NULL ;
00655   Matrix *LatIm ;
00656   Polyhedron *Pol, *PolImage ; 
00657   
00658 #ifdef DOMDEBUG
00659   FILE *fp;
00660   fp = fopen("_debug", "a");
00661   fprintf(fp,"\nEntered ZPOLYHEDRONIMAGE\n");
00662   fclose(fp);
00663 #endif
00664   
00665   if ((Func->NbRows != ZPol->Lat->NbRows) || (Func->NbColumns != ZPol->Lat->NbColumns)) {
00666     fprintf (stderr, "In ZPolImage - The Function, is not compatible with the ZPolyhedron\n");
00667     return NULL;
00668   }
00669   LatIm = LatticeImage(ZPol->Lat,Func);
00670   if (isEmptyLattice(LatIm)) {
00671     Matrix_Free(LatIm);
00672     return NULL;
00673   }
00674   Pol = DomainImage(ZPol->P,ZPol->Lat,MAXNOOFRAYS);
00675   PolImage = DomainImage(Pol,Func,MAXNOOFRAYS);
00676   Domain_Free(Pol);
00677   if(emptyQ(PolImage)) {
00678     Matrix_Free (LatIm);
00679     Domain_Free (PolImage);
00680     return NULL;
00681   } 
00682   Pol = DomainPreimage(PolImage,LatIm,MAXNOOFRAYS);
00683   Result = ZPolyhedron_Alloc(LatIm,Pol);
00684   Domain_Free(Pol);
00685   Domain_Free(PolImage);
00686   Matrix_Free(LatIm);
00687   return Result;  
00688 } /* ZPolyhedronImage */ 
00689 
00690 /*
00691  * Return the preimage of the Z-polyhedron 'Zpol' under an affine transformati-
00692  * on function 'G'. The number of rows of matrix representing the function 'G',
00693  * must be equal to the number of rows of the matrix representing the lattice 
00694  * of Z1. 
00695  * Algorithm: 
00696  *            1) Let Zpol = L (intersect) Q
00697  *            2) L1 =LatticePreimage(L,F);
00698  *            3) Q1 = DomainPreimage(Q,F);
00699  *            4) Z1 = L1(Inverse(L1)*Q1);
00700  *            5) Return Z1
00701  */
00702 static ZPolyhedron *ZPolyhedronPreimage(ZPolyhedron *Zpol, Matrix *G) {
00703   
00704   Lattice *Latpreim;
00705   Polyhedron *Qprime, *Q, *Polpreim;
00706   ZPolyhedron *Result;
00707   
00708 #ifdef DOMDEBUG
00709   FILE *fp;
00710   fp = fopen("_debug","a");
00711   fprintf(fp,"\nEntered ZPOLYHEDRONPREIMAGE\n");
00712   fclose(fp);
00713 #endif
00714   
00715   if(G->NbRows != Zpol->Lat->NbRows) {
00716     fprintf(stderr,"\nIn ZPolyhedronPreimage: Error, The dimensions of the ");
00717     fprintf(stderr,"function are not compatible with that of the Zpolyhedron");
00718     return EmptyZPolyhedron(G->NbColumns-1);
00719   }
00720   Q = DomainImage(Zpol->P,Zpol->Lat,MAXNOOFRAYS);
00721   Polpreim = DomainPreimage(Q,G,MAXNOOFRAYS);
00722   if (emptyQ(Polpreim))
00723     Result = NULL;
00724   else {
00725     Latpreim = LatticePreimage(Zpol->Lat,G);
00726     if(isEmptyLattice(Latpreim))
00727       Result = NULL;
00728     else {
00729       Qprime = DomainPreimage(Polpreim, Latpreim, MAXNOOFRAYS);
00730       Result = ZPolyhedron_Alloc(Latpreim, Qprime);
00731       Domain_Free(Qprime);
00732     }
00733     Matrix_Free(Latpreim);
00734   }  
00735   Domain_Free(Q);
00736   return Result; 
00737 } /* ZPolyhedronPreimage */ 
00738 
00739 /* 
00740  * Return the Z-polyhderon 'Zpol' in canonical form: 'Result' (for the Z-poly-
00741  * hedron in canonical form) and Basis 'Basis' (for the basis with respect to 
00742  * which 'Result' is in canonical form.   
00743  */
00744 void CanonicalForm(ZPolyhedron *Zpol,ZPolyhedron **Result,Matrix **Basis) {
00745 
00746   Matrix *B1 = NULL, *B2=NULL, *T1 , *B2inv;
00747   int i, l1, l2;
00748   Value tmp;
00749   Polyhedron *Image, *ImageP;
00750   Matrix *H, *U, *temp, *Hprime, *Uprime, *T2;
00751   
00752 #ifdef DOMDEBUG
00753   FILE *fp;
00754   fp = fopen("_debug", "a");
00755   fprintf(fp,"\nEntered CANONICALFORM\n");
00756   fclose(fp);
00757 #endif
00758   
00759   if(isEmptyZPolyhedron (Zpol)) {
00760     Basis[0] = Identity(Zpol->Lat->NbRows);
00761     Result[0] = ZDomain_Copy (Zpol);
00762     return ;
00763   }
00764   value_init(tmp);
00765   l1 = FindHermiteBasisofDomain(Zpol->P,&B1);
00766   Image = DomainImage (Zpol->P,(Matrix *)Zpol->Lat,MAXNOOFRAYS);
00767   l2 = FindHermiteBasisofDomain(Image,&B2);
00768     
00769   if (l1 != l2)
00770     fprintf(stderr,"In CNF : Something wrong with the Input Zpolyhedra \n"); 
00771   
00772   B2inv = Matrix_Alloc(B2->NbRows, B2->NbColumns);
00773   temp = Matrix_Copy(B2);
00774   Matrix_Inverse(temp,B2inv);
00775   Matrix_Free(temp);
00776   
00777   temp = Matrix_Alloc(B2inv->NbRows,Zpol->Lat->NbColumns);
00778   T1 = Matrix_Alloc(temp->NbRows,B1->NbColumns);
00779   Matrix_Product(B2inv,(Matrix *)Zpol->Lat,temp);
00780   Matrix_Product(temp,B1,T1);  
00781   Matrix_Free(temp);
00782   
00783   T2 = ChangeLatticeDimension(T1,l1);
00784   temp = ChangeLatticeDimension(T2,T2->NbRows+1);
00785 
00786   /* Adding the affine part */
00787   for(i = 0; i < l1; i ++)
00788     value_assign(temp->p[i][temp->NbColumns-1],T1->p[i][T1->NbColumns-1]);
00789   
00790   AffineHermite(temp,&H,&U);
00791   Hprime = ChangeLatticeDimension(H,Zpol->Lat->NbRows);
00792   
00793   /* Exchanging the Affine part */
00794   for(i = 0; i < l1; i ++) {
00795     value_assign(tmp,Hprime->p[i][Hprime->NbColumns-1]);
00796     value_assign(Hprime->p[i][Hprime->NbColumns-1],Hprime->p[i][H->NbColumns-1]);
00797     value_assign(Hprime->p[i][H->NbColumns-1],tmp);
00798   }
00799   Uprime = ChangeLatticeDimension(U,Zpol->Lat->NbRows);
00800   
00801   /* Exchanging the Affine part */
00802   for (i = 0;i < l1; i++) {
00803     value_assign(tmp,Uprime->p[i][Uprime->NbColumns-1]);
00804     value_assign(Uprime->p[i][Uprime->NbColumns-1],Uprime->p[i][U->NbColumns-1]);
00805     value_assign(Uprime->p[i][U->NbColumns-1],tmp);
00806   }    
00807   Polyhedron_Free (Image);
00808   Matrix_Free (B2inv);
00809   B2inv = Matrix_Alloc(B1->NbRows, B1->NbColumns);
00810   Matrix_Inverse(B1,B2inv);
00811   ImageP = DomainImage(Zpol->P, B2inv, MAXNOOFRAYS);
00812   Matrix_Free(B2inv);
00813   Image = DomainImage(ImageP, Uprime, MAXNOOFRAYS);
00814   Domain_Free(ImageP);
00815   Result[0] = ZPolyhedron_Alloc(Hprime, Image);
00816   Basis[0] = Matrix_Copy(B2); 
00817   
00818   /* Free the variables */
00819   Polyhedron_Free (Image);
00820   Matrix_Free (B1);
00821   Matrix_Free (B2);
00822   Matrix_Free (temp);
00823   Matrix_Free (T1);
00824   Matrix_Free (T2);
00825   Matrix_Free (H);
00826   Matrix_Free (U);
00827   Matrix_Free (Hprime);
00828   Matrix_Free (Uprime);
00829   value_clear(tmp);
00830   return;
00831 } /* CanonicalForm */ 
00832 
00833 /*
00834  * Given a Z-polyhedron 'A' in which the Lattice is not integral, return the
00835  * Z-polyhedron which contains all the integral points in the input lattice.
00836  */
00837 ZPolyhedron *IntegraliseLattice(ZPolyhedron *A) {
00838  
00839   ZPolyhedron *Result;
00840   Lattice *M = NULL, *Id;
00841   Polyhedron *Im = NULL, *Preim = NULL;
00842 
00843 #ifdef DOMDEBUG
00844   FILE *fp;
00845   fp = fopen("_debug","a");
00846   fprintf(fp,"\nEntered INTEGRALISELATTICE\n");
00847   fclose(fp);
00848 #endif
00849   
00850   Im = DomainImage(A->P,A->Lat,MAXNOOFRAYS);
00851   Id = Identity(A->Lat->NbRows);
00852   M = LatticeImage(Id, A->Lat);
00853   if (isEmptyLattice(M))
00854     Result = EmptyZPolyhedron(A->Lat->NbRows-1);
00855   else {
00856     Preim = DomainPreimage(Im,M,MAXNOOFRAYS);
00857     Result = ZPolyhedron_Alloc(M,Preim);
00858   }  
00859   Matrix_Free(M);
00860   Domain_Free(Im);
00861   Domain_Free(Preim);  
00862   return Result;
00863 } /* IntegraliseLattice */ 
00864 
00865 /* 
00866  * Return the simplified representation of the Z-domain 'ZDom'. It attempts to 
00867  * convexize unions of polyhedra when they correspond to the same lattices and
00868  * to simplify union of lattices when they correspond to the same polyhdera. 
00869  */
00870 ZPolyhedron *ZDomainSimplify(ZPolyhedron *ZDom) {
00871   
00872   ZPolyhedron *Ztmp, *Result;
00873   ForSimplify *Head, *Prev, *Curr;
00874   ZPolyhedron *ZDomHead, *Emp;
00875   
00876   if (ZDom == NULL) {
00877     fprintf(stderr,"\nError in ZDomainSimplify - ZDomHead = NULL\n");
00878     return NULL;
00879   }  
00880   if (ZDom->next == NULL)
00881     return (ZPolyhedron_Copy (ZDom));  
00882   Emp = EmptyZPolyhedron(ZDom->Lat->NbRows-1);
00883   ZDomHead = ZDomainUnion(ZDom, Emp);
00884   ZPolyhedron_Free(Emp);  
00885   Head = NULL;
00886   Ztmp = ZDomHead;
00887   do {
00888     Polyhedron *Img;
00889     Img = DomainImage(Ztmp->P,Ztmp->Lat,MAXNOOFRAYS);
00890     for(Curr = Head; Curr != NULL; Curr = Curr->next) {
00891       Polyhedron *Diff1;
00892       Bool flag = False;
00893       
00894       Diff1 = DomainDifference(Img,Curr->Pol,MAXNOOFRAYS);
00895       if (emptyQ(Diff1)) {
00896         Polyhedron *Diff2;
00897 
00898         Diff2 = DomainDifference(Curr->Pol,Img,MAXNOOFRAYS); 
00899         if (emptyQ(Diff2))
00900           flag = True;  
00901         Domain_Free(Diff2);
00902       }      
00903       Domain_Free (Diff1);
00904       if (flag == True) {
00905         LatticeUnion *temp;     
00906         
00907         temp = (LatticeUnion *)malloc(sizeof(LatticeUnion));
00908         temp->M = (Lattice *)Matrix_Copy((Matrix *)Ztmp->Lat); 
00909         temp->next = Curr->LatUni;
00910         Curr->LatUni = temp;
00911         break;
00912       }
00913     }
00914     if(Curr == NULL) {
00915       Curr = (ForSimplify *)malloc(sizeof(ForSimplify));      
00916       Curr->Pol = Domain_Copy(Img);
00917       Curr->LatUni = (LatticeUnion *)malloc(sizeof(LatticeUnion));
00918       Curr->LatUni->M = (Lattice *)Matrix_Copy((Matrix *)Ztmp->Lat); 
00919       Curr->LatUni->next = NULL;
00920       Curr->next = Head;
00921       Head = Curr;
00922     }   
00923     Domain_Free (Img);
00924     Ztmp = Ztmp->next;
00925   } while(Ztmp != NULL);
00926   
00927   for (Curr = Head; Curr != NULL; Curr = Curr->next)
00928     Curr->LatUni = LatticeSimplify(Curr->LatUni);  
00929   Result = NULL;
00930   for(Curr = Head; Curr != NULL; Curr = Curr->next) {
00931     LatticeUnion *L;    
00932     for(L = Curr->LatUni; L != NULL; L = L->next) {
00933       Polyhedron *Preim;
00934       ZPolyhedron *Zpol;
00935       
00936       Preim = DomainPreimage(Curr->Pol,L->M,MAXNOOFRAYS);
00937       Zpol = ZPolyhedron_Alloc(L->M, Preim);
00938       Zpol->next = Result;
00939       Result = Zpol;
00940       Domain_Free(Preim);
00941     }
00942   }  
00943   Curr = Head;
00944   while (Curr != NULL) {
00945     Prev = Curr;
00946     Curr = Curr->next;     
00947     LatticeUnion_Free(Prev->LatUni);
00948     Domain_Free(Prev->Pol);
00949     free(Prev);
00950   }
00951   return Result;
00952 } /* ZDomainSimplify */ 
00953 
00954 ZPolyhedron *SplitZpolyhedron(ZPolyhedron *ZPol,Lattice *B) {
00955  
00956   Lattice *Intersection = NULL;
00957   Lattice *B1 = NULL, *B2 = NULL, *newB1 = NULL, *newB2 = NULL;
00958   Matrix *U = NULL,*M1 = NULL, *M2 = NULL, *M1Inverse = NULL,*MtProduct = NULL;
00959   Matrix *Vinv, *V , *temp, *DiagMatrix ;
00960   Matrix *H , *U1 , *X, *Y ;
00961   ZPolyhedron *zpnew, *Result;
00962   LatticeUnion *Head = NULL, *tempHead = NULL;
00963   int i;
00964   Value k;
00965   
00966 #ifdef DOMDEBUG
00967   FILE *fp;
00968   fp = fopen("_debug", "a");
00969   fprintf(fp,"\nEntered SplitZpolyhedron \n"); 
00970   fclose(fp);
00971 #endif
00972 
00973   
00974   if (B->NbRows != B->NbColumns) { 
00975     fprintf(stderr,"\n SplitZpolyhedron : The Input Matrix B is not a proper Lattice \n");
00976     return NULL;
00977   }
00978   
00979   if (ZPol->Lat->NbRows != B->NbRows) {
00980     fprintf(stderr,"\nSplitZpolyhedron : The Lattice in Zpolyhedron and B have ");
00981     fprintf(stderr,"incompatible dimensions \n");
00982     return NULL;
00983   }
00984   
00985   if (isinHnf (ZPol->Lat) != True) {
00986     AffineHermite(ZPol->Lat,&H,&U1);
00987     X = Matrix_Copy(H);    
00988     Matrix_Free(U1);
00989     Matrix_Free(H);
00990   }
00991   else
00992     X = Matrix_Copy(ZPol->Lat);
00993   
00994   if (isinHnf(B) != True) {
00995     AffineHermite(B,&H,&U1);
00996     Y = Matrix_Copy(H);   
00997     Matrix_Free(H);
00998     Matrix_Free(U1);
00999   }
01000   else
01001     Y = Matrix_Copy(B);  
01002   if (isEmptyLattice(X)) {
01003     return NULL;  
01004   }
01005 
01006   Head=Lattice2LatticeUnion(X,Y);
01007 
01008 /* If the spliting operation can't be done the result is the original Zplyhedron. */
01009 
01010   if (Head == NULL) {
01011     Matrix_Free(X);
01012     Matrix_Free(Y);
01013     return ZPol;
01014   }  
01015 
01016 
01017   Result=NULL;
01018 
01019   if (Head)
01020    while(Head)
01021     {
01022       tempHead = Head;
01023       Head = Head->next;  
01024       zpnew=ZPolyhedron_Alloc(tempHead->M,ZPol->P);
01025       Result=AddZPoly2ZDomain(zpnew,Result);
01026       ZPolyhedron_Free(zpnew);
01027       tempHead->next = NULL; 
01028       free(tempHead);  
01029     }
01030 
01031   return Result;
01032 }
01033 
01034 
01035 

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