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

alpha.c

Go to the documentation of this file.
00001 /* polytest.c */
00002 #include <stdio.h>
00003 #include <polylib/polylib.h>
00004 
00005 /* alpha.c
00006      COPYRIGHT
00007           Both this software and its documentation are
00008 
00009               Copyright 1993 by IRISA /Universite de Rennes I - France,
00010               Copyright 1995,1996 by BYU, Provo, Utah
00011                          all rights reserved.
00012 
00013           Permission is granted to copy, use, and distribute
00014           for any commercial or noncommercial purpose under the terms
00015           of the GNU General Public license, version 2, June 1991
00016           (see file : LICENSING).
00017 */
00018 
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <string.h>
00022 
00023 /*---------------------------------------------------------------------*/
00024 /* int exist_points(pos,P,context)                                     */
00025 /*    pos : index position of current loop index (0..hdim-1)           */
00026 /*    P: loop domain                                                   */
00027 /*    context : context values for fixed indices                       */
00028 /* recursive procedure, recurs for each imbriquation                   */
00029 /* returns 1 if there exists any integer points in this polyhedron     */
00030 /* returns 0 if there are none                                         */
00031 /*---------------------------------------------------------------------*/
00032 static int exist_points(int pos,Polyhedron *Pol,Value *context) {
00033   
00034   Value LB, UB, k,tmp;
00035   
00036   value_init(LB); value_init(UB); 
00037   value_init(k);  value_init(tmp);
00038   value_set_si(LB,0);
00039   value_set_si(UB,0);
00040   
00041   /* Problem if UB or LB is INFINITY */
00042   if (lower_upper_bounds(pos,Pol,context,&LB,&UB) !=0) {
00043     errormsg1("exist_points", "infdom", "infinite domain");
00044     value_clear(LB);
00045     value_clear(UB);
00046     value_clear(k);
00047     value_clear(tmp);
00048     return -1;
00049   }
00050   value_set_si(context[pos],0);
00051   if(value_lt(UB,LB)) {
00052     value_clear(LB); 
00053     value_clear(UB);
00054     value_clear(k);
00055     value_clear(tmp);
00056     return 0;
00057   }  
00058   if (!Pol->next) {
00059     value_substract(tmp,UB,LB);
00060     value_increment(tmp,tmp);
00061     value_clear(UB);
00062     value_clear(LB);
00063     value_clear(k);
00064     return (value_pos_p(tmp));
00065   }
00066   
00067   for (value_assign(k,LB);value_le(k,UB);value_increment(k,k)) {
00068     
00069     /* insert k in context */
00070     value_assign(context[pos],k);    
00071     if (exist_points(pos+1,Pol->next,context) > 0 ) {
00072       value_clear(LB); value_clear(UB);
00073       value_clear(k); value_clear(tmp);
00074       return 1;
00075     }
00076   }   
00077   /* Reset context */
00078   value_set_si(context[pos],0);
00079   value_clear(UB); value_clear(LB);
00080   value_clear(k); value_clear(tmp);
00081   return 0;
00082 }
00083     
00084 /*--------------------------------------------------------------*/
00085 /* Test to see if there are any integral points in a polyhedron */
00086 /*--------------------------------------------------------------*/
00087 int Polyhedron_Not_Empty(Polyhedron *P,Polyhedron *C,int MAXRAYS) {
00088 
00089   int res,i;
00090   Value *context;
00091   Polyhedron *L;
00092   
00093   /* Create a context vector size dim+2 and set it to all zeros */
00094   context = (Value *) malloc((P->Dimension+2)*sizeof(Value));
00095   
00096   /* Initialize array 'context' */
00097   for (i=0;i<(P->Dimension+2);i++) 
00098     value_init(context[i]);
00099   
00100   Vector_Set(context,0,(P->Dimension+2));
00101   
00102   /* Set context[P->Dimension+1] = 1  (the constant) */
00103   value_set_si(context[P->Dimension+1],1);
00104   
00105   L = Polyhedron_Scan(P,C,MAXRAYS);
00106   res = exist_points(1,L,context);
00107   Domain_Free(L);
00108   
00109   /* Clear array 'context' */
00110   for (i=0;i<(P->Dimension+2);i++) 
00111     value_clear(context[i]);
00112   free(context);
00113   return res;
00114 }
00115 
00116 /* PolyhedronLTQ ( P1, P2 ) */
00117 /* P1 and P2 must be simple polyhedra */
00118 /* result =  0 --> not comparable */
00119 /* result = -1 --> P1 < P2        */
00120 /* result =  1 --> P1 > P2        */
00121 /* INDEX  = 1 .... Dimension      */
00122 int PolyhedronLTQ (Polyhedron *Pol1,Polyhedron *Pol2,int INDEX, int PDIM, int NbMaxConstrs) { 
00123   
00124   int res, dim, i, j, k;
00125   Polyhedron *Q1, *Q2, *Q3, *Q4, *Q;
00126   Matrix *Mat;
00127 
00128   if (Pol1->next || Pol2->next) {
00129     errormsg1("PolyhedronLTQ", "compoly", "Can only compare polyhedra");
00130     return 0;
00131   }
00132   if (Pol1->Dimension != Pol2->Dimension) {
00133     errormsg1("PolyhedronLTQ","diffdim","Polyhedra are not same dimension");
00134     return 0;
00135   }
00136   dim = Pol1->Dimension+2;
00137   
00138 #ifdef DEBUG
00139   fprintf(stdout, "P1\n");
00140   Polyhedron_Print(stdout,P_VALUE_FMT,Pol1);
00141   fprintf(stdout, "P2\n");
00142   Polyhedron_Print(stdout,P_VALUE_FMT,Pol2);
00143 #endif
00144   
00145   /* Create the Line to add */
00146   k = Pol1->Dimension-INDEX+1-PDIM;
00147   Mat = Matrix_Alloc(k,dim);
00148   Vector_Set(Mat->p_Init,0,dim*k);
00149   for(j=0,i=INDEX;j<k;i++,j++)
00150     value_set_si(Mat->p[j][i],1);
00151   
00152   Q1 = AddRays(Mat->p[0],k,Pol1,NbMaxConstrs);
00153   Q2 = AddRays(Mat->p[0],k,Pol2,NbMaxConstrs);
00154 
00155 #ifdef DEBUG
00156   fprintf(stdout, "Q1\n");
00157   Polyhedron_Print(stdout,P_VALUE_FMT,Q1);
00158   fprintf(stdout, "Q2\n");
00159   Polyhedron_Print(stdout,P_VALUE_FMT,Q2);
00160 #endif
00161   
00162   Matrix_Free(Mat);
00163   Q  = DomainIntersection(Q1,Q2,NbMaxConstrs);
00164   
00165 #ifdef DEBUG
00166   fprintf(stdout, "Q\n");
00167   Polyhedron_Print(stdout,P_VALUE_FMT,Q);
00168 #endif
00169   
00170   Domain_Free(Q1);
00171   Domain_Free(Q2);
00172   
00173   if (emptyQ(Q)) res = 0;       /* not comparable */
00174   else {
00175     Q1 = DomainIntersection(Pol1,Q,NbMaxConstrs);
00176     Q2 = DomainIntersection(Pol2,Q,NbMaxConstrs);
00177     
00178 #ifdef DEBUG
00179     fprintf(stdout, "Q1\n");
00180     Polyhedron_Print(stdout,P_VALUE_FMT,Q1);
00181     fprintf(stdout, "Q2\n");
00182     Polyhedron_Print(stdout,P_VALUE_FMT,Q2);
00183 #endif
00184 
00185     k = Q1->NbConstraints + Q2->NbConstraints;
00186     Mat = Matrix_Alloc(k, dim);
00187     Vector_Set(Mat->p_Init,0,k*dim);
00188     
00189     /* First compute surrounding polyhedron */    
00190     j=0;
00191     for (i=0; i<Q1->NbConstraints; i++) {
00192       if ((value_one_p(Q1->Constraint[i][0])) && (value_pos_p(Q1->Constraint[i][INDEX]))) {
00193         
00194         /* keep Q1's lower bounds */
00195         for (k=0; k<dim; k++) 
00196           value_assign(Mat->p[j][k],Q1->Constraint[i][k]);
00197         j++;
00198       }
00199     }
00200     for (i=0; i<Q2->NbConstraints; i++) {
00201       if ((value_one_p(Q2->Constraint[i][0])) && (value_neg_p(Q2->Constraint[i][INDEX]))) {
00202         
00203         /* and keep Q2's upper bounds */
00204         for (k=0; k<dim; k++) 
00205           value_assign(Mat->p[j][k],Q2->Constraint[i][k]);
00206         j++;
00207       }
00208     }
00209     Q4 = AddConstraints(Mat->p[0], j, Q, NbMaxConstrs);
00210     Matrix_Free(Mat);
00211     
00212 #ifdef debug
00213     fprintf(stderr, "Q4 surrounding polyhedron\n");
00214     Polyhderon_Print(stderr,P_VALUE_FMT, Q4);
00215 #endif
00216 
00217     /* if surrounding polyhedron is empty, D1>D2 */
00218     if (emptyQ(Q4)) {
00219       res = 1;
00220       
00221 #ifdef debug
00222       fprintf(stderr, "Surrounding polyhedron is empty\n");
00223 #endif
00224       goto LTQdone2; 
00225     }
00226     
00227     /* Test if Q1 < Q2 */      
00228     /* Build a constraint array for >= Q1 and <= Q2 */
00229     Mat = Matrix_Alloc(2,dim);
00230     Vector_Set(Mat->p_Init,0,2*dim);
00231     
00232     /* Choose a contraint from Q1 */
00233     for (i=0; i<Q1->NbConstraints; i++) {
00234       if (value_zero_p(Q1->Constraint[i][0])) {
00235         
00236         /* Equality */
00237         if (value_zero_p(Q1->Constraint[i][INDEX])) {
00238           
00239           /* Ignore side constraint (they are in Q) */
00240           continue;
00241         }
00242         else if (value_neg_p(Q1->Constraint[i][INDEX])) {
00243           
00244           /* copy -constraint to Mat */
00245           value_set_si(Mat->p[0][0],1);
00246           for (k=1; k<dim; k++)
00247             value_oppose(Mat->p[0][k],Q1->Constraint[i][k]);
00248         }
00249         else {
00250           
00251           /* Copy constraint to Mat */
00252           
00253           value_set_si(Mat->p[0][0],1);
00254           for (k=1; k<dim; k++)
00255             value_assign(Mat->p[0][k],Q1->Constraint[i][k]);
00256         }
00257       }
00258       else if(value_neg_p(Q1->Constraint[i][INDEX])) {
00259         
00260         /* Upper bound -- make a lower bound from it */
00261         value_set_si(Mat->p[0][0],1);
00262         for (k=1; k<dim; k++)
00263           value_oppose(Mat->p[0][k],Q1->Constraint[i][k]);
00264       }
00265       else {    
00266         
00267         /* Lower or side bound -- ignore it */
00268         continue;
00269       }
00270       
00271       /* Choose a constraint from Q2 */
00272       for (j=0; j<Q2->NbConstraints; j++) {
00273         if (value_zero_p(Q2->Constraint[j][0])) {   /* equality */
00274           if (value_zero_p(Q2->Constraint[j][INDEX])) {
00275             
00276             /* Ignore side constraint (they are in Q) */
00277             continue;
00278           }
00279           else if (value_pos_p(Q2->Constraint[j][INDEX])) {
00280             
00281             /* Copy -constraint to Mat */
00282             value_set_si(Mat->p[1][0],1);
00283             for (k=1; k<dim; k++)
00284               value_oppose(Mat->p[1][k],Q2->Constraint[j][k]);
00285           }
00286           else {
00287             
00288             /* Copy constraint to Mat */
00289             value_set_si(Mat->p[1][0],1);
00290             for (k=1; k<dim; k++)
00291               value_assign(Mat->p[1][k],Q2->Constraint[j][k]);
00292           };
00293         }
00294         else if (value_pos_p(Q2->Constraint[j][INDEX])) {
00295           
00296           /* Lower bound -- make an upper bound from it */
00297           value_set_si(Mat->p[1][0],1);
00298           for(k=1;k<dim;k++)
00299             value_oppose(Mat->p[1][k],Q2->Constraint[j][k]);
00300         }
00301         else {
00302           
00303           /* Upper or side bound -- ignore it */
00304           continue;
00305         };
00306         
00307 #ifdef DEBUG
00308         fprintf(stdout, "i=%d j=%d M=\n", i+1, j+1);
00309         Matrix_Print(stdout,P_VALUE_FMT,Mat);
00310 #endif
00311         
00312         /* Add Mat to Q and see if anything is made */
00313         Q3 = AddConstraints(Mat->p[0],2,Q,NbMaxConstrs);
00314 
00315 #ifdef DEBUG
00316         fprintf(stdout, "Q3\n");
00317         Polyhedron_Print(stdout,P_VALUE_FMT,Q3);
00318 #endif
00319         
00320         if (!emptyQ(Q3)) { 
00321           Domain_Free(Q3);
00322           
00323 #ifdef DEBUG
00324           fprintf(stdout, "not empty\n");
00325 #endif
00326           res = -1;
00327           goto LTQdone;
00328         }
00329 #ifdef DEBUG
00330         fprintf(stdout,"empty\n");      
00331 #endif
00332         Domain_Free(Q3);
00333       } /* end for j */
00334     } /* end for i */
00335     res = 1;
00336 LTQdone:
00337     Matrix_Free(Mat);
00338 LTQdone2: 
00339     Domain_Free(Q4);
00340     Domain_Free(Q1);
00341     Domain_Free(Q2);
00342   }
00343   Domain_Free(Q);
00344   
00345 #ifdef DEBUG
00346   fprintf(stdout, "res = %d\n", res);
00347 #endif
00348   
00349   return res;
00350 } /* PolyhedronLTQ */
00351 
00352 /* GaussSimplify --
00353    Given Mat1, a matrix of equalities, performs Gaussian elimination.
00354    Find a minimum basis, Returns the rank.
00355    Mat1 is context, Mat2 is reduced in context of Mat1
00356 */
00357 int GaussSimplify(Matrix *Mat1,Matrix *Mat2) {
00358   
00359   int NbRows = Mat1->NbRows;
00360   int NbCols = Mat1->NbColumns;
00361   int *column_index;
00362   int i, j, k, n, t, pivot, Rank; 
00363   Value gcd, tmp, *cp; 
00364   
00365   column_index=(int *)malloc(NbCols * sizeof(int));
00366   if (!column_index) {
00367     errormsg1("GaussSimplify", "outofmem", "out of memory space\n");
00368     Pol_status = 1;
00369     return 0;
00370   }
00371   
00372   /* Initialize all the 'Value' variables */
00373   value_init(gcd); value_init(tmp);
00374   
00375   Rank=0;
00376   for (j=0; j<NbCols; j++) {              /* for each column starting at */ 
00377     for (i=Rank; i<NbRows; i++)           /* diagonal, look down to find */
00378       if (value_notzero_p(Mat1->p[i][j])) /* the first non-zero entry    */
00379         break;                           
00380     if (i!=NbRows) {                      /* was one found ? */
00381       if (i!=Rank)                        /* was it found below the diagonal?*/
00382         Vector_Exchange(Mat1->p[Rank],Mat1->p[i],NbCols);
00383       
00384       /* Normalize the pivot row */
00385       Vector_Gcd(Mat1->p[Rank],NbCols,&gcd);
00386       
00387       /* If (gcd >= 2) */
00388       value_set_si(tmp,2);
00389       if (value_ge(gcd,tmp)) {
00390         cp = Mat1->p[Rank];
00391         for (k=0; k<NbCols; k++,cp++)
00392           value_division(*cp,*cp,gcd);          
00393       }
00394       if (value_neg_p(Mat1->p[Rank][j])) {
00395         cp = Mat1->p[Rank];
00396         for (k=0; k<NbCols; k++,cp++)
00397           value_oppose(*cp,*cp);
00398       }
00399       /* End of normalize */
00400       pivot=i;
00401       for (i=0;i<NbRows;i++)    /* Zero out the rest of the column */
00402         if (i!=Rank) {
00403           if (value_notzero_p(Mat1->p[i][j])) {
00404             Value a, a1, a2, a1abs, a2abs;
00405             value_init(a); value_init(a1); value_init(a2);
00406             value_init(a1abs); value_init(a2abs);
00407             value_assign(a1,Mat1->p[i][j]);
00408             value_absolute(a1abs,a1);
00409             value_assign(a2,Mat1->p[Rank][j]); 
00410             value_absolute(a2abs,a2);
00411             Gcd(a1abs,a2abs,&a);
00412             value_division(a1,a1,a);
00413             value_division(a2,a2,a);
00414             value_oppose(a1,a1);
00415             Vector_Combine(Mat1->p[i],Mat1->p[Rank],Mat1->p[i],a2, 
00416                            a1,NbCols);
00417             Vector_Normalize(Mat1->p[i],NbCols);
00418             value_clear(a); value_clear(a1); value_clear(a2);
00419             value_clear(a1abs); value_clear(a2abs);
00420           }
00421         }
00422       column_index[Rank]=j;
00423       Rank++;
00424     }
00425   } /* end of Gauss elimination */
00426 
00427 
00428   if (Mat2) {  /* Mat2 is a transformation matrix  (i,j->f(i,j))....
00429                   can't scale it because can't scale both sides of -> */
00430     /* normalizes an affine transformation        */
00431     /* priority of forms                          */
00432     /*    1. i' -> i                (identity)    */
00433     /*    2. i' -> i + constant     (uniform)     */
00434     /*    3. i' -> constant         (broadcast)   */
00435     /*    4. i' -> j                (permutation) */
00436     /*    5. i' -> j + constant     (      )      */
00437     /*    6. i' -> i + j + constant (non-uniform) */
00438     for (k=0; k<Rank; k++) {
00439       j = column_index[k];
00440       for (i=0; i<(Mat2->NbRows-1);i++) {   /* all but the last row 0...0 1 */
00441         if ((i!=j) && value_notzero_p(Mat2->p[i][j])) {
00442           
00443           /* Remove dependency of i' on j */
00444           Value a, a1, a1abs, a2, a2abs;
00445           value_init(a); value_init(a1); value_init(a2);
00446           value_init(a1abs); value_init(a2abs);
00447           value_assign(a1,Mat2->p[i][j]);
00448           value_absolute(a1abs,a1);
00449           value_assign(a2,Mat1->p[k][j]);
00450           value_absolute(a2abs,a2);
00451           Gcd(a1abs,a2abs,&a);
00452           value_division(a1,a1,a);
00453           value_division(a2,a2,a);
00454           value_oppose(a1,a1);
00455           if (value_one_p(a2)) {
00456             Vector_Combine(Mat2->p[i],Mat1->p[k],Mat2->p[i],a2,
00457                            a1,NbCols);
00458             
00459             /* Vector_Normalize(Mat2->p[i],NbCols); -- can't do T        */
00460           } /* otherwise, can't do it without mult lhs prod (2i,3j->...) */
00461           value_clear(a); value_clear(a1); value_clear(a2);
00462           value_clear(a1abs); value_clear(a2abs);
00463                 
00464         }
00465         else if ((i==j) && value_zero_p(Mat2->p[i][j])) {
00466           
00467           /* 'i' does not depend on j */
00468           for (n=j+1; n < (NbCols-1); n++) {
00469             if (value_notzero_p(Mat2->p[i][n])) { /* i' depends on some n */
00470               value_set_si(tmp,1);
00471               Vector_Combine(Mat2->p[i],Mat1->p[k],Mat2->p[i],tmp,
00472                              tmp,NbCols);
00473               break;
00474             }  /* if 'i' depends on just a constant, then leave it alone.*/
00475           }
00476         }
00477       }
00478     }
00479     
00480     /* Check last row of transformation Mat2 */
00481     for (j=0; j<(NbCols-1); j++)
00482       if (value_notzero_p(Mat2->p[Mat2->NbRows-1][j])) {
00483         errormsg1("GaussSimplify", "corrtrans", "Corrupted transformation\n");
00484         break;
00485       }
00486     
00487     if (value_notone_p(Mat2->p[Mat2->NbRows-1][NbCols-1])) {
00488       errormsg1("GaussSimplify", "corrtrans", "Corrupted transformation\n");
00489     }
00490   }
00491   value_clear(gcd); value_clear(tmp);
00492   free(column_index);
00493   return Rank;
00494 } /* GaussSimplify */
00495 
00496 /* 
00497  * Topologically sort 'n' polyhdera and return 0 on failure, otherwise return 
00498  * 1 on success. Here 'L' is a an array of pointers to polyhedra, 'n' is the 
00499  * number of polyhedra, 'index' is the level to consider for partial ordering
00500  * 'pdim' is the parameter space dimension, 'time' is an array of 'n' integers
00501  * to store logical time values, 'pvect', if not NULL, is an array of 'n' 
00502  * integers that contains a permutation specification after call and MAXRAYS is
00503  * the workspace size for polyhedra operations. 
00504  */
00505 int PolyhedronTSort (Polyhedron **L,unsigned int n,unsigned int index,unsigned int pdim,int *time,int *pvect,unsigned int MAXRAYS) {
00506  
00507   unsigned int const nbcells = ((n*(n-1))>>1);    /* Number of memory cells 
00508                                                      to allocate, see below */
00509   int *dag;  /* The upper triangular matrix */
00510   int **p;   /* Array of matrix row addresses */
00511   unsigned int i, j, k;
00512   unsigned int t, nb, isroot;
00513 
00514   if (n<2) return 0;
00515 
00516   /* we need an upper triangular matrix (example with n=4):
00517 
00518      . o o o
00519      . . o o     . are unuseful cells, o are useful cells
00520      . . . o
00521      . . . .
00522      
00523      so we need to allocate (n)(n-1)/2 cells
00524      - dag will point to this memory.
00525      - p[i] will point to row i of the matrix
00526      p[0] = dag - 1 (such that p[0][1] == dag[0])
00527      p[1] = dag - 1 + (n-1)
00528      p[2] = dag - 1 + (n-1) + (n-2)
00529      ...
00530      p[i] = p[i-1] + (n-1-i)
00531   */
00532 
00533   /* malloc n(n-1)/2 for dag and n-1 for p (node n does not have any row) */
00534   dag = (int *) malloc(nbcells*sizeof(int));
00535   if (!dag) return 0;
00536   p = (int **) malloc ((n-1) * sizeof(int *));
00537   if (!p) { 
00538     free(dag); return 0; 
00539   }
00540 
00541   /* Initialize 'p' and 'dag' */
00542   p[0] = dag-1;
00543   for (i=1; i<n-1; i++)
00544     p[i] = p[i-1] + (n-1)-i;
00545   for (i=0; i<nbcells; i++)
00546     dag[i] = -2;      /* -2 means 'not computed yet' */
00547   for (i=0; i<n; i++) time[i] = -1;
00548 
00549   /* Compute the dag using transitivity to reduce the number of */
00550   /*   PolyhedronLTQ calls.                                     */
00551   for (i=0; i<n-1; i++) {
00552     for (j=i+1; j<n; j++) {
00553       if (p[i][j] == -2) /* not computed yes */
00554         p[i][j] = PolyhedronLTQ(L[i], L[j], index, pdim, MAXRAYS);
00555       if (p[i][j] != 0) {
00556         
00557         /* if p[i][j] is 1 or -1, look for -p[i][j] on the same row:
00558            p[i][j] == -p[i][k] ==> p[j][k] = p[i][k] (transitivity)
00559            note: p[r][c] == -p[c][r], use this to avoid reading or writing
00560            under the matrix diagonal
00561         */  
00562            
00563         /* first, k<i so look for p[i][j] == p[k][i] (i.e. -p[i][k]) */
00564         for (k=0; k<i; k++)
00565           if (p[k][i] == p[i][j]) p[k][j] = p[k][i];
00566         
00567         /* then, i<k<j so look for p[i][j] == -p[i][k] */
00568         for (k=i+1; k<j; k++)
00569           if (p[i][k] == -p[i][j]) p[k][j] = -p[i][k];
00570         
00571         /* last, k>j same search but */
00572         for (k=j+1; k<n; k++)
00573           if (p[i][k] == -p[i][j]) p[j][k] = p[i][k];
00574       }
00575     }
00576   }
00577   
00578   /* walk thru the dag to compute the partial order (and optionally
00579      the permutation)
00580      Note: this is not the fastest way to do it but it takes
00581      negligible time compared to a single call of PolyhedronLTQ !
00582      Each macro-step (while loop) gives the same logical time to all
00583      found roots and optionally add these nodes in the permutation vector
00584   */ 
00585   
00586   t = 0; /* current logical time, assigned to current roots and
00587             increased by 1 at the end of each step */
00588   nb = 0; /* number of processed nodes (have been given a time) */
00589   while (nb<n) {
00590     for (i=0; i<n; i++) { /* search for roots */
00591       /* for any node, if it's not already been given a logical time
00592          then walk thru the node row; if we find a 1 at some column j,
00593          it means that node j preceeds the current node, so it is not
00594          a root */
00595       if (time[i]<0) {
00596         isroot = 1; /* assume that it is until it is definitely not */
00597         /* first search on a column */
00598         for (j=0; j<i; j++) {
00599           if (p[j][i]==-1) { /* found a node lower than it */
00600             isroot = 0; break;
00601           }
00602         }
00603         if /*still*/ (isroot)
00604           for (j=i+1; j<n; j++) {
00605             if (p[i][j]==1) { /* greater than this node */
00606               isroot = 0; break;
00607             }
00608           }
00609         if (isroot) { /* then it definitely is */
00610           time[i] = t; /* this node gets current logical time */
00611           if (pvect)
00612             pvect[nb] = i+1; /* nodes will be numbered from 1 to n */
00613           nb++; /* one more node processed */
00614         }
00615       }
00616     }
00617     /* now make roots become neutral, i.e. non comparable with all other nodes */
00618     for (i=0; i<n; i++) {
00619       if (time[i]==t) {
00620         for (j=0; j<i; j++)
00621           p[j][i] = 0;
00622         for (j=i+1; j<n; j++)
00623           p[i][j] = 0;
00624       }
00625     }
00626     t++; /* ready for next set of root nodes */
00627   }
00628   
00629   free (p);   /* let's be clean, collect the garbage */
00630   free (dag);
00631   return 1;
00632 } /* PolyhedronTSort */
00633 
00634 
00635 
00636 

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