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

Generated on Mon Sep 12 15:15:10 2005 for polylib by doxygen 1.3.5