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

Generated on Mon Sep 12 14:48:29 2005 for polylib by doxygen 1.3.5