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                         value_gcd(p, p, B->p[u][i]);
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_divexact(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         value_gcd(p, R->p[l1][piv], R->p[l2][piv]);
00278         value_divexact(a, R->p[l1][piv], p);
00279         value_divexact(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                 value_gcd(p, p, R->p[l2][i]);
00289         }
00290         /* Simplification par le pgcd de toute la ligne */
00291         for( i=piv+1 ; i<R->NbColumns && p!=0 ; i++ )
00292                 value_divexact(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          value_gcd(g, res->x.n,res->d);
00320          if (value_notone_p(g)) {
00321               value_divexact(res->d, res->d, g);
00322               value_divexact(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 
00539 Matrix *Orthogonal_Base(Matrix *Mat)  {
00540   Matrix *OrthMat;
00541   Value a,b,c,d;
00542   Vector *q,*p,*f;
00543   unsigned length;
00544   int i,j,k;
00545   value_init(a);
00546   value_init(b);
00547   value_init(c);
00548   value_init(d);
00549   OrthMat= Matrix_Alloc(Mat->NbRows,Mat->NbColumns);
00550   length=Mat->NbColumns;
00551   for(k=0; k<length; k++)  {
00552     value_assign(OrthMat->p[0][k],Mat->p[0][k]);                
00553   }
00554   f=Vector_Alloc(length);
00555   p=Vector_Alloc(length);
00556   q=Vector_Alloc(length);
00557   for(i=1; i<Mat->NbRows; i++)  {
00558     for(k=0;k<length;k++)  {
00559       value_assign(f->p[k],Mat->p[i][k]);
00560       value_assign(q->p[k],Mat->p[i][k]);
00561     }
00562     value_set_si(d,1);
00563     for(j=0; j<i; j++) {
00564       for(k=0;k<length;k++)  {
00565         value_assign(p->p[k],OrthMat->p[j][k]);
00566       }
00567       
00568       Scalar_product(p->p,f->p,length,&a);
00569       Scalar_product(p->p,p->p,length,&b);      
00570       value_gcd(c, a, b);
00571       value_divexact(a, a, c);
00572       value_divexact(b, b, c);
00573       for(k=0;k<length;k++) {
00574         value_multiply(p->p[k],p->p[k],a);
00575       }
00576       
00577       if(value_notone_p(d)|value_notone_p(b))  {
00578         value_lcm(c, d, b);
00579         value_divexact(a, c, b);
00580         value_divexact(b, c, d);
00581         value_assign(d,c);
00582         for(k=0;k<length;k++) {
00583           value_multiply(p->p[k],p->p[k],a);
00584           value_multiply(q->p[k],q->p[k],b);
00585         }
00586         
00587       }
00588       
00589       for(k=0;k<length;k++) {
00590         value_subtract(q->p[k],q->p[k],p->p[k]);
00591       }
00592       
00593     }
00594     Vector_Gcd(q->p,length,&c); 
00595     Vector_AntiScale(q->p, OrthMat->p[i], c, length);
00596   }
00597   value_clear(a);
00598   value_clear(b);
00599   value_clear(c);
00600   value_clear(d);
00601   return OrthMat;
00602 }  /* Orthogonal_Base  */
00603      
00604 
00605 /* Remove an element of a list */
00606 void  Remove_Element(Enumeration *en,Enumeration **re, Enumeration *prev)  {
00607   if (en== *re)  {
00608     *re= (*re)->next;
00609   }
00610   else {
00611     prev->next=en->next;
00612   }
00613 } /* Remove_Element */
00614   
00615  /* Remove validite domains and correspending ehrhart polynomials whitch are redundant after 
00616   the enumeration of a polyhedron */
00617 
00618  void Remove_RedundantDomains (Enumeration  **Ures)  {
00619         Enumeration *ren1, *ren2, *previous=NULL;
00620         int red;
00621         for (ren1=*Ures; ren1; ren1=ren1->next)  {
00622                 red=0;
00623                 for (ren2=*Ures; ren2; ren2=ren2->next)  {
00624                         if (ren1!=ren2)  {
00625                                   
00626                             if (PolyhedronIncludes(ren2->ValidityDomain, ren1->ValidityDomain)) {
00627                                         red= 1;
00628                                         break;
00629                 
00630                                 }
00631                                 
00632                         }
00633                 }
00634                 if (red)  {
00635                         Remove_Element(ren1,Ures,previous);
00636                 }
00637                 previous=ren1;
00638         }
00639  }/*Remove_RedendentDomains */
00640                                                       
00641                                   
00642 int IncludeInRes (Polyhedron *p, Enumeration *e, unsigned MR) {
00643         Enumeration *en;
00644            for (en=e; en; en=en->next)  {
00645                   
00646                 if (PolyhedronIncludes(e->ValidityDomain,p)) 
00647                          return 1;
00648            }
00649         return 0;       
00650 }
00651 
00652 Polyhedron *DMUnion(Enumeration *en, unsigned MR)  {
00653         Enumeration *e1;
00654         Polyhedron *d;
00655         e1=en;
00656         d=e1->ValidityDomain; 
00657          for (e1=en->next; e1; e1=e1->next) {
00658            d= DomainUnion( d, e1->ValidityDomain, MR);
00659          }
00660          return d;
00661   }
00662 
00663 
00664 void AffConstraints(Polyhedron *Poldisj)
00665 {
00666         Polyhedron *p;
00667 
00668         for(p=Poldisj;p;p=p->next)
00669         {
00670                 Polyhedron_PrintConstraints( stdout, P_VALUE_FMT, p);
00671                 printf("\n");
00672         }
00673 }
00674 int Degenerate (Enumeration *en) {
00675         if(value_notzero_p(en->EP.d)) {
00676                 
00677            if(value_mone_p(en->EP.x.n )) {
00678                return 1;    
00679            }
00680         }
00681    return 0;    
00682 }
00683 
00684 /* Enumeration of a domain D */
00685 
00686 Enumeration *Domain_Enumerate(Polyhedron *D, Polyhedron *C, unsigned MAXRAYS,
00687                                 const char **pn)
00688 {     Polyhedron_union *Polun,*pu;
00689       Polyhedron  *lp, *lp1, *lp1next;
00690       Polyhedron *d1,*d2,*d;  
00691       Enumeration *e,*pr,*en,*en1, *en2,*tmp, *res, *sen;
00692       Polun=NULL;
00693      
00694       for (d = D; d; d = d->next) {
00695           POL_ENSURE_FACETS(d);
00696           POL_ENSURE_VERTICES(d);
00697       }
00698       POL_ENSURE_FACETS(C);
00699       POL_ENSURE_VERTICES(C);
00700 
00701      lp = Disjoint_Domain( D, 0, MAXRAYS );
00702 
00703 #ifdef UE_DEBUG
00704      printf("##############################################################\n");
00705      printf("\n###### DISJOINT UNION  ######\n\n");
00706      AffConstraints(lp); 
00707      printf("##############################################################\n");
00708 #endif
00709      
00710         for (lp1=lp ; lp1; lp1=lp1->next)
00711         {
00712                 Enumeration *enext;
00713                 lp1next = lp1->next;
00714                 lp1->next = NULL;
00715                 en= Polyhedron_Enumerate(lp1, C, MAXRAYS,NULL);
00716                 lp1->next = lp1next;
00717                 sen= NULL;
00718                 for (e=en;e;e=enext) {
00719                         enext = e->next;
00720                         if (!Degenerate(e)) {
00721                                 e->next = sen;
00722                                 sen=e;
00723                         } else {
00724                                 free_evalue_refs(&e->EP);
00725                                 Domain_Free(e->ValidityDomain);
00726                                 free(e);
00727                         }
00728                 }
00729 
00730                 if(sen!= NULL)
00731                 {
00732                         pu = (Polyhedron_union  *)malloc(sizeof(Polyhedron_union));
00733                         pu->pt=sen;
00734                         pu->next = Polun;
00735                         Polun = pu;
00736                 }
00737         }
00738         if(!Polun)
00739         {
00740 #ifdef UE_DEBUG
00741                 fprintf(stdout,"Empty Polun\n");
00742 #endif
00743                 return ((Enumeration *) 0);
00744         }
00745       
00746         while(Polun->next != NULL)  {
00747                 Enumeration *enext;
00748                 res=NULL;
00749                 en1=Polun->pt;
00750                 en2=(Polun->next)->pt;
00751 
00752                 d1=DMUnion(en1, MAXRAYS);
00753                 d2=DMUnion(en2, MAXRAYS);
00754 
00755                 for (en1=Polun->pt;en1;en1=enext) {
00756                         enext = en1->next;
00757                         for(en2=(Polun->next)->pt;en2;en2=en2->next)
00758                         {
00759                                 d = DomainIntersection(en1->ValidityDomain,en2->ValidityDomain,MAXRAYS);
00760                                 if( d && !emptyQ(d)&&!IncludeInRes(d,res,MAXRAYS))  {
00761                                         tmp = (Enumeration  *)malloc(sizeof(Enumeration));
00762                                         value_init(tmp->EP.d);
00763                                         value_assign( tmp->EP.d, en2->EP.d );
00764                                         if(value_zero_p(tmp->EP.d))
00765                                                 tmp->EP.x.p=ecopy(en2->EP.x.p);
00766                                         else
00767                                         {
00768                                                 value_init(tmp->EP.x.n);
00769                                                 value_assign( tmp->EP.x.n, en2->EP.x.n );
00770                                         }
00771 
00772                                         new_eadd(&en1->EP,&tmp->EP);
00773                                         tmp->ValidityDomain =d;
00774                                         tmp->next= res;
00775                                         res=tmp;
00776                                 }
00777                         }
00778                         d=DomainDifference(en1->ValidityDomain,d2 ,MAXRAYS);
00779                         if (d && !emptyQ(d) && !IncludeInRes(d,res,MAXRAYS)) {
00780                                 en1->ValidityDomain = d;
00781                                 en1->next= res;
00782                                 res=en1;
00783                         } else {
00784                                 free_evalue_refs(&en1->EP);
00785                                 free(en1);
00786                         }
00787                 }
00788                 for (en2=(Polun->next)->pt; en2; en2 = enext) {
00789                         enext = en2->next;
00790                         d= DomainDifference(en2->ValidityDomain,d1,MAXRAYS);
00791                         if (d && !emptyQ(d)&&!IncludeInRes(d,res,MAXRAYS)) {
00792                                 en2->ValidityDomain = d;
00793                                 en2->next = res;
00794                                 res = en2;
00795                         } else {
00796                                 free_evalue_refs(&en2->EP);
00797                                 free(en2);
00798                         }
00799                 }
00800                 Domain_Free(d1);
00801                 Domain_Free(d2);
00802             
00803                 Polun->pt=res;
00804                                      
00805                 Polun->next= (Polun->next)->next;
00806         }
00807         res=Polun->pt;
00808                 
00809         Remove_RedundantDomains(&res); 
00810         return(res);
00811 }
00812 
00813 
00814 /**********
00815  DO NOT USE THE FOLLOWING FUNCTION IT'S NOT WORKING PROPERLY YET.
00816  **********/
00817 
00818 /* Enumeration of the image by T of domain D */
00819 Enumeration *Polyhedron_Image_Enumerate(Polyhedron *D,  Polyhedron *C, Matrix *T, unsigned MAXRAYS, const char **par_name)
00820 {   Polyhedron *polun,*pol;
00821     Enumeration *ee;
00822     Matrix *TCopy,*Tred, *d1,*d;
00823     Vector *v1,*v2;
00824     Value h;
00825     int i,j,k;
00826 
00827   POL_ENSURE_FACETS(D);
00828   POL_ENSURE_VERTICES(D);
00829   POL_ENSURE_FACETS(C);
00830   POL_ENSURE_VERTICES(C);
00831 
00832    value_init(h);
00833     if(!D) {
00834          fprintf(stdout,"             Error: in reading input domain \n");   
00835          value_clear(h);
00836            return ((Enumeration *) 0);
00837     }
00838     else {
00839       printf("\n ################   INPUT  POLYHEDRON  #######################\n\n");
00840       AffConstraints(D);
00841      }
00842 
00843 #ifdef DOMAIN_IMAGE
00844        fpol=DomainImage(D,T,MAXRAYS);
00845        printf("\n $$$$$$$$$$$$$  THE  DOMAIN IMAGE    $$$$$$$$$$$$$\n\n");
00846          AffConstraints(fpol);
00847           if(emptyQ(fpol)) {
00848                   value_clear(h);
00849                   return ((Enumeration *) 0);
00850           } 
00851           ee = Domain_Enumerate(fpol,C,MAXRAYS,par_name);
00852           value_clear(h);
00853        return  (ee);
00854 #endif
00855  
00856      TCopy= Matrix_Copy(T);
00857      Tred= Reduce_Matrix(TCopy);
00858      printf("\n ##################  INPUT REDUCED TRANSFORMATION MATRIX ##################\n" );
00859      Matrix_Print(stdout,P_VALUE_FMT,Tred);
00860 
00861          if (Tred->NbRows <Tred->NbColumns) {
00862                d1=(Matrix *) Matrix_Alloc(Tred->NbColumns,Tred->NbColumns);
00863                for (i=0;i<Tred->NbRows;i++) {
00864                     for (j=0; j<Tred->NbColumns;j++) {
00865                                 value_assign( d1->p[i][j], Tred->p[i][j] );
00866                     }
00867                }
00868                for(i=Tred->NbRows;i<Tred->NbColumns;i++) {
00869                      for (j=0;j<Tred->NbColumns;j++) {
00870                           value_set_si( d1->p[i][j], 0 );
00871                      }
00872                }
00873                d= (Matrix *) CalcBase(d1);
00874                Matrix_Free(Tred);
00875                Matrix_Free(d1);
00876          
00877          }
00878          else {
00879               d=(Matrix *) CalcBase(Tred);
00880               Matrix_Free(Tred);
00881          }
00882     if(d->NbRows==0) {
00883         if(emptyQ(D)) {
00884                 value_clear(h);
00885                 return ((Enumeration *) 0);
00886         }
00887         else {
00888            printf( "        Ker(A)=0  implys directly Enumeration on input polyhedron\n\n");            
00889            ee=Domain_Enumerate(D,C,MAXRAYS,par_name);
00890            value_clear(h);
00891            return ee;
00892         }
00893    }
00894    
00895    d1=Transpose(d);
00896    Matrix_Free(d);
00897    
00898    if(d1->NbRows!=D->Dimension) {
00899       fprintf(stdout,"      \n Error: incompatible dimension \n");
00900       value_clear(h);
00901       return ((Enumeration *) 0);
00902    }
00903    if(d1->NbColumns > 1) {
00904  fprintf(stdout,"   \n Error: Can not compute intégral points : More then vector in ker(A)! \n");
00905     value_clear(h);
00906     return ((Enumeration *) 0);
00907          
00908     }
00909    printf( "           \n Ker(A)=1  implys adding constraints befor Enumeration\n");
00910    v1=Vector_Alloc(d1->NbRows);
00911    v2=Vector_Alloc(d1->NbRows);
00912    
00913           polun=(Polyhedron *) NULL; 
00914             for (k=0;k<d1->NbRows;k++) {
00915                   value_assign(v1->p[k],d1->p[k][0]) ;
00916             }
00917           /* adding a new constraint for all constraints of D in which the scalar product of the*/
00918           /* normal whith vector v1 is greter then zero*/
00919             
00920           for (j=0;j<D->NbConstraints;j++)  {
00921                  for (k=0;k<=D->Dimension-1;k++) {
00922                         value_assign(v2->p[k],D->Constraint[j][k+1]) ;
00923                   }
00924                   Scalar_product(v1->p,v2->p,D->Dimension,&h);
00925                 
00926                   if(value_pos_p(h)&&!value_zero_p(D->Constraint[j][0])) {
00927                        Vector *NCont;
00928                        Value val;
00929                        value_init( val );
00930                        /* Create a new contraint whitch is added to the polyhedron*/
00931                        
00932                        NCont=Vector_Alloc(d1->NbRows+2);
00933                        value_set_si( NCont->p[0],1); /* the constraint is an inequality */
00934                                        
00935                        for (k=1;k<=D->Dimension;k++) {
00936                             value_oppose( NCont->p[k], D->Constraint[j][k]);
00937                                         }
00938                        value_decrement(val,h);
00939                        value_subtract(val,val,D->Constraint[j][D->Dimension+1]);
00940                        value_assign (NCont->p[D->Dimension+1],val);
00941                        value_clear(val);
00942                        /* add the new constraint to polyhedron D */
00943                        pol=AddConstraints(NCont->p,1,D,MAXRAYS);
00944                        POL_ENSURE_VERTICES(pol);
00945                        polun=AddPolyToDomain(Polyhedron_Copy(pol),polun);
00946                        Polyhedron_Free(pol);
00947                        Vector_Free(NCont);
00948                                  value_clear( val );
00949                     }
00950            }
00951           if(polun==NULL) { /*  No constraint is added to input polyhedron */
00952               if(emptyQ(D)) {
00953                       value_clear(h);
00954                       return ((Enumeration *) 0);
00955               }
00956               else {
00957                  ee= Domain_Enumerate(D,C,MAXRAYS,par_name);
00958               }
00959           }
00960           else { /* some constraintes are added to input polyhedron */
00961               if(emptyQ(polun)){
00962                       value_clear(h);
00963                       return ((Enumeration *) 0);
00964               }
00965               else {
00966         printf("\n ##################################################################");       
00967         printf("\n ****** THE RESULT OF ADDING CONSTRAINTS TO THE INPUT POLYHEDRON  ****** \n");         
00968                AffConstraints(polun);
00969                ee= Domain_Enumerate(polun,C,MAXRAYS,par_name);
00970                value_clear(h);
00971                return (ee );
00972               }
00973       }
00974               
00975 
00976         return( NULL );           
00977 }
00978 
00979 

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