2 This file is part of PolyLib.
4 PolyLib is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 PolyLib is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with PolyLib. If not, see <http://www.gnu.org/licenses/>.
20 Both this software and its documentation are
22 Copyright 1993 by IRISA /Universite de Rennes I - France,
23 Copyright 1995,1996 by BYU, Provo, Utah
30 1997/12/02 - Olivier Albiez
31 Ce fichier contient les fonctions de la polylib de l'IRISA,
33 La structure de la polylib a donc ete modifie pour permettre
34 le passage aux Value. La fonction Chernikova a ete reecrite.
40 1998/26/02 - Vincent Loechner
41 Ajout de nombreuses fonctions, a la fin de ce fichier,
42 pour les polyedres parametres 64 bits.
46 compatibilite avec la version de doran
50 #undef POLY_DEBUG /* debug printf: general functions */
51 #undef POLY_RR_DEBUG /* debug printf: Remove Redundants */
52 #undef POLY_CH_DEBUG /* debug printf: Chernikova */
58 #include <polylib/polylib.h>
64 /* WSIZE is the number of bits in a word or int type */
65 #define WSIZE (8*sizeof(int))
67 #define bexchange(a, b, l)\
69 char *t = (char *)malloc(l*sizeof(char));\
70 memcpy((t), (char *)(a), (int)(l));\
71 memcpy((char *)(a), (char *)(b), (int)(l));\
72 memcpy((char *)(b), (t), (int)(l));\
76 #define exchange(a, b, t)\
77 { (t)=(a); (a)=(b); (b)=(t); }
79 /* errormsg1 is an external function which is usually supplied by the
80 calling program (e.g. Domlib.c, ReadAlpha, etc...).
81 See errormsg.c for an example of such a function. */
83 void errormsg1(const char *f
, const char *msgname
, const char *msg
);
85 int Pol_status
; /* error status after operations */
88 * The Saturation matrix is defined to be an integer (int type) matrix.
89 * It is a boolean matrix which has a row for every constraint and a column
90 * for every line or ray. The bits in the binary format of each integer in
91 * the stauration matrix stores the information whether the corresponding
92 * constraint is saturated by ray(line) or not.
97 unsigned int NbColumns
;
103 * Allocate memory space for a saturation matrix.
105 static SatMatrix
*SMAlloc(int rows
,int cols
) {
110 result
= (SatMatrix
*) malloc (sizeof(SatMatrix
));
112 errormsg1("SMAlloc", "outofmem", "out of memory space");
115 result
->NbRows
= rows
;
116 result
->NbColumns
= cols
;
117 if(rows
== 0 || cols
== 0) {
121 result
->p
= q
= (int **)malloc(rows
* sizeof(int *));
123 errormsg1("SMAlloc", "outofmem", "out of memory space");
126 result
->p_init
= p
= (int *)malloc (rows
* cols
* sizeof (int));
127 if(!result
->p_init
) {
128 errormsg1("SMAlloc", "outofmem", "out of memory space");
131 for (i
=0; i
<rows
; i
++) {
139 * Free the memory space occupied by saturation matrix.
141 static void SMFree (SatMatrix
**matrix
) {
142 SatMatrix
*SM
= *matrix
;
146 free ((char *) SM
->p_init
);
147 free ((char *) SM
->p
);
155 * Print the contents of a saturation matrix.
156 * This function is defined only for debugging purpose.
158 static void SMPrint (SatMatrix
*matrix
) {
162 unsigned NbRows
, NbColumns
;
164 fprintf(stderr
,"%d %d\n",NbRows
=matrix
->NbRows
, NbColumns
=matrix
->NbColumns
);
165 for (i
=0;i
<NbRows
;i
++) {
167 for (j
=0;j
<NbColumns
;j
++)
168 fprintf(stderr
, " %10X ", *p
++);
169 fprintf(stderr
, "\n");
174 * Compute the bitwise OR of two saturation matrices.
176 static void SatVector_OR(int *p1
,int *p2
,int *p3
,unsigned length
) {
178 int *cp1
, *cp2
, *cp3
;
184 for (i
=0;i
<length
;i
++) {
193 * Copy a saturation matrix to another (macro definition).
195 #define SMVector_Copy(p1, p2, length) \
196 memcpy((char *)(p2), (char *)(p1), (int)((length)*sizeof(int)))
199 * Initialize a saturation matrix with zeros (macro definition)
201 #define SMVector_Init(p1, length) \
202 memset((char *)(p1), 0, (int)((length)*sizeof(int)))
205 * Defining operations on polyhedron --
209 * Vector p3 is a linear combination of two vectors (p1 and p2) such that
210 * p3[pos] is zero. First element of each vector (p1,p2,p3) is a status
211 * element and is not changed in p3. The value of 'pos' may be 0 however.
212 * The parameter 'length' does not include status element one.
214 static void Combine(Value
*p1
, Value
*p2
, Value
*p3
, int pos
, unsigned length
) {
217 Value abs_a1
,abs_a2
,neg_a1
;
219 /* Initialize all the 'Value' variables */
220 value_init(a1
); value_init(a2
); value_init(gcd
);
221 value_init(abs_a1
); value_init(abs_a2
); value_init(neg_a1
);
224 value_assign(a1
,p1
[pos
]);
227 value_assign(a2
,p2
[pos
]);
230 value_absolute(abs_a1
,a1
);
233 value_absolute(abs_a2
,a2
);
235 /* gcd = Gcd(abs(a1), abs(a2)) */
236 value_gcd(gcd
, abs_a1
, abs_a2
);
239 value_divexact(a1
, a1
, gcd
);
242 value_divexact(a2
, a2
, gcd
);
245 value_oppose(neg_a1
,a1
);
247 Vector_Combine(p1
+1,p2
+1,p3
+1,a2
,neg_a1
,length
);
248 Vector_Normalize(p3
+1,length
);
250 /* Clear all the 'Value' variables */
251 value_clear(a1
); value_clear(a2
); value_clear(gcd
);
252 value_clear(abs_a1
); value_clear(abs_a2
); value_clear(neg_a1
);
258 * Return the transpose of the saturation matrix 'Sat'. 'Mat' is a matrix
259 * of constraints and 'Ray' is a matrix of ray vectors and 'Sat' is the
260 * corresponding saturation matrix.
262 static SatMatrix
*TransformSat(Matrix
*Mat
, Matrix
*Ray
, SatMatrix
*Sat
) {
264 int i
, j
, sat_nbcolumns
;
265 unsigned jx1
, jx2
, bx1
, bx2
;
268 if (Mat
->NbRows
!= 0)
269 sat_nbcolumns
= (Mat
->NbRows
-1) /(sizeof(int)*8) + 1;
273 result
= SMAlloc(Ray
->NbRows
, sat_nbcolumns
);
274 SMVector_Init(result
->p_init
, Ray
->NbRows
* sat_nbcolumns
);
276 for(i
=0,jx1
=0,bx1
=MSB
; i
<Ray
->NbRows
; i
++) {
277 for(j
=0,jx2
=0,bx2
=MSB
; j
<Mat
->NbRows
; j
++) {
278 if (Sat
->p
[j
][jx1
] & bx1
)
279 result
->p
[i
][jx2
] |= bx2
;
288 * Sort the rays (Ray, Sat) into three tiers as used in 'Chernikova' function:
289 * NbBid <= i < equal_bound : saturates the constraint
290 * equal_bound <= i < sup_bound : verifies the constraint
291 * sup_bound <= i < NbRay : does not verify
293 * 'Ray' is the matrix of rays and 'Sat' is the corresponding saturation
294 * matrix. (jx,bx) pair specify the constraint in the saturation matrix. The
295 * status element of the 'Ray' matrix holds the saturation value w.r.t the
296 * constraint specified by (jx,bx). Thus
297 * Ray->p[i][0] = 0 -> ray(i) saturates the constraint
298 * Ray->p[i][0] > 0 -> ray(i) verifies the constraint
299 * Ray->p[i][0] < 0 -> ray(i) doesn't verify the constraint
301 static void RaySort(Matrix
*Ray
,SatMatrix
*Sat
,int NbBid
,int NbRay
,int *equal_bound
,int *sup_bound
,unsigned RowSize1
, unsigned RowSize2
, unsigned bx
, unsigned jx
) {
304 Value
**uni_eq
, **uni_sup
, **uni_inf
;
305 int **inc_eq
, **inc_sup
, **inc_inf
;
307 /* 'uni_eq' points to the first ray in the ray matrix which verifies a
308 * constraint, 'inc_eq' is the corresponding pointer in saturation
309 * matrix. 'uni_inf' points to the first ray (from top) which doesn't
310 * verify a constraint, 'inc_inf' is the corresponding pointer in
311 * saturation matrix. 'uni_sup' scans the ray matrix and 'inc_sup' is
312 * the corresponding pointer in saturation matrix. 'inf_bound' holds the
313 * number of the first ray which does not verify the constraints.
316 *sup_bound
= *equal_bound
= NbBid
;
317 uni_sup
= uni_eq
= Ray
->p
+NbBid
;
318 inc_sup
= inc_eq
= Sat
->p
+NbBid
;
320 uni_inf
= Ray
->p
+NbRay
;
321 inc_inf
= Sat
->p
+NbRay
;
323 while (inf_bound
>*sup_bound
) {
324 if (value_zero_p(**uni_sup
)) { /* status = satisfy */
325 if (inc_eq
!= inc_sup
) {
326 Vector_Exchange(*uni_eq
,*uni_sup
,RowSize1
);
327 bexchange(*inc_eq
,*inc_sup
,RowSize2
);
329 (*equal_bound
)++; uni_eq
++; inc_eq
++;
330 (*sup_bound
)++; uni_sup
++; inc_sup
++;
333 *((*inc_sup
)+jx
)|=bx
;
335 /* if (**uni_sup<0) */
336 if (value_neg_p(**uni_sup
)) { /* Status != verify */
337 inf_bound
--; uni_inf
--; inc_inf
--;
338 if (inc_inf
!= inc_sup
) {
339 Vector_Exchange(*uni_inf
,*uni_sup
,RowSize1
);
340 bexchange(*inc_inf
,*inc_sup
,RowSize2
);
343 else { /* status == verify */
344 (*sup_bound
)++; uni_sup
++; inc_sup
++;
350 static void SatMatrix_Extend(SatMatrix
*Sat
, Matrix
* Mat
, unsigned rows
)
354 cols
= (Mat
->NbRows
- 1)/(sizeof(int)*8) + 1;
356 Sat
->p
= (int **)realloc(Sat
->p
, rows
* sizeof(int *));
358 errormsg1("SatMatrix_Extend", "outofmem", "out of memory space");
361 Sat
->p_init
= (int *)realloc(Sat
->p_init
, rows
* cols
* sizeof (int));
363 errormsg1("SatMatrix_Extend", "outofmem", "out of memory space");
366 for (i
= 0; i
< rows
; ++i
)
367 Sat
->p
[i
] = Sat
->p_init
+ (i
* cols
);
372 * Compute the dual of matrix 'Mat' and place it in matrix 'Ray'.'Mat'
373 * contains the constraints (equalities and inequalities) in rows and 'Ray'
374 * contains the ray space (lines and rays) in its rows. 'Sat' is a boolean
375 * saturation matrix defined as Sat(i,j)=0 if ray(i) saturates constraint(j),
376 * otherwise 1. The constraints in the 'Mat' matrix are processed starting at
377 * 'FirstConstraint', 'Ray' and 'Sat' matrices are changed accordingly.'NbBid'
378 * is the number of lines in the ray matrix and 'NbMaxRays' is the maximum
379 * number of rows (rays) permissible in the 'Ray' and 'Sat' matrix. Return 0
380 * if successful, otherwise return 1.
382 static int Chernikova (Matrix
*Mat
,Matrix
*Ray
,SatMatrix
*Sat
, unsigned NbBid
, unsigned NbMaxRays
, unsigned FirstConstraint
,unsigned dual
) {
384 unsigned NbRay
, Dimension
, NbConstraints
, RowSize1
, RowSize2
, sat_nbcolumns
;
385 int sup_bound
, equal_bound
, index_non_zero
, bound
;
386 int i
, j
, k
, l
, redundant
, rayonly
, nbcommonconstraints
;
393 fprintf(stderr
, "[Chernikova: Input]\nRay = ");
394 Matrix_Print(stderr
,0,Ray
);
395 fprintf(stderr
, "\nConstraints = ");
396 Matrix_Print(stderr
,0,Mat
);
397 fprintf(stderr
, "\nSat = ");
401 NbConstraints
=Mat
->NbRows
;
403 Dimension
= Mat
->NbColumns
-1; /* Homogeneous Dimension */
404 sat_nbcolumns
=Sat
->NbColumns
;
406 RowSize1
=(Dimension
+1);
407 RowSize2
=sat_nbcolumns
* sizeof(int);
409 Temp
=(int *)malloc(RowSize2
);
411 errormsg1("Chernikova", "outofmem", "out of memory space");
414 CATCH(any_exception_error
) {
417 * In case of overflow, free the allocated memory!
418 * Rethrow upwards the stack to forward the exception.
424 jx
= FirstConstraint
/WSIZE
;
425 bx
= MSB
; bx
>>= FirstConstraint
%WSIZE
;
426 for (k
=FirstConstraint
; k
<NbConstraints
; k
++) {
428 /* Set the status word of each ray[i] to ray[i] dot constraint[k] */
429 /* This is equivalent to evaluating each ray by the constraint[k] */
430 /* 'index_non_zero' is assigned the smallest ray index which does */
431 /* not saturate the constraint. */
433 index_non_zero
= NbRay
;
434 for (i
=0; i
<NbRay
; i
++) {
439 /* *p3 = *p1 * *p2 */
440 value_multiply(*p3
,*p1
,*p2
);
442 for (j
=1; j
<Dimension
; j
++) {
444 /* *p3 += *p1 * *p2 */
445 value_addmul(*p3
, *p1
, *p2
);
448 if (value_notzero_p(*p3
) && (i
<index_non_zero
))
453 fprintf(stderr
, "[Chernikova: A]\nRay = ");
454 Matrix_Print(stderr
,0,Ray
);
455 fprintf(stderr
, "\nConstraints = ");
456 Matrix_Print(stderr
,0,Mat
);
457 fprintf(stderr
, "\nSat = ");
461 /* Find a bidirectional ray z such that cz <> 0 */
462 if (index_non_zero
<NbBid
) {
464 /* Discard index_non_zero bidirectional ray */
466 if (NbBid
!=index_non_zero
)
467 Vector_Exchange(Ray
->p
[index_non_zero
],Ray
->p
[NbBid
],RowSize1
);
470 fprintf(stderr
,"************\n");
471 for(i
=0;i
<RowSize1
;i
++) {
472 value_print(stderr
,P_VALUE_FMT
,Ray
->p
[index_non_zero
][i
]);
474 fprintf(stderr
,"\n******\n");
475 for(i
=0;i
<RowSize1
;i
++) {
476 value_print(stderr
,P_VALUE_FMT
,Ray
->p
[NbBid
][i
]);
478 fprintf(stderr
,"\n*******\n");
481 /* Compute the new lineality space */
482 for (i
=0; i
<NbBid
; i
++)
483 if (value_notzero_p(Ray
->p
[i
][0]))
484 Combine(Ray
->p
[i
],Ray
->p
[NbBid
],Ray
->p
[i
],0,Dimension
);
486 /* Add the positive part of index_non_zero bidirectional ray to */
487 /* the set of unidirectional rays */
489 if (value_neg_p(Ray
->p
[NbBid
][0])) {
491 for (j
=0;j
<Dimension
+1; j
++) {
494 value_oppose(*p1
,*p1
);
500 fprintf(stderr
, "[Chernikova: B]\nRay = ");
502 Matrix_Print(stderr
,0,Ray
);
503 fprintf(stderr
, "\nConstraints = ");
504 Matrix_Print(stderr
,0,Mat
);
505 fprintf(stderr
, "\nSat = ");
509 /* Compute the new pointed cone */
510 for (i
=NbBid
+1; i
<NbRay
; i
++)
511 if (value_notzero_p(Ray
->p
[i
][0]))
512 Combine(Ray
->p
[i
],Ray
->p
[NbBid
],Ray
->p
[i
],0,Dimension
);
514 /* Add the new ray */
515 if (value_notzero_p(Mat
->p
[k
][0])) { /* Constraint is an inequality */
516 for (j
=0;j
<sat_nbcolumns
;j
++) {
517 Sat
->p
[NbBid
][j
] = 0; /* Saturation vec for new ray */
519 /* The new ray saturates everything except last inequality */
520 Sat
->p
[NbBid
][jx
] |= bx
;
522 else { /* Constraint is an equality */
523 if (--NbRay
!= NbBid
) {
524 Vector_Copy(Ray
->p
[NbRay
],Ray
->p
[NbBid
],Dimension
+1);
525 SMVector_Copy(Sat
->p
[NbRay
],Sat
->p
[NbBid
],sat_nbcolumns
);
530 fprintf(stderr
, "[Chernikova: C]\nRay = ");
532 Matrix_Print(stderr
,0,Ray
);
533 fprintf(stderr
, "\nConstraints = ");
534 Matrix_Print(stderr
,0,Mat
);
535 fprintf(stderr
, "\nSat = ");
540 else { /* If the new constraint satisfies all the rays */
541 RaySort(Ray
, Sat
, NbBid
, NbRay
, &equal_bound
, &sup_bound
,
542 RowSize1
, RowSize2
,bx
,jx
);
544 /* Sort the unidirectional rays into R0, R+, R- */
546 NbRay-> bound-> ________
547 | R- | R- ==> ray.eq < 0 (outside domain)
549 | R+ | R+ ==> ray.eq > 0 (inside domain)
551 | R0 | R0 ==> ray.eq = 0 (on face of domain)
556 fprintf(stderr
, "[Chernikova: D]\nRay = ");
558 Matrix_Print(stderr
,0,Ray
);
559 fprintf(stderr
, "\nConstraints = ");
560 Matrix_Print(stderr
,0,Mat
);
561 fprintf(stderr
, "\nSat = ");
565 /* Compute only the new pointed cone */
567 for (i
=equal_bound
; i
<sup_bound
; i
++) /* for all pairs of R- and R+ */
568 for(j
=sup_bound
; j
<bound
; j
++) {
570 /*--------------------------------------------------------------*/
571 /* Count the set of constraints saturated by R+ and R- */
572 /* Includes equalities, inequalities and the positivity constraint */
573 /*-----------------------------------------------------------------*/
575 nbcommonconstraints
= 0;
576 for (l
=0; l
<jx
; l
++) {
577 aux
= Temp
[l
] = Sat
->p
[i
][l
] | Sat
->p
[j
][l
];
578 for (m
=MSB
; m
!=0; m
>>=1)
580 nbcommonconstraints
++;
582 aux
= Temp
[jx
] = Sat
->p
[i
][jx
] | Sat
->p
[j
][jx
];
583 for (m
=MSB
; m
!=bx
; m
>>=1)
585 nbcommonconstraints
++;
586 rayonly
= (value_zero_p(Ray
->p
[i
][Dimension
]) &&
587 value_zero_p(Ray
->p
[j
][Dimension
]) &&
590 nbcommonconstraints
++; /* account for pos constr */
592 /*-----------------------------------------------------------------*/
593 /* Adjacency Test : is combination [R-,R+] a non redundant ray? */
594 /*-----------------------------------------------------------------*/
596 if (nbcommonconstraints
+NbBid
>=Dimension
-2) { /* Dimensionality check*/
597 /* Check whether a ray m saturates the same set of constraints */
599 for (m
=NbBid
; m
<bound
; m
++)
600 if ((m
!=i
)&&(m
!=j
)) {
602 /* Two rays (r+ r-) are never made redundant by a vertex */
603 /* because the positivity constraint saturates both rays */
604 /* but not the vertex */
606 if (rayonly
&& value_notzero_p(Ray
->p
[m
][Dimension
]))
609 /* (r+ r-) is redundant if there doesn't exist an equation */
610 /* which saturates both r+ and r- but not rm. */
614 for (l
=0; l
<=jx
; l
++,ip2
++,ip1
++)
624 fprintf(stderr
, "[Chernikova: E]\nRay = ");
626 Matrix_Print(stderr
,0,Ray
);
627 fprintf(stderr
, "\nConstraints = ");
628 Matrix_Print(stderr
,0,Mat
);
629 fprintf(stderr
, "\nSat = ");
633 /*------------------------------------------------------------*/
634 /* Add new ray generated by [R+,R-] */
635 /*------------------------------------------------------------*/
638 if (NbRay
==NbMaxRays
) {
641 Matrix_Extend(Ray
, NbMaxRays
);
642 SatMatrix_Extend(Sat
, Mat
, NbMaxRays
);
645 /* Compute the new ray */
646 Combine(Ray
->p
[j
],Ray
->p
[i
],Ray
->p
[NbRay
],0,Dimension
);
647 SatVector_OR(Sat
->p
[j
],Sat
->p
[i
],Sat
->p
[NbRay
],sat_nbcolumns
);
648 Sat
->p
[NbRay
][jx
] &= ~bx
;
662 "Ray = ",sup_bound
,equal_bound
,bound
,NbRay
,Dimension
);
666 fprintf(stderr
, "[Chernikova: F]:\nRay = ");
667 Matrix_Print(stderr
,0,Ray
);
670 /* Eliminates all non extremal rays */
671 /* j = (Mat->p[k][0]) ? */
673 j
= (value_notzero_p(Mat
->p
[k
][0])) ?
674 sup_bound
: equal_bound
;
678 fprintf(stderr
, "i = %d\nj = %d \n", i
, j
);
680 while ((j
<bound
)&&(i
>bound
)) {
682 Vector_Copy(Ray
->p
[i
],Ray
->p
[j
],Dimension
+1);
683 SMVector_Copy(Sat
->p
[i
],Sat
->p
[j
],sat_nbcolumns
);
688 fprintf(stderr
, "i = %d\nj = %d \n", i
, j
);
696 "Ray = ",sup_bound
,equal_bound
,bound
,NbRay
, Dimension
);
700 fprintf(stderr
, "[Chernikova: G]\nRay = ");
701 Matrix_Print(stderr
,0,Ray
);
715 UNCATCH(any_exception_error
);
719 fprintf(stderr
, "[Chernikova: Output]\nRay = ");
720 Matrix_Print(stderr
,0,Ray
);
721 fprintf(stderr
, "\nConstraints = ");
722 Matrix_Print(stderr
,0,Mat
);
723 fprintf(stderr
, "\nSat = ");
730 static int Gauss4(Value
**p
, int NbEq
, int NbRows
, int Dimension
)
732 int i
, j
, k
, pivot
, Rank
;
733 int *column_index
= NULL
;
737 column_index
=(int *)malloc(Dimension
* sizeof(int));
739 errormsg1("Gauss","outofmem","out of memory space");
745 CATCH(any_exception_error
) {
753 for (j
=1; j
<=Dimension
; j
++) { /* for each column (except status) */
754 for (i
=Rank
; i
<NbEq
; i
++) /* starting at diagonal, look down */
756 /* if (Mat->p[i][j] != 0) */
757 if (value_notzero_p(p
[i
][j
]))
758 break; /* Find the first non zero element */
759 if (i
!=NbEq
) { /* If a non-zero element is found? */
760 if (i
!=Rank
) /* If it is found below the diagonal*/
761 Vector_Exchange(p
[Rank
]+1,p
[i
]+1,Dimension
);
763 /* Normalize the pivot row by dividing it by the gcd */
764 /* gcd = Vector_Gcd(p[Rank]+1,Dimension) */
765 Vector_Gcd(p
[Rank
]+1,Dimension
,&gcd
);
767 if (value_cmp_si(gcd
, 2) >= 0)
768 Vector_AntiScale(p
[Rank
]+1, p
[Rank
]+1, gcd
, Dimension
);
770 if (value_neg_p(p
[Rank
][j
]))
771 Vector_Oppose(p
[Rank
]+1, p
[Rank
]+1, Dimension
);
774 for (i
=pivot
+1; i
<NbEq
; i
++) { /* Zero out the rest of the column */
776 /* if (Mat->p[i][j] != 0) */
777 if (value_notzero_p(p
[i
][j
]))
778 Combine(p
[i
],p
[Rank
],p
[i
],j
,Dimension
);
781 /* For each row with non-zero entry Mat->p[Rank], store the column */
782 /* number 'j' in 'column_index[Rank]'. This information will be */
783 /* useful in performing Gaussian elimination backward step. */
785 column_index
[Rank
]=j
;
788 } /* end of Gaussian elimination forward step */
790 /* Back Substitution -- normalize the system of equations */
791 for (k
=Rank
-1; k
>=0; k
--) {
794 /* Normalize the equations */
795 for (i
=0; i
<k
; i
++) {
797 /* if (Mat->p[i][j] != 0) */
798 if (value_notzero_p(p
[i
][j
]))
799 Combine(p
[i
],p
[k
],p
[i
],j
,Dimension
);
802 /* Normalize the inequalities */
803 for (i
=NbEq
;i
<NbRows
;i
++) {
805 /* if (Mat->p[i][j] != 0) */
806 if (value_notzero_p(p
[i
][j
]))
807 Combine(p
[i
],p
[k
],p
[i
],j
,Dimension
);
812 UNCATCH(any_exception_error
);
813 free(column_index
), column_index
= NULL
;
820 * Compute a minimal system of equations using Gausian elimination method.
821 * 'Mat' is a matrix of constraints in which the first 'Nbeq' constraints
822 * are equations. The dimension of the homogenous system is 'Dimension'.
823 * The function returns the rank of the matrix 'Mat'.
825 int Gauss(Matrix
*Mat
, int NbEq
, int Dimension
)
830 fprintf(stderr
, "[Gauss : Input]\nRay =");
831 Matrix_Print(stderr
,0,Mat
);
834 Rank
= Gauss4(Mat
->p
, NbEq
, Mat
->NbRows
, Dimension
);
837 fprintf(stderr
, "[Gauss : Output]\nRay =");
838 Matrix_Print(stderr
,0,Mat
);
845 * Given 'Mat' - a matrix of equations and inequalities, 'Ray' - a matrix of
846 * lines and rays, 'Sat' - the corresponding saturation matrix, and 'Filter'
847 * - an array to mark (with 1) the non-redundant equalities and inequalities,
848 * compute a polyhedron composed of 'Mat' as constraint matrix and 'Ray' as
849 * ray matrix after reductions. This function is usually called as a follow
850 * up to 'Chernikova' to remove redundant constraints or rays.
851 * Note: (1) 'Chernikova' ensures that there are no redundant lines and rays.
852 * (2) The same function can be used with constraint and ray matrix used
855 static Polyhedron
*Remove_Redundants(Matrix
*Mat
,Matrix
*Ray
,SatMatrix
*Sat
,unsigned *Filter
) {
858 unsigned Dimension
, sat_nbcolumns
, NbRay
, NbConstraints
, RowSize2
,
859 *Trace
= NULL
, *bx
= NULL
, *jx
= NULL
, Dim_RaySpace
, b
;
860 unsigned NbBid
, NbUni
, NbEq
, NbIneq
;
861 unsigned NbBid2
, NbUni2
, NbEq2
, NbIneq2
;
863 int aux
, *temp2
= NULL
;
864 Polyhedron
*Pol
= NULL
;
865 Vector
*temp1
= NULL
;
868 Dimension
= Mat
->NbColumns
-1; /* Homogeneous Dimension */
870 sat_nbcolumns
= Sat
->NbColumns
;
871 NbConstraints
= Mat
->NbRows
;
872 RowSize2
=sat_nbcolumns
* sizeof(int);
874 temp1
= Vector_Alloc(Dimension
+1);
876 errormsg1("Remove_Redundants", "outofmem", "out of memory space");
881 temp2
= (int *)calloc(sat_nbcolumns
, sizeof(int));
886 /* Introduce indirections into saturation matrix 'Sat' to simplify */
887 /* processing with 'Sat' and allow easy exchanges of columns. */
888 bx
= (unsigned *)malloc(NbConstraints
* sizeof(unsigned));
891 jx
= (unsigned *)malloc(NbConstraints
* sizeof(unsigned));
894 CATCH(any_exception_error
) {
897 if (temp2
) free(temp2
);
900 if (Trace
) free(Trace
);
901 if (Pol
) Polyhedron_Free(Pol
);
907 /* For each constraint 'j' following mapping is defined to facilitate */
908 /* data access from saturation matrix 'Sat' :- */
909 /* (1) jx[j] -> floor[j/(8*sizeof(int))] */
910 /* (2) bx[j] -> bin(00..10..0) where position of 1 = j%(8*sizeof(int)) */
914 for (j
=0; j
<NbConstraints
; j
++) {
921 * STEP(0): Count the number of vertices among the rays while initializing
922 * the ray status count to 0. If no vertices are found, quit the procedure
923 * and return an empty polyhedron as the result.
926 /* Reset the status element of each ray to zero. Store the number of */
927 /* vertices in 'aux'. */
929 for (i
=0; i
<NbRay
; i
++) {
931 /* Ray->p[i][0] = 0 */
932 value_set_si(Ray
->p
[i
][0],0);
934 /* If ray(i) is a vertex of the Inhomogenous system */
935 if (value_notzero_p(Ray
->p
[i
][Dimension
]))
939 /* If no vertices, return an empty polyhedron. */
944 fprintf(stderr
, "[Remove_redundants : Init]\nConstraints =");
945 Matrix_Print(stderr
,0,Mat
);
946 fprintf(stderr
, "\nRays =");
947 Matrix_Print(stderr
,0,Ray
);
951 * STEP(1): Compute status counts for both rays and inequalities. For each
952 * constraint, count the number of vertices/rays saturated by that
953 * constraint, and put the result in the status words. At the same time,
954 * for each vertex/ray, count the number of constraints saturated by it.
955 * Delete any positivity constraints, but give rays credit in their status
956 * counts for saturating the positivity constraint.
962 fprintf (stderr
, " j = ");
965 for (j
=0; j
<NbConstraints
; j
++) {
968 fprintf (stderr
, " %i ", j
);
972 /* If constraint(j) is an equality, mark '1' in array 'temp2' */
973 if (Filter
&& value_zero_p(Mat
->p
[j
][0]))
974 temp2
[jx
[j
]] |= bx
[j
];
975 /* Reset the status element of each constraint to zero */
976 value_set_si(Mat
->p
[j
][0],0);
978 /* Identify and remove the positivity constraint 1>=0 */
979 i
= First_Non_Zero(Mat
->p
[j
]+1, Dimension
-1);
982 fprintf(stderr
, "[Remove_redundants : IntoStep1]\nConstraints =");
983 Matrix_Print(stderr
,0,Mat
);
984 fprintf (stderr
, " j = %i \n", j
);
987 /* Check if constraint(j) is a positivity constraint, 1 >= 0, or if it */
988 /* is 1==0. If constraint(j) saturates all the rays of the matrix 'Ray'*/
989 /* then it is an equality. in this case, return an empty polyhedron. */
992 for (i
=0; i
<NbRay
; i
++)
993 if (!(Sat
->p
[i
][jx
[j
]]&bx
[j
])) {
996 value_increment(Mat
->p
[j
][0],Mat
->p
[j
][0]);
999 /* if ((Mat->p[j][0] == NbRay) && : it is an equality
1000 (Mat->p[j][Dimension] != 0)) : and its not 0=0 */
1001 if ((value_cmp_si(Mat
->p
[j
][0], NbRay
) == 0) &&
1002 (value_notzero_p(Mat
->p
[j
][Dimension
])))
1005 /* Delete the positivity constraint */
1007 if (j
==NbConstraints
) continue;
1008 Vector_Exchange(Mat
->p
[j
], Mat
->p
[NbConstraints
], temp1
->Size
);
1009 exchange(jx
[j
], jx
[NbConstraints
], aux
);
1010 exchange(bx
[j
], bx
[NbConstraints
], aux
);
1014 /* Count the number of vertices/rays saturated by each constraint. At */
1015 /* the same time, count the number of constraints saturated by each ray*/
1016 for (i
=0; i
<NbRay
; i
++)
1017 if (!(Sat
->p
[i
][jx
[j
]]&bx
[j
])) {
1019 /* Mat->p[j][0]++ */
1020 value_increment(Mat
->p
[j
][0],Mat
->p
[j
][0]);
1022 /* Ray->p[i][0]++ */
1023 value_increment (Ray
->p
[i
][0],Ray
->p
[i
][0]);
1026 /* if (Mat->p[j][0]==NbRay) then increment the number of eq. count */
1027 if (value_cmp_si(Mat
->p
[j
][0], NbRay
) == 0)
1028 NbEq
++; /* all vertices/rays are saturated */
1030 Mat
->NbRows
= NbConstraints
;
1033 for (i
=0; i
<NbRay
; i
++) {
1035 /* Give rays credit for saturating the positivity constraint */
1036 if (value_zero_p(Ray
->p
[i
][Dimension
]))
1038 /* Ray->p[i][0]++ */
1039 value_increment(Ray
->p
[i
][0],Ray
->p
[i
][0]);
1041 /* If ray(i) saturates all the constraints including positivity */
1042 /* constraint then it is a bi-directional ray or line. Increment */
1043 /* 'NbBid' by one. */
1045 /* if (Ray->p[i][0]==NbConstraints+1) */
1046 if (value_cmp_si(Ray
->p
[i
][0], NbConstraints
+1) == 0)
1050 #ifdef POLY_RR_DEBUG
1051 fprintf(stderr
, "[Remove_redundants : Step1]\nConstraints =");
1052 Matrix_Print(stderr
,0,Mat
);
1053 fprintf(stderr
, "\nRay =");
1054 Matrix_Print(stderr
,0,Ray
);
1058 * STEP(2): Sort equalities to the top of constraint matrix 'Mat'. Detect
1059 * implicit equations such as y>=3; y<=3. Keep Inequalities in same
1060 * relative order. (Note: Equalities are constraints which saturate all of
1064 for (i
=0; i
<NbEq
; i
++) {
1066 /* If constraint(i) doesn't saturate some ray, then it is an inequality*/
1067 if (value_cmp_si(Mat
->p
[i
][0], NbRay
) != 0) {
1069 /* Skip over inequalities and find an equality */
1070 for (k
=i
+1; k
< NbConstraints
&& value_cmp_si(Mat
->p
[k
][0], NbRay
) != 0 ; k
++)
1072 if (k
>=NbConstraints
) /* If none found then error */ break;
1074 /* Slide inequalities down the array 'Mat' and move equality up to */
1076 Vector_Copy(Mat
->p
[k
], temp1
->p
, temp1
->Size
);
1080 Vector_Copy(Mat
->p
[k
-1], Mat
->p
[k
], temp1
->Size
);
1084 Vector_Copy(temp1
->p
, Mat
->p
[i
], temp1
->Size
);
1094 value_set_si(mone
, -1);
1095 /* Normalize equalities to have lexpositive coefficients to
1096 * be able to detect identical equalities.
1098 for (i
= 0; i
< NbEq
; i
++) {
1099 int pos
= First_Non_Zero(Mat
->p
[i
]+1, Dimension
);
1102 if (value_neg_p(Mat
->p
[i
][1+pos
]))
1103 Vector_Scale(Mat
->p
[i
]+1, Mat
->p
[i
]+1, mone
, Dimension
);
1106 for (i
=0; i
<NbEq
; i
++) {
1108 /* Detect implicit constraints such as y>=3 and y<=3 */
1110 for (j
=i
+1; j
<NbEq
; j
++) {
1111 /* Only check equalities, i.e., 'temp2' has entry 1 */
1112 if (!(temp2
[jx
[j
]] & bx
[j
]))
1114 /* Redundant if both are same `and' constraint(j) was equality. */
1115 if (Vector_Equal(Mat
->p
[i
]+1, Mat
->p
[j
]+1, Dimension
)) {
1121 /* Set 'Filter' entry to 1 corresponding to the irredundant equality*/
1122 if (!Redundant
) Filter
[jx
[i
]] |= bx
[i
]; /* set flag */
1126 #ifdef POLY_RR_DEBUG
1127 fprintf(stderr
, "[Remove_redundants : Step2]\nConstraints =");
1128 Matrix_Print(stderr
,0,Mat
);
1129 fprintf(stderr
, "\nRay =");
1130 Matrix_Print(stderr
,0,Ray
);
1134 * STEP(3): Perform Gaussian elimiation on the list of equalities. Obtain
1135 * a minimal basis by solving for as many variables as possible. Use this
1136 * solution to reduce the inequalities by eliminating as many variables as
1137 * possible. Set NbEq2 to the rank of the system of equalities.
1140 NbEq2
= Gauss(Mat
,NbEq
,Dimension
);
1142 /* If number of equalities is not less then the homogenous dimension, */
1143 /* return an empty polyhedron. */
1145 if (NbEq2
>= Dimension
)
1148 #ifdef POLY_RR_DEBUG
1149 fprintf(stderr
, "[Remove_redundants : Step3]\nConstraints =");
1150 Matrix_Print(stderr
,0,Mat
);
1151 fprintf(stderr
, "\nRay =");
1152 Matrix_Print(stderr
,0,Ray
);
1156 * STEP(4): Sort lines to the top of ray matrix 'Ray', leaving rays
1157 * afterwards. Detect implicit lines such as ray(1,2) and ray(-1,-2).
1158 * (Note: Lines are rays which saturate all of the constraints including
1159 * the positivity constraint 1>=0.
1163 for (i
=0, k
=NbRay
; i
<NbBid
&& k
>i
; i
++) {
1164 /* If ray(i) doesn't saturate some constraint then it is not a line */
1165 if (value_cmp_si(Ray
->p
[i
][0], NbConstraints
+1) != 0) {
1167 /* Skip over rays and vertices and find a line (bi-directional rays) */
1168 while (--k
> i
&& value_cmp_si(Ray
->p
[k
][0], NbConstraints
+1) != 0)
1171 /* Exchange positions of ray(i) and line(k), thus sorting lines to */
1172 /* the top of matrix 'Ray'. */
1173 Vector_Exchange(Ray
->p
[i
], Ray
->p
[k
], temp1
->Size
);
1174 bexchange(Sat
->p
[i
], Sat
->p
[k
], RowSize2
);
1178 #ifdef POLY_RR_DEBUG
1179 fprintf(stderr
, "[Remove_redundants : Step4]\nConstraints =");
1180 Matrix_Print(stderr
,0,Mat
);
1181 fprintf(stderr
, "\nRay =");
1182 Matrix_Print(stderr
,0,Ray
);
1186 * STEP(5): Perform Gaussian elimination on the lineality space to obtain
1187 * a minimal basis of lines. Use this basis to reduce the representation
1188 * of the uniderectional rays. Set 'NbBid2' to the rank of the system of
1192 NbBid2
= Gauss(Ray
, NbBid
, Dimension
);
1194 #ifdef POLY_RR_DEBUG
1195 fprintf(stderr
, "[Remove_redundants : After Gauss]\nRay =");
1196 Matrix_Print(stderr
,0,Ray
);
1199 /* If number of lines is not less then the homogenous dimension, return */
1200 /* an empty polyhedron. */
1201 if (NbBid2
>=Dimension
) {
1202 errormsg1("RemoveRedundants", "rmrdt", "dimension error");
1206 /* Compute dimension of non-homogenous ray space */
1207 Dim_RaySpace
= Dimension
-1-NbEq2
-NbBid2
;
1209 #ifdef POLY_RR_DEBUG
1210 fprintf(stderr
, "[Remove_redundants : Step5]\nConstraints =");
1211 Matrix_Print(stderr
,0,Mat
);
1212 fprintf(stderr
, "\nRay =");
1213 Matrix_Print(stderr
,0,Ray
);
1217 * STEP(6): Do a first pass filter of inequalities and equality identifi-
1218 * cation. New positivity constraints may have been created by step(3).
1219 * Check for and eliminate them. Count the irredundant inequalities and
1220 * store count in 'NbIneq'.
1224 for (j
=0; j
<NbConstraints
; j
++) {
1226 /* Identify and remove the positivity constraint 1>=0 */
1227 i
= First_Non_Zero(Mat
->p
[j
]+1, Dimension
-1);
1229 /* Check if constraint(j) is a positivity constraint, 1>= 0, or if it */
1232 /* if ((Mat->p[j][0]==NbRay) && : it is an equality
1233 (Mat->p[j][Dimension]!=0)) : and its not 0=0 */
1234 if ((value_cmp_si(Mat
->p
[j
][0], NbRay
) == 0) &&
1235 (value_notzero_p(Mat
->p
[j
][Dimension
])))
1238 /* Set the positivity constraint redundant by setting status element */
1240 value_set_si(Mat
->p
[j
][0],2);
1244 Status
= VALUE_TO_INT(Mat
->p
[j
][0]);
1247 value_set_si(Mat
->p
[j
][0], 2); /* constraint is redundant */
1248 else if (Status
< Dim_RaySpace
)
1249 value_set_si(Mat
->p
[j
][0], 2); /* constraint is redundant */
1250 else if (Status
== NbRay
)
1251 value_set_si(Mat
->p
[j
][0], 0); /* constraint is an equality */
1253 NbIneq
++; /* constraint is an irredundant inequality */
1254 value_set_si(Mat
->p
[j
][0], 1); /* inequality */
1258 #ifdef POLY_RR_DEBUG
1259 fprintf(stderr
, "[Remove_redundants : Step6]\nConstraints =");
1260 Matrix_Print(stderr
,0,Mat
);
1261 fprintf(stderr
, "\nRay =");
1262 Matrix_Print(stderr
,0,Ray
);
1266 * STEP(7): Do a first pass filter of rays and identification of lines.
1267 * Count the irredundant Rays and store count in 'NbUni'.
1271 for (j
=0; j
<NbRay
; j
++) {
1272 Status
= VALUE_TO_INT(Ray
->p
[j
][0]);
1274 if (Status
< Dim_RaySpace
)
1275 value_set_si(Ray
->p
[j
][0], 2); /* ray is redundant */
1276 else if (Status
== NbConstraints
+1)
1277 value_set_si(Ray
->p
[j
][0], 0); /* ray is a line */
1279 NbUni
++; /* an irredundant unidirectional ray. */
1280 value_set_si(Ray
->p
[j
][0], 1); /* ray */
1285 * STEP(8): Create the polyhedron (using approximate sizes).
1286 * Number of constraints = NbIneq + NbEq2 + 1
1287 * Number of rays = NbUni + NbBid2
1288 * Partially fill the polyhedron structure with the lines computed in step
1289 * 3 and the equalities computed in step 5.
1292 Pol
= Polyhedron_Alloc(Dimension
-1, NbIneq
+NbEq2
+1, NbUni
+NbBid2
);
1294 UNCATCH(any_exception_error
);
1297 Pol
->NbBid
= NbBid2
;
1300 /* Partially fill the polyhedron structure */
1301 if (NbBid2
) Vector_Copy(Ray
->p
[0], Pol
->Ray
[0], (Dimension
+1)*NbBid2
);
1302 if (NbEq2
) Vector_Copy(Mat
->p
[0], Pol
->Constraint
[0], (Dimension
+1)*NbEq2
);
1304 #ifdef POLY_RR_DEBUG
1305 fprintf(stderr
, "[Remove_redundants : Step7]\nConstraints =");
1306 Matrix_Print(stderr
,0,Mat
);
1307 fprintf(stderr
, "\nRay =");
1308 Matrix_Print(stderr
,0,Ray
);
1312 * STEP(9): Final Pass filter of inequalities and detection of redundant
1313 * inequalities. Redundant inequalities include:
1314 * (1) Inequalities which are always true, such as 1>=0,
1315 * (2) Redundant inequalities such as y>=4 given y>=3, or x>=1 given x=2.
1316 * (3) Redundant inequalities such as x+y>=5 given x>=3 and y>=2.
1317 * Every 'good' inequality must saturate at least 'Dimension' rays and be
1321 /* 'Trace' is a (1 X sat_nbcolumns) row matrix to hold the union of all */
1322 /* rows (corresponding to irredundant rays) of saturation matrix 'Sat' */
1323 /* which saturate some constraint 'j'. See figure below:- */
1324 Trace
=(unsigned *)malloc(sat_nbcolumns
* sizeof(unsigned));
1326 UNCATCH(any_exception_error
);
1330 /* NbEq NbConstraints
1337 NbRay ^ ________ ____________|____
1338 | |-------|--------|-----------0---|t1
1339 |i|-------|--------|-----------0---|t2
1341 NbBid - |-------|--------|-----------0---|tk
1342 |_______| |_______________|
1345 -OR- (of rows t1,t2,...,tk)
1352 for (j
=NbEq
; j
<NbConstraints
; j
++) {
1354 /* if (Mat->p[j][0]==1) : non-redundant inequality */
1355 if (value_one_p (Mat
->p
[j
][0])) {
1356 for (k
=0; k
<sat_nbcolumns
; k
++) Trace
[k
]=0; /* init Trace */
1358 /* Compute Trace: the union of all rows of Sat where constraint(j) */
1360 for (i
=NbBid
; i
<NbRay
; i
++)
1362 /* if (Ray->p[i][0]==1) */
1363 if (value_one_p(Ray
->p
[i
][0])) {
1364 if (!(Sat
->p
[i
][jx
[j
]]&bx
[j
]))
1365 for (k
=0; k
<sat_nbcolumns
; k
++) Trace
[k
] |= Sat
->p
[i
][k
];
1368 /* Only constraint(j) should saturate this set of vertices/rays. */
1369 /* If another non-redundant constraint also saturates this set, */
1370 /* then constraint(j) is redundant */
1372 for (i
=NbEq
; i
<NbConstraints
; i
++) {
1374 /* if ((Mat->p[i][0] ==1) && (i!=j) && !(Trace[jx[i]] & bx[i]) ) */
1375 if (value_one_p(Mat
->p
[i
][0]) && (i
!=j
) && !(Trace
[jx
[i
]] & bx
[i
])) {
1381 value_set_si(Mat
->p
[j
][0],2);
1384 Vector_Copy(Mat
->p
[j
], Pol
->Constraint
[NbEq2
+NbIneq2
], Dimension
+1);
1385 if (Filter
) Filter
[jx
[j
]] |= bx
[j
]; /* for SIMPLIFY */
1390 free(Trace
), Trace
= NULL
;
1392 #ifdef POLY_RR_DEBUG
1393 fprintf(stderr
, "[Remove_redundants : Step8]\nConstraints =");
1394 Matrix_Print(stderr
,0,Mat
);
1395 fprintf(stderr
, "\nRay =");
1396 Matrix_Print(stderr
,0,Ray
);
1400 * Step(10): Final pass filter of rays and detection of redundant rays.
1401 * The final list of rays is written to polyhedron.
1404 /* Trace is a (NbRay x 1) column matrix to hold the union of all columns */
1405 /* (corresponding to irredundant inequalities) of saturation matrix 'Sat'*/
1406 /* which saturate some ray 'i'. See figure below:- */
1408 Trace
=(unsigned *)malloc(NbRay
* sizeof(unsigned));
1410 UNCATCH(any_exception_error
);
1414 /* NbEq NbConstraints
1421 NbRay ^ _________ _______|_|___|__ ___
1423 | | Ray | | Sat| | | | |r|
1424 | | | | | | | | |a| Trace = Union[col(t1,t2,..,tk)]
1425 |i|-------|------>i 0 0 0 | |c|
1426 NbBid - | | | | | | | |e|
1427 |_______| |______|_|___|__| |_|
1433 /* Let 'aux' be the number of rays not vertices */
1435 for (i
=NbBid
; i
<NbRay
; i
++) {
1437 /* if (Ray->p[i][0]==1) */
1438 if (value_one_p (Ray
->p
[i
][0])) {
1440 /* if (Ray->p[i][Dimension]!=0) : vertex */
1441 if (value_notzero_p (Ray
->p
[i
][Dimension
]))
1442 for (k
=NbBid
; k
<NbRay
; k
++) Trace
[k
]=0; /* init Trace */
1445 /* Include the positivity constraint incidences for rays. The */
1446 /* positivity constraint saturates all rays and no vertices */
1448 for (k
=NbBid
; k
<NbRay
; k
++)
1450 /* Trace[k]=(Ray->p[k][Dimension]!=0); */
1451 Trace
[k
] = (value_notzero_p (Ray
->p
[k
][Dimension
]));
1453 /* Compute Trace: the union of all columns of Sat where ray(i) is */
1455 for (j
=NbEq
; j
<NbConstraints
; j
++)
1457 /* if (Mat->p[j][0]==1) : inequality */
1458 if (value_one_p (Mat
->p
[j
][0])) {
1459 if (!(Sat
->p
[i
][jx
[j
]]&bx
[j
]))
1460 for (k
=NbBid
; k
<NbRay
; k
++) Trace
[k
] |= Sat
->p
[k
][jx
[j
]]&bx
[j
];
1463 /* If ray i does not saturate any inequalities (other than the */
1464 /* the positivity constraint, then it is the case that there is */
1465 /* only one inequality and that ray is its orthogonal */
1467 /* only ray(i) should saturate this set of inequalities. If */
1468 /* another non-redundant ray also saturates this set, then ray(i)*/
1472 for (j
=NbBid
; j
<NbRay
; j
++) {
1474 /* if ( (Ray->p[j][0]==1) && (i!=j) && !Trace[j] ) */
1475 if (value_one_p (Ray
->p
[j
][0]) && (i
!=j
) && !Trace
[j
]) {
1481 value_set_si(Ray
->p
[i
][0],2);
1483 Vector_Copy(Ray
->p
[i
], Pol
->Ray
[NbBid2
+NbUni2
], Dimension
+1);
1484 NbUni2
++; /* Increment number of uni-directional rays */
1486 /* if (Ray->p[i][Dimension]==0) */
1487 if (value_zero_p (Ray
->p
[i
][Dimension
]))
1488 aux
++; /* Increment number of rays which are not vertices */
1493 /* Include the positivity constraint */
1494 if (aux
>=Dim_RaySpace
) {
1495 Vector_Set(Pol
->Constraint
[NbEq2
+NbIneq2
],0,Dimension
+1);
1496 value_set_si(Pol
->Constraint
[NbEq2
+NbIneq2
][0],1);
1497 value_set_si(Pol
->Constraint
[NbEq2
+NbIneq2
][Dimension
],1);
1502 UNCATCH(any_exception_error
);
1504 #ifdef POLY_RR_DEBUG
1505 fprintf(stderr
, "[Remove_redundants : Step9]\nConstraints =");
1506 Matrix_Print(stderr
,0,Mat
);
1507 fprintf(stderr
, "\nRay =");
1508 Matrix_Print(stderr
,0,Ray
);
1517 Pol
->NbConstraints
= NbEq2
+ NbIneq2
;
1518 Pol
->NbRays
= NbBid2
+ NbUni2
;
1522 POL_VALID
| POL_INEQUALITIES
| POL_FACETS
| POL_POINTS
| POL_VERTICES
);
1526 errormsg1("Remove_Redundants", "outofmem", "out of memory space");
1545 UNCATCH(any_exception_error
);
1546 return Empty_Polyhedron(Dimension
-1);
1547 } /* Remove_Redundants */
1550 * Allocate memory space for polyhedron.
1552 Polyhedron
* Polyhedron_Alloc(unsigned Dimension
,unsigned NbConstraints
,unsigned NbRays
) {
1555 unsigned NbRows
,NbColumns
;
1559 Pol
=(Polyhedron
*)malloc(sizeof(Polyhedron
));
1561 errormsg1("Polyhedron_Alloc", "outofmem", "out of memory space");
1565 Pol
->next
= (Polyhedron
*)0;
1566 Pol
->Dimension
= Dimension
;
1567 Pol
->NbConstraints
= NbConstraints
;
1568 Pol
->NbRays
= NbRays
;
1572 NbRows
= NbConstraints
+ NbRays
;
1573 NbColumns
= Dimension
+ 2;
1575 q
= (Value
**)malloc(NbRows
* sizeof(Value
*));
1577 errormsg1("Polyhedron_Alloc", "outofmem", "out of memory space");
1580 p
= value_alloc(NbRows
*NbColumns
, &Pol
->p_Init_size
);
1583 errormsg1("Polyhedron_Alloc", "outofmem", "out of memory space");
1586 Pol
->Constraint
= q
;
1587 Pol
->Ray
= q
+ NbConstraints
;
1589 for (i
=0;i
<NbRows
;i
++) {
1594 } /* Polyhedron_Alloc */
1597 * Free the memory space occupied by the single polyhedron.
1599 void Polyhedron_Free(Polyhedron
*Pol
)
1603 value_free(Pol
->p_Init
, Pol
->p_Init_size
);
1604 free(Pol
->Constraint
);
1607 } /* Polyhedron_Free */
1610 * Free the memory space occupied by the domain.
1612 void Domain_Free(Polyhedron
*Pol
)
1616 for (; Pol
; Pol
= Next
) {
1618 Polyhedron_Free(Pol
);
1624 * Print the contents of a polyhedron.
1626 void Polyhedron_Print(FILE *Dst
, const char *Format
, const Polyhedron
*Pol
)
1628 unsigned Dimension
, NbConstraints
, NbRays
;
1633 fprintf(Dst
, "<null polyhedron>\n");
1637 Dimension
= Pol
->Dimension
+ 2; /* Homogenous Dimension + status */
1638 NbConstraints
= Pol
->NbConstraints
;
1639 NbRays
= Pol
->NbRays
;
1640 fprintf(Dst
, "POLYHEDRON Dimension:%d\n", Pol
->Dimension
);
1641 fprintf(Dst
," Constraints:%d Equations:%d Rays:%d Lines:%d\n",
1642 Pol
->NbConstraints
, Pol
->NbEq
, Pol
->NbRays
, Pol
->NbBid
);
1643 fprintf(Dst
,"Constraints %d %d\n", NbConstraints
, Dimension
);
1645 for (i
=0;i
<NbConstraints
;i
++) {
1646 p
=Pol
->Constraint
[i
];
1649 if (value_notzero_p (*p
))
1650 fprintf(Dst
,"Inequality: [");
1652 fprintf(Dst
,"Equality: [");
1654 for (j
=1;j
<Dimension
;j
++) {
1655 value_print(Dst
,Format
,*p
++);
1657 (void)fprintf(Dst
," ]\n");
1660 (void)fprintf(Dst
, "Rays %d %d\n", NbRays
, Dimension
);
1661 for (i
=0;i
<NbRays
;i
++) {
1665 if (value_notzero_p (*p
)) {
1668 /* if ( p[Dimension-2] ) */
1669 if (value_notzero_p (p
[Dimension
-2]))
1670 fprintf(Dst
, "Vertex: [");
1672 fprintf(Dst
, "Ray: [");
1676 fprintf(Dst
, "Line: [");
1678 for (j
=1; j
< Dimension
-1; j
++) {
1679 value_print(Dst
,Format
,*p
++);
1683 if (value_notzero_p (*p
)) {
1684 fprintf( Dst
, " ]/" );
1685 value_print(Dst
,VALUE_FMT
,*p
);
1686 fprintf( Dst
, "\n" );
1689 fprintf(Dst
, " ]\n");
1692 fprintf(Dst
, "UNION ");
1693 Polyhedron_Print(Dst
,Format
,Pol
->next
);
1695 } /* Polyhedron_Print */
1698 * Print the contents of a polyhedron 'Pol' (used for debugging purpose).
1700 void PolyPrint (Polyhedron
*Pol
) {
1701 Polyhedron_Print(stderr
,"%4d",Pol
);
1705 * Create and return an empty polyhedron of non-homogenous dimension
1706 * 'Dimension'. An empty polyhedron is characterized by :-
1707 * (a) The dimension of the ray-space is -1.
1708 * (b) There is an over-constrained system of equations given by:
1709 * x=0, y=0, ...... z=0, 1=0
1711 Polyhedron
*Empty_Polyhedron(unsigned Dimension
) {
1716 Pol
= Polyhedron_Alloc(Dimension
, Dimension
+1, 0);
1718 errormsg1("Empty_Polyhedron", "outofmem", "out of memory space");
1721 Vector_Set(Pol
->Constraint
[0],0,(Dimension
+1)*(Dimension
+2));
1722 for (i
=0; i
<=Dimension
; i
++) {
1724 /* Pol->Constraint[i][i+1]=1 */
1725 value_set_si(Pol
->Constraint
[i
][i
+1],1);
1727 Pol
->NbEq
= Dimension
+1;
1730 POL_VALID
| POL_INEQUALITIES
| POL_FACETS
| POL_POINTS
| POL_VERTICES
);
1732 } /* Empty_Polyhedron */
1735 * Create and return a universe polyhedron of non-homogenous dimension
1736 * 'Dimension'. A universe polyhedron is characterized by :-
1737 * (a) The dimension of rayspace is zero.
1738 * (b) The dimension of lineality space is the dimension of the polyhedron.
1739 * (c) There is only one constraint (positivity constraint) in the constraint
1740 * set given by : 1 >= 0.
1741 * (d) The bi-directional ray set is the canonical set of vectors.
1742 * (e) The only vertex is the origin (0,0,0,....0).
1744 Polyhedron
*Universe_Polyhedron(unsigned Dimension
) {
1749 Pol
= Polyhedron_Alloc(Dimension
,1,Dimension
+1);
1751 errormsg1("Universe_Polyhedron", "outofmem", "out of memory space");
1754 Vector_Set(Pol
->Constraint
[0],0,(Dimension
+2));
1756 /* Pol->Constraint[0][0] = 1 */
1757 value_set_si(Pol
->Constraint
[0][0],1);
1759 /* Pol->Constraint[0][Dimension+1] = 1 */
1760 value_set_si(Pol
->Constraint
[0][Dimension
+1],1);
1761 Vector_Set(Pol
->Ray
[0],0,(Dimension
+1)*(Dimension
+2));
1762 for (i
=0;i
<=Dimension
;i
++) {
1764 /* Pol->Ray[i][i+1]=1 */
1765 value_set_si(Pol
->Ray
[i
][i
+1],1);
1768 /* Pol->Ray[Dimension][0] = 1 : vertex status */
1769 value_set_si(Pol
->Ray
[Dimension
][0],1);
1771 Pol
->NbBid
= Dimension
;
1773 POL_VALID
| POL_INEQUALITIES
| POL_FACETS
| POL_POINTS
| POL_VERTICES
);
1775 } /* Universe_Polyhedron */
1779 Sort constraints and remove trivially redundant constraints.
1782 static void SortConstraints(Matrix
*Constraints
, unsigned NbEq
)
1785 for (i
= NbEq
; i
< Constraints
->NbRows
; ++i
) {
1787 for (k
= i
+1; k
< Constraints
->NbRows
; ++k
) {
1788 for (j
= 1; j
< Constraints
->NbColumns
-1; ++j
) {
1789 if (value_eq(Constraints
->p
[k
][j
],
1790 Constraints
->p
[max
][j
]))
1792 if (value_abs_lt(Constraints
->p
[k
][j
],
1793 Constraints
->p
[max
][j
]))
1795 if (value_abs_eq(Constraints
->p
[k
][j
],
1796 Constraints
->p
[max
][j
]) &&
1797 value_pos_p(Constraints
->p
[max
][j
]))
1802 /* equal, except for possibly the constant
1803 * => remove constraint with biggest constant
1805 if (j
== Constraints
->NbColumns
-1) {
1806 if (value_lt(Constraints
->p
[k
][j
], Constraints
->p
[max
][j
]))
1807 Vector_Exchange(Constraints
->p
[k
],
1808 Constraints
->p
[max
],
1809 Constraints
->NbColumns
);
1810 Constraints
->NbRows
--;
1811 if (k
< Constraints
->NbRows
)
1812 Vector_Exchange(Constraints
->p
[k
],
1813 Constraints
->p
[Constraints
->NbRows
],
1814 Constraints
->NbColumns
);
1819 Vector_Exchange(Constraints
->p
[max
], Constraints
->p
[i
],
1820 Constraints
->NbColumns
);
1826 Search for trivial implicit equalities,
1827 assuming the constraints have been sorted.
1831 static int ImplicitEqualities(Matrix
*Constraints
, unsigned NbEq
)
1836 for (row
= NbEq
; row
< Constraints
->NbRows
; ++row
) {
1837 int d
= First_Non_Zero(Constraints
->p
[row
]+1, Constraints
->NbColumns
-2);
1840 if (value_neg_p(Constraints
->p
[row
][Constraints
->NbColumns
-1])) {
1841 value_set_si(Constraints
->p
[row
][0], 0);
1846 if (value_neg_p(Constraints
->p
[row
][1+d
]))
1848 for (nrow
= row
+1; nrow
< Constraints
->NbRows
; ++nrow
) {
1849 if (value_zero_p(Constraints
->p
[nrow
][1+d
]))
1851 if (value_pos_p(Constraints
->p
[nrow
][1+d
]))
1853 for (k
= d
; k
< Constraints
->NbColumns
-1; ++k
) {
1854 if (value_abs_ne(Constraints
->p
[row
][1+k
],
1855 Constraints
->p
[nrow
][1+k
]))
1857 if (value_zero_p(Constraints
->p
[row
][1+k
]))
1859 if (value_eq(Constraints
->p
[row
][1+k
], Constraints
->p
[nrow
][1+k
]))
1862 if (k
== Constraints
->NbColumns
-1) {
1863 value_set_si(Constraints
->p
[row
][0], 0);
1864 value_set_si(Constraints
->p
[nrow
][0], 0);
1868 if (k
!= Constraints
->NbColumns
-2)
1870 /* if the constants are such that
1871 * the sum c1+c2 is negative then the constraints conflict
1874 value_addto(tmp
, Constraints
->p
[row
][1+k
],
1875 Constraints
->p
[nrow
][1+k
]);
1876 if (value_sign(tmp
) < 0) {
1877 Vector_Set(Constraints
->p
[row
], 0, Constraints
->NbColumns
-1);
1878 Vector_Set(Constraints
->p
[nrow
], 0, Constraints
->NbColumns
-1);
1879 value_set_si(Constraints
->p
[row
][1+k
], 1);
1880 value_set_si(Constraints
->p
[nrow
][1+k
], 1);
1893 Given a matrix of constraints ('Constraints'), construct and return a
1896 @param Constraints Constraints (may be modified!)
1897 @param NbMaxRays Estimated number of rays in the ray matrix of the
1899 @return newly allocated Polyhedron
1902 Polyhedron
*Constraints2Polyhedron(Matrix
*Constraints
,unsigned NbMaxRays
) {
1904 Polyhedron
*Pol
= NULL
;
1906 SatMatrix
*Sat
= NULL
;
1907 unsigned Dimension
, nbcolumns
;
1910 Dimension
= Constraints
->NbColumns
- 1; /* Homogeneous Dimension */
1911 if (Dimension
< 1) {
1912 errormsg1("Constraints2Polyhedron","invalidpoly","invalid polyhedron dimension");
1916 /* If there is no constraint in the constraint matrix, return universe */
1918 if (Constraints
->NbRows
==0) {
1919 Pol
= Universe_Polyhedron(Dimension
-1);
1923 if (POL_ISSET(NbMaxRays
, POL_NO_DUAL
)) {
1927 if (POL_ISSET(NbMaxRays
, POL_INTEGER
))
1931 /* Move equalities up */
1932 for (i
= 0; i
< Constraints
->NbRows
; ++i
)
1933 if (value_zero_p(Constraints
->p
[i
][0])) {
1934 if (POL_ISSET(NbMaxRays
, POL_INTEGER
) &&
1935 ConstraintSimplify(Constraints
->p
[i
],
1936 Constraints
->p
[i
], Dimension
+1, &tmp
)) {
1938 return Empty_Polyhedron(Dimension
-1);
1940 /* detect 1 == 0, possibly created by ImplicitEqualities */
1941 if (First_Non_Zero(Constraints
->p
[i
]+1, Dimension
-1) == -1 &&
1942 value_notzero_p(Constraints
->p
[i
][Dimension
])) {
1943 if (POL_ISSET(NbMaxRays
, POL_INTEGER
))
1945 return Empty_Polyhedron(Dimension
-1);
1948 ExchangeRows(Constraints
, i
, NbEq
);
1951 Rank
= Gauss(Constraints
, NbEq
, Dimension
);
1952 if (POL_ISSET(NbMaxRays
, POL_INTEGER
))
1953 for (i
= NbEq
; i
< Constraints
->NbRows
; ++i
)
1954 ConstraintSimplify(Constraints
->p
[i
],
1955 Constraints
->p
[i
], Dimension
+1, &tmp
);
1956 SortConstraints(Constraints
, NbEq
);
1957 } while (ImplicitEqualities(Constraints
, NbEq
));
1958 if (POL_ISSET(NbMaxRays
, POL_INTEGER
))
1960 Pol
= Polyhedron_Alloc(Dimension
-1, Constraints
->NbRows
- (NbEq
-Rank
), 0);
1962 Vector_Copy(Constraints
->p
[0], Pol
->Constraint
[0],
1963 Rank
* Constraints
->NbColumns
);
1964 if (Constraints
->NbRows
> NbEq
)
1965 Vector_Copy(Constraints
->p
[NbEq
], Pol
->Constraint
[Rank
],
1966 (Constraints
->NbRows
- NbEq
) * Constraints
->NbColumns
);
1968 /* Make sure nobody accesses the rays by accident */
1970 F_SET(Pol
, POL_VALID
| POL_INEQUALITIES
);
1974 if (Dimension
> NbMaxRays
)
1975 NbMaxRays
= Dimension
;
1978 * Rather than adding a 'positivity constraint', it is better to
1979 * initialize the lineality space with line in each of the index
1980 * dimensions, but no line in the lambda dimension. Then initialize
1981 * the ray space with an origin at 0. This is what you get anyway,
1982 * after the positivity constraint has been processed by Chernikova
1986 /* Allocate and initialize the Ray Space */
1987 Ray
= Matrix_Alloc(NbMaxRays
, Dimension
+1);
1989 errormsg1("Constraints2Polyhedron","outofmem","out of memory space");
1992 Vector_Set(Ray
->p_Init
,0, NbMaxRays
* (Dimension
+1));
1993 for (i
=0; i
<Dimension
; i
++) {
1995 /* Ray->p[i][i+1] = 1 */
1996 value_set_si(Ray
->p
[i
][i
+1],1);
1999 /* Ray->p[Dimension-1][0] = 1 : mark for ray */
2000 value_set_si(Ray
->p
[Dimension
-1][0],1);
2001 Ray
->NbRows
= Dimension
;
2003 /* Initialize the Sat Matrix */
2004 nbcolumns
= (Constraints
->NbRows
- 1)/(sizeof(int)*8) + 1;
2005 Sat
= SMAlloc(NbMaxRays
, nbcolumns
);
2006 SMVector_Init(Sat
->p_init
,Dimension
*nbcolumns
);
2007 Sat
->NbRows
= Dimension
;
2009 CATCH(any_exception_error
) {
2011 /* In case of overflow, free the allocated memory and forward. */
2012 if (Sat
) SMFree(&Sat
);
2013 if (Ray
) Matrix_Free(Ray
);
2014 if (Pol
) Polyhedron_Free(Pol
);
2019 /* Create ray matrix 'Ray' from constraint matrix 'Constraints' */
2020 Chernikova(Constraints
,Ray
,Sat
,Dimension
-1,NbMaxRays
,0,0);
2023 fprintf(stderr
, "[constraints2polyhedron]\nConstraints = ");
2024 Matrix_Print(stderr
,0,Constraints
);
2025 fprintf(stderr
, "\nRay = ");
2026 Matrix_Print(stderr
,0,Ray
);
2027 fprintf(stderr
, "\nSat = ");
2031 /* Remove the redundant constraints and create the polyhedron */
2032 Pol
= Remove_Redundants(Constraints
,Ray
,Sat
,0);
2035 UNCATCH(any_exception_error
);
2038 fprintf(stderr
, "\nPol = ");
2039 Polyhedron_Print(stderr
,"%4d",Pol
);
2042 SMFree(&Sat
), Sat
= NULL
;
2043 Matrix_Free(Ray
), Ray
= NULL
;
2045 } /* Constraints2Polyhedron */
2050 * Given a polyhedron 'Pol', return a matrix of constraints.
2052 Matrix
*Polyhedron2Constraints(Polyhedron
*Pol
) {
2055 unsigned NbConstraints
,Dimension
;
2057 POL_ENSURE_INEQUALITIES(Pol
);
2059 NbConstraints
= Pol
->NbConstraints
;
2060 Dimension
= Pol
->Dimension
+2;
2061 Mat
= Matrix_Alloc(NbConstraints
,Dimension
);
2063 errormsg1("Polyhedron2Constraints", "outofmem", "out of memory space");
2066 Vector_Copy(Pol
->Constraint
[0],Mat
->p_Init
,NbConstraints
* Dimension
);
2068 } /* Polyhedron2Constraints */
2072 Given a matrix of rays 'Ray', create and return a polyhedron.
2074 @param Ray Rays (may be modified!)
2075 @param NbMaxConstrs Estimated number of constraints in the polyhedron.
2076 @return newly allocated Polyhedron
2079 Polyhedron
*Rays2Polyhedron(Matrix
*Ray
,unsigned NbMaxConstrs
) {
2081 Polyhedron
*Pol
= NULL
;
2083 SatMatrix
*Sat
= NULL
, *SatTranspose
= NULL
;
2084 unsigned Dimension
, nbcolumns
;
2087 Dimension
= Ray
->NbColumns
-1; /* Homogeneous Dimension */
2089 SatTranspose
= NULL
;
2092 if (Ray
->NbRows
==0) {
2094 /* If there is no ray in the matrix 'Ray', return an empty polyhedron */
2095 Pol
= Empty_Polyhedron(Dimension
-1);
2099 /* Ignore for now */
2100 if (POL_ISSET(NbMaxConstrs
, POL_NO_DUAL
))
2103 if (Dimension
> NbMaxConstrs
)
2104 NbMaxConstrs
= Dimension
;
2106 /* Allocate space for constraint matrix 'Mat' */
2107 Mat
= Matrix_Alloc(NbMaxConstrs
,Dimension
+1);
2109 errormsg1("Rays2Polyhedron","outofmem","out of memory space");
2113 /* Initialize the constraint matrix 'Mat' */
2114 Vector_Set(Mat
->p_Init
,0,NbMaxConstrs
* (Dimension
+1));
2115 for (i
=0; i
<Dimension
; i
++) {
2117 /* Mat->p[i][i+1]=1 */
2118 value_set_si(Mat
->p
[i
][i
+1],1);
2121 /* Allocate and assign the saturation matrix. Remember we are using a */
2122 /* transposed saturation matrix referenced by (constraint,ray) pair. */
2123 Mat
->NbRows
= Dimension
;
2124 nbcolumns
= (Ray
->NbRows
-1)/(sizeof(int)*8) + 1;
2125 SatTranspose
= SMAlloc(NbMaxConstrs
,nbcolumns
);
2126 SMVector_Init(SatTranspose
->p
[0],Dimension
* nbcolumns
);
2127 SatTranspose
->NbRows
= Dimension
;
2130 fprintf(stderr
, "[ray2polyhedron: Before]\nRay = ");
2131 Matrix_Print(stderr
,0,Ray
);
2132 fprintf(stderr
, "\nConstraints = ");
2133 Matrix_Print(stderr
,0,Mat
);
2134 fprintf(stderr
, "\nSatTranspose = ");
2135 SMPrint (SatTranspose
);
2138 CATCH(any_exception_error
) {
2140 /* In case of overflow, free the allocated memory before forwarding
2143 if (SatTranspose
) SMFree(&SatTranspose
);
2144 if (Sat
) SMFree(&Sat
);
2145 if (Mat
) Matrix_Free(Mat
);
2146 if (Pol
) Polyhedron_Free(Pol
);
2151 /* Create constraint matrix 'Mat' from ray matrix 'Ray' */
2152 Chernikova(Ray
,Mat
,SatTranspose
,Dimension
,NbMaxConstrs
,0,1);
2155 fprintf(stderr
, "[ray2polyhedron: After]\nRay = ");
2156 Matrix_Print(stderr
,0,Ray
);
2157 fprintf(stderr
, "\nConstraints = ");
2158 Matrix_Print(stderr
,0,Mat
);
2159 fprintf(stderr
, "\nSatTranspose = ");
2160 SMPrint (SatTranspose
);
2163 /* Transform the saturation matrix 'SatTranspose' in the standard */
2164 /* format, that is, ray X constraint format. */
2165 Sat
= TransformSat(Mat
,Ray
,SatTranspose
);
2168 fprintf(stderr
, "\nSat =");
2172 SMFree(&SatTranspose
), SatTranspose
= NULL
;
2174 /* Remove redundant rays from the ray matrix 'Ray' */
2175 Pol
= Remove_Redundants(Mat
,Ray
,Sat
,0);
2178 UNCATCH(any_exception_error
);
2181 fprintf(stderr
, "\nPol = ");
2182 Polyhedron_Print(stderr
,"%4d",Pol
);
2188 } /* Rays2Polyhedron */
2191 * Compute the dual representation if P only contains one representation.
2192 * Currently only handles the case where only the equalities are known.
2194 void Polyhedron_Compute_Dual(Polyhedron
*P
)
2196 if (!F_ISSET(P
, POL_VALID
))
2199 if (F_ISSET(P
, POL_FACETS
| POL_VERTICES
))
2202 if (F_ISSET(P
, POL_INEQUALITIES
)) {
2205 /* Pretend P is a Matrix for a second */
2206 M
.NbRows
= P
->NbConstraints
;
2207 M
.NbColumns
= P
->Dimension
+2;
2208 M
.p_Init
= P
->p_Init
;
2209 M
.p
= P
->Constraint
;
2210 Q
= Constraints2Polyhedron(&M
, 0);
2212 /* Switch contents of P and Q ... */
2216 /* ... but keep the next pointer */
2222 /* other cases not handled yet */
2227 * Build a saturation matrix from constraint matrix 'Mat' and ray matrix
2228 * 'Ray'. Only 'NbConstraints' constraint of matrix 'Mat' are considered
2229 * in creating the saturation matrix. 'NbMaxRays' is the maximum number
2230 * of rows (rays) allowed in the saturation matrix.
2231 * Vin100's stuff, for the polyparam vertices to work.
2233 static SatMatrix
*BuildSat(Matrix
*Mat
,Matrix
*Ray
,unsigned NbConstraints
,unsigned NbMaxRays
) {
2235 SatMatrix
*Sat
= NULL
;
2237 Value
*p1
, *p2
, *p3
;
2238 unsigned Dimension
, NbRay
, bx
, nbcolumns
;
2240 CATCH(any_exception_error
) {
2246 NbRay
= Ray
->NbRows
;
2247 Dimension
= Mat
->NbColumns
-1; /* Homogeneous Dimension */
2249 /* Build the Sat matrix */
2250 nbcolumns
= (Mat
->NbRows
- 1)/(sizeof(int)*8) + 1;
2251 Sat
= SMAlloc(NbMaxRays
,nbcolumns
);
2252 Sat
->NbRows
= NbRay
;
2253 SMVector_Init(Sat
->p_init
, nbcolumns
* NbRay
);
2255 for (k
=0; k
<NbConstraints
; k
++) {
2256 for (i
=0; i
<NbRay
; i
++) {
2258 /* Compute the dot product of ray(i) and constraint(k) and */
2259 /* store in the status element of ray(i). */
2263 value_set_si(*p3
,0);
2264 for (j
=0; j
<Dimension
; j
++) {
2265 value_addmul(*p3
, *p1
, *p2
);
2269 for (j
=0; j
<NbRay
; j
++) {
2271 /* Set 1 in the saturation matrix if the ray doesn't saturate */
2272 /* the constraint, otherwise the entry is 0. */
2273 if (value_notzero_p(Ray
->p
[j
][0]))
2280 UNCATCH(any_exception_error
);
2285 * Add 'Nbconstraints' new constraints to polyhedron 'Pol'. Constraints are
2286 * pointed by 'Con' and the maximum allowed rays in the new polyhedron is
2289 Polyhedron
*AddConstraints(Value
*Con
,unsigned NbConstraints
,Polyhedron
*Pol
,unsigned NbMaxRays
) {
2291 Polyhedron
*NewPol
= NULL
;
2292 Matrix
*Mat
= NULL
, *Ray
= NULL
;
2293 SatMatrix
*Sat
= NULL
;
2294 unsigned NbRay
, NbCon
, Dimension
;
2296 if (NbConstraints
== 0)
2297 return Polyhedron_Copy(Pol
);
2299 POL_ENSURE_INEQUALITIES(Pol
);
2300 Dimension
= Pol
->Dimension
+ 2; /* Homogeneous Dimension + Status */
2302 if (POL_ISSET(NbMaxRays
, POL_NO_DUAL
)) {
2303 NbCon
= Pol
->NbConstraints
+ NbConstraints
;
2305 Mat
= Matrix_Alloc(NbCon
, Dimension
);
2307 errormsg1("AddConstraints", "outofmem", "out of memory space");
2310 Vector_Copy(Pol
->Constraint
[0], Mat
->p
[0], Pol
->NbConstraints
* Dimension
);
2311 Vector_Copy(Con
, Mat
->p
[Pol
->NbConstraints
], NbConstraints
* Dimension
);
2312 NewPol
= Constraints2Polyhedron(Mat
, NbMaxRays
);
2317 POL_ENSURE_VERTICES(Pol
);
2319 CATCH(any_exception_error
) {
2320 if (NewPol
) Polyhedron_Free(NewPol
);
2321 if (Mat
) Matrix_Free(Mat
);
2322 if (Ray
) Matrix_Free(Ray
);
2323 if (Sat
) SMFree(&Sat
);
2327 NbRay
= Pol
->NbRays
;
2328 NbCon
= Pol
->NbConstraints
+ NbConstraints
;
2330 if (NbRay
> NbMaxRays
)
2333 Mat
= Matrix_Alloc(NbCon
, Dimension
);
2335 errormsg1("AddConstraints", "outofmem", "out of memory space");
2336 UNCATCH(any_exception_error
);
2340 /* Copy constraints of polyhedron 'Pol' to matrix 'Mat' */
2341 Vector_Copy(Pol
->Constraint
[0], Mat
->p
[0], Pol
->NbConstraints
* Dimension
);
2343 /* Add the new constraints pointed by 'Con' to matrix 'Mat' */
2344 Vector_Copy(Con
, Mat
->p
[Pol
->NbConstraints
], NbConstraints
* Dimension
);
2346 /* Allocate space for ray matrix 'Ray' */
2347 Ray
= Matrix_Alloc(NbMaxRays
, Dimension
);
2349 errormsg1("AddConstraints", "outofmem", "out of memory space");
2350 UNCATCH(any_exception_error
);
2353 Ray
->NbRows
= NbRay
;
2355 /* Copy rays of polyhedron 'Pol' to matrix 'Ray' */
2357 Vector_Copy(Pol
->Ray
[0], Ray
->p
[0], NbRay
* Dimension
);
2359 /* Create the saturation matrix 'Sat' from constraint matrix 'Mat' and */
2360 /* ray matrix 'Ray' . */
2361 Sat
= BuildSat(Mat
, Ray
, Pol
->NbConstraints
, NbMaxRays
);
2363 /* Create the ray matrix 'Ray' from the constraint matrix 'Mat' */
2364 Pol_status
= Chernikova(Mat
, Ray
, Sat
, Pol
->NbBid
, NbMaxRays
, Pol
->NbConstraints
,0);
2366 /* Remove redundant constraints from matrix 'Mat' */
2367 NewPol
= Remove_Redundants(Mat
, Ray
, Sat
, 0);
2371 UNCATCH(any_exception_error
);
2376 } /* AddConstraints */
2379 * Return 1 if 'Pol1' includes (covers) 'Pol2', 0 otherwise.
2380 * Polyhedron 'A' includes polyhedron 'B' if the rays of 'B' saturate
2381 * the equalities and verify the inequalities of 'A'. Both 'Pol1' and
2382 * 'Pol2' have same dimensions.
2384 int PolyhedronIncludes(Polyhedron
*Pol1
,Polyhedron
*Pol2
) {
2386 int Dimension
= Pol1
->Dimension
+ 1; /* Homogenous Dimension */
2390 POL_ENSURE_FACETS(Pol1
);
2391 POL_ENSURE_VERTICES(Pol1
);
2392 POL_ENSURE_FACETS(Pol2
);
2393 POL_ENSURE_VERTICES(Pol2
);
2396 for (k
=0; k
<Pol1
->NbConstraints
; k
++) {
2397 for (i
=0;i
<Pol2
->NbRays
;i
++) {
2399 /* Compute the dot product of ray(i) and constraint(k) and store in p3 */
2400 p1
= Pol2
->Ray
[i
]+1;
2401 p2
= Pol1
->Constraint
[k
]+1;
2403 for(j
=0;j
<Dimension
;j
++) {
2404 value_addmul(p3
, *p1
,*p2
);
2408 /* If (p3 < 0) or (p3 > 0 and (constraint(k) is equality
2409 or ray(i) is a line)), return 0 */
2410 if(value_neg_p(p3
) ||
2411 (value_notzero_p(p3
)
2412 && (value_zero_p(Pol1
->Constraint
[k
][0]) || (value_zero_p(Pol2
->Ray
[i
][0])) ) )) {
2420 } /* PolyhedronIncludes */
2423 * Add Polyhedron 'Pol' to polhedral domain 'PolDomain'. If 'Pol' covers
2424 * some polyhedron in the domain 'PolDomain', it is removed from the list.
2425 * On the other hand if some polyhedron in the domain covers polyhedron
2426 * 'Pol' then 'Pol' is not included in the domain.
2428 Polyhedron
*AddPolyToDomain(Polyhedron
*Pol
,Polyhedron
*PolDomain
) {
2430 Polyhedron
*p
, *pnext
, *p_domain_end
= (Polyhedron
*) 0;
2438 POL_ENSURE_FACETS(Pol
);
2439 POL_ENSURE_VERTICES(Pol
);
2441 /* Check for emptiness of polyhedron 'Pol' */
2443 Polyhedron_Free(Pol
);
2447 POL_ENSURE_FACETS(PolDomain
);
2448 POL_ENSURE_VERTICES(PolDomain
);
2450 /* Check for emptiness of polyhedral domain 'PolDomain' */
2451 if (emptyQ(PolDomain
)) {
2452 Polyhedron_Free(PolDomain
);
2456 /* Test 'Pol' against the domain 'PolDomain' */
2458 for (p
=PolDomain
,PolDomain
=(Polyhedron
*)0; p
; p
=pnext
) {
2460 /* If 'Pol' covers 'p' */
2461 if (PolyhedronIncludes(Pol
, p
))
2465 Polyhedron_Free( p
);
2469 /* Add polyhedron p to the new domain list */
2470 if (!PolDomain
) PolDomain
= p
; else p_domain_end
->next
= p
;
2473 /* If p covers Pol */
2474 if (PolyhedronIncludes(p
,Pol
)) {
2482 /* The whole list has been checked. Add new polyhedron 'Pol' to the */
2483 /* new domain list. */
2484 if (!PolDomain
) PolDomain
= Pol
; else p_domain_end
->next
= Pol
;
2488 /* The rest of the list is just inherited from p */
2489 Polyhedron_Free(Pol
);
2492 } /* AddPolyToDomain */
2495 * Given a polyhedra 'Pol' and a single constraint 'Con' and an integer 'Pass'
2496 * whose value ranges from 0 to 3, add the inverse of constraint 'Con' to the
2497 * constraint set of 'Pol' and return the new polyhedron. 'NbMaxRays' is the
2498 * maximum allowed rays in the new generated polyhedron.
2499 * If Pass == 0, add ( -constraint -1) >= 0
2500 * If Pass == 1, add ( +constraint -1) >= 0
2501 * If Pass == 2, add ( -constraint ) >= 0
2502 * If Pass == 3, add ( +constraint ) >= 0
2504 Polyhedron
*SubConstraint(Value
*Con
,Polyhedron
*Pol
,unsigned NbMaxRays
,int Pass
) {
2506 Polyhedron
*NewPol
= NULL
;
2507 Matrix
*Mat
= NULL
, *Ray
= NULL
;
2508 SatMatrix
*Sat
= NULL
;
2509 unsigned NbRay
, NbCon
, NbEle1
, Dimension
;
2512 POL_ENSURE_FACETS(Pol
);
2513 POL_ENSURE_VERTICES(Pol
);
2515 CATCH(any_exception_error
) {
2516 if (NewPol
) Polyhedron_Free(NewPol
);
2517 if (Mat
) Matrix_Free(Mat
);
2518 if (Ray
) Matrix_Free(Ray
);
2519 if (Sat
) SMFree(&Sat
);
2524 /* If 'Con' is the positivity constraint, return Null */
2525 Dimension
= Pol
->Dimension
+1; /* Homogeneous Dimension */
2526 for (i
=1; i
<Dimension
; i
++)
2527 if (value_notzero_p(Con
[i
])) break;
2529 UNCATCH(any_exception_error
);
2530 return (Polyhedron
*) 0;
2533 NbRay
= Pol
->NbRays
;
2534 NbCon
= Pol
->NbConstraints
;
2535 Dimension
= Pol
->Dimension
+2; /* Homogeneous Dimension + Status */
2536 NbEle1
= NbCon
* Dimension
;
2538 /* Ignore for now */
2539 if (POL_ISSET(NbMaxRays
, POL_NO_DUAL
))
2542 if (NbRay
> NbMaxRays
)
2545 Mat
= Matrix_Alloc(NbCon
+ 1, Dimension
);
2547 errormsg1("SubConstraint", "outofmem", "out of memory space");
2548 UNCATCH(any_exception_error
);
2552 /* Set the constraints of Pol */
2553 Vector_Copy(Pol
->Constraint
[0], Mat
->p
[0], NbEle1
);
2555 /* Add the new constraint */
2556 value_set_si(Mat
->p
[NbCon
][0],1);
2558 for(i
=1; i
<Dimension
; i
++)
2559 value_oppose(Mat
->p
[NbCon
][i
],Con
[i
]);
2561 for(i
=1; i
<Dimension
; i
++)
2562 value_assign(Mat
->p
[NbCon
][i
],Con
[i
]);
2564 value_decrement(Mat
->p
[NbCon
][Dimension
-1],Mat
->p
[NbCon
][Dimension
-1]);
2566 /* Allocate the ray matrix. */
2567 Ray
= Matrix_Alloc(NbMaxRays
, Dimension
);
2569 errormsg1("SubConstraint", "outofmem", "out of memory space");
2570 UNCATCH(any_exception_error
);
2574 /* Initialize the ray matrix with the rays of polyhedron 'Pol' */
2575 Ray
->NbRows
= NbRay
;
2577 Vector_Copy(Pol
->Ray
[0], Ray
->p
[0], NbRay
* Dimension
);
2579 /* Create the saturation matrix from the constraint matrix 'mat' and */
2580 /* ray matrix 'Ray'. */
2581 Sat
= BuildSat(Mat
, Ray
, NbCon
, NbMaxRays
);
2583 /* Create the ray matrix 'Ray' from consraint matrix 'Mat' */
2584 Pol_status
= Chernikova(Mat
, Ray
, Sat
, Pol
->NbBid
, NbMaxRays
, NbCon
,0);
2586 /* Remove redundant constraints from matrix 'Mat' */
2587 NewPol
= Remove_Redundants(Mat
, Ray
, Sat
, 0);
2591 UNCATCH(any_exception_error
);
2597 } /* SubConstraint */
2600 * Return the intersection of two polyhedral domains 'Pol1' and 'Pol2'.
2601 * The maximum allowed rays in the new polyhedron generated is 'NbMaxRays'.
2603 Polyhedron
*DomainIntersection(Polyhedron
*Pol1
,Polyhedron
*Pol2
,unsigned NbMaxRays
) {
2605 Polyhedron
*p1
, *p2
, *p3
, *d
;
2607 if (!Pol1
|| !Pol2
) return (Polyhedron
*) 0;
2608 if (Pol1
->Dimension
!= Pol2
->Dimension
) {
2609 errormsg1( "DomainIntersection", "diffdim",
2610 "operation on different dimensions");
2611 return (Polyhedron
*) 0;
2614 /* For every polyhedron pair (p1,p2) where p1 belongs to domain Pol1 and */
2615 /* p2 belongs to domain Pol2, compute the intersection and add it to the */
2616 /* new domain 'd'. */
2617 d
= (Polyhedron
*)0;
2618 for (p1
=Pol1
; p1
; p1
=p1
->next
) {
2619 for (p2
=Pol2
; p2
; p2
=p2
->next
) {
2620 p3
= AddConstraints(p2
->Constraint
[0],
2621 p2
->NbConstraints
, p1
, NbMaxRays
);
2622 d
= AddPolyToDomain(p3
,d
);
2626 return Empty_Polyhedron(Pol1
->Dimension
);
2630 } /* DomainIntersection */
2633 * Given a polyhedron 'Pol', return a matrix of rays.
2635 Matrix
*Polyhedron2Rays(Polyhedron
*Pol
) {
2638 unsigned NbRays
, Dimension
;
2640 POL_ENSURE_POINTS(Pol
);
2642 NbRays
= Pol
->NbRays
;
2643 Dimension
= Pol
->Dimension
+2; /* Homogeneous Dimension + Status */
2644 Ray
= Matrix_Alloc(NbRays
, Dimension
);
2646 errormsg1("Polyhedron2Rays", "outofmem", "out of memory space");
2649 Vector_Copy(Pol
->Ray
[0], Ray
->p_Init
, NbRays
*Dimension
);
2651 } /* Polyhedron2Rays */
2654 * Add 'NbAddedRays' rays to polyhedron 'Pol'. Rays are pointed by 'AddedRays'
2655 * and the maximum allowed constraints in the new polyhedron is 'NbMaxConstrs'.
2657 Polyhedron
*AddRays(Value
*AddedRays
,unsigned NbAddedRays
,Polyhedron
*Pol
,unsigned NbMaxConstrs
) {
2659 Polyhedron
*NewPol
= NULL
;
2660 Matrix
*Mat
= NULL
, *Ray
= NULL
;
2661 SatMatrix
*Sat
= NULL
, *SatTranspose
= NULL
;
2662 unsigned NbCon
, NbRay
,NbEle1
, Dimension
;
2664 POL_ENSURE_FACETS(Pol
);
2665 POL_ENSURE_VERTICES(Pol
);
2667 CATCH(any_exception_error
) {
2668 if (NewPol
) Polyhedron_Free(NewPol
);
2669 if (Mat
) Matrix_Free(Mat
);
2670 if (Ray
) Matrix_Free(Ray
);
2671 if (Sat
) SMFree(&Sat
);
2672 if (SatTranspose
) SMFree(&SatTranspose
);
2677 NbCon
= Pol
->NbConstraints
;
2678 NbRay
= Pol
->NbRays
;
2679 Dimension
= Pol
->Dimension
+ 2; /* Homogeneous Dimension + Status */
2680 NbEle1
= NbRay
* Dimension
;
2682 Ray
= Matrix_Alloc(NbAddedRays
+ NbRay
, Dimension
);
2684 errormsg1("AddRays", "outofmem", "out of memory space");
2685 UNCATCH(any_exception_error
);
2689 /* Copy rays of polyhedron 'Pol' to matrix 'Ray' */
2691 Vector_Copy(Pol
->Ray
[0], Ray
->p_Init
, NbEle1
);
2693 /* Add the new rays pointed by 'AddedRays' to matrix 'Ray' */
2694 Vector_Copy(AddedRays
, Ray
->p_Init
+NbEle1
, NbAddedRays
* Dimension
);
2696 /* Ignore for now */
2697 if (POL_ISSET(NbMaxConstrs
, POL_NO_DUAL
))
2700 /* We need at least NbCon rows */
2701 if (NbMaxConstrs
< NbCon
)
2702 NbMaxConstrs
= NbCon
;
2704 /* Allocate space for constraint matrix 'Mat' */
2705 Mat
= Matrix_Alloc(NbMaxConstrs
, Dimension
);
2707 errormsg1("AddRays", "outofmem", "out of memory space");
2708 UNCATCH(any_exception_error
);
2711 Mat
->NbRows
= NbCon
;
2713 /* Copy constraints of polyhedron 'Pol' to matrix 'Mat' */
2714 Vector_Copy(Pol
->Constraint
[0], Mat
->p_Init
, NbCon
*Dimension
);
2716 /* Create the saturation matrix 'SatTranspose' from constraint matrix */
2717 /* 'Mat' and ray matrix 'Ray'. Remember the saturation matrix is */
2718 /* referenced by (constraint,ray) pair */
2719 SatTranspose
= BuildSat(Ray
, Mat
, NbRay
, NbMaxConstrs
);
2721 /* Create the constraint matrix 'Mat' from the ray matrix 'Ray' */
2722 Pol_status
= Chernikova(Ray
, Mat
, SatTranspose
, Pol
->NbEq
, NbMaxConstrs
, NbRay
,1);
2724 /* Transform the saturation matrix 'SatTranspose' in the standard format */
2725 /* , that is, (ray X constraint) format. */
2726 Sat
= TransformSat(Mat
, Ray
, SatTranspose
);
2727 SMFree(&SatTranspose
), SatTranspose
= NULL
;
2729 /* Remove redundant rays from the ray matrix 'Ray' */
2730 NewPol
= Remove_Redundants(Mat
, Ray
, Sat
, 0);
2732 SMFree(&Sat
), Sat
= NULL
;
2733 Matrix_Free(Mat
), Mat
= NULL
;
2734 Matrix_Free(Ray
), Ray
= NULL
;
2737 UNCATCH(any_exception_error
);
2742 * Add rays pointed by 'Ray' to each and every polyhedron in the polyhedral
2743 * domain 'Pol'. 'NbMaxConstrs' is maximum allowed constraints in the
2744 * constraint set of a polyhedron.
2746 Polyhedron
*DomainAddRays(Polyhedron
*Pol
,Matrix
*Ray
,unsigned NbMaxConstrs
) {
2748 Polyhedron
*PolA
, *PolEndA
, *p1
, *p2
, *p3
;
2751 if (!Pol
) return (Polyhedron
*) 0;
2752 if (!Ray
|| Ray
->NbRows
== 0)
2753 return Domain_Copy(Pol
);
2754 if (Pol
->Dimension
!= Ray
->NbColumns
-2) {
2756 "DomainAddRays", "diffdim", "operation on different dimensions");
2757 return (Polyhedron
*) 0;
2760 /* Copy Pol to PolA */
2761 PolA
= PolEndA
= (Polyhedron
*)0;
2762 for (p1
=Pol
; p1
; p1
=p1
->next
) {
2763 p3
= AddRays(Ray
->p
[0], Ray
->NbRows
, p1
, NbMaxConstrs
);
2765 /* Does any component of PolA cover 'p3' ? */
2767 for (p2
=PolA
; p2
; p2
=p2
->next
) {
2768 if (PolyhedronIncludes(p2
, p3
)) { /* If p2 covers p3 */
2774 /* If the new polyheron is not redundant, add it ('p3') to the list */
2776 Polyhedron_Free(p3
);
2779 PolEndA
= PolA
= p3
;
2782 PolEndA
= PolEndA
->next
;
2787 } /* DomainAddRays */
2790 * Create a copy of the polyhedron 'Pol'
2792 Polyhedron
*Polyhedron_Copy(Polyhedron
*Pol
) {
2796 if (!Pol
) return (Polyhedron
*)0;
2798 /* Allocate space for the new polyhedron */
2799 Pol1
= Polyhedron_Alloc(Pol
->Dimension
, Pol
->NbConstraints
, Pol
->NbRays
);
2801 errormsg1("Polyhedron_Copy", "outofmem", "out of memory space");
2804 if( Pol
->NbConstraints
)
2805 Vector_Copy(Pol
->Constraint
[0], Pol1
->Constraint
[0],
2806 Pol
->NbConstraints
*(Pol
->Dimension
+2));
2808 Vector_Copy(Pol
->Ray
[0], Pol1
->Ray
[0],
2809 Pol
->NbRays
*(Pol
->Dimension
+2));
2810 Pol1
->NbBid
= Pol
->NbBid
;
2811 Pol1
->NbEq
= Pol
->NbEq
;
2812 Pol1
->flags
= Pol
->flags
;
2814 } /* Polyhedron_Copy */
2817 * Create a copy of a polyhedral domain.
2819 Polyhedron
*Domain_Copy(Polyhedron
*Pol
) {
2823 if (!Pol
) return (Polyhedron
*) 0;
2824 Pol1
= Polyhedron_Copy(Pol
);
2825 if (Pol
->next
) Pol1
->next
= Domain_Copy(Pol
->next
);
2830 * Given constraint number 'k' of a polyhedron, and an array 'Filter' to store
2831 * the non-redundant constraints of the polyhedron in bit-wise notation, and
2832 * a Matrix 'Sat', add the constraint 'k' in 'Filter' array. tmpR[i] stores the
2833 * number of constraints, other than those in 'Filter', which ray(i) saturates
2834 * or verifies. In case, ray(i) does not saturate or verify a constraint in
2835 * array 'Filter', it is assigned to -1. Similarly, tmpC[j] stores the number
2836 * of rays which constraint(j), if it doesn't belong to Filter, saturates or
2837 * verifies. If constraint(j) belongs to 'Filter', then tmpC[j] is assigned to
2838 * -1. 'NbConstraints' is the number of constraints in the constraint matrix of
2840 * NOTE: (1) 'Sat' is not the saturation matrix of the polyhedron. In fact,
2841 * entry in 'Sat' is set to 1 if ray(i) of polyhedron1 verifies or
2842 * saturates the constraint(j) of polyhedron2 and otherwise it is set
2843 * to 0. So here the difference with saturation matrix is in terms
2844 * definition and entries(1<->0) of the matrix 'Sat'.
2847 * (1) Include constraint(k) in array 'Filter'.
2848 * (2) Set tmpC[k] to -1.
2849 * (3) For all ray(i) {
2850 * If ray(i) saturates or verifies constraint(k) then --(tmpR[i])
2852 * Discard ray(i) by assigning tmpR[i] = -1
2853 * Decrement tmpC[j] for all constraint(j) not in array 'Filter'.
2857 static void addToFilter(int k
, unsigned *Filter
, SatMatrix
*Sat
,Value
*tmpR
,Value
*tmpC
,int NbRays
,int NbConstraints
) {
2862 /* Remove constraint k */
2863 kj
= k
/WSIZE
; kb
= MSB
; kb
>>= k
%WSIZE
;
2865 value_set_si(tmpC
[k
],-1);
2867 /* Remove rays excluded by constraint k */
2868 for(i
=0; i
<NbRays
; i
++)
2869 if (value_posz_p(tmpR
[i
])) {
2870 if (Sat
->p
[i
][kj
]&kb
)
2871 value_decrement(tmpR
[i
],tmpR
[i
]); /* adjust included ray */
2874 /* Constraint k excludes ray i -- delete ray i */
2875 value_set_si(tmpR
[i
],-1);
2877 /* Adjust non-deleted constraints */
2879 for(j
=0; j
<NbConstraints
; j
++) {
2880 if (value_posz_p(tmpC
[j
]) && (Sat
->p
[i
][jx
]&bx
) )
2881 value_decrement(tmpC
[j
],tmpC
[j
]);
2889 * Given polyhedra 'P1' and 'P2' such that their intersection is an empty
2890 * polyhedron, find the minimal set of constraints of 'P1' which contradict
2891 * all of the constraints of 'P2'. This is believed to be an NP-hard problem
2892 * and so a heuristic is employed to solve it in worst case. The heuristic is
2893 * to select in every turn that constraint of 'P1' which excludes most rays of
2894 * 'P2'. A bit in the binary format of an element of array 'Filter' is set to
2895 * 1 if the corresponding constraint is to be included in the minimal set of
2896 * constraints otherwise it is set to 0.
2898 static void FindSimple(Polyhedron
*P1
,Polyhedron
*P2
,unsigned *Filter
,unsigned NbMaxRays
) {
2901 SatMatrix
*Sat
= NULL
;
2902 int i
, j
, k
, jx
, found
;
2904 unsigned Dimension
, NbRays
, NbConstraints
, bx
, nc
;
2905 Value NbConstraintsLeft
, tmp
;
2906 Value
*tmpC
= NULL
, *tmpR
= NULL
;
2907 Polyhedron
*Pol
= NULL
, *Pol2
= NULL
;
2909 /* Initialize all the 'Value' variables */
2910 value_init(p3
); value_init(NbConstraintsLeft
);
2913 CATCH(any_exception_error
) {
2914 if (tmpC
) free(tmpC
);
2915 if (tmpR
) free(tmpR
);
2916 if (Mat
) Matrix_Free(Mat
);
2917 if (Sat
) SMFree(&Sat
);
2918 if (Pol2
&& Pol2
!=P2
) Polyhedron_Free(Pol2
);
2919 if (Pol
&& Pol
!=Pol2
&& Pol
!=P2
) Polyhedron_Free(Pol
);
2921 /* Clear all the 'Value' variables */
2922 value_clear(p3
); value_clear(NbConstraintsLeft
);
2928 Dimension
= P1
->Dimension
+2; /* status + homogeneous Dimension */
2929 Mat
= Matrix_Alloc(P1
->NbConstraints
, Dimension
);
2931 errormsg1("FindSimple", "outofmem", "out of memory space");
2932 UNCATCH(any_exception_error
);
2934 /* Clear all the 'Value' variables */
2935 value_clear(p3
); value_clear(NbConstraintsLeft
); value_clear(tmp
);
2939 /* Post constraints in P1 already included by Filter */
2940 jx
= 0; bx
= MSB
; Mat
->NbRows
=0;
2941 value_set_si(NbConstraintsLeft
,0);
2942 for (k
=0; k
<P1
->NbConstraints
; k
++) {
2943 if (Filter
[jx
]&bx
) {
2944 Vector_Copy(P1
->Constraint
[k
], Mat
->p
[Mat
->NbRows
], Dimension
);
2948 value_increment(NbConstraintsLeft
,NbConstraintsLeft
);
2955 Pol
= Polyhedron_Copy(Pol2
);
2957 Pol
= AddConstraints(Mat
->p_Init
, Mat
->NbRows
, Pol2
, NbMaxRays
);
2958 if (Pol2
!= P2
) Polyhedron_Free(Pol2
), Pol2
= NULL
;
2961 Matrix_Free(Mat
), Mat
= NULL
;
2962 Polyhedron_Free(Pol
), Pol
= NULL
;
2963 UNCATCH(any_exception_error
);
2965 /* Clear all the 'Value' variables */
2966 value_clear(p3
); value_clear(NbConstraintsLeft
); value_clear(tmp
);
2969 Mat
->NbRows
= 0; /* Reset Mat */
2972 /* Its not enough-- find some more constraints */
2973 Dimension
= Pol
->Dimension
+1; /* homogeneous Dimension */
2974 NbRays
= Pol
->NbRays
;
2975 NbConstraints
= P1
->NbConstraints
;
2976 tmpR
= (Value
*)malloc(NbRays
*sizeof(Value
));
2978 errormsg1("FindSimple", "outofmem", "out of memory space");
2979 UNCATCH(any_exception_error
);
2981 /* Clear all the 'Value' variables */
2982 value_clear(p3
); value_clear(NbConstraintsLeft
); value_clear(tmp
);
2985 for(i
=0;i
<NbRays
;i
++)
2986 value_init(tmpR
[i
]);
2987 tmpC
= (Value
*)malloc(NbConstraints
*sizeof(Value
));
2989 errormsg1("FindSimple", "outofmem", "out of memory space");
2990 UNCATCH(any_exception_error
);
2992 /* Clear all the 'Value' variables */
2993 value_clear(p3
); value_clear(NbConstraintsLeft
);
2994 for(i
=0;i
<NbRays
;i
++)
2995 value_clear(tmpR
[i
]);
2999 for(i
=0;i
<NbConstraints
;i
++)
3000 value_init(tmpC
[i
]);
3001 Vector_Set(tmpR
,0,NbRays
);
3002 Vector_Set(tmpC
,0,NbConstraints
);
3004 /* Build the Sat matrix */
3005 nc
= (NbConstraints
- 1) / (sizeof(int)*8) + 1;
3006 Sat
= SMAlloc(NbRays
, nc
);
3007 Sat
->NbRows
= NbRays
;
3008 SMVector_Init(Sat
->p_init
, nc
*NbRays
);
3011 for (k
=0; k
<NbConstraints
; k
++) {
3013 value_set_si(tmpC
[k
],-1);
3015 for (i
=0; i
<NbRays
; i
++) {
3017 p2
= P1
->Constraint
[k
]+1;
3019 for (j
=0; j
<Dimension
; j
++) {
3020 value_addmul(p3
, *p1
, *p2
);
3023 if(value_zero_p(p3
) ||
3024 (value_pos_p(p3
) && value_notzero_p(P1
->Constraint
[k
][0]))) {
3025 Sat
->p
[i
][jx
]|=bx
; /* constraint includes ray, set flag */
3026 value_increment(tmpR
[i
],tmpR
[i
]);
3027 value_increment(tmpC
[k
],tmpC
[k
]);
3033 do { /* find all of the essential constraints */
3035 for(i
=0; i
<NbRays
; i
++)
3036 if(value_posz_p(tmpR
[i
])) {
3037 value_add_int(tmp
,tmpR
[i
],1);
3038 if(value_eq(tmp
,NbConstraintsLeft
)) {
3040 /* Ray i is excluded by only one constraint... find it */
3042 for(k
=0; k
<NbConstraints
; k
++) {
3043 if(value_posz_p(tmpC
[k
]) && ((Sat
->p
[i
][jx
]&bx
)==0)) {
3044 addToFilter(k
, Filter
, Sat
, tmpR
, tmpC
,
3045 NbRays
, NbConstraints
);
3046 Vector_Copy(P1
->Constraint
[k
],
3047 Mat
->p
[Mat
->NbRows
],Dimension
+1);
3049 value_decrement(NbConstraintsLeft
,NbConstraintsLeft
);
3061 if (!Mat
->NbRows
) { /* Well then, just use a stupid heuristic */
3062 /* find the constraint which excludes the most */
3066 #ifndef LINEAR_VALUE_IS_CHARS
3067 value_set_si(cmax
,(NbRays
* NbConstraints
+1));
3069 value_set_si(cmax
,1);
3073 for(k
=0; k
<NbConstraints
; k
++)
3074 if (value_posz_p(tmpC
[k
])) {
3075 if (value_gt(cmax
,tmpC
[k
])) {
3076 value_assign(cmax
,tmpC
[k
]);
3082 errormsg1("DomSimplify","logerror","logic error");
3085 addToFilter(j
, Filter
, Sat
, tmpR
, tmpC
, NbRays
, NbConstraints
);
3086 Vector_Copy(P1
->Constraint
[j
],Mat
->p
[Mat
->NbRows
],Dimension
+1);
3088 value_decrement(NbConstraintsLeft
,NbConstraintsLeft
);
3091 SMFree(&Sat
), Sat
= NULL
;
3092 free(tmpC
), tmpC
= NULL
;
3093 free(tmpR
), tmpR
= NULL
;
3097 /* Clear all the 'Value' variables */
3098 value_clear(p3
); value_clear(NbConstraintsLeft
);
3100 for(i
=0;i
<NbRays
;i
++)
3101 value_clear(tmpR
[i
]);
3102 for(i
=0;i
<NbRays
;i
++)
3103 value_clear(tmpC
[i
]);
3105 UNCATCH(any_exception_error
);
3109 * Return 0 if the intersection of Pol1 and Pol2 is empty, otherwise return 1.
3110 * If the intersection is non-empty, store the non-redundant constraints in
3111 * 'Filter' array. If the intersection is empty then store the smallest set of
3112 * constraints of 'Pol1' which on intersection with 'Pol2' gives empty set, in
3113 * 'Filter' array. 'NbMaxRays' is the maximum allowed rays in the intersection
3114 * of 'Pol1' and 'Pol2'.
3116 static int SimplifyConstraints(Polyhedron
*Pol1
,Polyhedron
*Pol2
,unsigned *Filter
,unsigned NbMaxRays
) {
3118 Polyhedron
*Pol
= NULL
;
3119 Matrix
*Mat
= NULL
, *Ray
= NULL
;
3120 SatMatrix
*Sat
= NULL
;
3121 unsigned NbRay
, NbCon
, NbCon1
, NbCon2
, NbEle1
, Dimension
, notempty
;
3123 CATCH(any_exception_error
) {
3124 if (Pol
) Polyhedron_Free(Pol
);
3125 if (Mat
) Matrix_Free(Mat
);
3126 if (Ray
) Matrix_Free(Ray
);
3127 if (Sat
) SMFree(&Sat
);
3132 NbRay
= Pol1
->NbRays
;
3133 NbCon1
= Pol1
->NbConstraints
;
3134 NbCon2
= Pol2
->NbConstraints
;
3135 NbCon
= NbCon1
+ NbCon2
;
3136 Dimension
= Pol1
->Dimension
+2; /* Homogeneous Dimension + Status */
3137 NbEle1
= NbCon1
*Dimension
;
3139 /* Ignore for now */
3140 if (POL_ISSET(NbMaxRays
, POL_NO_DUAL
))
3143 if (NbRay
> NbMaxRays
)
3146 /* Allocate space for constraint matrix 'Mat' */
3147 Mat
= Matrix_Alloc(NbCon
, Dimension
);
3149 errormsg1("SimplifyConstraints", "outofmem", "out of memory space");
3150 UNCATCH(any_exception_error
);
3154 /* Copy constraints of 'Pol1' to matrix 'Mat' */
3155 Vector_Copy(Pol1
->Constraint
[0], Mat
->p_Init
, NbEle1
);
3157 /* Add constraints of 'Pol2' to matrix 'Mat'*/
3158 Vector_Copy(Pol2
->Constraint
[0], Mat
->p_Init
+NbEle1
, NbCon2
*Dimension
);
3160 /* Allocate space for ray matrix 'Ray' */
3161 Ray
= Matrix_Alloc(NbMaxRays
, Dimension
);
3163 errormsg1("SimplifyConstraints", "outofmem", "out of memory space");
3164 UNCATCH(any_exception_error
);
3167 Ray
->NbRows
= NbRay
;
3169 /* Copy rays of polyhedron 'Pol1' to matrix 'Ray' */
3170 Vector_Copy(Pol1
->Ray
[0], Ray
->p_Init
, NbRay
*Dimension
);
3172 /* Create saturation matrix from constraint matrix 'Mat' and ray matrix */
3174 Sat
= BuildSat(Mat
, Ray
, NbCon1
, NbMaxRays
);
3176 /* Create the ray matrix 'Ray' from the constraint matrix 'Mat' */
3177 Pol_status
= Chernikova(Mat
, Ray
, Sat
, Pol1
->NbBid
, NbMaxRays
, NbCon1
,0);
3179 /* Remove redundant constraints from the constraint matrix 'Mat' */
3180 Pol
= Remove_Redundants(Mat
, Ray
, Sat
, Filter
);
3182 if (Filter
&& emptyQ(Pol
)) {
3184 FindSimple(Pol1
, Pol2
, Filter
, NbMaxRays
);
3186 /* Polyhedron_Print(stderr,"%4d",Pol1); */
3188 Polyhedron_Free(Pol
), Pol
= NULL
;
3189 SMFree(&Sat
), Sat
= NULL
;
3190 Matrix_Free(Ray
), Ray
= NULL
;
3191 Matrix_Free(Mat
), Mat
= NULL
;
3195 UNCATCH(any_exception_error
);
3197 } /* SimplifyConstraints */
3200 * Eliminate equations of Pol1 using equations of Pol2. Mark as needed,
3201 * equations of Pol1 that are not eliminated. Or info into Filter vector.
3203 static void SimplifyEqualities(Polyhedron
*Pol1
, Polyhedron
*Pol2
, unsigned *Filter
) {
3206 unsigned ix
, bx
, NbEqn
, NbEqn1
, NbEqn2
, NbEle2
, Dimension
;
3209 NbEqn1
= Pol1
->NbEq
;
3210 NbEqn2
= Pol2
->NbEq
;
3211 NbEqn
= NbEqn1
+ NbEqn2
;
3212 Dimension
= Pol1
->Dimension
+2; /* Homogeneous Dimension + Status */
3213 NbEle2
= NbEqn2
*Dimension
;
3215 Mat
= Matrix_Alloc(NbEqn
, Dimension
);
3217 errormsg1("SimplifyEqualities", "outofmem", "out of memory space");
3222 /* Set the equalities of Pol2 */
3223 Vector_Copy(Pol2
->Constraint
[0], Mat
->p_Init
, NbEle2
);
3225 /* Add the equalities of Pol1 */
3226 Vector_Copy(Pol1
->Constraint
[0], Mat
->p_Init
+NbEle2
, NbEqn1
*Dimension
);
3228 Gauss(Mat
, NbEqn2
, Dimension
-1);
3232 for (i
=NbEqn2
; i
<NbEqn
; i
++) {
3233 for (j
=1; j
<Dimension
; j
++) {
3234 if (value_notzero_p(Mat
->p
[i
][j
])) {
3235 /* If any coefficient of the equation is non-zero */
3236 /* Set the filter bit for the equation */
3246 } /* SimplifyEqualities */
3250 * Given two polyhedral domains 'Pol1' and 'Pol2', find the largest domain
3251 * set (or the smallest list of non-redundant constraints), that when
3252 * intersected with polyhedral domain 'Pol2' equals (Pol1)intersect(Pol2).
3253 * The output is a polyhedral domain with the "redundant" constraints removed.
3254 * 'NbMaxRays' is the maximium allowed rays in the new polyhedra.
3256 Polyhedron
*DomainSimplify(Polyhedron
*Pol1
, Polyhedron
*Pol2
, unsigned NbMaxRays
) {
3258 Polyhedron
*p1
, *p2
, *p3
, *d
;
3259 unsigned k
, jx
, bx
, nbentries
, NbConstraints
, Dimension
, NbCon
, empty
;
3261 Matrix
*Constraints
;
3264 if (!Pol1
|| !Pol2
) return Pol1
;
3265 if (Pol1
->Dimension
!= Pol2
->Dimension
) {
3266 errormsg1("DomSimplify","diffdim","operation on different dimensions");
3270 POL_ENSURE_VERTICES(Pol1
);
3271 POL_ENSURE_VERTICES(Pol2
);
3272 if (emptyQ(Pol1
)||emptyQ(Pol2
))
3273 return Empty_Polyhedron(Pol1
->Dimension
);
3275 /* Find the maximum number of constraints over all polyhedron in the */
3276 /* polyhedral domain 'Pol2' and store in 'NbCon'. */
3278 for (p2
=Pol2
; p2
; p2
=p2
->next
)
3279 if (p2
->NbConstraints
> NbCon
)
3280 NbCon
= p2
->NbConstraints
;
3282 Dimension
= Pol1
->Dimension
+2; /* Homogenous Dimension + Status */
3283 d
= (Polyhedron
*)0;
3284 for (p1
=Pol1
; p1
; p1
=p1
->next
) {
3286 POL_ENSURE_VERTICES(p1
);
3288 /* Filter is an array of integers, each bit in an element of Filter */
3289 /* array corresponds to a constraint. The bit is marked 1 if the */
3290 /* corresponding constraint is non-redundant and is 0 if it is */
3293 NbConstraints
= p1
->NbConstraints
;
3294 nbentries
= (NbConstraints
+ NbCon
- 1) / (sizeof(int)*8) + 1;
3296 /* Allocate space for array 'Filter' */
3297 Filter
= (unsigned *)malloc(nbentries
* sizeof(int));
3299 errormsg1("DomSimplify", "outofmem", "out of memory space\n");
3304 /* Initialize 'Filter' with zeros */
3305 SMVector_Init(Filter
, nbentries
);
3307 /* Filter the constraints of p1 in context of polyhedra p2(s) */
3309 for (p2
=Pol2
; p2
; p2
=p2
->next
) {
3311 POL_ENSURE_VERTICES(p2
);
3313 /* Store the non-redundant constraints in array 'Filter'. With */
3314 /* successive loops, the array 'Filter' holds the union of all */
3315 /* non-redundant constraints. 'empty' is set to zero if the */
3316 /* intersection of two polyhedra is non-empty and Filter is !Null */
3318 SimplifyEqualities(p1
, p2
, Filter
);
3319 if (SimplifyConstraints(p1
, p2
, Filter
, NbMaxRays
))
3322 /* takes the union of all non redundant constraints */
3327 /* Copy all non-redundant constraints to matrix 'Constraints' */
3328 Constraints
= Matrix_Alloc(NbConstraints
, Dimension
);
3330 errormsg1("DomSimplify", "outofmem", "out of memory space\n");
3334 Constraints
->NbRows
= 0;
3335 for (k
=0, jx
=0, bx
=MSB
; k
<NbConstraints
; k
++) {
3337 /* If a bit entry in Filter[jx] is marked 1, copy the correspond- */
3338 /* ing constraint in matrix 'Constraints'. */
3339 if (Filter
[jx
]&bx
) {
3340 Vector_Copy(p1
->Constraint
[k
],
3341 Constraints
->p
[Constraints
->NbRows
],
3343 Constraints
->NbRows
++;
3348 /* Create the polyhedron 'p3' corresponding to the constraints in */
3349 /* matrix 'Constraints'. */
3350 p3
= Constraints2Polyhedron(Constraints
,NbMaxRays
);
3351 Matrix_Free(Constraints
);
3353 /* Add polyhedron 'p3' in the domain 'd'. */
3354 d
= AddPolyToDomain (p3
, d
);
3360 return Empty_Polyhedron(Pol1
->Dimension
);
3363 } /* DomainSimplify */
3366 * Domain Simplify as defined in Strasborg Polylib version.
3368 Polyhedron
*Stras_DomainSimplify(Polyhedron
*Pol1
,Polyhedron
*Pol2
,unsigned NbMaxRays
) {
3370 Polyhedron
*p1
, *p2
, *p3
= NULL
, *d
= NULL
;
3371 unsigned k
, jx
, bx
, nbentries
, NbConstraints
, Dimension
, NbCon
, empty
;
3372 unsigned *Filter
= NULL
;
3373 Matrix
*Constraints
= NULL
;
3375 CATCH(any_exception_error
) {
3376 if (Constraints
) Matrix_Free(Constraints
);
3377 if (Filter
) free(Filter
);
3378 if (d
) Polyhedron_Free(d
);
3379 if (p2
) Polyhedron_Free(p3
);
3383 if (!Pol1
|| !Pol2
) {
3384 UNCATCH(any_exception_error
);
3387 if (Pol1
->Dimension
!= Pol2
->Dimension
) {
3388 errormsg1("DomainSimplify","diffdim","operation on different dimensions");
3389 UNCATCH(any_exception_error
);
3392 POL_ENSURE_VERTICES(Pol1
);
3393 POL_ENSURE_VERTICES(Pol2
);
3394 if (emptyQ(Pol1
)||emptyQ(Pol2
)) {
3395 UNCATCH(any_exception_error
);
3396 return Empty_Polyhedron(Pol1
->Dimension
);
3399 /* Find the maximum number of constraints over all polyhedron in the */
3400 /* polyhedral domain 'Pol2' and store in 'NbCon'. */
3402 for (p2
=Pol2
; p2
; p2
=p2
->next
)
3403 if (p2
->NbConstraints
> NbCon
)
3404 NbCon
= p2
->NbConstraints
;
3406 Dimension
= Pol1
->Dimension
+2; /* Homogenous Dimension + Status */
3407 d
= (Polyhedron
*)0;
3408 for (p1
=Pol1
; p1
; p1
=p1
->next
) {
3410 /* Filter is an array of integers, each bit in an element of Filter */
3411 /* array corresponds to a constraint. The bit is marked 1 if the */
3412 /* corresponding constraint is non-redundant and is 0 if it is */
3415 NbConstraints
= p1
->NbConstraints
;
3416 nbentries
= (NbConstraints
+ NbCon
- 1)/(sizeof(int)*8) + 1;
3418 /* Allocate space for array 'Filter' */
3419 Filter
= (unsigned *)malloc(nbentries
* sizeof(int));
3421 errormsg1("DomainSimplify", "outofmem", "out of memory space");
3422 UNCATCH(any_exception_error
);
3426 /* Initialize 'Filter' with zeros */
3427 SMVector_Init(Filter
, nbentries
);
3429 /* Filter the constraints of p1 in context to the polyhedra p2(s) */
3431 for (p2
=Pol2
; p2
; p2
=p2
->next
) {
3433 /* Store the non-redundant constraints in array 'Filter'. With */
3434 /* successive loops, the array 'Filter' holds the union of all */
3435 /* non-redundant constraints. 'empty' is set to zero if the */
3436 /* intersection of two polyhedra is non-empty and Filter is !Null */
3438 if (SimplifyConstraints(p1
, p2
, Filter
, NbMaxRays
))
3444 /* Copy all non-redundant constraints to matrix 'Constraints' */
3445 Constraints
= Matrix_Alloc(NbConstraints
,Dimension
);
3447 errormsg1("DomainSimplify", "outofmem", "out of memory space");
3448 UNCATCH(any_exception_error
);
3451 Constraints
->NbRows
= 0;
3452 for (k
=0, jx
=0, bx
=MSB
; k
<NbConstraints
; k
++) {
3454 /* If a bit entry in Filter[jx] is marked 1, copy the correspond- */
3455 /* ing constraint in matrix 'Constraints'. */
3456 if (Filter
[jx
]&bx
) {
3457 Vector_Copy(p1
->Constraint
[k
],
3458 Constraints
->p
[Constraints
->NbRows
],
3460 Constraints
->NbRows
++;
3465 /* Create the polyhedron 'p3' corresponding to the constraints in */
3466 /* matrix 'Constraints'. */
3467 p3
= Constraints2Polyhedron(Constraints
,NbMaxRays
);
3468 Matrix_Free(Constraints
), Constraints
= NULL
;
3470 /* Add polyhedron 'p3' in the domain 'd'. */
3471 d
= AddPolyToDomain (p3
, d
);
3474 free(Filter
), Filter
= NULL
;
3478 UNCATCH(any_exception_error
);
3480 return Empty_Polyhedron(Pol1
->Dimension
);
3483 } /* DomainSimplify */
3486 * Return the Union of two polyhedral domains 'Pol1' and Pol2'. The result is
3487 * a new polyhedral domain.
3489 Polyhedron
*DomainUnion(Polyhedron
*Pol1
,Polyhedron
*Pol2
,unsigned NbMaxRays
) {
3491 Polyhedron
*PolA
, *PolEndA
, *PolB
, *PolEndB
, *p1
, *p2
;
3494 if (!Pol1
|| !Pol2
) return (Polyhedron
*) 0;
3495 if (Pol1
->Dimension
!= Pol2
->Dimension
) {
3496 errormsg1("DomainUnion","diffdim","operation on different dimensions");
3497 return (Polyhedron
*) 0;
3505 /* Copy 'Pol1' to 'PolA' */
3506 PolA
= PolEndA
= (Polyhedron
*)0;
3507 for (p1
=Pol1
; p1
; p1
=p1
->next
) {
3509 /* Does any component of 'Pol2' cover 'p1' ? */
3511 for (p2
=Pol2
; p2
; p2
=p2
->next
) {
3512 if (PolyhedronIncludes(p2
, p1
) ) { /* p2 covers p1 */
3522 /* Add 'p1' to 'PolA' */
3524 PolEndA
= PolA
= Polyhedron_Copy(p1
);
3526 PolEndA
->next
= Polyhedron_Copy(p1
);
3527 PolEndA
= PolEndA
->next
;
3533 /* Copy 'Pol2' to PolB */
3534 PolB
= PolEndB
= (Polyhedron
*)0;
3535 for (p2
=Pol2
; p2
; p2
=p2
->next
) {
3537 /* Does any component of PolA cover 'p2' ? */
3539 for (p1
=PolA
; p1
; p1
=p1
->next
) {
3540 if (PolyhedronIncludes(p1
, p2
)) { /* p1 covers p2 */
3547 /* Add 'p2' to 'PolB' */
3549 PolEndB
= PolB
= Polyhedron_Copy(p2
);
3551 PolEndB
->next
= Polyhedron_Copy(p2
);
3552 PolEndB
= PolEndB
->next
;
3559 if (!PolA
) return PolB
;
3560 PolEndA
->next
= PolB
;
3565 * Given a polyhedral domain 'Pol', concatenate the lists of rays and lines
3566 * of the two (or more) polyhedra in the domain into one combined list, and
3567 * find the set of constraints which tightly bound all of those objects.
3568 * 'NbMaxConstrs' is the maximum allowed constraints in the new polyhedron.
3570 Polyhedron
*DomainConvex(Polyhedron
*Pol
,unsigned NbMaxConstrs
) {
3572 Polyhedron
*p
, *q
, *NewPol
= NULL
;
3574 CATCH(any_exception_error
) {
3575 if (NewPol
) Polyhedron_Free(NewPol
);
3581 UNCATCH(any_exception_error
);
3582 return (Polyhedron
*) 0;
3585 POL_ENSURE_VERTICES(Pol
);
3586 NewPol
= Polyhedron_Copy(Pol
);
3587 for (p
=Pol
->next
; p
; p
=p
->next
) {
3588 POL_ENSURE_VERTICES(p
);
3589 q
= AddRays(p
->Ray
[0], p
->NbRays
, NewPol
, NbMaxConstrs
);
3590 Polyhedron_Free(NewPol
);
3595 UNCATCH(any_exception_error
);
3598 } /* DomainConvex */
3601 * Given polyhedral domains 'Pol1' and 'Pol2', create a new polyhedral
3602 * domain which is mathematically the differnce of the two domains.
3604 Polyhedron
*DomainDifference(Polyhedron
*Pol1
,Polyhedron
*Pol2
,unsigned NbMaxRays
) {
3606 Polyhedron
*p1
, *p2
, *p3
, *d
;
3609 if (!Pol1
|| !Pol2
) return (Polyhedron
*) 0;
3610 if (Pol1
->Dimension
!= Pol2
->Dimension
) {
3611 errormsg1("DomainDifference",
3612 "diffdim", "operation on different dimensions");
3613 return (Polyhedron
*) 0;
3615 POL_ENSURE_FACETS(Pol1
);
3616 POL_ENSURE_VERTICES(Pol1
);
3617 POL_ENSURE_FACETS(Pol2
);
3618 POL_ENSURE_VERTICES(Pol2
);
3619 if (emptyQ(Pol1
) || emptyQ(Pol2
))
3620 return (Domain_Copy(Pol1
));
3621 d
= (Polyhedron
*)0;
3622 for (p2
=Pol2
; p2
; p2
=p2
->next
) {
3623 for (p1
=Pol1
; p1
; p1
=p1
->next
) {
3624 for (i
=0; i
<p2
->NbConstraints
; i
++) {
3626 /* Add the constraint ( -p2->constraint[i] -1) >= 0 in 'p1' */
3627 /* and create the new polyhedron 'p3'. */
3628 p3
= SubConstraint(p2
->Constraint
[i
], p1
, NbMaxRays
,0);
3630 /* Add 'p3' in the new domain 'd' */
3631 d
= AddPolyToDomain (p3
, d
);
3633 /* If the constraint p2->constraint[i][0] is an equality, then */
3634 /* add the constraint ( +p2->constraint[i] -1) >= 0 in 'p1' and*/
3635 /* create the new polyhedron 'p3'. */
3637 if( value_notzero_p(p2
->Constraint
[i
][0]) ) /* Inequality */
3639 p3
= SubConstraint(p2
->Constraint
[i
], p1
, NbMaxRays
,1);
3641 /* Add 'p3' in the new domain 'd' */
3642 d
= AddPolyToDomain (p3
, d
);
3648 d
= (Polyhedron
*)0;
3651 return Empty_Polyhedron(Pol2
->Dimension
);
3654 } /* DomainDifference */
3657 * Given a polyhedral domain 'Pol', convert it to a new polyhedral domain
3658 * with dimension expanded to 'align_dimension'. 'NbMaxRays' is the maximum
3659 * allowed rays in the new polyhedra.
3661 Polyhedron
*align_context(Polyhedron
*Pol
,int align_dimension
,int NbMaxRays
) {
3664 Polyhedron
*p
= NULL
, **next
, *result
= NULL
;
3667 CATCH(any_exception_error
) {
3668 if (result
) Polyhedron_Free(result
);
3673 if (!Pol
) return Pol
;
3674 dim
= Pol
->Dimension
;
3675 if (align_dimension
< Pol
->Dimension
) {
3676 errormsg1("align_context", "diffdim", "context dimension exceeds data");
3677 UNCATCH(any_exception_error
);
3680 if (align_dimension
== Pol
->Dimension
) {
3681 UNCATCH(any_exception_error
);
3682 return Domain_Copy(Pol
);
3685 /* 'k' is the dimension increment */
3686 k
= align_dimension
- Pol
->Dimension
;
3689 /* Expand the dimension of all polyhedra in the polyhedral domain 'Pol' */
3690 for (; Pol
; Pol
=Pol
->next
) {
3691 int have_cons
= !F_ISSET(Pol
, POL_VALID
) || F_ISSET(Pol
, POL_INEQUALITIES
);
3692 int have_rays
= !F_ISSET(Pol
, POL_VALID
) || F_ISSET(Pol
, POL_POINTS
);
3693 unsigned NbCons
= have_cons
? Pol
->NbConstraints
: 0;
3694 unsigned NbRays
= have_rays
? Pol
->NbRays
+ k
: 0;
3696 if (Pol
->Dimension
!= dim
) {
3697 Domain_Free(result
);
3698 errormsg1("align_context", "diffdim", "context not of uniform dimension");
3699 UNCATCH(any_exception_error
);
3703 p
= Polyhedron_Alloc(align_dimension
, NbCons
, NbRays
);
3705 for (i
= 0; i
< NbCons
; ++i
) {
3706 value_assign(p
->Constraint
[i
][0], Pol
->Constraint
[i
][0]); /* Status bit */
3707 Vector_Copy(Pol
->Constraint
[i
]+1, p
->Constraint
[i
]+k
+1, Pol
->Dimension
+1);
3709 p
->NbEq
= Pol
->NbEq
;
3713 for (i
= 0; i
< k
; ++i
)
3714 value_set_si(p
->Ray
[i
][1+i
], 1); /* A line */
3715 for (i
= 0; i
< Pol
->NbRays
; ++i
) {
3716 value_assign(p
->Ray
[k
+i
][0], Pol
->Ray
[i
][0]); /* Status bit */
3717 Vector_Copy(Pol
->Ray
[i
]+1, p
->Ray
[i
+k
]+k
+1, Pol
->Dimension
+1);
3719 p
->NbBid
= Pol
->NbBid
+ k
;
3721 p
->flags
= Pol
->flags
;
3728 UNCATCH(any_exception_error
);
3730 } /* align_context */
3732 /*----------------------------------------------------------------------*/
3733 /* Polyhedron *Polyhedron_Scan(D, C, NbMaxRays) */
3734 /* D : Domain to be scanned (single polyhedron only) */
3735 /* C : Context domain */
3736 /* NbMaxRays : Workspace size */
3737 /* Returns a linked list of scan domains, outer loop first */
3738 /*----------------------------------------------------------------------*/
3739 Polyhedron
*Polyhedron_Scan(Polyhedron
*D
, Polyhedron
*C
,unsigned NbMaxRays
) {
3743 Polyhedron
*C1
, *C2
, *D1
, *D2
;
3744 Polyhedron
*res
, *last
, *tmp
;
3746 dim
= D
->Dimension
- C
->Dimension
;
3747 res
= last
= (Polyhedron
*) 0;
3748 if (dim
==0) return (Polyhedron
*)0;
3752 POL_ENSURE_FACETS(D
);
3753 POL_ENSURE_VERTICES(D
);
3754 POL_ENSURE_FACETS(C
);
3755 POL_ENSURE_VERTICES(C
);
3757 /* Allocate space for constraint matrix. */
3758 Mat
= Matrix_Alloc(D
->Dimension
, D
->Dimension
+2);
3760 errormsg1("Polyhedron_Scan", "outofmem", "out of memory space");
3763 C1
= align_context(C
,D
->Dimension
,NbMaxRays
);
3767 /* Vin100, aug 16, 2001: The context is intersected with D */
3768 D2
= DomainIntersection( C1
, D
, NbMaxRays
);
3770 for (i
=0; i
<dim
; i
++)
3772 Vector_Set(Mat
->p_Init
,0,D2
->Dimension
*(D2
->Dimension
+ 2));
3773 for (j
=i
+1; j
<dim
; j
++) {
3774 value_set_si(Mat
->p
[j
-i
-1][j
+1],1);
3776 Mat
->NbRows
= dim
-i
-1;
3777 D1
= Mat
->NbRows
? DomainAddRays(D2
, Mat
, NbMaxRays
) : D2
;
3778 tmp
= DomainSimplify(D1
, C1
, NbMaxRays
);
3779 if (!last
) res
= last
= tmp
;
3780 else { last
->next
= tmp
; last
= tmp
; }
3781 C2
= DomainIntersection(C1
, D1
, NbMaxRays
);
3784 if (Mat
->NbRows
) Domain_Free(D1
);
3790 } /* Polyhedron_Scan */
3792 /*---------------------------------------------------------------------*/
3793 /* int lower_upper_bounds(pos,P,context,LBp,UBp) */
3794 /* pos : index position of current loop index (1..hdim-1) */
3795 /* P: loop domain */
3796 /* context : context values for fixed indices */
3797 /* notice that context[hdim] must be 1 */
3798 /* LBp, UBp : pointers to resulting bounds */
3799 /* returns the flag = (UB_INFINITY, LB_INFINITY) */
3800 /*---------------------------------------------------------------------*/
3801 int lower_upper_bounds(int pos
,Polyhedron
*P
,Value
*context
,Value
*LBp
,Value
*UBp
) {
3805 Value n
, n1
, d
, tmp
;
3807 POL_ENSURE_FACETS(P
);
3808 POL_ENSURE_VERTICES(P
);
3810 /* Initialize all the 'Value' variables */
3811 value_init(LB
); value_init(UB
); value_init(tmp
);
3812 value_init(n
); value_init(n1
); value_init(d
);
3817 /* Compute Upper Bound and Lower Bound for current loop */
3818 flag
= LB_INFINITY
| UB_INFINITY
;
3819 for (i
=0; i
<P
->NbConstraints
; i
++) {
3820 value_assign(d
,P
->Constraint
[i
][pos
]);
3821 Inner_Product(&context
[1],&(P
->Constraint
[i
][1]),P
->Dimension
+1,&n
);
3822 if (value_zero_p(d
)) {
3823 /* If context doesn't satisfy constraints, return empty loop. */
3824 if (value_neg_p(n
) ||
3825 (value_zero_p(P
->Constraint
[i
][0]) && value_notzero_p(n
)))
3831 /*---------------------------------------------------*/
3832 /* Compute n/d n/d<0 n/d>0 */
3833 /*---------------------------------------------------*/
3834 /* n%d == 0 floor = n/d floor = n/d */
3835 /* ceiling = n/d ceiling = n/d */
3836 /*---------------------------------------------------*/
3837 /* n%d != 0 floor = n/d - 1 floor = n/d */
3838 /* ceiling = n/d ceiling = n/d + 1 */
3839 /*---------------------------------------------------*/
3841 /* Check to see if constraint is inequality */
3842 /* if constraint is equality, both upper and lower bounds are fixed */
3843 if(value_zero_p(P
->Constraint
[i
][0])) { /* Equality */
3844 value_modulus(tmp
,n
,d
);
3846 /* if not integer, return 0; */
3847 if (value_notzero_p(tmp
))
3850 value_division(n1
,n
,d
);
3852 /* Upper and Lower bounds found */
3853 if((flag
&LB_INFINITY
) || value_gt(n1
,LB
))
3854 value_assign(LB
,n1
);
3855 if((flag
&UB_INFINITY
) || value_lt(n1
,UB
))
3856 value_assign(UB
,n1
);
3860 if (value_pos_p(d
)) { /* Lower Bound */
3861 value_modulus(tmp
,n
,d
);
3863 /* n1 = ceiling(n/d) */
3864 if (value_pos_p(n
) && value_notzero_p(tmp
)) {
3865 value_division(n1
,n
,d
);
3866 value_add_int(n1
,n1
,1);
3869 value_division(n1
,n
,d
);
3870 if (flag
&LB_INFINITY
) {
3871 value_assign(LB
,n1
);
3874 else if(value_gt(n1
,LB
))
3875 value_assign(LB
,n1
);
3878 if (value_neg_p(d
)) { /* Upper Bound */
3879 value_modulus(tmp
,n
,d
);
3881 /* n1 = floor(n/d) */
3882 if (value_pos_p(n
) && value_notzero_p(tmp
)) {
3883 value_division(n1
,n
,d
);
3884 value_sub_int(n1
,n1
,1);
3887 value_division(n1
,n
,d
);
3889 if (flag
&UB_INFINITY
) {
3890 value_assign(UB
,n1
);
3893 else if (value_lt(n1
,UB
))
3894 value_assign(UB
, n1
);
3897 if ((flag
& LB_INFINITY
)==0) value_assign(*LBp
,LB
);
3898 if ((flag
& UB_INFINITY
)==0) value_assign(*UBp
,UB
);
3903 value_set_si(*LBp
, 1);
3904 value_set_si(*UBp
, 0); /* empty loop */
3907 /* Clear all the 'Value' variables */
3908 value_clear(LB
); value_clear(UB
); value_clear(tmp
);
3909 value_clear(n
); value_clear(n1
); value_clear(d
);
3911 } /* lower_upper_bounds */
3916 static void Rays_Mult(Value
**A
, Matrix
*B
, Value
**C
, unsigned NbRays
)
3919 unsigned Dimension1
, Dimension2
;
3922 value_init(Sum
); value_init(tmp
);
3924 CATCH(any_exception_error
) {
3925 value_clear(Sum
); value_clear(tmp
);
3929 Dimension1
= B
->NbRows
;
3930 Dimension2
= B
->NbColumns
;
3932 for (i
=0; i
<NbRays
; i
++) {
3933 value_assign(C
[i
][0],A
[i
][0]);
3934 for (j
=0; j
<Dimension2
; j
++) {
3935 value_set_si(Sum
,0);
3936 for (k
=0; k
<Dimension1
; k
++) {
3938 /* Sum+=A[i][k+1] * B->p[k][j]; */
3939 value_addmul(Sum
, A
[i
][k
+1], B
->p
[k
][j
]);
3941 value_assign(C
[i
][j
+1],Sum
);
3943 Vector_Gcd(C
[i
]+1, Dimension2
, &tmp
);
3944 if (value_notone_p(tmp
))
3945 Vector_AntiScale(C
[i
]+1, C
[i
]+1, tmp
, Dimension2
);
3948 UNCATCH(any_exception_error
);
3949 value_clear(Sum
); value_clear(tmp
);
3955 static void Rays_Mult_Transpose(Value
**A
, Matrix
*B
, Value
**C
,
3959 unsigned Dimension1
, Dimension2
;
3962 value_init(Sum
); value_init(tmp
);
3964 CATCH(any_exception_error
) {
3965 value_clear(Sum
); value_clear(tmp
);
3969 Dimension1
= B
->NbColumns
;
3970 Dimension2
= B
->NbRows
;
3972 for (i
=0; i
<NbRays
; i
++) {
3973 value_assign(C
[i
][0],A
[i
][0]);
3974 for (j
=0; j
<Dimension2
; j
++) {
3975 value_set_si(Sum
,0);
3976 for (k
=0; k
<Dimension1
; k
++) {
3978 /* Sum+=A[i][k+1] * B->p[j][k]; */
3979 value_addmul(Sum
, A
[i
][k
+1], B
->p
[j
][k
]);
3981 value_assign(C
[i
][j
+1],Sum
);
3983 Vector_Gcd(C
[i
]+1, Dimension2
, &tmp
);
3984 if (value_notone_p(tmp
))
3985 Vector_AntiScale(C
[i
]+1, C
[i
]+1, tmp
, Dimension2
);
3988 UNCATCH(any_exception_error
);
3989 value_clear(Sum
); value_clear(tmp
);
3993 * Given a polyhedron 'Pol' and a transformation matrix 'Func', return the
3994 * polyhedron which when transformed by mapping function 'Func' gives 'Pol'.
3995 * 'NbMaxRays' is the maximum number of rays that can be in the ray matrix
3996 * of the resulting polyhedron.
3998 Polyhedron
*Polyhedron_Preimage(Polyhedron
*Pol
,Matrix
*Func
,unsigned NbMaxRays
) {
4000 Matrix
*Constraints
= NULL
;
4001 Polyhedron
*NewPol
= NULL
;
4002 unsigned NbConstraints
, Dimension1
, Dimension2
;
4004 POL_ENSURE_INEQUALITIES(Pol
);
4006 CATCH(any_exception_error
) {
4007 if (Constraints
) Matrix_Free(Constraints
);
4008 if (NewPol
) Polyhedron_Free(NewPol
);
4013 NbConstraints
= Pol
->NbConstraints
;
4014 Dimension1
= Pol
->Dimension
+1; /* Homogeneous Dimension */
4015 Dimension2
= Func
->NbColumns
; /* Homogeneous Dimension */
4016 if (Dimension1
!=(Func
->NbRows
)) {
4017 errormsg1("Polyhedron_Preimage", "dimincomp", "incompatible dimensions");
4018 UNCATCH(any_exception_error
);
4019 return Empty_Polyhedron(Dimension2
-1);
4024 NbCon | | X Dim1| | = NbCon | |
4025 i |___| k |___| i |___|
4026 Pol->Constraints Function Constraints
4029 /* Allocate space for the resulting constraint matrix */
4030 Constraints
= Matrix_Alloc(NbConstraints
, Dimension2
+1);
4032 errormsg1("Polyhedron_Preimage", "outofmem", "out of memory space\n");
4034 UNCATCH(any_exception_error
);
4038 /* The new constraint matrix is the product of constraint matrix of the */
4039 /* polyhedron and the function matrix. */
4040 Rays_Mult(Pol
->Constraint
, Func
, Constraints
->p
, NbConstraints
);
4041 NewPol
= Constraints2Polyhedron(Constraints
, NbMaxRays
);
4042 Matrix_Free(Constraints
), Constraints
= NULL
;
4046 UNCATCH(any_exception_error
);
4049 } /* Polyhedron_Preimage */
4052 * Given a polyhedral domain 'Pol' and a transformation matrix 'Func', return
4053 * the polyhedral domain which when transformed by mapping function 'Func'
4054 * gives 'Pol'. 'NbMaxRays' is the maximum number of rays that can be in the
4055 * ray matrix of the resulting domain.
4057 Polyhedron
*DomainPreimage(Polyhedron
*Pol
,Matrix
*Func
,unsigned NbMaxRays
) {
4059 Polyhedron
*p
, *q
, *d
= NULL
;
4061 CATCH(any_exception_error
) {
4062 if (d
) Polyhedron_Free(d
);
4066 if (!Pol
|| !Func
) {
4067 UNCATCH(any_exception_error
);
4068 return (Polyhedron
*) 0;
4070 d
= (Polyhedron
*) 0;
4071 for (p
=Pol
; p
; p
=p
->next
) {
4072 q
= Polyhedron_Preimage(p
, Func
, NbMaxRays
);
4073 d
= AddPolyToDomain (q
, d
);
4076 UNCATCH(any_exception_error
);
4078 } /* DomainPreimage */
4081 * Transform a polyhedron 'Pol' into another polyhedron according to a given
4082 * affine mapping function 'Func'. 'NbMaxConstrs' is the maximum number of
4083 * constraints that can be in the constraint matrix of the new polyhedron.
4085 Polyhedron
*Polyhedron_Image(Polyhedron
*Pol
, Matrix
*Func
,unsigned NbMaxConstrs
) {
4087 Matrix
*Rays
= NULL
;
4088 Polyhedron
*NewPol
= NULL
;
4089 unsigned NbRays
, Dimension1
, Dimension2
;
4091 POL_ENSURE_FACETS(Pol
);
4092 POL_ENSURE_VERTICES(Pol
);
4094 CATCH(any_exception_error
) {
4095 if (Rays
) Matrix_Free(Rays
);
4096 if (NewPol
) Polyhedron_Free(NewPol
);
4101 NbRays
= Pol
->NbRays
;
4102 Dimension1
= Pol
->Dimension
+1; /* Homogeneous Dimension */
4103 Dimension2
= Func
->NbRows
; /* Homogeneous Dimension */
4104 if (Dimension1
!=Func
->NbColumns
) {
4105 errormsg1("Polyhedron_Image", "dimincomp", "incompatible dimensions");
4106 UNCATCH(any_exception_error
);
4107 return Empty_Polyhedron(Dimension2
-1);
4111 Dim1 / Dim1 \Transpose Dim2
4112 __k__ | __k__ | __j__
4113 NbRays| | X | Dim2 | | | = NbRays| |
4114 i |___| | j |___| | i |___|
4115 Pol->Rays \ Func / Rays
4119 if (Dimension1
== Dimension2
) {
4122 M
= Matrix_Copy(Func
);
4123 M2
= Matrix_Alloc(Dimension2
, Dimension1
);
4125 errormsg1("Polyhedron_Image", "outofmem", "out of memory space\n");
4126 UNCATCH(any_exception_error
);
4130 ok
= Matrix_Inverse(M
, M2
);
4133 NewPol
= Polyhedron_Alloc(Pol
->Dimension
, Pol
->NbConstraints
,
4136 errormsg1("Polyhedron_Image", "outofmem",
4137 "out of memory space\n");
4138 UNCATCH(any_exception_error
);
4141 Rays_Mult_Transpose(Pol
->Ray
, Func
, NewPol
->Ray
, NbRays
);
4142 Rays_Mult(Pol
->Constraint
, M2
, NewPol
->Constraint
,
4143 Pol
->NbConstraints
);
4144 NewPol
->NbEq
= Pol
->NbEq
;
4145 NewPol
->NbBid
= Pol
->NbBid
;
4147 Gauss4(NewPol
->Constraint
, NewPol
->NbEq
, NewPol
->NbConstraints
,
4148 NewPol
->Dimension
+1);
4150 Gauss4(NewPol
->Ray
, NewPol
->NbBid
, NewPol
->NbRays
,
4151 NewPol
->Dimension
+1);
4157 /* Allocate space for the resulting ray matrix */
4158 Rays
= Matrix_Alloc(NbRays
, Dimension2
+1);
4160 errormsg1("Polyhedron_Image", "outofmem", "out of memory space\n");
4161 UNCATCH(any_exception_error
);
4165 /* The new ray space is the product of ray matrix of the polyhedron and */
4166 /* the transpose matrix of the mapping function. */
4167 Rays_Mult_Transpose(Pol
->Ray
, Func
, Rays
->p
, NbRays
);
4168 NewPol
= Rays2Polyhedron(Rays
, NbMaxConstrs
);
4169 Matrix_Free(Rays
), Rays
= NULL
;
4174 UNCATCH(any_exception_error
);
4176 } /* Polyhedron_Image */
4179 *Transform a polyhedral domain 'Pol' into another domain according to a given
4180 * affine mapping function 'Func'. 'NbMaxConstrs' is the maximum number of
4181 * constraints that can be in the constraint matrix of the resulting domain.
4183 Polyhedron
*DomainImage(Polyhedron
*Pol
,Matrix
*Func
,unsigned NbMaxConstrs
) {
4185 Polyhedron
*p
, *q
, *d
= NULL
;
4187 CATCH(any_exception_error
) {
4188 if (d
) Polyhedron_Free(d
);
4193 if (!Pol
|| !Func
) {
4194 UNCATCH(any_exception_error
);
4195 return (Polyhedron
*) 0;
4197 d
= (Polyhedron
*) 0;
4198 for (p
=Pol
; p
; p
=p
->next
) {
4199 q
= Polyhedron_Image(p
, Func
, NbMaxConstrs
);
4200 d
= AddPolyToDomain (q
, d
);
4204 UNCATCH(any_exception_error
);
4210 * Given a polyhedron 'Pol' and an affine cost function 'Cost', compute the
4211 * maximum and minimum value of the function over set of points representing
4213 * Note: If Polyhedron 'Pol' is empty, then there is no feasible solution.
4214 * Otherwise, if there is a bidirectional ray with Sum[cost(i)*ray(i)] != 0 or
4215 * a unidirectional ray with Sum[cost(i)*ray(i)] >0, then the maximum is un-
4216 * bounded else the finite optimal solution occurs at one of the vertices of
4219 Interval
*DomainCost(Polyhedron
*Pol
,Value
*Cost
) {
4221 int i
, j
, NbRay
, Dim
;
4222 Value
*p1
, *p2
, p3
, d
, status
;
4223 Value tmp1
, tmp2
, tmp3
;
4227 value_init(p3
); value_init(d
); value_init(status
);
4228 value_init(tmp1
); value_init(tmp2
); value_init(tmp3
);
4230 POL_ENSURE_FACETS(Pol
);
4231 POL_ENSURE_VERTICES(Pol
);
4233 CATCH(any_exception_error
) {
4236 value_clear(p3
); value_clear(d
); value_clear(status
);
4237 value_clear(tmp1
); value_clear(tmp2
); value_clear(tmp3
);
4242 NbRay
= Pol
->NbRays
;
4243 Dim
= Pol
->Dimension
+1; /* Homogenous Dimension */
4244 I
= (Interval
*) malloc (sizeof(Interval
));
4246 errormsg1("DomainCost", "outofmem", "out of memory space\n");
4247 UNCATCH(any_exception_error
);
4248 value_clear(p3
); value_clear(d
); value_clear(status
);
4249 value_clear(tmp1
); value_clear(tmp2
); value_clear(tmp3
);
4253 /* The maximum and minimum values of the cost function over polyhedral */
4254 /* domain is stored in 'I'. I->MaxN and I->MaxD store the numerator and */
4255 /* denominator of the maximum value. Likewise,I->MinN and I->MinD store */
4256 /* the numerator and denominator of the minimum value. I->MaxI and */
4257 /* I->MinI store the ray indices corresponding to the max and min values*/
4258 /* of the function. */
4260 value_set_si(I
->MaxN
,-1);
4261 value_set_si(I
->MaxD
,0); /* Actual cost is MaxN/MaxD */
4263 value_set_si(I
->MinN
,1);
4264 value_set_si(I
->MinD
,0);
4267 /* Compute the cost of each ray[i] */
4268 for (i
=0; i
<NbRay
; i
++) {
4270 value_assign(status
, *p1
);
4274 /* p3 = *p1++ * *p2++; */
4275 value_multiply(p3
,*p1
,*p2
);
4277 for (j
=1; j
<Dim
; j
++) {
4278 value_multiply(tmp1
,*p1
,*p2
);
4280 /* p3 += *p1++ * *p2++; */
4281 value_addto(p3
,p3
,tmp1
);
4287 value_assign(d
,*p1
); /* d == 0 for lines and ray, non-zero for vertex */
4288 value_multiply(tmp1
,p3
,I
->MaxD
);
4289 value_multiply(tmp2
,I
->MaxN
,d
);
4290 value_set_si(tmp3
,1);
4292 /* Compare p3/d with MaxN/MaxD to assign new maximum cost value */
4294 value_gt(tmp1
,tmp2
) ||
4295 (value_eq(tmp1
,tmp2
) &&
4296 value_eq(d
,tmp3
) && value_ne(I
->MaxD
,tmp3
))) {
4297 value_assign(I
->MaxN
,p3
);
4298 value_assign(I
->MaxD
,d
);
4301 value_multiply(tmp1
,p3
,I
->MinD
);
4302 value_multiply(tmp2
,I
->MinN
,d
);
4303 value_set_si(tmp3
,1);
4305 /* Compare p3/d with MinN/MinD to assign new minimum cost value */
4307 value_lt(tmp1
,tmp2
) ||
4308 (value_eq(tmp1
,tmp2
) &&
4309 value_eq(d
,tmp3
) && value_ne(I
->MinD
,tmp3
))) {
4310 value_assign(I
->MinN
, p3
);
4311 value_assign(I
->MinD
, d
);
4314 value_multiply(tmp1
,p3
,I
->MaxD
);
4315 value_set_si(tmp2
,0);
4317 /* If there is a line, assign max to +infinity and min to -infinity */
4318 if (value_zero_p(status
)) { /* line , d is 0 */
4319 if (value_lt(tmp1
,tmp2
)) {
4320 value_oppose(I
->MaxN
,p3
);
4321 value_set_si(I
->MaxD
,0);
4324 value_multiply(tmp1
,p3
,I
->MinD
);
4325 value_set_si(tmp2
,0);
4327 if (value_gt(tmp1
,tmp2
)) {
4328 value_oppose(I
->MinN
,p3
);
4329 value_set_si(I
->MinD
,0);
4336 UNCATCH(any_exception_error
);
4337 value_clear(p3
); value_clear(d
); value_clear(status
);
4338 value_clear(tmp1
); value_clear(tmp2
); value_clear(tmp3
);
4343 * Add constraints pointed by 'Mat' to each and every polyhedron in the
4344 * polyhedral domain 'Pol'. 'NbMaxRays' is maximum allowed rays in the ray
4345 * matrix of a polyhedron.
4347 Polyhedron
*DomainAddConstraints(Polyhedron
*Pol
,Matrix
*Mat
,unsigned NbMaxRays
) {
4349 Polyhedron
*PolA
, *PolEndA
, *p1
, *p2
, *p3
;
4352 if (!Pol
) return (Polyhedron
*) 0;
4353 if (!Mat
) return Pol
;
4354 if (Pol
->Dimension
!= Mat
->NbColumns
-2) {
4355 errormsg1("DomainAddConstraints",
4356 "diffdim", "operation on different dimensions");
4357 return (Polyhedron
*) 0;
4360 /* Copy 'Pol' to 'PolA' */
4361 PolA
= PolEndA
= (Polyhedron
*)0;
4362 for (p1
=Pol
; p1
; p1
=p1
->next
) {
4363 p3
= AddConstraints(Mat
->p_Init
, Mat
->NbRows
, p1
, NbMaxRays
);
4365 /* Does any component of 'PolA' cover 'p3' */
4367 for (p2
=PolA
; p2
; p2
=p2
->next
) {
4368 if (PolyhedronIncludes(p2
, p3
)) { /* 'p2' covers 'p3' */
4374 /* If the new polyhedron 'p3' is not redundant, add it to the domain */
4376 Polyhedron_Free(p3
);
4379 PolEndA
= PolA
= p3
;
4382 PolEndA
= PolEndA
->next
;
4387 } /* DomainAddConstraints */
4391 * Computes the disjoint union of a union of polyhedra.
4392 * If flag = 0 the result is such that there are no intersections
4393 * between the resulting polyhedra,
4394 * if flag = 1 it computes a joint union, the resulting polyhedra are
4395 * adjacent (they have their facets in common).
4397 * WARNING: if all polyhedra are not of same geometrical dimension
4398 * duplicates may appear.
4400 Polyhedron
*Disjoint_Domain( Polyhedron
*P
, int flag
, unsigned NbMaxRays
)
4402 Polyhedron
*lP
, *tmp
, *Result
, *lR
, *prec
, *reste
;
4403 Polyhedron
*p1
, *p2
, *p3
, *Pol1
, *dx
, *d1
, *d2
, *pi
, *newpi
;
4406 if( flag
!=0 && flag
!=1 )
4408 errormsg1("Disjoint_Domain",
4409 "invalidarg", "flag should be equal to 0 or 1");
4410 return (Polyhedron
*) 0;
4412 if(!P
) return (Polyhedron
*) 0;
4413 if(!P
->next
) return Polyhedron_Copy(P
);
4415 Result
= (Polyhedron
*)0;
4417 for(lP
=P
;lP
;lP
=lP
->next
)
4419 reste
= Polyhedron_Copy(lP
);
4420 prec
= (Polyhedron
*)0; /* preceeding lR */
4421 /* Intersection with each polyhedron of the current Result */
4423 while( lR
&& reste
)
4425 /* dx = DomainIntersection(reste,lR->P,WS); */
4426 dx
= (Polyhedron
*)0;
4427 for( p1
=reste
; p1
; p1
=p1
->next
)
4429 p3
= AddConstraints(lR
->Constraint
[0], lR
->NbConstraints
, p1
,
4431 dx
= AddPolyToDomain(p3
,dx
);
4434 /* if empty intersection, continue */
4447 /* intersection is not empty, we need to compute the differences */
4448 /* between the intersection and the two polyhedra, such that the */
4449 /* results are disjoint unions (according to flag) */
4450 /* d1 = reste \ P = DomainDifference(reste,lR->P,WS); */
4451 /* d2 = P \ reste = DomainDifference(lR->P,reste,WS); */
4454 d1
= (Polyhedron
*)0;
4455 for (p1
=reste
; p1
; p1
=p1
->next
)
4458 for (i
=0; i
<P
->NbConstraints
&& pi
; i
++)
4461 /* Add the constraint ( -P->constraint[i] [-1 if flag=0]) >= 0 in 'p1' */
4462 /* and create the new polyhedron 'p3'. */
4463 p3
= SubConstraint(P
->Constraint
[i
], pi
, NbMaxRays
,2*flag
);
4464 /* Add 'p3' in the new domain 'd1' */
4465 d1
= AddPolyToDomain (p3
, d1
);
4467 /* If the constraint P->constraint[i][0] is an equality, then add */
4468 /* the constraint ( +P->constraint[i] [-1 if flag=0]) >= 0 in 'pi' */
4469 /* and create the new polyhedron 'p3'. */
4470 if( value_zero_p(P
->Constraint
[i
][0]) ) /* Inequality */
4472 p3
= SubConstraint(P
->Constraint
[i
], pi
, NbMaxRays
,1+2*flag
);
4473 /* Add 'p3' in the new domain 'd1' */
4474 d1
= AddPolyToDomain (p3
, d1
);
4476 /* newpi : add constraint P->constraint[i]==0 to pi */
4477 newpi
= AddConstraints( P
->Constraint
[i
], 1, pi
, NbMaxRays
);
4481 /* newpi : add constraint +P->constraint[i] >= 0 in pi */
4482 newpi
= SubConstraint(P
->Constraint
[i
], pi
, NbMaxRays
,3);
4484 if( newpi
&& emptyQ( newpi
) )
4486 Domain_Free( newpi
);
4487 newpi
= (Polyhedron
*)0;
4498 Pol1
= Polyhedron_Copy( lR
);
4499 for (p2
=reste
; p2
; p2
=p2
->next
)
4501 d2
= (Polyhedron
*)0;
4502 for (p1
=Pol1
; p1
; p1
=p1
->next
)
4505 for (i
=0; i
<p2
->NbConstraints
&& pi
; i
++)
4508 /* Add the constraint ( -p2->constraint[i] [-1 if flag=0]) >= 0 in 'pi' */
4509 /* and create the new polyhedron 'p3'. */
4510 p3
= SubConstraint(p2
->Constraint
[i
], pi
, NbMaxRays
,2*flag
);
4511 /* Add 'p3' in the new domain 'd2' */
4512 d2
= AddPolyToDomain (p3
, d2
);
4514 /* If the constraint p2->constraint[i][0] is an equality, then add */
4515 /* the constraint ( +p2->constraint[i] [-1 if flag=0]) >= 0 in 'pi' */
4516 /* and create the new polyhedron 'p3'. */
4517 if( value_zero_p(p2
->Constraint
[i
][0]) ) /* Inequality */
4519 p3
= SubConstraint(p2
->Constraint
[i
], pi
, NbMaxRays
,1+2*flag
);
4520 /* Add 'p3' in the new domain 'd2' */
4521 d2
= AddPolyToDomain (p3
, d2
);
4523 /* newpi : add constraint p2->constraint[i]==0 to pi */
4524 newpi
= AddConstraints( p2
->Constraint
[i
], 1, pi
, NbMaxRays
);
4528 /* newpi : add constraint +p2->constraint[i] >= 0 in pi */
4529 newpi
= SubConstraint(p2
->Constraint
[i
], pi
, NbMaxRays
,3);
4531 if( newpi
&& emptyQ( newpi
) )
4533 Domain_Free( newpi
);
4534 newpi
= (Polyhedron
*)0;
4544 Domain_Free( Pol1
);
4547 /* ok, d1 and d2 are computed */
4549 /* now, replace lR by d2+dx (at least dx is nonempty) and set reste to d1 */
4550 if( d1
&& emptyQ(d1
) )
4555 if( d2
&& emptyQ(d2
) )
4562 Domain_Free( reste
);
4565 /* add d2 at beginning of Result */
4568 for( tmp
=d2
; tmp
->next
; tmp
=tmp
->next
)
4576 /* add dx at beginning of Result */
4577 for( tmp
=dx
; tmp
->next
; tmp
=tmp
->next
)
4584 /* suppress current lR */
4586 errormsg1( "Disjoint_Domain","internalerror","internal error");
4587 prec
->next
= lR
->next
;
4588 Polyhedron_Free( lR
);
4590 } /* end for result */
4592 /* if there is something left, add it to Result : */
4597 Domain_Free( reste
);
4603 for( tmp
=reste
; tmp
; tmp
=tnext
)
4607 Result
= AddPolyToDomain(tmp
, Result
);
4618 /* Procedure to print constraint matrix of a polyhedron */
4619 void Polyhedron_PrintConstraints(FILE *Dst
, const char *Format
, Polyhedron
*Pol
)
4623 fprintf( Dst
, "%d %d\n", Pol
->NbConstraints
, Pol
->Dimension
+2 );
4624 for( i
=0 ; i
<Pol
->NbConstraints
; i
++ )
4626 for( j
=0 ; j
<Pol
->Dimension
+2 ; j
++ )
4627 value_print( Dst
, Format
, Pol
->Constraint
[i
][j
] );
4628 fprintf( Dst
, "\n" );
4633 /* Procedure to print constraint matrix of a domain */
4634 void Domain_PrintConstraints(FILE *Dst
, const char *Format
, Polyhedron
*Pol
)
4637 for (Q
= Pol
; Q
; Q
= Q
->next
)
4638 Polyhedron_PrintConstraints(Dst
, Format
, Q
);
4641 static Polyhedron
*p_simplify_constraints(Polyhedron
*P
, Vector
*row
,
4642 Value
*g
, unsigned MaxRays
)
4644 Polyhedron
*T
, *R
= P
;
4645 int len
= P
->Dimension
+2;
4648 /* Also look at equalities.
4649 * If an equality can be "simplified" then there
4650 * are no integer solutions and we return an empty polyhedron
4652 for (r
= 0; r
< R
->NbConstraints
; ++r
) {
4653 if (ConstraintSimplify(R
->Constraint
[r
], row
->p
, len
, g
)) {
4655 if (value_zero_p(R
->Constraint
[r
][0])) {
4656 R
= Empty_Polyhedron(R
->Dimension
);
4657 r
= R
->NbConstraints
;
4658 } else if (POL_ISSET(MaxRays
, POL_NO_DUAL
)) {
4659 R
= Polyhedron_Copy(R
);
4660 F_CLR(R
, POL_FACETS
| POL_VERTICES
| POL_POINTS
);
4661 Vector_Copy(row
->p
+1, R
->Constraint
[r
]+1, R
->Dimension
+1);
4663 R
= AddConstraints(row
->p
, 1, R
, MaxRays
);
4676 * Replaces constraint a x >= c by x >= ceil(c/a)
4677 * where "a" is a common factor in the coefficients
4678 * Destroys P and returns a newly allocated Polyhedron
4679 * or just returns P in case no changes were made
4681 Polyhedron
*DomainConstraintSimplify(Polyhedron
*P
, unsigned MaxRays
)
4684 int len
= P
->Dimension
+2;
4685 Vector
*row
= Vector_Alloc(len
);
4687 Polyhedron
*R
= P
, *N
;
4688 value_set_si(row
->p
[0], 1);
4691 for (prev
= &R
; P
; P
= N
) {
4694 T
= p_simplify_constraints(P
, row
, &g
, MaxRays
);
4696 if (emptyQ(T
) && prev
!= &R
) {
4708 if (R
->next
&& emptyQ(R
)) {