polylib: Zpolyhedron.c Source File

- Main Page
- Classes
- Files

# 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