polylib: Zpolyhedron.c Source File

- Main Page
- Classes
- Files

- File List
- File Members

# Zpolyhedron.c

Go to the documentation of this file.

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