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

ext_ehrhart.c

Go to the documentation of this file.
00001 
00002 #include <stdlib.h>
00003 #include <polylib/polylib.h>
00004 #define WS 200 
00005 
00006 /* #define UE_DEBUG */
00007 
00008 
00009 typedef struct _Polyhedron_union { 
00010         Enumeration *pt;
00011         struct _Polyhedron_union *next;} Polyhedron_union;
00012 
00013 static int ppcm1 (int a, int b);
00014 Matrix *CalcBase( Matrix *R);
00015 
00016 
00017 /**** ker.c ****/
00018 
00019 static void Soustraire_ligne(Matrix *R, int l1, int l2, int piv );
00020 static int existepivot( Matrix *R, int l );
00021 static void swap_line(Matrix *R, int l1, int l2);
00022 
00023 
00024 /* Caclule une base du noyau de l'application definie
00025 par la matrice _carree_ R (completee par des 0..0) */
00026 
00027 /* /!\ R est alteree par cette fonction. */
00028 
00029 Matrix *CalcBase( Matrix *R )
00030 {
00031         Matrix *B/*,*BTran*/;   /* matrice des vect. de la base */
00032         int i, j;
00033         Value p;
00034         int l;          /* ligne en cours de `pivotage' */
00035         int lnn;
00036         int dimbase;
00037         int u;          /* vecteur util en cours de calcul */
00038         Value  som;
00039         int c;
00040         /* diagonalisation de R : algo du pivot */
00041         /* avec conservation des pivots nuls */
00042         for( l=0 ; l<R->NbRows ; ++l )
00043         {
00044                 /* cherche le prochain pivot non nul */
00045                 if( (lnn=existepivot(R,l)) != -1 )
00046                 {
00047                         swap_line( R, l, lnn );
00048 
00049                         /* met la colonne dessous a 0 */
00050                         for( j=l+1 ; j<R->NbRows ; ++j )
00051                                 if(value_notzero_p( R->p[j][l]) )
00052                                         Soustraire_ligne( R, l, j, l );
00053 
00054                         /* et celle dessus aussi */
00055                         for( j=0 ; j<l ; ++j )
00056                                 if( value_notzero_p(R->p[j][l]) )
00057                                         Soustraire_ligne( R, l, j, l );
00058 
00059                 }
00060                 /* s'ils sont tous nuls on passe au suivant */
00061                 /* en laissant cette ligne inchangee. */
00062         }
00063 
00064         dimbase = 0;
00065         for( l=0 ; l<R->NbRows ; ++l )
00066                 if( value_zero_p(R->p[l][l]) )
00067                         ++dimbase;     /* = nb de 0 dans la diagonale */
00068 
00069         B = Matrix_Alloc( dimbase, R->NbRows );
00070 
00071         l=0;
00072         for( u=0 ; u<dimbase ; ++u )
00073         {
00074                 while(value_notzero_p( R->p[l][l]) )
00075                         ++l;
00076 
00077         /* calcul effectif de ce vecteur : chaque coord en commencant par le bas */
00078                 for( i=R->NbRows-1 ; i>l ; --i )
00079                         value_set_si(B->p[u][i], 0);
00080                 value_set_si(B->p[u][l], 1);
00081                 for( i=l-1 ; i>=0 ; --i )       /* i=chaque coord du vecteur */
00082                 {
00083                         if(value_zero_p( R->p[i][i]) )
00084                           /* on a deux 0... un seul dans */
00085                           /* ce vect util suffit */
00086                                 value_set_si(B->p[u][i],0); 
00087                         else
00088                         {
00089                                 /* somme des coef deja calcules * coef dans la matrice */
00090                                 value_set_si(som,0);
00091                                 for( c=l ; c>i ; --c )
00092                                 {
00093                                   value_addmul(som, R->p[i][c], B->p[u][c]);
00094                                   value_multiply(B->p[u][c] ,B->p[u][c] , R->p[i][i]);  
00095                                 }
00096                                 value_oppose(B->p[u][i] , som );
00097                         }
00098                 }
00099                 /* reste a faire le pgcd du vecteur et a l'orienter */
00100                 value_set_si(p,0);
00101                 for( i=0 ; i<R->NbRows ; ++i )
00102                   Gcd( p, B->p[u][i], &p );
00103                 if( value_zero_p(p))
00104                         value_set_si(p,1);
00105                 for( i=0 ; i<R->NbRows && value_zero_p(B->p[u][i]); ++i )
00106                         ;
00107                 if( i<R->NbRows )
00108                         if( value_neg_p(B->p[u][i]) )
00109                       value_oppose( p,p );
00110 
00111                 for( i=0 ; i<R->NbRows ; ++i )
00112                         value_division(B->p[u][i],B->p[u][i], p);
00113 
00114                 /* incrementer le compteur de lignes */
00115                 ++l;
00116         }
00117         return B;
00118 }
00119 
00120 
00121 /* fonction qui calcule les vect generateurs de l'espace vectoriel
00122    contenant le polyhedre P */
00123 /*
00124 Matrix *CalcPolyhedronBase( Polyhedron *P )
00125 {
00126   Matrix *R;
00127   Matrix *B;
00128   int n, lines;
00129   
00130   if( emptyQ(P) )
00131     return( Matrix_Alloc( 0, P->Dimension ) ); */ /* pas de vect. gen */ /*
00132   
00133   R = Matrix_Alloc( P->Dimension, P->Dimension );
00134   
00135   */ /* recopie le 'lineality space' du polyedre dans la matrice R */ /*
00136   for( lines=0,n=0 ; n<P->NbConstraints ; ++n )
00137     {
00138       if( P->Constraint[n][0]==0 )
00139         */ /* c'est une direction definissant un ss-espace */ /*
00140         {
00141           memcpy( &R->p[lines][0], &P->Constraint[n][1],
00142                   sizeof(int)*P->Dimension );
00143           ++lines;
00144         }
00145     }
00146   */ /* remplit le reste de 0..0 */ /*
00147   for( ; lines<R->NbRows ; ++lines )
00148     memset( &R->p[lines][0], 0, sizeof(int)*P->Dimension );
00149   
00150   B = CalcBase( R );
00151   Matrix_Free( R );
00152   
00153   return( B );
00154 }*/
00155 
00156 
00157 /* fonction qui calcule l'espace vectoriel non parametre de dimension dim
00158         contenant le polyhedre parametre P */
00159 /* les _egalites_ sont stockees par la polylib sous forme triangulaire
00160 superieure donc il suffit de prendre les premieres. */
00161 
00162 /*Matrix *CalcEVPolyhedronNP( Polyhedron *P, int dim )
00163 {
00164         Matrix *R;
00165         Matrix *B;
00166         int n, lines;
00167 
00168         if( emptyQ(P) ) */ /* pas de vect. gen */ /*
00169         {
00170           B = Matrix_Alloc( 1, dim );   */ /* on ne peut pas allouer 0 lignes ! */ /*
00171                 B->NbRows = 0;
00172                 return( B );
00173         }
00174 
00175         R = Matrix_Alloc( dim, dim );
00176 
00177 */ /* recopie le 'lineality space' du polyedre dans la matrice R */ /*
00178         for( lines=0,n=0 ; n<P->NbConstraints && lines<dim ; ++n )
00179         {
00180                 if( P->Constraint[n][0]==0 )
00181                   */ /* c'est une direction definissant un ss-espace */ /*
00182                 {
00183                         memcpy( &R->p[lines][0], &P->Constraint[n][1],
00184                                         sizeof(int)*P->Dimension );
00185                         ++lines;
00186                 }
00187         }
00188 */ /* remplit le reste de 0..0 */ /*
00189         for( ; lines<R->NbRows ; ++lines )
00190                 memset( &R->p[lines][0], 0, sizeof(int)*dim );
00191 
00192         B = CalcBase( R );
00193         Matrix_Free( R );
00194 
00195         return( B );
00196 }*/
00197 
00198 
00199 /* renvoie la ligne sur laquelle on a trouve un coef non nul */
00200 /* pareil mais cherche dans toutes les lignes */
00201 /* et -1 s'il n'y en a pas. */
00202 static int existepivot( Matrix *R, int l )
00203 {
00204         int j, c;
00205 
00206         for( j=l ; j<R->NbRows ; ++j )
00207                 if(value_notzero_p( R->p[j][l]) )
00208                         return( j );
00209 
00210         /* on ne l'a pas trouve pour l'instant... on cherche au dessus */
00211         /* les lignes ayant que des 0 jusqu'a la position l */
00212         for( j=0 ; j<l ; ++j )
00213         {
00214                 for( c=0 ; c<l && value_zero_p(R->p[j][c]) ; c++ )
00215                         ;
00216                 if( c==l && value_notzero_p(R->p[j][l]) )
00217                         return( j );
00218         }
00219 
00220         return( -1 );
00221 }
00222 
00223 
00224 /* echange les lignes l1 et l2 dans la matrice R */
00225 static void swap_line(Matrix *R, int l1, int l2)
00226 {
00227         int i;
00228         Value  tmp;
00229 
00230         if( l1 != l2 )
00231                 for(i = 0;i < R->NbColumns;i ++)
00232                 {
00233                         value_assign(tmp , R->p[l1][i]);
00234                         value_assign(R->p[l1][i] , R->p[l2][i]);
00235                         value_assign(R->p[l2][i] , tmp);
00236                 }
00237 }
00238 
00239 
00240 
00241 int pgcd1( int a, int b)
00242 {
00243  int r;
00244  if( a== 0 )
00245  return( abs(b) );
00246   if(b==0 )
00247   return(abs(a) );
00248   do
00249   {
00250     r= a % b; 
00251     a= b;
00252    b = r;
00253    }
00254    while ( r!=0 );
00255  return(abs(a));
00256 }
00257 
00258 
00259 
00260 
00261 /* Soustraire la ligne l1 de l2 */
00262 /* On effectue l2 = (l1[piv]/pgcd)*l2 - l1 * (l2[piv]/pgcd) */
00263 static void Soustraire_ligne(Matrix *R, int l1, int l2, int piv )
00264 {
00265         int i;
00266         Value  a, b, p, t;
00267         /* l2 = a*l2 - b*l1 */
00268 
00269         if (value_zero_p(R->p[l2][piv] ))               /* c'est deja fait ! */
00270                 return;
00271 
00272         value_init(a);
00273         value_init(b);
00274         value_init(p);
00275         value_init(t);
00276 
00277         Gcd( R->p[l1][piv], R->p[l2][piv], &p );
00278         value_division(a, R->p[l1][piv] , p);
00279         value_division(b , R->p[l2][piv] , p);
00280 
00281         value_set_si(R->p[l2][piv] , 0);
00282         value_set_si(p,0);
00283         for(i = piv + 1;i < R->NbColumns;i ++)
00284         {
00285                 value_multiply(t,b,R->p[l1][i]);
00286                 value_multiply(R->p[l2][i],a,R->p[l2][i]);
00287                 value_subtract(R->p[l2][i],R->p[l2][i],t);
00288                 Gcd(p, R->p[l2][i], &p );
00289         }
00290         /* Simplification par le pgcd de toute la ligne */
00291         for( i=piv+1 ; i<R->NbColumns && p!=0 ; i++ )
00292                 value_division(R->p[l2][i],R->p[l2][i], p);
00293 
00294         value_clear(a);
00295         value_clear(b);
00296         value_clear(p);
00297         value_clear(t);
00298 }
00299 
00300 
00301 /*** ext_ehrhart.c ****/
00302 
00303 
00304 void new_eadd(evalue *e1,evalue *res) {
00305 int i, p, x, y;
00306 
00307 evalue *ne;
00308 Value g,m1,m2;
00309 
00310   value_init(g);
00311   value_init(m1);
00312   value_init(m2);
00313     if (value_notzero_p(e1->d) && value_notzero_p(res->d)) {
00314          /* Add two rational numbers*/
00315          value_multiply(m1,e1->x.n,res->d);
00316          value_multiply(m2,res->x.n,e1->d);
00317          value_addto(res->x.n,m1,m2);
00318          value_multiply(res->d,e1->d,res->d);
00319          Gcd(res->x.n,res->d,&g);
00320          if (value_notone_p(g)) {
00321               value_division(res->d,res->d,g);
00322               value_division(res->x.n,res->x.n,g);
00323          }
00324          value_clear(g); value_clear(m1); value_clear(m2);
00325          return ;
00326      }
00327      else if (value_notzero_p(e1->d) && value_zero_p(res->d)) {
00328               if (res->x.p->type==polynomial) {
00329                   /* Add the constant to the constant term of a polynomial*/
00330                    new_eadd(e1, &res->x.p->arr[0]);
00331                    value_clear(g); value_clear(m1); value_clear(m2);
00332                    return ;
00333               }
00334               else if (res->x.p->type==periodic) {
00335                           /* Add the constant to all elements of a periodic number */
00336                           for (i=0; i<res->x.p->size; i++) {
00337                               new_eadd(e1, &res->x.p->arr[i]);
00338                           }
00339                           value_clear(g); value_clear(m1); value_clear(m2);
00340                              
00341                           return ;
00342                     } 
00343                     else {
00344                             fprintf(stderr, "eadd: cannot add const with vector\n");
00345                             value_clear(g); value_clear(m1); value_clear(m2);
00346                         
00347                             return;
00348                     }
00349      }
00350     /* ######### add polynomial or periodic to constant #############
00351        you have to exchange e1 and res, before doing addition */
00352      
00353      else if (value_zero_p(e1->d) && value_notzero_p(res->d)) {
00354               enode *tmp;
00355               evalue x;
00356               x=*res;
00357               tmp= ecopy(e1->x.p);
00358               value_init(res->d);
00359               value_set_si( res->d, 0 );
00360               res->x.p=tmp;
00361 
00362               new_eadd(&x,res);
00363               value_clear(g); value_clear(m1); value_clear(m2);
00364               return ;
00365      }
00366     else {   /* ((e1->d==0) && (res->d==0)) */
00367                  if ((e1->x.p->type != res->x.p->type) ) {
00368                    /* ##### adding to evalues of different type. two cases are possible  #### 
00369                       
00370                    #### res is periodic and e1 is polynomial, you have to exchange
00371                    e1 and res then to add e1 to the constant term of res  #### */
00372                      if ((res->x.p->type == periodic)&&(e1->x.p->type == polynomial)) {
00373                        
00374                           evalue eval;
00375                           value_set_si( eval.d, 0 );
00376                           eval.x.p=ecopy(res->x.p);
00377                           res->x.p= ecopy(e1->x.p);
00378                           new_eadd(&eval,&res->x.p->arr[0]);
00379                                                              
00380                      }
00381                      else if ((res->x.p->type == polynomial)&&(e1->x.p->type == periodic)) {
00382                        /* #### res is polynomial and e1 is periodic,
00383                           add e1 to the constant term of res  #### */
00384                          
00385                           new_eadd(e1,&res->x.p->arr[0]);
00386                      }
00387                                  
00388                      value_clear(g); value_clear(m1); value_clear(m2);
00389                      return;
00390                  }
00391                  else if (e1->x.p->pos  != res->x.p->pos ) { 
00392                    /* ### adding evalues of different position (i.e function of different unknowns
00393                       to case are possible  ### */
00394                            
00395                          if (res->x.p->type == polynomial) {/*  ### res and e1 are polynomials
00396                                                                 add e1 to the constant term of res */
00397                                
00398                                new_eadd(e1,&res->x.p->arr[0]);
00399                                value_clear(g); value_clear(m1); value_clear(m2);
00400                                return;
00401                           }
00402                           else {  /* ### res and e1 are pointers to periodic numbers
00403                                      add e1 to all elements of res */
00404                                    
00405                                   for (i=0;i<res->x.p->size;i++) {
00406                                        new_eadd(e1,&res->x.p->arr[i]);
00407                                   }
00408                                   value_clear(g); value_clear(m1); value_clear(m2);
00409                                   return;
00410                           }
00411                  
00412                                           
00413                  }  /* ### */
00414                  
00415                 
00416                  /* same type , same pos  and same size */
00417                  if (e1->x.p->size == res->x.p->size) {
00418                    /* add any element in e1 to the corresponding element in res */
00419                       for (i=0; i<res->x.p->size; i++) {
00420                             new_eadd(&e1->x.p->arr[i], &res->x.p->arr[i]);
00421                       }
00422                       value_clear(g); value_clear(m1); value_clear(m2);
00423                       return ;
00424                 }
00425                 
00426                 /* Sizes are different */
00427                 if (res->x.p->type==polynomial) {
00428                     /* VIN100: if e1-size > res-size you have to copy e1 in a   */
00429                     /* new enode and add res to that new node. If you do not do */
00430                     /* that, you lose the the upper weight part of e1 !         */
00431 
00432                      if(e1->x.p->size > res->x.p->size) {
00433                           enode *tmp;
00434                           tmp = ecopy(e1->x.p);
00435                           for(i=0;i<res->x.p->size;++i) {
00436                               new_eadd(&res->x.p->arr[i], &tmp->arr[i]);
00437                               /*  free_evalue_refs(&res->x.p->arr[i]); */
00438                           }
00439                           res->x.p = tmp;
00440           
00441                      }
00442                      else {
00443                      
00444                         for (i=0; i<e1->x.p->size ; i++) {
00445                              new_eadd(&e1->x.p->arr[i], &res->x.p->arr[i]);
00446                         } 
00447                         value_clear(g); value_clear(m1); value_clear(m2);
00448                                    
00449                         return ;
00450                      } 
00451                 }
00452                 
00453                 /* ### add two periodics of the same pos (unknown) but whith different sizes (periods) ### */
00454                 else if (res->x.p->type==periodic) {
00455                       /* you have to create a new evalue 'ne' in whitch size equals to the scm
00456                        of the sizes of e1 and res, then to copy res periodicaly in ne, after
00457                        to add periodicaly elements of e1 to elements of ne, and finaly to 
00458                        return ne. */
00459                                                     
00460                        x=e1->x.p->size;
00461                        y= res->x.p->size;
00462                        p=ppcm1(x,y);
00463                        ne= (evalue *) malloc (sizeof(evalue)); 
00464                        value_init(ne->d);
00465                        value_set_si( ne->d,0);
00466                                     
00467                        ne->x.p=new_enode(res->x.p->type,p, res->x.p->pos);
00468                        for(i=0;i<p;i++)  {
00469                               value_assign(ne->x.p->arr[i].d, res->x.p->arr[i%y].d);
00470                               if (value_notzero_p(ne->x.p->arr[i].d))   {
00471                             value_init(ne->x.p->arr[i].x.n);
00472                             value_assign(ne->x.p->arr[i].x.n, res->x.p->arr[i%y].x.n);
00473                               }
00474                               else { 
00475                                   ne->x.p->arr[i].x.p =ecopy(res->x.p->arr[i%y].x.p);
00476                               }
00477                        }
00478                        for(i=0;i<p;i++)  {
00479                             new_eadd(&e1->x.p->arr[i%x], &ne->x.p->arr[i]);
00480                        }
00481       
00482                        res=ne;
00483                     
00484                         value_clear(g); value_clear(m1); value_clear(m2);
00485                         return ;
00486                 }
00487                 else { /* evector */
00488                      fprintf(stderr, "eadd: ?cannot add vectors of different length\n");
00489                      value_clear(g); value_clear(m1); value_clear(m2);
00490                      return ;
00491                 }
00492      }
00493      value_clear(g); value_clear(m1); value_clear(m2);
00494      return ;
00495  } /* new_eadd */
00496    
00497 /* remove the last row and the last column of a matrix Mat */
00498 Matrix *Reduce_Matrix (Matrix *Mat) {
00499            int i; 
00500            Value *p;
00501            p=*(Mat->p+(Mat->NbRows-1));
00502            for (i=0;i<Mat->NbColumns; i++)  {
00503                    value_clear(*p++);
00504            }
00505            for (i=0; i<Mat->NbRows-1; i++)  { 
00506                    p=*(Mat->p+i);
00507                    value_clear(*(p+(Mat->NbColumns-1)));
00508            }
00509            Mat->NbRows--;
00510            Mat->NbColumns--;
00511            return Mat;
00512    } /* Reduce_Matrix */
00513     
00514   
00515   /* Computes the scalar product (in euclidien space) of two vectors */ 
00516   
00517 void Scalar_product(Value *p1,Value *p2,unsigned length, Value *r) {
00518         Value *cp1, *cp2;
00519         
00520         int i;
00521           cp1=p1;
00522           cp2=p2;
00523           value_set_si(*r,0);
00524                for (i=0;i<length;i++) {
00525                  value_addmul(*r, *cp1, *cp2);
00526                   cp1++; cp2++;
00527                }
00528   } /* Scalar_product */
00529 
00530     /* computes the scm of two integrals  */
00531      
00532       int ppcm1 (int a, int b) {
00533            int t;
00534            t = (a*b)/ pgcd1(a,b);
00535           return t;
00536        } /* ppcm1 */
00537   
00538 /* computes the scm of two values */
00539 
00540 void ppcm(Value a, Value b, Value *r) {
00541         Value g;
00542         value_init(g); 
00543         Gcd(a,b,&g);
00544         value_multiply(*r,a,b);
00545         value_division(*r,*r,g);
00546 } /* ppcm  */
00547 
00548 
00549 Matrix *Orthogonal_Base(Matrix *Mat)  {
00550   Matrix *OrthMat;
00551   Value a,b,c,d;
00552   Vector *q,*p,*f;
00553   unsigned length;
00554   int i,j,k;
00555   value_init(a);
00556   value_init(b);
00557   value_init(c);
00558   value_init(d);
00559   OrthMat= Matrix_Alloc(Mat->NbRows,Mat->NbColumns);
00560   length=Mat->NbColumns;
00561   for(k=0; k<length; k++)  {
00562     value_assign(OrthMat->p[0][k],Mat->p[0][k]);                
00563   }
00564   f=Vector_Alloc(length);
00565   p=Vector_Alloc(length);
00566   q=Vector_Alloc(length);
00567   for(i=1; i<Mat->NbRows; i++)  {
00568     for(k=0;k<length;k++)  {
00569       value_assign(f->p[k],Mat->p[i][k]);
00570       value_assign(q->p[k],Mat->p[i][k]);
00571     }
00572     value_set_si(d,1);
00573     for(j=0; j<i; j++) {
00574       for(k=0;k<length;k++)  {
00575         value_assign(p->p[k],OrthMat->p[j][k]);
00576       }
00577       
00578       Scalar_product(p->p,f->p,length,&a);
00579       Scalar_product(p->p,p->p,length,&b);      
00580       Gcd(a,b,&c);
00581       value_division(a,a,c);
00582       value_division(b,b,c);
00583       for(k=0;k<length;k++) {
00584         value_multiply(p->p[k],p->p[k],a);
00585       }
00586       
00587       if(value_notone_p(d)|value_notone_p(b))  {
00588         ppcm(d,b,&c);
00589         value_division(a,c,b);
00590         value_division(b,c,d);
00591         value_assign(d,c);
00592         for(k=0;k<length;k++) {
00593           value_multiply(p->p[k],p->p[k],a);
00594           value_multiply(q->p[k],q->p[k],b);
00595         }
00596         
00597       }
00598       
00599       for(k=0;k<length;k++) {
00600         value_subtract(q->p[k],q->p[k],p->p[k]);
00601       }
00602       
00603     }
00604     Vector_Gcd(q->p,length,&c); 
00605     for(k=0;k<length;k++) {
00606       value_division(OrthMat->p[i][k],q->p[k],c);
00607     }
00608     
00609   }
00610   value_clear(a);
00611   value_clear(b);
00612   value_clear(c);
00613   value_clear(d);
00614   return OrthMat;
00615 }  /* Orthogonal_Base  */
00616      
00617 
00618 /* Remove an element of a list */
00619 void  Remove_Element(Enumeration *en,Enumeration **re, Enumeration *prev)  {
00620   if (en== *re)  {
00621     *re= (*re)->next;
00622   }
00623   else {
00624     prev->next=en->next;
00625   }
00626 } /* Remove_Element */
00627   
00628  /* Remove validite domains and correspending ehrhart polynomials whitch are redundant after 
00629   the enumeration of a polyhedron */
00630 
00631  void Remove_RedundantDomains (Enumeration  **Ures)  {
00632         Enumeration *ren1, *ren2, *previous=NULL;
00633         int red;
00634         for (ren1=*Ures; ren1; ren1=ren1->next)  {
00635                 red=0;
00636                 for (ren2=*Ures; ren2; ren2=ren2->next)  {
00637                         if (ren1!=ren2)  {
00638                                   
00639                             if (PolyhedronIncludes(ren2->ValidityDomain, ren1->ValidityDomain)) {
00640                                         red= 1;
00641                                         break;
00642                 
00643                                 }
00644                                 
00645                         }
00646                 }
00647                 if (red)  {
00648                         Remove_Element(ren1,Ures,previous);
00649                 }
00650                 previous=ren1;
00651         }
00652  }/*Remove_RedendentDomains */
00653                                                       
00654                                   
00655 int IncludeInRes (Polyhedron *p, Enumeration *e, unsigned MR) {
00656         Enumeration *en;
00657            for (en=e; en; en=en->next)  {
00658                   
00659                 if (PolyhedronIncludes(e->ValidityDomain,p)) 
00660                          return 1;
00661            }
00662         return 0;       
00663 }
00664 
00665 Polyhedron *DMUnion(Enumeration *en, unsigned MR)  {
00666         Enumeration *e1;
00667         Polyhedron *d;
00668         e1=en;
00669         d=e1->ValidityDomain; 
00670          for (e1=en->next; e1; e1=e1->next) {
00671            d= DomainUnion( d, e1->ValidityDomain, MR);
00672          }
00673          return d;
00674   }
00675 
00676 
00677 void AffConstraints(Polyhedron *Poldisj)
00678 {
00679         Polyhedron *p;
00680 
00681         for(p=Poldisj;p;p=p->next)
00682         {
00683                 Polyhedron_PrintConstraints( stdout, P_VALUE_FMT, p);
00684                 printf("\n");
00685         }
00686 }
00687 int Degenerate (Enumeration *en) {
00688         if(value_notzero_p(en->EP.d)) {
00689                 
00690            if(value_mone_p(en->EP.x.n )) {
00691                return 1;    
00692            }
00693         }
00694    return 0;    
00695 }
00696 
00697 /* Enumeration of a domain D */
00698 
00699 Enumeration *Domain_Enumerate(Polyhedron *D, Polyhedron *C, unsigned MAXRAYS,char **pn)
00700 {     Polyhedron_union *Polun,*pu;
00701       Polyhedron  *lp, *lp1, *lp1next;
00702       Polyhedron *d1,*d2,*d;  
00703       Enumeration *e,*pr,*en,*en1, *en2,*tmp, *res, *sen;
00704       Polun=NULL;
00705      
00706       for (d = D; d; d = d->next) {
00707           POL_ENSURE_FACETS(d);
00708           POL_ENSURE_VERTICES(d);
00709       }
00710       POL_ENSURE_FACETS(C);
00711       POL_ENSURE_VERTICES(C);
00712 
00713      lp = Disjoint_Domain( D, 0, MAXRAYS );
00714 
00715 #ifdef UE_DEBUG
00716      printf("##############################################################\n");
00717      printf("\n###### DISJOINT UNION  ######\n\n");
00718      AffConstraints(lp); 
00719      printf("##############################################################\n");
00720 #endif
00721      
00722         for (lp1=lp ; lp1; lp1=lp1->next)
00723         {
00724                 Enumeration *enext;
00725                 lp1next = lp1->next;
00726                 lp1->next = NULL;
00727                 en= Polyhedron_Enumerate(lp1, C, MAXRAYS,NULL);
00728                 lp1->next = lp1next;
00729                 sen= NULL;
00730                 for (e=en;e;e=enext) {
00731                         enext = e->next;
00732                         if (!Degenerate(e)) {
00733                                 e->next = sen;
00734                                 sen=e;
00735                         } else {
00736                                 free_evalue_refs(&e->EP);
00737                                 Domain_Free(e->ValidityDomain);
00738                                 free(e);
00739                         }
00740                 }
00741 
00742                 if(sen!= NULL)
00743                 {
00744                         pu = (Polyhedron_union  *)malloc(sizeof(Polyhedron_union));
00745                         pu->pt=sen;
00746                         pu->next = Polun;
00747                         Polun = pu;
00748                 }
00749         }
00750         if(!Polun)
00751         {
00752 #ifdef UE_DEBUG
00753                 fprintf(stdout,"Empty Polun\n");
00754 #endif
00755                 return ((Enumeration *) 0);
00756         }
00757       
00758         while(Polun->next != NULL)  {
00759                 Enumeration *enext;
00760                 res=NULL;
00761                 en1=Polun->pt;
00762                 en2=(Polun->next)->pt;
00763 
00764                 d1=DMUnion(en1, MAXRAYS);
00765                 d2=DMUnion(en2, MAXRAYS);
00766 
00767                 for (en1=Polun->pt;en1;en1=enext) {
00768                         enext = en1->next;
00769                         for(en2=(Polun->next)->pt;en2;en2=en2->next)
00770                         {
00771                                 d = DomainIntersection(en1->ValidityDomain,en2->ValidityDomain,MAXRAYS);
00772                                 if( d && !emptyQ(d)&&!IncludeInRes(d,res,MAXRAYS))  {
00773                                         tmp = (Enumeration  *)malloc(sizeof(Enumeration));
00774                                         value_init(tmp->EP.d);
00775                                         value_assign( tmp->EP.d, en2->EP.d );
00776                                         if(value_zero_p(tmp->EP.d))
00777                                                 tmp->EP.x.p=ecopy(en2->EP.x.p);
00778                                         else
00779                                         {
00780                                                 value_init(tmp->EP.x.n);
00781                                                 value_assign( tmp->EP.x.n, en2->EP.x.n );
00782                                         }
00783 
00784                                         new_eadd(&en1->EP,&tmp->EP);
00785                                         tmp->ValidityDomain =d;
00786                                         tmp->next= res;
00787                                         res=tmp;
00788                                 }
00789                         }
00790                         d=DomainDifference(en1->ValidityDomain,d2 ,MAXRAYS);
00791                         if (d && !emptyQ(d) && !IncludeInRes(d,res,MAXRAYS)) {
00792                                 en1->ValidityDomain = d;
00793                                 en1->next= res;
00794                                 res=en1;
00795                         } else {
00796                                 free_evalue_refs(&en1->EP);
00797                                 free(en1);
00798                         }
00799                 }
00800                 for (en2=(Polun->next)->pt; en2; en2 = enext) {
00801                         enext = en2->next;
00802                         d= DomainDifference(en2->ValidityDomain,d1,MAXRAYS);
00803                         if (d && !emptyQ(d)&&!IncludeInRes(d,res,MAXRAYS)) {
00804                                 en2->ValidityDomain = d;
00805                                 en2->next = res;
00806                                 res = en2;
00807                         } else {
00808                                 free_evalue_refs(&en2->EP);
00809                                 free(en2);
00810                         }
00811                 }
00812                 Domain_Free(d1);
00813                 Domain_Free(d2);
00814             
00815                 Polun->pt=res;
00816                                      
00817                 Polun->next= (Polun->next)->next;
00818         }
00819         res=Polun->pt;
00820                 
00821         Remove_RedundantDomains(&res); 
00822         return(res);
00823 }
00824 
00825 
00826 /**********
00827  DO NOT USE THE FOLLOWING FUNCTION IT'S NOT WORKING PROPERLY YET.
00828  **********/
00829 
00830 /* Enumeration of the image by T of domain D */
00831 Enumeration *Polyhedron_Image_Enumerate(Polyhedron *D,  Polyhedron *C, Matrix *T, unsigned MAXRAYS, char **par_name)
00832 {   Polyhedron *polun,*pol;
00833     Enumeration *ee;
00834     Matrix *TCopy,*Tred, *d1,*d;
00835     Vector *v1,*v2;
00836     Value h;
00837     int i,j,k;
00838 
00839   POL_ENSURE_FACETS(D);
00840   POL_ENSURE_VERTICES(D);
00841   POL_ENSURE_FACETS(C);
00842   POL_ENSURE_VERTICES(C);
00843 
00844    value_init(h);
00845     if(!D) {
00846          fprintf(stdout,"             Error: in reading input domain \n");   
00847          value_clear(h);
00848            return ((Enumeration *) 0);
00849     }
00850     else {
00851       printf("\n ################   INPUT  POLYHEDRON  #######################\n\n");
00852       AffConstraints(D);
00853      }
00854 
00855 #ifdef DOMAIN_IMAGE
00856        fpol=DomainImage(D,T,MAXRAYS);
00857        printf("\n $$$$$$$$$$$$$  THE  DOMAIN IMAGE    $$$$$$$$$$$$$\n\n");
00858          AffConstraints(fpol);
00859           if(emptyQ(fpol)) {
00860                   value_clear(h);
00861                   return ((Enumeration *) 0);
00862           } 
00863           ee = Domain_Enumerate(fpol,C,MAXRAYS,par_name);
00864           value_clear(h);
00865        return  (ee);
00866 #endif
00867  
00868      TCopy= Matrix_Copy(T);
00869      Tred= Reduce_Matrix(TCopy);
00870      printf("\n ##################  INPUT REDUCED TRANSFORMATION MATRIX ##################\n" );
00871      Matrix_Print(stdout,P_VALUE_FMT,Tred);
00872 
00873          if (Tred->NbRows <Tred->NbColumns) {
00874                d1=(Matrix *) Matrix_Alloc(Tred->NbColumns,Tred->NbColumns);
00875                for (i=0;i<Tred->NbRows;i++) {
00876                     for (j=0; j<Tred->NbColumns;j++) {
00877                                 value_assign( d1->p[i][j], Tred->p[i][j] );
00878                     }
00879                }
00880                for(i=Tred->NbRows;i<Tred->NbColumns;i++) {
00881                      for (j=0;j<Tred->NbColumns;j++) {
00882                           value_set_si( d1->p[i][j], 0 );
00883                      }
00884                }
00885                d= (Matrix *) CalcBase(d1);
00886                Matrix_Free(Tred);
00887                Matrix_Free(d1);
00888          
00889          }
00890          else {
00891               d=(Matrix *) CalcBase(Tred);
00892               Matrix_Free(Tred);
00893          }
00894     if(d->NbRows==0) {
00895         if(emptyQ(D)) {
00896                 value_clear(h);
00897                 return ((Enumeration *) 0);
00898         }
00899         else {
00900            printf( "        Ker(A)=0  implys directly Enumeration on input polyhedron\n\n");            
00901            ee=Domain_Enumerate(D,C,MAXRAYS,par_name);
00902            value_clear(h);
00903            return ee;
00904         }
00905    }
00906    
00907    d1=Transpose(d);
00908    Matrix_Free(d);
00909    
00910    if(d1->NbRows!=D->Dimension) {
00911       fprintf(stdout,"      \n Error: incompatible dimension \n");
00912       value_clear(h);
00913       return ((Enumeration *) 0);
00914    }
00915    if(d1->NbColumns > 1) {
00916  fprintf(stdout,"   \n Error: Can not compute intégral points : More then vector in ker(A)! \n");
00917     value_clear(h);
00918     return ((Enumeration *) 0);
00919          
00920     }
00921    printf( "           \n Ker(A)=1  implys adding constraints befor Enumeration\n");
00922    v1=Vector_Alloc(d1->NbRows);
00923    v2=Vector_Alloc(d1->NbRows);
00924    
00925           polun=(Polyhedron *) NULL; 
00926             for (k=0;k<d1->NbRows;k++) {
00927                   value_assign(v1->p[k],d1->p[k][0]) ;
00928             }
00929           /* adding a new constraint for all constraints of D in which the scalar product of the*/
00930           /* normal whith vector v1 is greter then zero*/
00931             
00932           for (j=0;j<D->NbConstraints;j++)  {
00933                  for (k=0;k<=D->Dimension-1;k++) {
00934                         value_assign(v2->p[k],D->Constraint[j][k+1]) ;
00935                   }
00936                   Scalar_product(v1->p,v2->p,D->Dimension,&h);
00937                 
00938                   if(value_pos_p(h)&&!value_zero_p(D->Constraint[j][0])) {
00939                        Vector *NCont;
00940                        Value val;
00941                        value_init( val );
00942                        /* Create a new contraint whitch is added to the polyhedron*/
00943                        
00944                        NCont=Vector_Alloc(d1->NbRows+2);
00945                        value_set_si( NCont->p[0],1); /* the constraint is an inequality */
00946                                        
00947                        for (k=1;k<=D->Dimension;k++) {
00948                             value_oppose( NCont->p[k], D->Constraint[j][k]);
00949                                         }
00950                        value_decrement(val,h);
00951                        value_subtract(val,val,D->Constraint[j][D->Dimension+1]);
00952                        value_assign (NCont->p[D->Dimension+1],val);
00953                        value_clear(val);
00954                        /* add the new constraint to polyhedron D */
00955                        pol=AddConstraints(NCont->p,1,D,MAXRAYS);
00956                        polun=AddPolyToDomain(Polyhedron_Copy(pol),polun);
00957                        Polyhedron_Free(pol);
00958                        Vector_Free(NCont);
00959                                  value_clear( val );
00960                     }
00961            }
00962           if(polun==NULL) { /*  No constraint is added to input polyhedron */
00963               if(emptyQ(D)) {
00964                       value_clear(h);
00965                       return ((Enumeration *) 0);
00966               }
00967               else {
00968                  ee= Domain_Enumerate(D,C,MAXRAYS,par_name);
00969               }
00970           }
00971           else { /* some constraintes are added to input polyhedron */
00972               if(emptyQ(polun)){
00973                       value_clear(h);
00974                       return ((Enumeration *) 0);
00975               }
00976               else {
00977         printf("\n ##################################################################");       
00978         printf("\n ****** THE RESULT OF ADDING CONSTRAINTS TO THE INPUT POLYHEDRON  ****** \n");         
00979                AffConstraints(polun);
00980                ee= Domain_Enumerate(polun,C,MAXRAYS,par_name);
00981                value_clear(h);
00982                return (ee );
00983               }
00984       }
00985               
00986 
00987         return( NULL );           
00988 }
00989 
00990 

Generated on Mon Apr 23 19:23:52 2007 for polylib by doxygen 1.3.5