1 /***********************************************************************/
2 /* Parametrized polyhedra V4.20 */
3 /* copyright 1995-2000 Vincent Loechner */
4 /* copyright 1996-1997, Doran Wilde */
5 /* Permission is granted to copy, use, and distribute */
6 /* for any commercial or noncommercial purpose under the terms */
7 /* of the GNU General Public license, version 2, June 1991 */
8 /* (see file : LICENSING). */
9 /***********************************************************************/
11 /********************* -----------USER #DEFS-------- ***********************/
12 /* These are mainly for debug purposes. You shouldn't need to change */
13 /* anything for daily usage... */
14 /***************************************************************************/
16 /* you may define each macro independently */
18 /* #define DEBUGPP3 */ /* initialization of domain, context, ... */
19 /* #define DEBUGPP31 */ /* even more init-domains */
20 /* #define DEBUGPP32 */ /* even even more... (Elim_Columns) */
21 /* #define DEBUGPP4 */ /* m-faces scan */
22 /* #define DEBUGPP41 */ /* inverse Di in scan */
23 /* #define DEBUGPP5 */ /* Compute_PDomains */
24 /********************* ---------END USER #DEFS------ ***********************/
34 #include <polylib/polylib.h>
36 static void traite_m_face(Polyhedron
*, unsigned int *, unsigned int *);
37 static void scan_m_face(int,int,Polyhedron
*,unsigned int *);
40 * Return the intersection of two polyhedral domains 'Pol1' and 'Pol2' such
41 * that if the intersection is a polyhedron of lower dimension (a degenerate
42 * polyhedron) than the operands, it is discarded from the resulting polyhedra
45 Polyhedron
*PDomainIntersection(Polyhedron
*Pol1
,Polyhedron
*Pol2
,unsigned NbMaxRays
) {
47 Polyhedron
*p1
, *p2
, *p3
, *d
;
49 if (!Pol1
|| !Pol2
) return (Polyhedron
*) 0;
50 if((Pol1
->Dimension
!= Pol2
->Dimension
) || (Pol1
->NbEq
!= Pol2
->NbEq
)) {
52 "? PDomainIntersection: operation on different dimensions\n");
53 return (Polyhedron
*) 0;
56 POL_ENSURE_FACETS(Pol1
);
57 POL_ENSURE_VERTICES(Pol1
);
58 POL_ENSURE_FACETS(Pol2
);
59 POL_ENSURE_VERTICES(Pol2
);
62 for (p1
=Pol1
; p1
; p1
=p1
->next
) {
63 for (p2
=Pol2
; p2
; p2
=p2
->next
) {
64 p3
= AddConstraints(p2
->Constraint
[0],
65 p2
->NbConstraints
,p1
,NbMaxRays
);
68 /* If the new polyhedron 'p3' has lower dimension, discard it */
69 if (p3
->NbEq
!=Pol1
->NbEq
)
72 /* Otherwise add it to the new polyhderal domain 'd'. */
74 d
= AddPolyToDomain(p3
,d
);
78 } /* PDomainIntersection */
81 * Given polyhderal domains 'Pol1' and 'Pol2', return the difference of the
82 * two domains with a modification that the resulting polyhedra in the new
83 * domain don't have a 1 unit space around cut and the degenerate results
84 * (of smaller dimension) are discarded.
86 Polyhedron
*PDomainDifference(Polyhedron
*Pol1
,Polyhedron
*Pol2
,unsigned NbMaxRays
) {
88 Polyhedron
*p1
, *p2
, *p3
, *d
;
92 return (Polyhedron
*) 0;
93 if((Pol1
->Dimension
!= Pol2
->Dimension
) || (Pol1
->NbEq
!= Pol2
->NbEq
)) {
95 "? PDomainDifference: operation on different dimensions\n");
96 return (Polyhedron
*) 0;
99 POL_ENSURE_FACETS(Pol1
);
100 POL_ENSURE_VERTICES(Pol1
);
101 POL_ENSURE_FACETS(Pol2
);
102 POL_ENSURE_VERTICES(Pol2
);
105 for (p2
=Pol2
; p2
; p2
=p2
->next
) {
106 for (p1
=Pol1
; p1
; p1
=p1
->next
) {
107 for (i
=0; i
<p2
->NbConstraints
; i
++) {
109 /* Add the constraint (-p2->Constraint[i]) >= 0 in 'p1' */
110 p3
= SubConstraint(p2
->Constraint
[i
],p1
,NbMaxRays
,2);
113 /* If the new polyhedron 'p3' is empty or is a polyhedron of lower */
114 /* dimension, discard it. */
115 if (emptyQ(p3
) || p3
->NbEq
!=Pol1
->NbEq
)
118 /* Otherwise add 'p3' to the new polyhderal domain 'd' */
120 d
= AddPolyToDomain(p3
,d
);
129 } /* PDomainDifference */
132 * Return 1 if matrix 'Mat' is full column ranked, otherwise return 0.
134 static int TestRank(Matrix
*Mat
) {
137 Value m1
,m2
,m3
,gcd
,tmp
;
139 /* Initialize all the 'Value' variables */
140 value_init(m1
); value_init(m2
);
141 value_init(m3
); value_init(gcd
); value_init(tmp
);
143 for(k
=0;k
<Mat
->NbColumns
;++k
) {
145 /* If the digonal entry (k,k) is zero, search down the column(k) */
146 /* starting from row(k) to find a non-zero entry */
147 if(value_zero_p(Mat
->p
[k
][k
])) {
148 for(j
=k
+1;j
<Mat
->NbRows
;++j
) {
150 /* If a non-zero entry (j,k) is found */
151 if(value_notzero_p(Mat
->p
[j
][k
])) {
153 /* Exchange row(k) and row(j) */
154 for(i
=k
;i
<Mat
->NbColumns
;++i
) {
155 value_assign(tmp
,Mat
->p
[j
][i
]);
156 value_assign(Mat
->p
[j
][i
],Mat
->p
[k
][i
]);
157 value_assign(Mat
->p
[k
][i
],tmp
);
163 /* If no non-zero entry is found then the matrix 'Mat' is not full */
164 /* ranked. Return zero. */
167 /* Clear all the 'Value' variables */
168 value_clear(m1
); value_clear(m2
);
169 value_clear(m3
); value_clear(gcd
); value_clear(tmp
);
174 /* Now Mat[k][k] is the pivot element */
175 for(j
=k
+1;j
<Mat
->NbRows
;++j
) {
177 /* Make every other entry (below row(k)) in column(k) zero */
178 value_gcd(gcd
, Mat
->p
[j
][k
], Mat
->p
[k
][k
]);
179 for(i
=k
+1;i
<Mat
->NbColumns
;++i
) {
181 /* pour tous les indices i > k */
182 value_multiply(m1
,Mat
->p
[j
][i
],Mat
->p
[k
][k
]);
183 value_multiply(m2
,Mat
->p
[j
][k
],Mat
->p
[k
][i
]);
184 value_subtract(m3
,m1
,m2
);
185 value_division(Mat
->p
[j
][i
],m3
,gcd
);
190 /* Clear all the 'Value' variables */
191 value_clear(m1
); value_clear(m2
);
192 value_clear(m3
); value_clear(gcd
); value_clear(tmp
);
194 /* The matrix 'Mat' is full ranked, return 1 */
199 * The Saturation matrix is defined to be an integer (int type) matrix. It is
200 * a boolean matrix which has a row for every constraint and a column for
201 * every line or ray. The bits in the binary format of each integer in the
202 * saturation matrix stores the information whether the corresponding constr-
203 * aint is saturated by ray(line) or not.
207 unsigned int NbColumns
;
209 unsigned int *p_init
;
212 static SatMatrix
*SMAlloc(int rows
,int cols
) {
214 unsigned int **q
, *p
;
217 SatMatrix
*result
= (SatMatrix
*)malloc(sizeof(SatMatrix
));
218 assert (result
!= NULL
);
220 result
->NbRows
= rows
;
221 result
->NbColumns
= cols
;
222 result
->p
= q
= (unsigned int **)malloc(rows
* sizeof(unsigned int *));
223 assert (result
->p
!= NULL
);
224 result
->p_init
= p
= (unsigned int *)malloc(rows
* cols
* sizeof(unsigned int));
225 assert (result
->p_init
!= NULL
);
227 for (i
=0;i
<rows
;i
++) {
235 static void SMPrint (SatMatrix
*matrix
) {
239 unsigned NbRows
, NbColumns
;
241 fprintf(stderr
,"%d %d\n",NbRows
=matrix
->NbRows
, NbColumns
=matrix
->NbColumns
);
242 for (i
=0;i
<NbRows
;i
++) {
244 for (j
=0;j
<NbColumns
;j
++)
245 fprintf(stderr
, " %10X ", *p
++);
246 fprintf(stderr
, "\n");
251 static void SMFree (SatMatrix
*matrix
) {
253 free ((char *) matrix
->p_init
);
254 free ((char *) matrix
->p
);
255 free ((char *) matrix
);
259 /* -------------------------------------------------------------------------
260 * Shared Global Variables:
261 * Used by procedures: Find_m_face, scan_m_face, Poly2Sat, traite_m_face,
263 * -------------------------------------------------------------------------
265 static int m
; /* number of parameters */
266 static int m_dim
; /* dimension of m-face */
267 static int n
; /* dimension (not including parameters) */
268 static int ws
; /* Working Space size */
269 static int nr
; /* (NbRays-1)/32 + 1 */
271 static Polyhedron
*CEqualities
;/* Equalities in the context */
272 static SatMatrix
*Sat
; /* Saturation Matrix (row=constraint, col=ray)*/
273 static unsigned int *egalite
; /* Bool vector marking constraints in m-face */
274 static Matrix
*Xi
, *Pi
; /* Xi and Pi */
275 static Matrix
*PiTest
; /* Matrix used to test if Pi is full ranked? */
276 static Matrix
*CTest
;
277 static Matrix
*PiInv
; /* Matrix inverse Pi, with the last col of */
278 /* each line = denominator of the line */
279 static Matrix
*RaysDi
; /* Constraint matrix for computing Di */
281 static int KD
; /* Flag : keep the full domains in memory ? */
282 /* 1 = yes; 0 = no, keep constraints only */
284 static int nbPV
; /* The number of parameterized vertices */
285 static Param_Vertices
*PV_Result
; /* List of parameterized vertices */
286 static Param_Domain
*PDomains
; /* List of domains. */
293 * Add the constraints from the context polyhedron 'CEqualities' to the
294 * constraints of polyhedra in the polyhedral domain 'D' and return the new
295 * polyhedral domain. Polyhedral domain 'D' is subsequently deleted from memory
297 static Polyhedron
*Add_CEqualities(Polyhedron
*D
) {
299 Polyhedron
*d
,*r
,*tmp
;
304 if(!D
|| emptyQ(D
)) {
307 return(Polyhedron_Copy(CEqualities
));
309 r
= AddConstraints(D
->Constraint
[0],D
->NbConstraints
,
312 for(d
=D
->next
;d
;d
=d
->next
) {
313 tmp
->next
= AddConstraints(d
->Constraint
[0],d
->NbConstraints
,
320 } /* Add_CEqualities */
322 #define INT_BITS (sizeof(unsigned) * 8)
324 unsigned int *int_array2bit_vector(unsigned int *array
, int n
)
328 int words
= (n
+INT_BITS
-1)/INT_BITS
;
329 unsigned int *bv
= (unsigned int *)calloc(words
, sizeof(unsigned));
331 for (i
= 0, ix
= 0, bx
= MSB
; i
< n
; ++i
) {
339 /*----------------------------------------------------------------------*/
341 /* Given an m-face, compute the parameterized vertex */
342 /* D - The entire domain */
343 /* mf - Bit vector marking the lines/rays in the m-face */
344 /* egalite - boolean vector marking saturated constraints in m-face */
345 /*----------------------------------------------------------------------*/
346 static void traite_m_face(Polyhedron
*D
, unsigned int *mf
,
347 unsigned int *egalite
)
349 Matrix
*Si
; /* Solution */
350 Polyhedron
*PDi
; /* polyhedron Di */
359 /* Extract Xi, Pi, and RaysDi from D */
361 for(k
=0,c
=0,kx
=0,bx
=MSB
;k
<D
->NbRays
;++k
) {
362 if(mf
[kx
]&bx
) { /* this ray is in the current m-face */
366 /* tester si cette nouvelle colonne est lin. indep. des autres */
367 /* i.e. si gauss ne donne pas de '0' sur la colonne Pi */
368 /* jusqu'a l'indice 'c' */
370 /* construit PiTest */
374 /* les c premieres colonnes */
375 value_assign(PiTest
->p
[j
][i
],Pi
->p
[j
][i
]);
378 value_assign(PiTest
->p
[j
][c
],D
->Ray
[k
][j
+1+n
]);
380 PiTest
->NbColumns
= c
+1;
381 r
= TestRank(PiTest
);
382 if(r
/* TestRank(PiTest) */) {
384 /* Ok, c'est lin. indep. */
386 value_assign(Xi
->p
[j
][c
],D
->Ray
[k
][j
+1]); /* Xi */
388 value_assign(Pi
->p
[j
][c
],D
->Ray
[k
][j
+1+n
]); /* Pi */
389 value_assign(Xi
->p
[n
][c
],D
->Ray
[k
][n
+m
+1]); /* const */
390 value_assign(Pi
->p
[m
][c
],D
->Ray
[k
][n
+m
+1]); /* const */
396 value_assign(RaysDi
->p
[RaysDi
->NbRows
][0],D
->Ray
[k
][0]);
397 Vector_Copy(&D
->Ray
[k
][n
+1],&RaysDi
->p
[RaysDi
->NbRows
][1],(m
+1));
404 fprintf(stderr
, "\nRaysDi=\n");
405 Matrix_Print(stderr
,P_VALUE_FMT
,RaysDi
);
407 fprintf(stderr
, "Invalid ");
408 fprintf(stderr
, "Pi=\n");
409 Matrix_Print(stderr
,P_VALUE_FMT
,Pi
);
414 fprintf(stderr
,"Eliminated because of no vertex\n");
420 /* RaysDi->numColumns = m+2; */ /* stays the same */
422 /* Xi->NbColumns = m+1;*/ /* VIN100: stays the same. was 'c'! */
423 /* Xi->NbRows = n+1; */ /* stays the same */
424 /* Pi->NbColumns = m+1;*/ /* VIN100: stays the same. was 'c'! */
425 /* Pi->NbRows = m+1; */ /* stays the same */
428 fprintf(stderr
,"Xi = ");
429 Matrix_Print(stderr
,P_VALUE_FMT
,Xi
);
430 fprintf(stderr
,"Pi = ");
431 Matrix_Print(stderr
,P_VALUE_FMT
,Pi
);
434 /* (Right) invert Pi if POSSIBLE, if not then next m-face */
435 /* Pi is destroyed */
436 if(!MatInverse(Pi
,PiInv
)) {
439 fprintf(stderr
, "Eliminated because of no inverse Pi\n");
446 fprintf(stderr
,"FACE GENERATED!\n");
447 fprintf(stderr
,"PiInv = ");
448 Matrix_Print(stderr
,P_VALUE_FMT
,PiInv
);
451 /* Compute Si (now called Ti in the paper) */
452 Si
= Matrix_Alloc(Xi
->NbRows
,PiInv
->NbColumns
);
453 rat_prodmat(Si
,Xi
,PiInv
);
456 fprintf(stderr
,"Si = ");
457 Matrix_Print(stderr
,P_VALUE_FMT
,Si
);
460 Si
->NbRows
--; /* throw out the last row = 0 ... 0 1 */
462 /* Copy all of that into the PV structure */
463 PV
= (Param_Vertices
*) malloc(sizeof(Param_Vertices
));
464 PV
->next
= PV_Result
;
467 PV
->Facets
= int_array2bit_vector(egalite
, D
->NbConstraints
);
469 nbPV
++; /* increment vertex count */
471 /* Ok... now compute the parameter domain */
472 PDi
= Rays2Polyhedron(RaysDi
,ws
);
475 fprintf(stderr
,"RaysDi = ");
476 Matrix_Print(stderr
,P_VALUE_FMT
,RaysDi
);
477 fprintf(stderr
,"PDi = ");
478 Polyhedron_Print(stderr
,P_VALUE_FMT
,PDi
);
483 /* Add the equalities again to the domain */
484 PDi
= Add_CEqualities(PDi
);
485 PV
->Domain
= Polyhedron2Constraints(PDi
);
486 Polyhedron_Free(PDi
);
490 PD
= (Param_Domain
*) malloc(sizeof(Param_Domain
));
497 } /* traite_m_face */
499 /*----------------------------------------------------------------------*/
501 /* count the number of saturated rays in the bit vector mf */
502 /* Uses nr from global area */
503 /*----------------------------------------------------------------------*/
504 int cntbit
[256] = { /* counts for 8 bits */
505 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
506 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
507 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
508 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
510 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
511 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
512 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
513 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
515 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
516 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
517 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
518 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
520 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
521 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
522 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
523 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 };
525 static int count_sat (unsigned int *mf
) {
527 register unsigned int i
, tmp
, cnt
=0;
529 for (i
=0; i
<nr
; i
++) {
532 + cntbit
[ tmp
& 0xff ]
533 + cntbit
[ (tmp
>>8) & 0xff ]
534 + cntbit
[ (tmp
>>16) & 0xff ]
535 + cntbit
[ (tmp
>>24) & 0xff ]
541 /* Returns true if all bits in part are also set in bv */
542 static int bit_vector_includes(unsigned int *bv
, int len
, unsigned int *part
)
546 for (j
= 0; j
< len
; j
++) {
548 fprintf(stderr
, "mf=%08X Sat=%08X &=%08X\n",
549 part
[j
],bv
[j
], (part
[j
] & bv
[j
]));
551 if ((part
[j
] & bv
[j
]) != part
[j
])
557 /*----------------------------------------------------------------------*/
558 /* let D + E + L be the dimension of the polyhedron */
559 /* D = Dimension of polytope (ray space) */
560 /* L = Dimension of Lineality space (number of lines, bid) */
561 /* E = Dimension of Affine hull (number of equations) */
562 /* n = number of data indices */
563 /* m = number of parameters */
565 /* n + m = D + E + L */
566 /* projected domains: */
567 /* m = D_m + E_m + L_m */
568 /* n = D_n + E_n + L_n */
569 /* What dimension M-face, when projected onto parameter space, */
570 /* will give an L_m-face? */
571 /* What are the conditions? */
572 /* - at least one vertex */
573 /* - number of rays >= D_m+1 after removal of redundants */
575 /* dim of face nb saturated constraints nb saturated lines,rays */
576 /* ----------- ------------------------ ----------------------- */
577 /* (0+L)-face all E eqns + >=D ineq all L lines + 1 ray */
578 /* (M+L)-face all E eqns + >=(D-M) ineq all L lines + >=(M+1) rays */
579 /* (D+L)-face all E eqns + 0 ineq all L lines + >=(D+1) rays */
580 /*----------------------------------------------------------------------*/
581 /*----------------------------------------------------------------------*/
583 /* pos : the next candidate constraint position */
584 /* nb_un : number of saturated constraints needed to finish a face */
585 /* D : the source polyhedron (context included ) */
586 /* mf : bit-array marking rays which are saturated so far */
587 /* From Global area: */
588 /* ---------------- */
589 /* n : number of data indices */
590 /* m : number of parameters */
591 /* egalite : boolean vector marking saturated constraints in m-face */
592 /* Sat : Saturation Matrix (row=constraints, col=rays) */
593 /* ws : working space size */
594 /* nr : (NbRays-1)/32 + 1 */
596 /* Recursive function to find the rays and vertices of each m-face */
597 /*----------------------------------------------------------------------*/
598 static void scan_m_face(int pos
,int nb_un
,Polyhedron
*D
,unsigned int *mf
) {
599 /* pos - the next candidate constraint position */
600 /* nb_un - the number of constraints needed to finish a face */
601 /* D - the source polyhedron */
602 /* mf - (bit vector) marks rays that are saturated so far */
604 unsigned int *new_mf
;
607 fprintf(stderr
,"Start scan_m_face(pos=%d, nb_un=%d, n=%d, m=%d\n",
609 fprintf(stderr
,"mf = ");
613 fprintf(stderr
,"%08X", mf
[i
]);
614 fprintf(stderr
,"\nequality = [");
615 for(i
=0;i
<D
->NbConstraints
;i
++)
616 fprintf(stderr
," %1d",egalite
[i
]);
617 fprintf(stderr
,"]\n");
621 if(nb_un
== 0) { /* Base case */
624 /*********** ELIMINATION OF REDUNDANT FACES ***********/
625 /* if all these vertices also verify a previous constraint */
626 /* which is NOT already selected, we eliminate this face */
627 /* This keeps the lexicographically greatest selection */
631 continue; /* already selected */
633 /* if Sat[i] & mf == mf then it's redundant */
635 fprintf(stderr
, "Sat[%d]\n", i
);
637 if (bit_vector_includes(Sat
->p
[i
], nr
, mf
)) {
639 fprintf(stderr
, "Redundant with constraint %d\n", i
);
641 return; /* it is redundant */
644 /********* END OF ELIMINATION OF DEGENERATE FACES *********/
645 /* Now check for other constraints that are verified */
646 for (i
= pos
; i
< D
->NbConstraints
; ++i
) {
647 if (bit_vector_includes(Sat
->p
[i
], nr
, mf
))
650 /* if we haven't found a constraint verified by all */
651 /* the rays, its OK, it's a new face. */
652 traite_m_face(D
, mf
, egalite
);
653 for (i
= pos
; i
< D
->NbConstraints
; ++i
)
658 /* See if there are enough constraints left to finish */
659 if((pos
+nb_un
)>D
->NbConstraints
) return;
661 /* Recurring part of the procedure */
662 /* Add the pos'th constraint, compute new saturation vector */
665 new_mf
= (unsigned int *)malloc(nr
*sizeof(unsigned int));
667 new_mf
[k
] = mf
[k
] & Sat
->p
[pos
][k
];
670 fprintf(stderr
,"new_mf = ");
674 fprintf(stderr
,"%08X", new_mf
[i
]);
676 fprintf(stderr
,"\ncount(new_mf) = %d\n",count_sat(new_mf
));
682 c
= count_sat(new_mf
);
683 /* optimization : at least m_dim+1 rays must be saturated to add this constraint */
688 egalite
[pos
]=1; /* Try it with the pos-th constraint */
690 /* If this constraint does not change anything,
691 * it is redundant with respect to the selected
692 * equalities and the remaining inequalities.
693 * Check whether it is redundant with respect
694 * to just the selected equalities.
696 if( c
==count_sat(mf
) ) {
699 for (i
= 0, c
= 0; i
< D
->NbConstraints
; ++i
) {
700 if (egalite
[i
] == 0 || egalite
[i
] == -1)
702 for (j
= 0; j
< D
->Dimension
+1; ++j
)
703 value_assign(CTest
->p
[j
][c
],
704 D
->Constraint
[i
][j
+1]);
707 CTest
->NbColumns
= c
;
709 Matrix_Print(stderr
,P_VALUE_FMT
,CTest
);
711 redundant
= !TestRank(CTest
);
714 /* Do not decrement nb_un if equality is redundant. */
717 egalite
[pos
]=-1; /* Don't use in further redundance test
719 scan_m_face(pos
+1,nb_un
,D
,new_mf
);
723 scan_m_face(pos
+1,nb_un
-1,D
,new_mf
);
728 egalite
[pos
]=0; /* Try it without the pos-th constraint */
729 if ((pos
+nb_un
)>=D
->NbConstraints
) return;
730 scan_m_face(pos
+1,nb_un
,D
,mf
);
735 * Create a saturation matrix with rows correspond to the constraints and
736 * columns correspond to the rays of the polyhedron 'Pol'. Global variable
737 * 'nr' is set in the function.
739 static SatMatrix
*Poly2Sat(Polyhedron
*Pol
,unsigned int **L
) {
744 Value
*p1
, *p2
, p3
,tmp
;
745 unsigned Dimension
, NbRay
, NbCon
, bx
;
747 /* Initialize all the 'Value' variables */
748 value_init(p3
); value_init(tmp
);
751 NbCon
= Pol
->NbConstraints
;
752 Dimension
= Pol
->Dimension
+1; /* Homogeneous Dimension */
754 /* Build the Sat matrix */
755 nr
= (NbRay
- 1)/(sizeof(int)*8) + 1; /* Set globally */
756 Sat
= SMAlloc(NbCon
,nr
);
757 Temp
= (unsigned int *)malloc(nr
*sizeof(unsigned int));
758 memset(Sat
->p_init
,0,nr
*NbCon
*sizeof(int));
759 memset(Temp
,0,nr
*sizeof(unsigned int));
761 for (k
=0; k
<NbRay
; k
++) {
762 for (i
=0; i
<NbCon
; i
++) {
763 p1
= &Pol
->Constraint
[i
][1];
764 p2
= &Pol
->Ray
[k
][1];
766 for (j
=0;j
<Dimension
;j
++) {
767 value_multiply(tmp
,*p1
,*p2
);
768 value_addto(p3
,p3
,tmp
);
771 if (value_zero_p(p3
))
778 /* Set 'L' to an array containing ones in every bit position of its */
782 /* Clear all the 'Value' variables */
783 value_clear(p3
); value_clear(tmp
);
789 * Create a parametrized polyhedron with zero parameters. This function was
790 * first written by Xavier Redon, and was later modified by others.
792 Param_Polyhedron
*GenParamPolyhedron(Polyhedron
*Pol
, Matrix
*Rays
)
794 Param_Polyhedron
*result
;
795 int nbRows
, nbColumns
;
799 nbColumns
=Pol
->Dimension
+2;
801 /* Count the number of rays */
802 for(i
=0, rays
=0; i
<nbRows
; i
++)
803 if(value_notone_p(Pol
->Ray
[i
][0]) ||
804 value_zero_p(Pol
->Ray
[i
][nbColumns
-1]))
807 /* Initialize the result */
808 result
=(Param_Polyhedron
*)malloc(sizeof(Param_Polyhedron
));
809 result
->nbV
=nbRows
-rays
;
811 result
->Constraints
= Polyhedron2Constraints(Pol
);
814 /* Build the parametric vertices */
815 for(i
=0;i
<nbRows
;i
++) {
817 Param_Vertices
*paramVertex
;
820 if (value_notone_p(Pol
->Ray
[i
][0]) ||
821 value_zero_p(Pol
->Ray
[i
][nbColumns
-1]))
824 vertex
=Matrix_Alloc(nbColumns
-2,2);
825 for(j
=1;j
<nbColumns
-1;j
++) {
826 value_assign(vertex
->p
[j
-1][0],Pol
->Ray
[i
][j
]);
827 value_assign(vertex
->p
[j
-1][1],Pol
->Ray
[i
][nbColumns
-1]);
829 paramVertex
=(Param_Vertices
*)malloc(sizeof(Param_Vertices
));
830 paramVertex
->Vertex
=vertex
;
832 /* There is one validity domain : universe of dimension 0 */
833 paramVertex
->Domain
=Matrix_Alloc(1,2);
834 value_set_si(paramVertex
->Domain
->p
[0][0],1);
835 value_set_si(paramVertex
->Domain
->p
[0][1],1);
836 paramVertex
->Facets
= NULL
;
837 paramVertex
->next
=result
->V
;
838 result
->V
=paramVertex
;
841 /* Build the parametric domains (only one here) */
843 size
=(nbRows
-1)/(8*sizeof(int))+1;
846 result
->D
=(Param_Domain
*)malloc(sizeof(Param_Domain
));
847 result
->D
->next
=NULL
;
848 result
->D
->Domain
=Universe_Polyhedron(0);
849 result
->D
->F
=(unsigned int *)malloc(size
*sizeof(int));
850 memset(&result
->D
->F
[0],0xFF,size
*sizeof(int));
853 } /* GenParamPolyhedron */
856 /*----------------------------------------------------------------------*/
857 /* PreElim_Columns */
858 /* function being called before Elim_Columns */
859 /* Equalities in E are analysed to initialize ref and p. */
860 /* These two vectors are used to construct the new constraint matrix */
861 /* PreElim_Columns returns the transformation matrix to re-convert the */
862 /* resulting domains in the same format (by adding empty columns) */
863 /* in the parameter space */
864 /*----------------------------------------------------------------------*/
865 Matrix
*PreElim_Columns(Polyhedron
*E
,int *p
,int *ref
,int m
) {
870 /* find which columns to eliminate */
871 /* p contains, for each line in E, the column to eliminate */
872 /* (i.e. the corresponding parameter index to eliminate) */
873 /* 0 <= i <= E->NbEq, and 1 <= p[i] <= E->Dimension */
874 memset(p
,0,sizeof(int)*(E
->NbEq
));
877 fprintf(stderr
,"\n\nPreElim_Columns starting\n");
878 fprintf(stderr
,"E =\n");
879 Polyhedron_Print(stderr
,P_VALUE_FMT
,E
);
882 for(l
=0;l
<E
->NbEq
;++l
) {
883 if(value_notzero_p(E
->Constraint
[l
][0])) {
884 fprintf(stderr
,"Internal error: Elim_Columns (polyparam.c), expecting equalities first in E.\n");
888 for(i
=1;value_zero_p(E
->Constraint
[l
][i
]);++i
) {
889 if(i
==E
->Dimension
+1) {
890 fprintf(stderr
,"Internal error: Elim_Columns (polyparam.c), expecting non-empty constraint in E.\n");
898 fprintf(stderr
,"p[%d] = %d,",l
,p
[l
]);
902 /* Reference vector: column ref[i] in A corresponds to column i in M */
903 for(i
=0;i
<E
->Dimension
+2-E
->NbEq
;++i
) {
905 for(j
=0;j
<E
->NbEq
;++j
)
910 fprintf(stderr
,"ref[%d] = %d,",i
,ref
[i
]);
914 /* Size of T : phdim-nbEq * phdim */
915 T
= Matrix_Alloc(m
+1-E
->NbEq
,m
+1);
916 for(i
=0;i
<T
->NbColumns
;i
++)
917 for(j
=0;j
<T
->NbRows
;j
++)
918 if(ref
[E
->Dimension
-m
+j
+1] == E
->Dimension
-m
+i
+1)
919 value_set_si(T
->p
[j
][i
],1);
921 value_set_si(T
->p
[j
][i
],0);
924 fprintf(stderr
,"\nTransMatrix =\n");
925 Matrix_Print(stderr
,P_VALUE_FMT
,T
);
930 } /* PreElim_Columns */
932 /*----------------------------------------------------------------------*/
934 /* Eliminate columns from A, using the equalities in E. */
935 /* ref and p are precalculated by PreElim_Columns, using E; */
936 /* these two vectors are used to construct the new constraint matrix */
937 /*----------------------------------------------------------------------*/
938 Polyhedron
*Elim_Columns(Polyhedron
*A
,Polyhedron
*E
,int *p
,int *ref
) {
945 /* Initialize all the 'Value' variables */
946 value_init(tmp1
); value_init(tmp2
);
949 fprintf(stderr
,"\nElim_Columns starting\n");
950 fprintf(stderr
,"A =\n" );
951 Polyhedron_Print(stderr
,P_VALUE_FMT
,A
);
954 /* Builds M = constraint matrix of A, useless columns zeroed */
955 M
= Polyhedron2Constraints(A
);
956 for(l
=0;l
<E
->NbEq
;++l
) {
957 for(c
=0;c
<M
->NbRows
;++c
) {
958 if(value_notzero_p(M
->p
[c
][p
[l
]])) {
960 /* A parameter to eliminate here ! */
961 for(i
=1;i
<M
->NbColumns
;++i
) {
962 value_multiply(tmp1
,M
->p
[c
][i
],E
->Constraint
[l
][p
[l
]]);
963 value_multiply(tmp2
,E
->Constraint
[l
][i
],M
->p
[c
][p
[l
]]);
964 value_subtract(M
->p
[c
][i
],tmp1
,tmp2
);
971 fprintf(stderr
,"\nElim_Columns after zeroing columns of A.\n");
972 fprintf(stderr
,"M =\n");
973 Matrix_Print(stderr
,P_VALUE_FMT
,M
);
976 /* Builds C = constraint matrix, useless columns eliminated */
977 C
= Matrix_Alloc(M
->NbRows
,M
->NbColumns
- E
->NbEq
);
978 for(l
=0;l
<C
->NbRows
;++l
)
979 for(c
=0;c
<C
->NbColumns
;++c
) {
980 value_assign(C
->p
[l
][c
],M
->p
[l
][ref
[c
]]);
984 fprintf(stderr
,"\nElim_Columns after eliminating columns of A.\n");
985 fprintf(stderr
,"C =\n");
986 Matrix_Print(stderr
,P_VALUE_FMT
,C
);
989 R
= Constraints2Polyhedron(C
,ws
);
992 value_clear(tmp1
); value_clear(tmp2
);
997 static Polyhedron
*Recession_Cone(Polyhedron
*P
, unsigned nvar
, unsigned MaxRays
)
1000 Matrix
*M
= Matrix_Alloc(P
->NbConstraints
, 1 + nvar
+ 1);
1002 for (i
= 0; i
< P
->NbConstraints
; ++i
)
1003 Vector_Copy(P
->Constraint
[i
], M
->p
[i
], 1+nvar
);
1004 R
= Constraints2Polyhedron(M
, MaxRays
);
1009 /* Compute lines/unidirectional rays of the (non parametric) polyhedron */
1011 * D1 : combined polyhedron,
1013 * Rays : non parametric ray matrix
1014 * return value : number of lines
1016 static int ComputeNPLinesRays(int n
, Polyhedron
*D1
, Matrix
**Rays
)
1018 int i
, j
, nbr
, dimfaces
;
1019 Polyhedron
*RC
; /* Recession Cone */
1021 RC
= Recession_Cone(D1
, n
, ws
);
1023 /* get the rays/lines from RC */
1025 for (i
= 0; i
< RC
->NbRays
;i
++)
1026 if (value_zero_p(RC
->Ray
[i
][n
+1]))
1028 *Rays
=Matrix_Alloc(nbr
, n
+2);
1029 for (i
= 0, j
= 0; j
< nbr
;i
++)
1030 if (value_zero_p(RC
->Ray
[i
][n
+1]))
1031 Vector_Copy(RC
->Ray
[i
], (*Rays
)->p
[j
++], n
+2);
1033 dimfaces
= RC
->NbBid
;
1034 Polyhedron_Free(RC
);
1037 fprintf(stderr
, "Rays = ");
1038 Matrix_Print(stderr
, P_VALUE_FMT
, *Rays
);
1039 fprintf(stderr
, "dimfaces = %d\n", dimfaces
);
1046 * Given a polyhedron 'Di' in combined data and parameter space and a context
1047 * polyhedron 'C' representing the constraints on the parameter space, create
1048 * a list of parameterized vertices and assign values to global variables:
1049 * m,n,ws,Sat,egalite,mf,Xi,Pi,PiInv,RaysDi,CEqualities.
1051 Param_Polyhedron
*Find_m_faces(Polyhedron
**Di
,Polyhedron
*C
,int keep_dom
,int working_space
,Polyhedron
**CEq
,Matrix
**CT
) {
1056 *C1
, /* true context */
1057 *D1
; /* the combined polyhedron, including context C */
1058 Matrix
*Rays
, /* lines/rays (non parametric) */
1060 Param_Polyhedron
*res
;
1071 return (Param_Polyhedron
*) 0;
1075 n
= D
->Dimension
- m
;
1078 "Find_m_faces: ?%d parameters of a %d-polyhedron !\n",m
,n
);
1079 return (Param_Polyhedron
*) 0;
1082 return GenParamPolyhedron(D
,Matrix_Alloc(0,2));
1084 /* Add constraints from Context to D -> result in D1 */
1085 C1
= align_context(C
,D
->Dimension
,ws
);
1088 fprintf(stderr
,"m = %d\n",m
);
1089 fprintf(stderr
, "D = ");
1090 Polyhedron_Print(stderr
,P_VALUE_FMT
,D
);
1091 fprintf(stderr
,"C1 = ");
1092 Polyhedron_Print(stderr
,P_VALUE_FMT
,C1
);
1095 D1
= DomainIntersection(D
,C1
,ws
);
1098 fprintf(stderr
,"D1 = ");
1099 Polyhedron_Print(stderr
,P_VALUE_FMT
,D1
);
1107 Polyhedron_Free(D1
);
1111 /* Compute the true context C1 */
1112 /* M : lines in the direction of the first n indices (index space) */
1113 M
= Matrix_Alloc(n
, D1
->Dimension
+2);
1115 value_set_si(M
->p
[i
][i
+1],1);
1116 C1
= DomainAddRays(D1
,M
,ws
);
1120 fprintf(stderr
,"True context C1 = ");
1121 Polyhedron_Print(stderr
,P_VALUE_FMT
,C1
);
1124 dimfaces
= ComputeNPLinesRays(n
, D1
, &Rays
);
1126 /* CEqualities contains the constraints (to be added again later) */
1127 /* *CT is the transformation matrix to add the removed parameters */
1129 if (C1
->NbEq
== 0) {
1130 Polyhedron_Free(C1
);
1133 Polyhedron
*CEq1
, /* CEqualities, in homogeneous dim */
1134 *D2
; /* D1, (temporary) simplified */
1136 /* Remove equalities from true context C1 and from D1 */
1137 /* Compute CEqualities = matrix of equalities in C1, projected in */
1138 /* the parameter space */
1139 M
= Matrix_Alloc(C1
->NbEq
,m
+2);
1140 for(j
=0,i
=0;i
<C1
->NbEq
;++i
,++j
) {
1141 while(value_notzero_p(C1
->Constraint
[j
][0]))
1143 value_assign(M
->p
[i
][0],C1
->Constraint
[j
][0]);
1144 Vector_Copy(&C1
->Constraint
[j
][D
->Dimension
-m
+1],&M
->p
[i
][1],(m
+1));
1146 CEqualities
= Constraints2Polyhedron(M
,ws
);
1148 CEq1
= align_context(CEqualities
,D
->Dimension
,ws
);
1150 /* Simplify D1 and C1 (remove the equalities) */
1151 D2
= DomainSimplify(D1
,CEq1
,ws
);
1152 Polyhedron_Free(D1
);
1153 Polyhedron_Free(C1
);
1154 Polyhedron_Free(CEq1
);
1159 else { /* if( CT ) */
1160 Polyhedron
*CEq1
, /* CEqualities */
1161 *D2
; /* D1, (temporary) simplified */
1163 /* Suppress all useless constraints in parameter domain */
1164 /* when CT is not NULL (ehrhart) */
1165 /* Vin100, march 01 */
1167 M
= Matrix_Alloc(C1
->NbConstraints
,m
+2);
1168 for(i
=0;i
<C1
->NbConstraints
;++i
) {
1169 value_assign(M
->p
[i
][0],C1
->Constraint
[i
][0]);
1170 Vector_Copy(&C1
->Constraint
[i
][D
->Dimension
-m
+1],&M
->p
[i
][1],(m
+1));
1172 CEqualities
= Constraints2Polyhedron( M
, ws
);
1175 D2
= DomainSimplify(D1
,CEq1
,ws
);
1176 Polyhedron_Free(D1
);
1178 C1
= Universe_Polyhedron(D2
->Dimension
);
1180 /* if CT is not NULL, the constraints are eliminated */
1181 /* *CT will contain the transformation matrix to come back to the */
1182 /* original dimension (for a polyhedron, in the parameter space) */
1186 p
= (int *)malloc(sizeof(int)*(CEq1
->NbEq
));
1190 ref
= (int*) malloc(sizeof(int)*
1191 (CEq1
->Dimension
+2-CEq1
->NbEq
));
1192 *CT
= PreElim_Columns(CEq1
,p
,ref
,CEqualities
->Dimension
);
1193 D2
= Elim_Columns(D1
,CEq1
,p
,ref
);
1199 fprintf(stderr
,"D2\t Dim = %3d\tNbEq = %3d\tLines = %3d\n",
1200 D2
->Dimension
,D2
->NbEq
,D2
->NbBid
);
1201 C2
= Elim_Columns(C1
,CEq1
,p
,ref
);
1202 fprintf(stderr
,"C2\t Dim = %3d\tNbEq = %3d\tLines = %3d\n",
1203 C2
->Dimension
,C2
->NbEq
,C2
->NbBid
);
1204 Polyhedron_Free(C2
);
1207 Polyhedron_Free(D1
);
1208 Polyhedron_Free(C1
);
1214 fprintf(stderr
,"Polyhedron CEq = ");
1215 Polyhedron_Print(stderr
,P_VALUE_FMT
,*CEq
);
1216 fprintf(stderr
,"Matrix CT = ");
1217 Matrix_Print(stderr
,P_VALUE_FMT
,*CT
);
1220 Polyhedron_Free(CEq1
);
1221 CEqualities
= NULL
; /* don't simplify ! */
1225 /* return the new D1 too */
1228 return GenParamPolyhedron(D1
, Rays
);
1233 fprintf(stderr
,"Polyhedron D1 (D AND C) = ");
1234 Polyhedron_Print(stderr
,P_VALUE_FMT
, D1
);
1235 fprintf(stderr
,"Polyhedron CEqualities = ");
1236 if(CEqualities
) Polyhedron_Print(stderr
,P_VALUE_FMT
, CEqualities
);
1237 else fprintf(stderr
,"NULL\n");
1246 Polyhedron_Free(D1
);
1251 /* mf : a bit array indicating which rays are part of the m-face */
1252 /* Poly2Sat initializes mf to all ones */
1253 /* set global variable nr to size (number of words) of mf */
1254 Sat
= Poly2Sat(D1
,&mf
);
1257 fprintf(stderr
,"Sat = ");
1260 fprintf(stderr
,"mf = ");
1261 for (i
=0; i
<nr
; i
++)
1262 fprintf(stderr
,"%08X", mf
[i
]);
1263 fprintf(stderr
, "\n");
1266 /* A boolean array saying which constraints are part of the m-face */
1267 egalite
= (unsigned int *)malloc(sizeof(int)*D1
->NbConstraints
);
1268 memset(egalite
,0, sizeof(int)*D1
->NbConstraints
);
1270 for (i
=0; i
<D1
->NbEq
; i
++)
1273 Xi
= Matrix_Alloc(n
+1,m
+1);
1274 Pi
= Matrix_Alloc(m
+1,m
+1);
1275 PiTest
= Matrix_Alloc(m
+1,m
+1);
1276 CTest
= Matrix_Alloc(D
->Dimension
+1,D
->NbConstraints
);
1277 PiInv
= Matrix_Alloc(m
+1,m
+2);
1278 RaysDi
= Matrix_Alloc(D1
->NbRays
,m
+2);
1281 /* m_dim has to be increased by the dimension of the smallest faces
1282 * of the (non parametric) polyhedron
1286 /* if the smallest face is of smaller dimension than m_dim,
1287 * then increase m_dim (I think this should never happen --Vincent)
1290 if (m_dim
< D1
->NbBid
)
1291 fprintf(stderr
, "m_dim (%d) < D1->NbBid (%d)\n", m_dim
, D1
->NbBid
);
1293 if (m_dim
< D1
->NbBid
)
1300 fprintf(stderr
, "m_dim = %d\n", m_dim
);
1302 "Target: find faces that saturate %d constraints and %d rays/lines\n",
1303 D1
->Dimension
- m_dim
,m_dim
+1);
1306 /* D1->NbEq constraints already saturated ! */
1307 scan_m_face(D1
->NbEq
,(D1
->Dimension
- m_dim
- D1
->NbEq
),D1
,mf
);
1309 /* pos, number of constraints needed */
1312 fprintf( stderr
, "Number of m-faces: %d\n", nbfaces
);
1315 Matrix_Free(RaysDi
);
1317 Matrix_Free(PiTest
);
1325 /* if(CEqualities && keep_dom==0) {
1326 Domain_Free(CEqualities);
1330 res
= (Param_Polyhedron
*) malloc (sizeof(Param_Polyhedron
));
1334 res
->Constraints
= Polyhedron2Constraints(D1
);
1337 if(CT
) /* return the new D1 too ! */
1343 } /* Find_m_faces */
1346 * Given parametric domain 'PD' and number of parametric vertices 'nb_domains',
1347 * find the vertices that belong to distinct sub-domains.
1349 void Compute_PDomains(Param_Domain
*PD
,int nb_domains
,int working_space
) {
1353 Polyhedron
*dx
, *d1
, *d2
;
1354 Param_Domain
*p1
, *p2
, *p2prev
, *PDNew
;
1356 if (nb_domains
==0) {
1359 fprintf(stderr
,"No domains\n");
1365 /* Already filled out by GenParamPolyhedron */
1366 if (!PD
->next
&& PD
->F
)
1369 /* Initialization */
1370 nv
= (nb_domains
- 1)/(8*sizeof(int)) + 1;
1373 fprintf(stderr
,"nv = %d\n",nv
);
1376 for(p1
=PD
,i
=0,ix
=0,bx
=MSB
;p1
;p1
=p1
->next
,i
++) {
1378 /* Assign a bit array 'p1->F' of suitable size to include the vertices */
1379 p1
->F
= (unsigned *) malloc (nv
* sizeof(unsigned));
1381 /* Set the bit array to zeros */
1382 memset(p1
->F
,0,nv
* sizeof(unsigned));
1383 p1
->F
[ix
] |= bx
; /* Set i'th bit to one */
1388 fprintf(stderr
,"nb of vertices=%d\n",i
);
1391 /* Walk the PD list with two pointers */
1393 for (p1
=PD
;p1
;p1
=p1
->next
) {
1394 for (p2prev
=p1
,p2
=p1
->next
;p2
;p2prev
=p2
,p2
=p2
->next
) {
1396 /* Find intersection */
1397 dx
= PDomainIntersection(p1
->Domain
,p2
->Domain
,working_space
);
1399 if (!dx
|| emptyQ(dx
)) {
1402 fprintf( stderr
, "Empty dx (p1 inter p2). Continuing\n");
1410 fprintf(stderr
,"Begin PDomainDifference\n");
1411 fprintf(stderr
, "p1=");
1412 Polyhedron_Print(stderr
,P_VALUE_FMT
,p1
->Domain
);
1413 fprintf(stderr
,"p2=");
1414 Polyhedron_Print(stderr
,P_VALUE_FMT
,p2
->Domain
);
1416 d1
= PDomainDifference(p1
->Domain
,p2
->Domain
,working_space
);
1417 d2
= PDomainDifference(p2
->Domain
,p1
->Domain
,working_space
);
1420 fprintf(stderr
,"p1\\p2=");
1421 Polyhedron_Print(stderr
,P_VALUE_FMT
,d1
);
1422 fprintf(stderr
,"p2\\p1=");
1423 Polyhedron_Print(stderr
,P_VALUE_FMT
,d2
);
1424 fprintf(stderr
,"END PDomainDifference\n\n");
1426 if (!d1
|| emptyQ(d1
) || d1
->NbEq
!=0) {
1429 fprintf(stderr
,"Empty d1\n");
1435 if (!d2
|| emptyQ(d2
) || d2
->NbEq
!=0) {
1438 fprintf( stderr
, "Empty d2 (deleting)\n");
1440 /* dx = p1->Domain = p2->Domain */
1441 if (d2
) Domain_Free(d2
);
1445 p1
->F
[i
] |= p2
->F
[i
];
1448 p2prev
->next
= p2
->next
;
1449 Domain_Free(p2
->Domain
);
1454 else { /* d2 is not empty --> dx==p1->domain */
1457 fprintf( stderr
, "p2 replaced by d2\n");
1461 p1
->F
[i
] |= p2
->F
[i
];
1463 /* Replace p2 with d2 */
1464 Domain_Free( p2
->Domain
);
1468 else { /* d1 is not empty */
1469 if (!d2
|| emptyQ(d2
) || d2
->NbEq
!=0) {
1472 fprintf( stderr
, "p1 replaced by d1\n");
1474 if (d2
) Domain_Free(d2
);
1476 /* dx = p2->domain */
1481 p2
->F
[i
] |= p1
->F
[i
];
1483 /* Replace p1 with d1 */
1484 Domain_Free(p1
->Domain
);
1487 else { /*d2 is not empty-->d1,d2,dx are distinct */
1490 fprintf(stderr
,"Non-empty d1 and d2\nNew node created\n");
1492 /* Create a new node for dx */
1493 PDNew
= (Param_Domain
*) malloc( sizeof(Param_Domain
) );
1494 PDNew
->F
= (unsigned int *)malloc( nv
*sizeof(int) );
1495 memset(PDNew
->F
,0,nv
*sizeof(int));
1499 PDNew
->F
[i
] = p1
->F
[i
] | p2
->F
[i
];
1501 /* Replace p1 with d1 */
1502 Domain_Free( p1
->Domain
);
1505 /* Replace p2 with d2 */
1506 Domain_Free( p2
->Domain
);
1509 /* Insert new node after p1 */
1510 PDNew
->next
= p1
->next
;
1514 } /* end of p2 scan */
1515 if (p1
->Domain
->next
) {
1516 Polyhedron
*C
= DomainConvex(p1
->Domain
, working_space
);
1517 Domain_Free(p1
->Domain
);
1520 } /* end of p1 scan */
1521 } /* Compute_PDomains */
1524 * Given a polyhedron 'Din' in combined data and parametre space, a context
1525 * polyhedron 'Cin' representing the constraints on the parameter space and
1526 * a working space size 'working_space', return a parametric polyhedron with
1527 * a list of parametric vertices and their defining domains.
1529 Param_Polyhedron
*Polyhedron2Param_Vertices(Polyhedron
*Din
,Polyhedron
*Cin
,int working_space
) {
1531 Param_Polyhedron
*result
;
1533 POL_ENSURE_FACETS(Din
);
1534 POL_ENSURE_VERTICES(Din
);
1535 POL_ENSURE_FACETS(Cin
);
1536 POL_ENSURE_VERTICES(Cin
);
1539 fprintf(stderr
,"Polyhedron2Param_Vertices algorithm starting at : %.2fs\n",
1540 (float)clock()/CLOCKS_PER_SEC
);
1543 /***************** Scan the m-faces ****************/
1544 result
= Find_m_faces(&Din
,Cin
,0,working_space
,NULL
,NULL
);
1547 fprintf(stderr
, "nb of points : %d\n",result
->nbV
);
1551 fprintf(stderr
, "end main loop : %.2fs\n", (float)clock()/CLOCKS_PER_SEC
);
1555 } /* Polyhedron2Param_Vertices */
1558 * Free the memory allocated to a list of parametrized vertices
1560 void Param_Vertices_Free(Param_Vertices
*PV
) {
1562 Param_Vertices
*next_pv
;
1566 if (PV
->Vertex
) Matrix_Free(PV
->Vertex
);
1567 if (PV
->Domain
) Matrix_Free(PV
->Domain
);
1568 if (PV
->Facets
) free(PV
->Facets
);
1572 } /* Param_Vertices_Free */
1575 * Print a list of parametrized vertices *
1577 void Print_Vertex(FILE *DST
, Matrix
*V
, const char **param_names
)
1583 value_init(gcd
); value_init(tmp
);
1586 for(l
=0;l
<V
->NbRows
;++l
){
1591 for(v
=0;v
< V
->NbColumns
-2;++v
) {
1592 if(value_notzero_p(V
->p
[l
][v
])) {
1593 value_gcd(gcd
, V
->p
[l
][v
], V
->p
[l
][V
->NbColumns
-1]);
1594 value_divexact(tmp
, V
->p
[l
][v
], gcd
);
1595 if(value_posz_p(tmp
)) {
1598 if(value_notone_p(tmp
)) {
1599 value_print(DST
,VALUE_FMT
,tmp
);
1602 else { /* V->p[l][v]/gcd<0 */
1603 if(value_mone_p(tmp
))
1606 value_print(DST
,VALUE_FMT
,tmp
);
1609 value_divexact(tmp
, V
->p
[l
][V
->NbColumns
-1], gcd
);
1610 if(value_notone_p(tmp
)) {
1611 fprintf(DST
, "%s/", param_names
[v
]);
1612 value_print(DST
,VALUE_FMT
,tmp
);
1615 fprintf(DST
, "%s", param_names
[v
]);
1621 if(value_notzero_p(V
->p
[l
][v
]) || first
) {
1622 if(value_posz_p(V
->p
[l
][v
]) && !first
)
1624 value_gcd(gcd
, V
->p
[l
][v
], V
->p
[l
][V
->NbColumns
-1]);
1625 value_divexact(tmp
, V
->p
[l
][v
], gcd
);
1626 value_print(DST
,VALUE_FMT
,tmp
);
1627 value_divexact(tmp
, V
->p
[l
][V
->NbColumns
-1], gcd
);
1628 if(value_notone_p(tmp
)) {
1630 value_print(DST
,VALUE_FMT
,tmp
);
1638 value_clear(gcd
); value_clear(tmp
);
1640 } /* Print_Vertex */
1642 /*----------------------------------------------------------------------*/
1644 /* convert a paramvertex from reduced space to normal m-space */
1645 /*----------------------------------------------------------------------*/
1646 Matrix
*VertexCT(Matrix
*V
,Matrix
*CT
) {
1653 /* Have to transform the vertices to original dimension */
1654 Vt
= Matrix_Alloc(V
->NbRows
,CT
->NbColumns
+1);
1655 for(i
=0;i
<V
->NbRows
;++i
) {
1656 value_assign(Vt
->p
[i
][CT
->NbColumns
],V
->p
[i
][V
->NbColumns
-1]);
1657 for(j
=0;j
<CT
->NbColumns
;j
++) {
1658 for(k
=0;k
<CT
->NbRows
;k
++)
1659 if(value_notzero_p(CT
->p
[k
][j
]))
1662 value_assign(Vt
->p
[i
][j
],V
->p
[i
][k
]);
1664 value_set_si(Vt
->p
[i
][j
],0);
1674 * Print the validity Domain 'D' of a parametric polyhedron
1676 void Print_Domain(FILE *DST
, Polyhedron
*D
, const char **pname
)
1681 POL_ENSURE_FACETS(D
);
1682 POL_ENSURE_VERTICES(D
);
1684 for(l
=0;l
<D
->NbConstraints
;++l
) {
1687 for(v
=1;v
<=D
->Dimension
;++v
) {
1688 if(value_notzero_p(D
->Constraint
[l
][v
])) {
1689 if(value_one_p(D
->Constraint
[l
][v
])) {
1691 fprintf(DST
, "%s ", pname
[v
-1]);
1693 fprintf(DST
, "+ %s ", pname
[v
-1] );
1695 else if(value_mone_p(D
->Constraint
[l
][v
]))
1696 fprintf(DST
, "- %s ", pname
[v
-1] );
1698 if(value_pos_p(D
->Constraint
[l
][v
]) && !first
)
1699 fprintf(DST
, "+ " );
1700 value_print(DST
,VALUE_FMT
,D
->Constraint
[l
][v
]);
1701 fprintf(DST
,"%s ",pname
[v
-1]);
1706 if(value_notzero_p(D
->Constraint
[l
][v
])) {
1707 if(value_pos_p(D
->Constraint
[l
][v
]) && !first
)
1710 value_print(DST
,VALUE_FMT
,D
->Constraint
[l
][v
]);
1712 fprintf(DST
,(value_notzero_p(D
->Constraint
[l
][0])) ?" >= 0":" = 0");
1713 fprintf(DST
, "\n" );
1719 fprintf( DST
, "UNION\n" );
1720 Print_Domain( DST
, D
->next
, pname
);
1723 } /* Print_Domain */
1726 * Given a list of parametrized vertices and an array of parameter names, Print
1727 * a list of parametrized vertices in a comprehensible format.
1729 void Param_Vertices_Print(FILE *DST
, Param_Vertices
*PV
, const char **param_names
)
1734 fprintf(DST
, "Vertex :\n" );
1735 Print_Vertex(DST
,PV
->Vertex
,param_names
);
1737 /* Pour le domaine : */
1738 fprintf(DST
, " If :\n" );
1739 poly
= Constraints2Polyhedron(PV
->Domain
,200);
1740 Print_Domain(DST
,poly
,param_names
);
1745 } /* Param_Vertices_Print */
1748 * Given a polyhedron 'Din' in combined data and parametre space, a context
1749 * polyhedron 'Cin' representing the constraints on the parameter space and
1750 * a working space size 'working_space', return a parametric polyhedron with
1751 * a list of distinct validity domains and a complete list of valid vertices
1752 * associated to each validity domain.
1754 Param_Polyhedron
*Polyhedron2Param_Domain(Polyhedron
*Din
,Polyhedron
*Cin
,int working_space
) {
1756 Param_Polyhedron
*result
;
1759 POL_ENSURE_FACETS(Din
);
1760 POL_ENSURE_VERTICES(Din
);
1761 POL_ENSURE_FACETS(Cin
);
1762 POL_ENSURE_VERTICES(Cin
);
1764 if (emptyQ(Din
) || emptyQ(Cin
))
1768 fprintf(stderr
,"Polyhedron2Param_Polyhedron algorithm starting at : %.2fs\n",
1769 (float)clock()/CLOCKS_PER_SEC
);
1772 /* Find the m-faces, keeping the corresponding domains */
1773 /* in the linked list PDomains */
1774 result
= Find_m_faces(&Din
,Cin
,1,working_space
,NULL
,NULL
);
1777 if(result
) fprintf(stderr
, "Number of vertices : %d\n",result
->nbV
);
1778 fprintf(stderr
,"Vertices found at : %.2fs\n",(float)clock()/CLOCKS_PER_SEC
);
1781 /* Processing of PVResult and PDomains */
1782 if(result
&& Cin
->Dimension
>0) /* at least 1 parameter */
1783 Compute_PDomains(result
->D
,result
->nbV
,working_space
);
1784 if(result
&& CEqualities
)
1785 for(D
=result
->D
;D
;D
=D
->next
)
1786 D
->Domain
= Add_CEqualities(D
->Domain
);
1787 Polyhedron_Free(CEqualities
);
1790 fprintf(stderr
, "domains found at : %.2fs\n", (float)clock()/CLOCKS_PER_SEC
);
1794 } /* Polyhedon2Param_Domain */
1799 Param_Polyhedron
*Polyhedron2Param_SimplifiedDomain(Polyhedron
**Din
,Polyhedron
*Cin
,int working_space
,Polyhedron
**CEq
,Matrix
**CT
) {
1801 Param_Polyhedron
*result
;
1803 assert(CEq
!= NULL
);
1806 POL_ENSURE_FACETS(*Din
);
1807 POL_ENSURE_VERTICES(*Din
);
1808 POL_ENSURE_FACETS(Cin
);
1809 POL_ENSURE_VERTICES(Cin
);
1812 fprintf(stderr
,"Polyhedron2Param_Polyhedron algorithm starting at : %.2fs\n",
1813 (float)clock()/CLOCKS_PER_SEC
);
1816 /* Find the m-faces, keeping the corresponding domains */
1817 /* in the linked list PDomains */
1818 result
= Find_m_faces(Din
,Cin
,1,working_space
,CEq
,CT
);
1821 if(result
) fprintf(stderr
, "Number of vertices : %d\n",result
->nbV
);
1822 fprintf(stderr
,"Vertices found at : %.2fs\n",(float)clock()/CLOCKS_PER_SEC
);
1825 /* Processing of PVResult and PDomains */
1826 if(result
&& Cin
->Dimension
>0) /* at least 1 parameter */
1827 Compute_PDomains(result
->D
,result
->nbV
,working_space
);
1829 /* Removed this, Vin100, March 01 */
1830 /* if(result && CEqualities )
1831 for(D=result->D;D;D=D->next)
1832 D->Domain = Add_CEqualities(D->Domain);
1836 fprintf(stderr
, "domains found at : %.2fs\n", (float)clock()/CLOCKS_PER_SEC
);
1840 } /* Polyhedron2Param_SimplifiedDomain */
1843 * Free the memory allocated to a list of validity domain of a parametrized
1846 void Param_Domain_Free(Param_Domain
*PD
) {
1848 Param_Domain
*next_pd
;
1852 Domain_Free(PD
->Domain
);
1858 } /* Param_Domain_Free */
1861 * Free the memory allocated to a parametric polyhedron 'P'
1863 void Param_Polyhedron_Free(Param_Polyhedron
*P
) {
1866 Param_Vertices_Free(P
->V
);
1867 Param_Domain_Free(P
->D
);
1869 Matrix_Free(P
->Constraints
);
1871 Matrix_Free(P
->Rays
);
1874 } /* Param_Polyhedron_Free */
1877 * Scales the parametric polyhedron such that all vertices are integer.
1879 void Param_Polyhedron_Scale_Integer(Param_Polyhedron
*PP
, Polyhedron
**P
,
1880 Value
*det
, unsigned MaxRays
)
1883 int nb_param
, nb_vars
;
1886 Value global_var_lcm
;
1889 value_set_si(*det
, 1);
1893 nb_param
= PP
->D
->Domain
->Dimension
;
1894 nb_vars
= PP
->V
->Vertex
->NbRows
;
1896 /* Scan the vertices and make an orthogonal expansion of the variable
1898 /* a- prepare the array of common denominators */
1899 denoms
= Vector_Alloc(nb_vars
);
1900 value_init(global_var_lcm
);
1902 /* b- scan the vertices and compute the variables' global lcms */
1903 for (V
= PP
->V
; V
; V
= V
->next
)
1904 for (i
= 0; i
< nb_vars
; i
++)
1905 value_lcm(denoms
->p
[i
], denoms
->p
[i
], V
->Vertex
->p
[i
][nb_param
+1]);
1907 value_set_si(global_var_lcm
, 1);
1908 for (i
= 0; i
< nb_vars
; i
++) {
1909 value_multiply(*det
, *det
, denoms
->p
[i
]);
1910 value_lcm(global_var_lcm
, global_var_lcm
, denoms
->p
[i
]);
1913 /* scale vertices */
1914 for (V
= PP
->V
; V
; V
= V
->next
)
1915 for (i
= 0; i
< nb_vars
; i
++) {
1916 Vector_Scale(V
->Vertex
->p
[i
], V
->Vertex
->p
[i
], denoms
->p
[i
], nb_param
+1);
1917 Vector_Normalize(V
->Vertex
->p
[i
], nb_param
+2);
1920 /* the expansion can be actually writen as global_var_lcm.L^{-1} */
1921 /* this is equivalent to multiply the rows of P by denoms_det */
1922 for (i
= 0; i
< nb_vars
; i
++)
1923 value_division(denoms
->p
[i
], global_var_lcm
, denoms
->p
[i
]);
1925 /* OPT : we could use a vector instead of a diagonal matrix here (c- and d-).*/
1926 /* c- make the quick expansion matrix */
1927 expansion
= Matrix_Alloc(nb_vars
+nb_param
+1, nb_vars
+nb_param
+1);
1928 for (i
= 0; i
< nb_vars
; i
++)
1929 value_assign(expansion
->p
[i
][i
], denoms
->p
[i
]);
1930 for (i
= nb_vars
; i
< nb_vars
+nb_param
+1; i
++)
1931 value_assign(expansion
->p
[i
][i
], global_var_lcm
);
1933 /* d- apply the variable expansion to the polyhedron */
1935 *P
= Polyhedron_Preimage(*P
, expansion
, MaxRays
);
1937 Matrix_Free(expansion
);
1938 value_clear(global_var_lcm
);
1939 Vector_Free(denoms
);