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/>.
18 /***********************************************************************/
19 /* Parametrized polyhedra V4.20 */
20 /* copyright 1995-2000 Vincent Loechner */
21 /* copyright 1996-1997, Doran Wilde */
22 /***********************************************************************/
24 /********************* -----------USER #DEFS-------- ***********************/
25 /* These are mainly for debug purposes. You shouldn't need to change */
26 /* anything for daily usage... */
27 /***************************************************************************/
29 /* you may define each macro independently */
31 /* #define DEBUGPP3 */ /* initialization of domain, context, ... */
32 /* #define DEBUGPP31 */ /* even more init-domains */
33 /* #define DEBUGPP32 */ /* even even more... (Elim_Columns) */
34 /* #define DEBUGPP4 */ /* m-faces scan */
35 /* #define DEBUGPP41 */ /* inverse Di in scan */
36 /* #define DEBUGPP5 */ /* Compute_PDomains */
37 /********************* ---------END USER #DEFS------ ***********************/
47 #include <polylib/polylib.h>
49 static void traite_m_face(Polyhedron
*, unsigned int *, unsigned int *);
50 static void scan_m_face(int,int,Polyhedron
*,unsigned int *);
53 * Return the intersection of two polyhedral domains 'Pol1' and 'Pol2' such
54 * that if the intersection is a polyhedron of lower dimension (a degenerate
55 * polyhedron) than the operands, it is discarded from the resulting polyhedra
58 Polyhedron
*PDomainIntersection(Polyhedron
*Pol1
,Polyhedron
*Pol2
,unsigned NbMaxRays
) {
60 Polyhedron
*p1
, *p2
, *p3
, *d
;
62 if (!Pol1
|| !Pol2
) return (Polyhedron
*) 0;
63 if((Pol1
->Dimension
!= Pol2
->Dimension
) || (Pol1
->NbEq
!= Pol2
->NbEq
)) {
65 "? PDomainIntersection: operation on different dimensions\n");
66 return (Polyhedron
*) 0;
69 POL_ENSURE_FACETS(Pol1
);
70 POL_ENSURE_VERTICES(Pol1
);
71 POL_ENSURE_FACETS(Pol2
);
72 POL_ENSURE_VERTICES(Pol2
);
75 for (p1
=Pol1
; p1
; p1
=p1
->next
) {
76 for (p2
=Pol2
; p2
; p2
=p2
->next
) {
77 p3
= AddConstraints(p2
->Constraint
[0],
78 p2
->NbConstraints
,p1
,NbMaxRays
);
81 /* If the new polyhedron 'p3' has lower dimension, discard it */
82 if (p3
->NbEq
!=Pol1
->NbEq
)
85 /* Otherwise add it to the new polyhderal domain 'd'. */
87 d
= AddPolyToDomain(p3
,d
);
91 } /* PDomainIntersection */
94 * Given polyhderal domains 'Pol1' and 'Pol2', return the difference of the
95 * two domains with a modification that the resulting polyhedra in the new
96 * domain don't have a 1 unit space around cut and the degenerate results
97 * (of smaller dimension) are discarded.
99 Polyhedron
*PDomainDifference(Polyhedron
*Pol1
,Polyhedron
*Pol2
,unsigned NbMaxRays
) {
101 Polyhedron
*p1
, *p2
, *p3
, *d
;
105 return (Polyhedron
*) 0;
106 if((Pol1
->Dimension
!= Pol2
->Dimension
) || (Pol1
->NbEq
!= Pol2
->NbEq
)) {
108 "? PDomainDifference: operation on different dimensions\n");
109 return (Polyhedron
*) 0;
112 POL_ENSURE_FACETS(Pol1
);
113 POL_ENSURE_VERTICES(Pol1
);
114 POL_ENSURE_FACETS(Pol2
);
115 POL_ENSURE_VERTICES(Pol2
);
118 for (p2
=Pol2
; p2
; p2
=p2
->next
) {
119 for (p1
=Pol1
; p1
; p1
=p1
->next
) {
120 for (i
=0; i
<p2
->NbConstraints
; i
++) {
122 /* Add the constraint (-p2->Constraint[i]) >= 0 in 'p1' */
123 p3
= SubConstraint(p2
->Constraint
[i
],p1
,NbMaxRays
,2);
126 /* If the new polyhedron 'p3' is empty or is a polyhedron of lower */
127 /* dimension, discard it. */
128 if (emptyQ(p3
) || p3
->NbEq
!=Pol1
->NbEq
)
131 /* Otherwise add 'p3' to the new polyhderal domain 'd' */
133 d
= AddPolyToDomain(p3
,d
);
142 } /* PDomainDifference */
145 * Return 1 if matrix 'Mat' is full column ranked, otherwise return 0.
147 static int TestRank(Matrix
*Mat
) {
150 Value m1
,m2
,m3
,gcd
,tmp
;
152 /* Initialize all the 'Value' variables */
153 value_init(m1
); value_init(m2
);
154 value_init(m3
); value_init(gcd
); value_init(tmp
);
156 for(k
=0;k
<Mat
->NbColumns
;++k
) {
158 /* If the digonal entry (k,k) is zero, search down the column(k) */
159 /* starting from row(k) to find a non-zero entry */
160 if(value_zero_p(Mat
->p
[k
][k
])) {
161 for(j
=k
+1;j
<Mat
->NbRows
;++j
) {
163 /* If a non-zero entry (j,k) is found */
164 if(value_notzero_p(Mat
->p
[j
][k
])) {
166 /* Exchange row(k) and row(j) */
167 for(i
=k
;i
<Mat
->NbColumns
;++i
) {
168 value_assign(tmp
,Mat
->p
[j
][i
]);
169 value_assign(Mat
->p
[j
][i
],Mat
->p
[k
][i
]);
170 value_assign(Mat
->p
[k
][i
],tmp
);
176 /* If no non-zero entry is found then the matrix 'Mat' is not full */
177 /* ranked. Return zero. */
180 /* Clear all the 'Value' variables */
181 value_clear(m1
); value_clear(m2
);
182 value_clear(m3
); value_clear(gcd
); value_clear(tmp
);
187 /* Now Mat[k][k] is the pivot element */
188 for(j
=k
+1;j
<Mat
->NbRows
;++j
) {
190 /* Make every other entry (below row(k)) in column(k) zero */
191 value_gcd(gcd
, Mat
->p
[j
][k
], Mat
->p
[k
][k
]);
192 for(i
=k
+1;i
<Mat
->NbColumns
;++i
) {
194 /* pour tous les indices i > k */
195 value_multiply(m1
,Mat
->p
[j
][i
],Mat
->p
[k
][k
]);
196 value_multiply(m2
,Mat
->p
[j
][k
],Mat
->p
[k
][i
]);
197 value_subtract(m3
,m1
,m2
);
198 value_division(Mat
->p
[j
][i
],m3
,gcd
);
203 /* Clear all the 'Value' variables */
204 value_clear(m1
); value_clear(m2
);
205 value_clear(m3
); value_clear(gcd
); value_clear(tmp
);
207 /* The matrix 'Mat' is full ranked, return 1 */
212 * The Saturation matrix is defined to be an integer (int type) matrix. It is
213 * a boolean matrix which has a row for every constraint and a column for
214 * every line or ray. The bits in the binary format of each integer in the
215 * saturation matrix stores the information whether the corresponding constr-
216 * aint is saturated by ray(line) or not.
220 unsigned int NbColumns
;
222 unsigned int *p_init
;
225 static SatMatrix
*SMAlloc(int rows
,int cols
) {
227 unsigned int **q
, *p
;
230 SatMatrix
*result
= (SatMatrix
*)malloc(sizeof(SatMatrix
));
231 assert (result
!= NULL
);
233 result
->NbRows
= rows
;
234 result
->NbColumns
= cols
;
235 result
->p
= q
= (unsigned int **)malloc(rows
* sizeof(unsigned int *));
236 assert (result
->p
!= NULL
);
237 result
->p_init
= p
= (unsigned int *)malloc(rows
* cols
* sizeof(unsigned int));
238 assert (result
->p_init
!= NULL
);
240 for (i
=0;i
<rows
;i
++) {
248 static void SMPrint (SatMatrix
*matrix
) {
252 unsigned NbRows
, NbColumns
;
254 fprintf(stderr
,"%d %d\n",NbRows
=matrix
->NbRows
, NbColumns
=matrix
->NbColumns
);
255 for (i
=0;i
<NbRows
;i
++) {
257 for (j
=0;j
<NbColumns
;j
++)
258 fprintf(stderr
, " %10X ", *p
++);
259 fprintf(stderr
, "\n");
264 static void SMFree (SatMatrix
*matrix
) {
266 free ((char *) matrix
->p_init
);
267 free ((char *) matrix
->p
);
268 free ((char *) matrix
);
272 /* -------------------------------------------------------------------------
273 * Shared Global Variables:
274 * Used by procedures: Find_m_face, scan_m_face, Poly2Sat, traite_m_face,
276 * -------------------------------------------------------------------------
278 static int m
; /* number of parameters */
279 static int m_dim
; /* dimension of m-face */
280 static int n
; /* dimension (not including parameters) */
281 static int ws
; /* Working Space size */
282 static int nr
; /* (NbRays-1)/32 + 1 */
284 static Polyhedron
*CEqualities
;/* Equalities in the context */
285 static SatMatrix
*Sat
; /* Saturation Matrix (row=constraint, col=ray)*/
286 static unsigned int *egalite
; /* Bool vector marking constraints in m-face */
287 static Matrix
*Xi
, *Pi
; /* Xi and Pi */
288 static Matrix
*PiTest
; /* Matrix used to test if Pi is full ranked? */
289 static Matrix
*CTest
;
290 static Matrix
*PiInv
; /* Matrix inverse Pi, with the last col of */
291 /* each line = denominator of the line */
292 static Matrix
*RaysDi
; /* Constraint matrix for computing Di */
294 static int KD
; /* Flag : keep the full domains in memory ? */
295 /* 1 = yes; 0 = no, keep constraints only */
297 static int nbPV
; /* The number of parameterized vertices */
298 static Param_Vertices
*PV_Result
; /* List of parameterized vertices */
299 static Param_Domain
*PDomains
; /* List of domains. */
306 * Add the constraints from the context polyhedron 'CEqualities' to the
307 * constraints of polyhedra in the polyhedral domain 'D' and return the new
308 * polyhedral domain. Polyhedral domain 'D' is subsequently deleted from memory
310 static Polyhedron
*Add_CEqualities(Polyhedron
*D
) {
312 Polyhedron
*d
,*r
,*tmp
;
317 if(!D
|| emptyQ(D
)) {
320 return(Polyhedron_Copy(CEqualities
));
322 r
= AddConstraints(D
->Constraint
[0],D
->NbConstraints
,
325 for(d
=D
->next
;d
;d
=d
->next
) {
326 tmp
->next
= AddConstraints(d
->Constraint
[0],d
->NbConstraints
,
333 } /* Add_CEqualities */
335 #define INT_BITS (sizeof(unsigned) * 8)
337 unsigned int *int_array2bit_vector(unsigned int *array
, int n
)
341 int words
= (n
+INT_BITS
-1)/INT_BITS
;
342 unsigned int *bv
= (unsigned int *)calloc(words
, sizeof(unsigned));
344 for (i
= 0, ix
= 0, bx
= MSB
; i
< n
; ++i
) {
352 /*----------------------------------------------------------------------*/
354 /* Given an m-face, compute the parameterized vertex */
355 /* D - The entire domain */
356 /* mf - Bit vector marking the lines/rays in the m-face */
357 /* egalite - boolean vector marking saturated constraints in m-face */
358 /*----------------------------------------------------------------------*/
359 static void traite_m_face(Polyhedron
*D
, unsigned int *mf
,
360 unsigned int *egalite
)
362 Matrix
*Si
; /* Solution */
363 Polyhedron
*PDi
; /* polyhedron Di */
372 /* Extract Xi, Pi, and RaysDi from D */
374 for(k
=0,c
=0,kx
=0,bx
=MSB
;k
<D
->NbRays
;++k
) {
375 if(mf
[kx
]&bx
) { /* this ray is in the current m-face */
379 /* tester si cette nouvelle colonne est lin. indep. des autres */
380 /* i.e. si gauss ne donne pas de '0' sur la colonne Pi */
381 /* jusqu'a l'indice 'c' */
383 /* construit PiTest */
387 /* les c premieres colonnes */
388 value_assign(PiTest
->p
[j
][i
],Pi
->p
[j
][i
]);
391 value_assign(PiTest
->p
[j
][c
],D
->Ray
[k
][j
+1+n
]);
393 PiTest
->NbColumns
= c
+1;
394 r
= TestRank(PiTest
);
395 if(r
/* TestRank(PiTest) */) {
397 /* Ok, c'est lin. indep. */
399 value_assign(Xi
->p
[j
][c
],D
->Ray
[k
][j
+1]); /* Xi */
401 value_assign(Pi
->p
[j
][c
],D
->Ray
[k
][j
+1+n
]); /* Pi */
402 value_assign(Xi
->p
[n
][c
],D
->Ray
[k
][n
+m
+1]); /* const */
403 value_assign(Pi
->p
[m
][c
],D
->Ray
[k
][n
+m
+1]); /* const */
409 value_assign(RaysDi
->p
[RaysDi
->NbRows
][0],D
->Ray
[k
][0]);
410 Vector_Copy(&D
->Ray
[k
][n
+1],&RaysDi
->p
[RaysDi
->NbRows
][1],(m
+1));
417 fprintf(stderr
, "\nRaysDi=\n");
418 Matrix_Print(stderr
,P_VALUE_FMT
,RaysDi
);
420 fprintf(stderr
, "Invalid ");
421 fprintf(stderr
, "Pi=\n");
422 Matrix_Print(stderr
,P_VALUE_FMT
,Pi
);
427 fprintf(stderr
,"Eliminated because of no vertex\n");
433 /* RaysDi->numColumns = m+2; */ /* stays the same */
435 /* Xi->NbColumns = m+1;*/ /* VIN100: stays the same. was 'c'! */
436 /* Xi->NbRows = n+1; */ /* stays the same */
437 /* Pi->NbColumns = m+1;*/ /* VIN100: stays the same. was 'c'! */
438 /* Pi->NbRows = m+1; */ /* stays the same */
441 fprintf(stderr
,"Xi = ");
442 Matrix_Print(stderr
,P_VALUE_FMT
,Xi
);
443 fprintf(stderr
,"Pi = ");
444 Matrix_Print(stderr
,P_VALUE_FMT
,Pi
);
447 /* (Right) invert Pi if POSSIBLE, if not then next m-face */
448 /* Pi is destroyed */
449 if(!MatInverse(Pi
,PiInv
)) {
452 fprintf(stderr
, "Eliminated because of no inverse Pi\n");
459 fprintf(stderr
,"FACE GENERATED!\n");
460 fprintf(stderr
,"PiInv = ");
461 Matrix_Print(stderr
,P_VALUE_FMT
,PiInv
);
464 /* Compute Si (now called Ti in the paper) */
465 Si
= Matrix_Alloc(Xi
->NbRows
,PiInv
->NbColumns
);
466 rat_prodmat(Si
,Xi
,PiInv
);
469 fprintf(stderr
,"Si = ");
470 Matrix_Print(stderr
,P_VALUE_FMT
,Si
);
473 Si
->NbRows
--; /* throw out the last row = 0 ... 0 1 */
475 /* Copy all of that into the PV structure */
476 PV
= (Param_Vertices
*) malloc(sizeof(Param_Vertices
));
477 PV
->next
= PV_Result
;
480 PV
->Facets
= int_array2bit_vector(egalite
, D
->NbConstraints
);
482 nbPV
++; /* increment vertex count */
484 /* Ok... now compute the parameter domain */
485 PDi
= Rays2Polyhedron(RaysDi
,ws
);
488 fprintf(stderr
,"RaysDi = ");
489 Matrix_Print(stderr
,P_VALUE_FMT
,RaysDi
);
490 fprintf(stderr
,"PDi = ");
491 Polyhedron_Print(stderr
,P_VALUE_FMT
,PDi
);
496 /* Add the equalities again to the domain */
497 PDi
= Add_CEqualities(PDi
);
498 PV
->Domain
= Polyhedron2Constraints(PDi
);
499 Polyhedron_Free(PDi
);
503 PD
= (Param_Domain
*) malloc(sizeof(Param_Domain
));
510 } /* traite_m_face */
512 /*----------------------------------------------------------------------*/
514 /* count the number of saturated rays in the bit vector mf */
515 /* Uses nr from global area */
516 /*----------------------------------------------------------------------*/
517 int cntbit
[256] = { /* counts for 8 bits */
518 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
519 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
520 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
521 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
523 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
524 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
525 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
526 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
528 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
529 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
530 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
531 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
533 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
534 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
535 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
536 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 };
538 static int count_sat (unsigned int *mf
) {
540 register unsigned int i
, tmp
, cnt
=0;
542 for (i
=0; i
<nr
; i
++) {
545 + cntbit
[ tmp
& 0xff ]
546 + cntbit
[ (tmp
>>8) & 0xff ]
547 + cntbit
[ (tmp
>>16) & 0xff ]
548 + cntbit
[ (tmp
>>24) & 0xff ]
554 /* Returns true if all bits in part are also set in bv */
555 static int bit_vector_includes(unsigned int *bv
, int len
, unsigned int *part
)
559 for (j
= 0; j
< len
; j
++) {
561 fprintf(stderr
, "mf=%08X Sat=%08X &=%08X\n",
562 part
[j
],bv
[j
], (part
[j
] & bv
[j
]));
564 if ((part
[j
] & bv
[j
]) != part
[j
])
570 /*----------------------------------------------------------------------*/
571 /* let D + E + L be the dimension of the polyhedron */
572 /* D = Dimension of polytope (ray space) */
573 /* L = Dimension of Lineality space (number of lines, bid) */
574 /* E = Dimension of Affine hull (number of equations) */
575 /* n = number of data indices */
576 /* m = number of parameters */
578 /* n + m = D + E + L */
579 /* projected domains: */
580 /* m = D_m + E_m + L_m */
581 /* n = D_n + E_n + L_n */
582 /* What dimension M-face, when projected onto parameter space, */
583 /* will give an L_m-face? */
584 /* What are the conditions? */
585 /* - at least one vertex */
586 /* - number of rays >= D_m+1 after removal of redundants */
588 /* dim of face nb saturated constraints nb saturated lines,rays */
589 /* ----------- ------------------------ ----------------------- */
590 /* (0+L)-face all E eqns + >=D ineq all L lines + 1 ray */
591 /* (M+L)-face all E eqns + >=(D-M) ineq all L lines + >=(M+1) rays */
592 /* (D+L)-face all E eqns + 0 ineq all L lines + >=(D+1) rays */
593 /*----------------------------------------------------------------------*/
594 /*----------------------------------------------------------------------*/
596 /* pos : the next candidate constraint position */
597 /* nb_un : number of saturated constraints needed to finish a face */
598 /* D : the source polyhedron (context included ) */
599 /* mf : bit-array marking rays which are saturated so far */
600 /* From Global area: */
601 /* ---------------- */
602 /* n : number of data indices */
603 /* m : number of parameters */
604 /* egalite : boolean vector marking saturated constraints in m-face */
605 /* Sat : Saturation Matrix (row=constraints, col=rays) */
606 /* ws : working space size */
607 /* nr : (NbRays-1)/32 + 1 */
609 /* Recursive function to find the rays and vertices of each m-face */
610 /*----------------------------------------------------------------------*/
611 static void scan_m_face(int pos
,int nb_un
,Polyhedron
*D
,unsigned int *mf
) {
612 /* pos - the next candidate constraint position */
613 /* nb_un - the number of constraints needed to finish a face */
614 /* D - the source polyhedron */
615 /* mf - (bit vector) marks rays that are saturated so far */
617 unsigned int *new_mf
;
620 fprintf(stderr
,"Start scan_m_face(pos=%d, nb_un=%d, n=%d, m=%d\n",
622 fprintf(stderr
,"mf = ");
626 fprintf(stderr
,"%08X", mf
[i
]);
627 fprintf(stderr
,"\nequality = [");
628 for(i
=0;i
<D
->NbConstraints
;i
++)
629 fprintf(stderr
," %1d",egalite
[i
]);
630 fprintf(stderr
,"]\n");
634 if(nb_un
== 0) { /* Base case */
637 /*********** ELIMINATION OF REDUNDANT FACES ***********/
638 /* if all these vertices also verify a previous constraint */
639 /* which is NOT already selected, we eliminate this face */
640 /* This keeps the lexicographically greatest selection */
644 continue; /* already selected */
646 /* if Sat[i] & mf == mf then it's redundant */
648 fprintf(stderr
, "Sat[%d]\n", i
);
650 if (bit_vector_includes(Sat
->p
[i
], nr
, mf
)) {
652 fprintf(stderr
, "Redundant with constraint %d\n", i
);
654 return; /* it is redundant */
657 /********* END OF ELIMINATION OF DEGENERATE FACES *********/
658 /* Now check for other constraints that are verified */
659 for (i
= pos
; i
< D
->NbConstraints
; ++i
) {
660 if (bit_vector_includes(Sat
->p
[i
], nr
, mf
))
663 /* if we haven't found a constraint verified by all */
664 /* the rays, its OK, it's a new face. */
665 traite_m_face(D
, mf
, egalite
);
666 for (i
= pos
; i
< D
->NbConstraints
; ++i
)
671 /* See if there are enough constraints left to finish */
672 if((pos
+nb_un
)>D
->NbConstraints
) return;
674 /* Recurring part of the procedure */
675 /* Add the pos'th constraint, compute new saturation vector */
678 new_mf
= (unsigned int *)malloc(nr
*sizeof(unsigned int));
680 new_mf
[k
] = mf
[k
] & Sat
->p
[pos
][k
];
683 fprintf(stderr
,"new_mf = ");
687 fprintf(stderr
,"%08X", new_mf
[i
]);
689 fprintf(stderr
,"\ncount(new_mf) = %d\n",count_sat(new_mf
));
695 c
= count_sat(new_mf
);
696 /* optimization : at least m_dim+1 rays must be saturated to add this constraint */
701 egalite
[pos
]=1; /* Try it with the pos-th constraint */
703 /* If this constraint does not change anything,
704 * it is redundant with respect to the selected
705 * equalities and the remaining inequalities.
706 * Check whether it is redundant with respect
707 * to just the selected equalities.
709 if( c
==count_sat(mf
) ) {
712 for (i
= 0, c
= 0; i
< D
->NbConstraints
; ++i
) {
713 if (egalite
[i
] == 0 || egalite
[i
] == -1)
715 for (j
= 0; j
< D
->Dimension
+1; ++j
)
716 value_assign(CTest
->p
[j
][c
],
717 D
->Constraint
[i
][j
+1]);
720 CTest
->NbColumns
= c
;
722 Matrix_Print(stderr
,P_VALUE_FMT
,CTest
);
724 redundant
= !TestRank(CTest
);
727 /* Do not decrement nb_un if equality is redundant. */
730 egalite
[pos
]=-1; /* Don't use in further redundance test
732 scan_m_face(pos
+1,nb_un
,D
,new_mf
);
736 scan_m_face(pos
+1,nb_un
-1,D
,new_mf
);
741 egalite
[pos
]=0; /* Try it without the pos-th constraint */
742 if ((pos
+nb_un
)>=D
->NbConstraints
) return;
743 scan_m_face(pos
+1,nb_un
,D
,mf
);
748 * Create a saturation matrix with rows correspond to the constraints and
749 * columns correspond to the rays of the polyhedron 'Pol'. Global variable
750 * 'nr' is set in the function.
752 static SatMatrix
*Poly2Sat(Polyhedron
*Pol
,unsigned int **L
) {
757 Value
*p1
, *p2
, p3
,tmp
;
758 unsigned Dimension
, NbRay
, NbCon
, bx
;
760 /* Initialize all the 'Value' variables */
761 value_init(p3
); value_init(tmp
);
764 NbCon
= Pol
->NbConstraints
;
765 Dimension
= Pol
->Dimension
+1; /* Homogeneous Dimension */
767 /* Build the Sat matrix */
768 nr
= (NbRay
- 1)/(sizeof(int)*8) + 1; /* Set globally */
769 Sat
= SMAlloc(NbCon
,nr
);
770 Temp
= (unsigned int *)malloc(nr
*sizeof(unsigned int));
771 memset(Sat
->p_init
,0,nr
*NbCon
*sizeof(int));
772 memset(Temp
,0,nr
*sizeof(unsigned int));
774 for (k
=0; k
<NbRay
; k
++) {
775 for (i
=0; i
<NbCon
; i
++) {
776 p1
= &Pol
->Constraint
[i
][1];
777 p2
= &Pol
->Ray
[k
][1];
779 for (j
=0;j
<Dimension
;j
++) {
780 value_multiply(tmp
,*p1
,*p2
);
781 value_addto(p3
,p3
,tmp
);
784 if (value_zero_p(p3
))
791 /* Set 'L' to an array containing ones in every bit position of its */
795 /* Clear all the 'Value' variables */
796 value_clear(p3
); value_clear(tmp
);
802 * Create a parametrized polyhedron with zero parameters. This function was
803 * first written by Xavier Redon, and was later modified by others.
805 Param_Polyhedron
*GenParamPolyhedron(Polyhedron
*Pol
, Matrix
*Rays
)
807 Param_Polyhedron
*result
;
808 int nbRows
, nbColumns
;
812 nbColumns
=Pol
->Dimension
+2;
814 /* Count the number of rays */
815 for(i
=0, rays
=0; i
<nbRows
; i
++)
816 if(value_notone_p(Pol
->Ray
[i
][0]) ||
817 value_zero_p(Pol
->Ray
[i
][nbColumns
-1]))
820 /* Initialize the result */
821 result
=(Param_Polyhedron
*)malloc(sizeof(Param_Polyhedron
));
822 result
->nbV
=nbRows
-rays
;
824 result
->Constraints
= Polyhedron2Constraints(Pol
);
827 /* Build the parametric vertices */
828 for(i
=0;i
<nbRows
;i
++) {
830 Param_Vertices
*paramVertex
;
833 if (value_notone_p(Pol
->Ray
[i
][0]) ||
834 value_zero_p(Pol
->Ray
[i
][nbColumns
-1]))
837 vertex
=Matrix_Alloc(nbColumns
-2,2);
838 for(j
=1;j
<nbColumns
-1;j
++) {
839 value_assign(vertex
->p
[j
-1][0],Pol
->Ray
[i
][j
]);
840 value_assign(vertex
->p
[j
-1][1],Pol
->Ray
[i
][nbColumns
-1]);
842 paramVertex
=(Param_Vertices
*)malloc(sizeof(Param_Vertices
));
843 paramVertex
->Vertex
=vertex
;
845 /* There is one validity domain : universe of dimension 0 */
846 paramVertex
->Domain
=Matrix_Alloc(1,2);
847 value_set_si(paramVertex
->Domain
->p
[0][0],1);
848 value_set_si(paramVertex
->Domain
->p
[0][1],1);
849 paramVertex
->Facets
= NULL
;
850 paramVertex
->next
=result
->V
;
851 result
->V
=paramVertex
;
854 /* Build the parametric domains (only one here) */
856 size
=(nbRows
-1)/(8*sizeof(int))+1;
859 result
->D
=(Param_Domain
*)malloc(sizeof(Param_Domain
));
860 result
->D
->next
=NULL
;
861 result
->D
->Domain
=Universe_Polyhedron(0);
862 result
->D
->F
=(unsigned int *)malloc(size
*sizeof(int));
863 memset(&result
->D
->F
[0],0xFF,size
*sizeof(int));
866 } /* GenParamPolyhedron */
869 /*----------------------------------------------------------------------*/
870 /* PreElim_Columns */
871 /* function being called before Elim_Columns */
872 /* Equalities in E are analysed to initialize ref and p. */
873 /* These two vectors are used to construct the new constraint matrix */
874 /* PreElim_Columns returns the transformation matrix to re-convert the */
875 /* resulting domains in the same format (by adding empty columns) */
876 /* in the parameter space */
877 /*----------------------------------------------------------------------*/
878 Matrix
*PreElim_Columns(Polyhedron
*E
,int *p
,int *ref
,int m
) {
883 /* find which columns to eliminate */
884 /* p contains, for each line in E, the column to eliminate */
885 /* (i.e. the corresponding parameter index to eliminate) */
886 /* 0 <= i <= E->NbEq, and 1 <= p[i] <= E->Dimension */
887 memset(p
,0,sizeof(int)*(E
->NbEq
));
890 fprintf(stderr
,"\n\nPreElim_Columns starting\n");
891 fprintf(stderr
,"E =\n");
892 Polyhedron_Print(stderr
,P_VALUE_FMT
,E
);
895 for(l
=0;l
<E
->NbEq
;++l
) {
896 if(value_notzero_p(E
->Constraint
[l
][0])) {
897 fprintf(stderr
,"Internal error: Elim_Columns (polyparam.c), expecting equalities first in E.\n");
901 for(i
=1;value_zero_p(E
->Constraint
[l
][i
]);++i
) {
902 if(i
==E
->Dimension
+1) {
903 fprintf(stderr
,"Internal error: Elim_Columns (polyparam.c), expecting non-empty constraint in E.\n");
911 fprintf(stderr
,"p[%d] = %d,",l
,p
[l
]);
915 /* Reference vector: column ref[i] in A corresponds to column i in M */
916 for(i
=0;i
<E
->Dimension
+2-E
->NbEq
;++i
) {
918 for(j
=0;j
<E
->NbEq
;++j
)
923 fprintf(stderr
,"ref[%d] = %d,",i
,ref
[i
]);
927 /* Size of T : phdim-nbEq * phdim */
928 T
= Matrix_Alloc(m
+1-E
->NbEq
,m
+1);
929 for(i
=0;i
<T
->NbColumns
;i
++)
930 for(j
=0;j
<T
->NbRows
;j
++)
931 if(ref
[E
->Dimension
-m
+j
+1] == E
->Dimension
-m
+i
+1)
932 value_set_si(T
->p
[j
][i
],1);
934 value_set_si(T
->p
[j
][i
],0);
937 fprintf(stderr
,"\nTransMatrix =\n");
938 Matrix_Print(stderr
,P_VALUE_FMT
,T
);
943 } /* PreElim_Columns */
945 /*----------------------------------------------------------------------*/
947 /* Eliminate columns from A, using the equalities in E. */
948 /* ref and p are precalculated by PreElim_Columns, using E; */
949 /* these two vectors are used to construct the new constraint matrix */
950 /*----------------------------------------------------------------------*/
951 Polyhedron
*Elim_Columns(Polyhedron
*A
,Polyhedron
*E
,int *p
,int *ref
) {
958 /* Initialize all the 'Value' variables */
959 value_init(tmp1
); value_init(tmp2
);
962 fprintf(stderr
,"\nElim_Columns starting\n");
963 fprintf(stderr
,"A =\n" );
964 Polyhedron_Print(stderr
,P_VALUE_FMT
,A
);
967 /* Builds M = constraint matrix of A, useless columns zeroed */
968 M
= Polyhedron2Constraints(A
);
969 for(l
=0;l
<E
->NbEq
;++l
) {
970 for(c
=0;c
<M
->NbRows
;++c
) {
971 if(value_notzero_p(M
->p
[c
][p
[l
]])) {
973 /* A parameter to eliminate here ! */
974 for(i
=1;i
<M
->NbColumns
;++i
) {
975 value_multiply(tmp1
,M
->p
[c
][i
],E
->Constraint
[l
][p
[l
]]);
976 value_multiply(tmp2
,E
->Constraint
[l
][i
],M
->p
[c
][p
[l
]]);
977 value_subtract(M
->p
[c
][i
],tmp1
,tmp2
);
984 fprintf(stderr
,"\nElim_Columns after zeroing columns of A.\n");
985 fprintf(stderr
,"M =\n");
986 Matrix_Print(stderr
,P_VALUE_FMT
,M
);
989 /* Builds C = constraint matrix, useless columns eliminated */
990 C
= Matrix_Alloc(M
->NbRows
,M
->NbColumns
- E
->NbEq
);
991 for(l
=0;l
<C
->NbRows
;++l
)
992 for(c
=0;c
<C
->NbColumns
;++c
) {
993 value_assign(C
->p
[l
][c
],M
->p
[l
][ref
[c
]]);
997 fprintf(stderr
,"\nElim_Columns after eliminating columns of A.\n");
998 fprintf(stderr
,"C =\n");
999 Matrix_Print(stderr
,P_VALUE_FMT
,C
);
1002 R
= Constraints2Polyhedron(C
,ws
);
1005 value_clear(tmp1
); value_clear(tmp2
);
1007 } /* Elim_Columns */
1010 static Polyhedron
*Recession_Cone(Polyhedron
*P
, unsigned nvar
, unsigned MaxRays
)
1013 Matrix
*M
= Matrix_Alloc(P
->NbConstraints
, 1 + nvar
+ 1);
1015 for (i
= 0; i
< P
->NbConstraints
; ++i
)
1016 Vector_Copy(P
->Constraint
[i
], M
->p
[i
], 1+nvar
);
1017 R
= Constraints2Polyhedron(M
, MaxRays
);
1022 /* Compute lines/unidirectional rays of the (non parametric) polyhedron */
1024 * D1 : combined polyhedron,
1026 * Rays : non parametric ray matrix
1027 * return value : number of lines
1029 static int ComputeNPLinesRays(int n
, Polyhedron
*D1
, Matrix
**Rays
)
1031 int i
, j
, nbr
, dimfaces
;
1032 Polyhedron
*RC
; /* Recession Cone */
1034 RC
= Recession_Cone(D1
, n
, ws
);
1036 /* get the rays/lines from RC */
1038 for (i
= 0; i
< RC
->NbRays
;i
++)
1039 if (value_zero_p(RC
->Ray
[i
][n
+1]))
1041 *Rays
=Matrix_Alloc(nbr
, n
+2);
1042 for (i
= 0, j
= 0; j
< nbr
;i
++)
1043 if (value_zero_p(RC
->Ray
[i
][n
+1]))
1044 Vector_Copy(RC
->Ray
[i
], (*Rays
)->p
[j
++], n
+2);
1046 dimfaces
= RC
->NbBid
;
1047 Polyhedron_Free(RC
);
1050 fprintf(stderr
, "Rays = ");
1051 Matrix_Print(stderr
, P_VALUE_FMT
, *Rays
);
1052 fprintf(stderr
, "dimfaces = %d\n", dimfaces
);
1059 * Given a polyhedron 'Di' in combined data and parameter space and a context
1060 * polyhedron 'C' representing the constraints on the parameter space, create
1061 * a list of parameterized vertices and assign values to global variables:
1062 * m,n,ws,Sat,egalite,mf,Xi,Pi,PiInv,RaysDi,CEqualities.
1064 Param_Polyhedron
*Find_m_faces(Polyhedron
**Di
,Polyhedron
*C
,int keep_dom
,int working_space
,Polyhedron
**CEq
,Matrix
**CT
) {
1069 *C1
, /* true context */
1070 *D1
; /* the combined polyhedron, including context C */
1071 Matrix
*Rays
, /* lines/rays (non parametric) */
1073 Param_Polyhedron
*res
;
1084 return (Param_Polyhedron
*) 0;
1088 n
= D
->Dimension
- m
;
1091 "Find_m_faces: ?%d parameters of a %d-polyhedron !\n",m
,n
);
1092 return (Param_Polyhedron
*) 0;
1095 return GenParamPolyhedron(D
,Matrix_Alloc(0,2));
1097 /* Add constraints from Context to D -> result in D1 */
1098 C1
= align_context(C
,D
->Dimension
,ws
);
1101 fprintf(stderr
,"m = %d\n",m
);
1102 fprintf(stderr
, "D = ");
1103 Polyhedron_Print(stderr
,P_VALUE_FMT
,D
);
1104 fprintf(stderr
,"C1 = ");
1105 Polyhedron_Print(stderr
,P_VALUE_FMT
,C1
);
1108 D1
= DomainIntersection(D
,C1
,ws
);
1111 fprintf(stderr
,"D1 = ");
1112 Polyhedron_Print(stderr
,P_VALUE_FMT
,D1
);
1120 Polyhedron_Free(D1
);
1124 /* Compute the true context C1 */
1125 /* M : lines in the direction of the first n indices (index space) */
1126 M
= Matrix_Alloc(n
, D1
->Dimension
+2);
1128 value_set_si(M
->p
[i
][i
+1],1);
1129 C1
= DomainAddRays(D1
,M
,ws
);
1133 fprintf(stderr
,"True context C1 = ");
1134 Polyhedron_Print(stderr
,P_VALUE_FMT
,C1
);
1137 dimfaces
= ComputeNPLinesRays(n
, D1
, &Rays
);
1139 /* CEqualities contains the constraints (to be added again later) */
1140 /* *CT is the transformation matrix to add the removed parameters */
1142 if (C1
->NbEq
== 0) {
1143 Polyhedron_Free(C1
);
1146 Polyhedron
*CEq1
, /* CEqualities, in homogeneous dim */
1147 *D2
; /* D1, (temporary) simplified */
1149 /* Remove equalities from true context C1 and from D1 */
1150 /* Compute CEqualities = matrix of equalities in C1, projected in */
1151 /* the parameter space */
1152 M
= Matrix_Alloc(C1
->NbEq
,m
+2);
1153 for(j
=0,i
=0;i
<C1
->NbEq
;++i
,++j
) {
1154 while(value_notzero_p(C1
->Constraint
[j
][0]))
1156 value_assign(M
->p
[i
][0],C1
->Constraint
[j
][0]);
1157 Vector_Copy(&C1
->Constraint
[j
][D
->Dimension
-m
+1],&M
->p
[i
][1],(m
+1));
1159 CEqualities
= Constraints2Polyhedron(M
,ws
);
1161 CEq1
= align_context(CEqualities
,D
->Dimension
,ws
);
1163 /* Simplify D1 and C1 (remove the equalities) */
1164 D2
= DomainSimplify(D1
,CEq1
,ws
);
1165 Polyhedron_Free(D1
);
1166 Polyhedron_Free(C1
);
1167 Polyhedron_Free(CEq1
);
1172 else { /* if( CT ) */
1173 Polyhedron
*CEq1
, /* CEqualities */
1174 *D2
; /* D1, (temporary) simplified */
1176 /* Suppress all useless constraints in parameter domain */
1177 /* when CT is not NULL (ehrhart) */
1178 /* Vin100, march 01 */
1180 M
= Matrix_Alloc(C1
->NbConstraints
,m
+2);
1181 for(i
=0;i
<C1
->NbConstraints
;++i
) {
1182 value_assign(M
->p
[i
][0],C1
->Constraint
[i
][0]);
1183 Vector_Copy(&C1
->Constraint
[i
][D
->Dimension
-m
+1],&M
->p
[i
][1],(m
+1));
1185 CEqualities
= Constraints2Polyhedron( M
, ws
);
1188 D2
= DomainSimplify(D1
,CEq1
,ws
);
1189 Polyhedron_Free(D1
);
1191 C1
= Universe_Polyhedron(D2
->Dimension
);
1193 /* if CT is not NULL, the constraints are eliminated */
1194 /* *CT will contain the transformation matrix to come back to the */
1195 /* original dimension (for a polyhedron, in the parameter space) */
1199 p
= (int *)malloc(sizeof(int)*(CEq1
->NbEq
));
1203 ref
= (int*) malloc(sizeof(int)*
1204 (CEq1
->Dimension
+2-CEq1
->NbEq
));
1205 *CT
= PreElim_Columns(CEq1
,p
,ref
,CEqualities
->Dimension
);
1206 D2
= Elim_Columns(D1
,CEq1
,p
,ref
);
1212 fprintf(stderr
,"D2\t Dim = %3d\tNbEq = %3d\tLines = %3d\n",
1213 D2
->Dimension
,D2
->NbEq
,D2
->NbBid
);
1214 C2
= Elim_Columns(C1
,CEq1
,p
,ref
);
1215 fprintf(stderr
,"C2\t Dim = %3d\tNbEq = %3d\tLines = %3d\n",
1216 C2
->Dimension
,C2
->NbEq
,C2
->NbBid
);
1217 Polyhedron_Free(C2
);
1220 Polyhedron_Free(D1
);
1221 Polyhedron_Free(C1
);
1227 fprintf(stderr
,"Polyhedron CEq = ");
1228 Polyhedron_Print(stderr
,P_VALUE_FMT
,*CEq
);
1229 fprintf(stderr
,"Matrix CT = ");
1230 Matrix_Print(stderr
,P_VALUE_FMT
,*CT
);
1233 Polyhedron_Free(CEq1
);
1234 CEqualities
= NULL
; /* don't simplify ! */
1238 /* return the new D1 too */
1241 return GenParamPolyhedron(D1
, Rays
);
1246 fprintf(stderr
,"Polyhedron D1 (D AND C) = ");
1247 Polyhedron_Print(stderr
,P_VALUE_FMT
, D1
);
1248 fprintf(stderr
,"Polyhedron CEqualities = ");
1249 if(CEqualities
) Polyhedron_Print(stderr
,P_VALUE_FMT
, CEqualities
);
1250 else fprintf(stderr
,"NULL\n");
1259 Polyhedron_Free(D1
);
1264 /* mf : a bit array indicating which rays are part of the m-face */
1265 /* Poly2Sat initializes mf to all ones */
1266 /* set global variable nr to size (number of words) of mf */
1267 Sat
= Poly2Sat(D1
,&mf
);
1270 fprintf(stderr
,"Sat = ");
1273 fprintf(stderr
,"mf = ");
1274 for (i
=0; i
<nr
; i
++)
1275 fprintf(stderr
,"%08X", mf
[i
]);
1276 fprintf(stderr
, "\n");
1279 /* A boolean array saying which constraints are part of the m-face */
1280 egalite
= (unsigned int *)malloc(sizeof(int)*D1
->NbConstraints
);
1281 memset(egalite
,0, sizeof(int)*D1
->NbConstraints
);
1283 for (i
=0; i
<D1
->NbEq
; i
++)
1286 Xi
= Matrix_Alloc(n
+1,m
+1);
1287 Pi
= Matrix_Alloc(m
+1,m
+1);
1288 PiTest
= Matrix_Alloc(m
+1,m
+1);
1289 CTest
= Matrix_Alloc(D
->Dimension
+1,D
->NbConstraints
);
1290 PiInv
= Matrix_Alloc(m
+1,m
+2);
1291 RaysDi
= Matrix_Alloc(D1
->NbRays
,m
+2);
1294 /* m_dim has to be increased by the dimension of the smallest faces
1295 * of the (non parametric) polyhedron
1299 /* if the smallest face is of smaller dimension than m_dim,
1300 * then increase m_dim (I think this should never happen --Vincent)
1303 if (m_dim
< D1
->NbBid
)
1304 fprintf(stderr
, "m_dim (%d) < D1->NbBid (%d)\n", m_dim
, D1
->NbBid
);
1306 if (m_dim
< D1
->NbBid
)
1313 fprintf(stderr
, "m_dim = %d\n", m_dim
);
1315 "Target: find faces that saturate %d constraints and %d rays/lines\n",
1316 D1
->Dimension
- m_dim
,m_dim
+1);
1319 /* D1->NbEq constraints already saturated ! */
1320 scan_m_face(D1
->NbEq
,(D1
->Dimension
- m_dim
- D1
->NbEq
),D1
,mf
);
1322 /* pos, number of constraints needed */
1325 fprintf( stderr
, "Number of m-faces: %d\n", nbfaces
);
1328 Matrix_Free(RaysDi
);
1330 Matrix_Free(PiTest
);
1338 /* if(CEqualities && keep_dom==0) {
1339 Domain_Free(CEqualities);
1343 res
= (Param_Polyhedron
*) malloc (sizeof(Param_Polyhedron
));
1347 res
->Constraints
= Polyhedron2Constraints(D1
);
1350 if(CT
) /* return the new D1 too ! */
1356 } /* Find_m_faces */
1359 * Given parametric domain 'PD' and number of parametric vertices 'nb_domains',
1360 * find the vertices that belong to distinct sub-domains.
1362 void Compute_PDomains(Param_Domain
*PD
,int nb_domains
,int working_space
) {
1366 Polyhedron
*dx
, *d1
, *d2
;
1367 Param_Domain
*p1
, *p2
, *p2prev
, *PDNew
;
1369 if (nb_domains
==0) {
1372 fprintf(stderr
,"No domains\n");
1378 /* Already filled out by GenParamPolyhedron */
1379 if (!PD
->next
&& PD
->F
)
1382 /* Initialization */
1383 nv
= (nb_domains
- 1)/(8*sizeof(int)) + 1;
1386 fprintf(stderr
,"nv = %d\n",nv
);
1389 for(p1
=PD
,i
=0,ix
=0,bx
=MSB
;p1
;p1
=p1
->next
,i
++) {
1391 /* Assign a bit array 'p1->F' of suitable size to include the vertices */
1392 p1
->F
= (unsigned *) malloc (nv
* sizeof(unsigned));
1394 /* Set the bit array to zeros */
1395 memset(p1
->F
,0,nv
* sizeof(unsigned));
1396 p1
->F
[ix
] |= bx
; /* Set i'th bit to one */
1401 fprintf(stderr
,"nb of vertices=%d\n",i
);
1404 /* Walk the PD list with two pointers */
1406 for (p1
=PD
;p1
;p1
=p1
->next
) {
1407 for (p2prev
=p1
,p2
=p1
->next
;p2
;p2prev
=p2
,p2
=p2
->next
) {
1409 /* Find intersection */
1410 dx
= PDomainIntersection(p1
->Domain
,p2
->Domain
,working_space
);
1412 if (!dx
|| emptyQ(dx
)) {
1415 fprintf( stderr
, "Empty dx (p1 inter p2). Continuing\n");
1423 fprintf(stderr
,"Begin PDomainDifference\n");
1424 fprintf(stderr
, "p1=");
1425 Polyhedron_Print(stderr
,P_VALUE_FMT
,p1
->Domain
);
1426 fprintf(stderr
,"p2=");
1427 Polyhedron_Print(stderr
,P_VALUE_FMT
,p2
->Domain
);
1429 d1
= PDomainDifference(p1
->Domain
,p2
->Domain
,working_space
);
1430 d2
= PDomainDifference(p2
->Domain
,p1
->Domain
,working_space
);
1433 fprintf(stderr
,"p1\\p2=");
1434 Polyhedron_Print(stderr
,P_VALUE_FMT
,d1
);
1435 fprintf(stderr
,"p2\\p1=");
1436 Polyhedron_Print(stderr
,P_VALUE_FMT
,d2
);
1437 fprintf(stderr
,"END PDomainDifference\n\n");
1439 if (!d1
|| emptyQ(d1
) || d1
->NbEq
!=0) {
1442 fprintf(stderr
,"Empty d1\n");
1448 if (!d2
|| emptyQ(d2
) || d2
->NbEq
!=0) {
1451 fprintf( stderr
, "Empty d2 (deleting)\n");
1453 /* dx = p1->Domain = p2->Domain */
1454 if (d2
) Domain_Free(d2
);
1458 p1
->F
[i
] |= p2
->F
[i
];
1461 p2prev
->next
= p2
->next
;
1462 Domain_Free(p2
->Domain
);
1467 else { /* d2 is not empty --> dx==p1->domain */
1470 fprintf( stderr
, "p2 replaced by d2\n");
1474 p1
->F
[i
] |= p2
->F
[i
];
1476 /* Replace p2 with d2 */
1477 Domain_Free( p2
->Domain
);
1481 else { /* d1 is not empty */
1482 if (!d2
|| emptyQ(d2
) || d2
->NbEq
!=0) {
1485 fprintf( stderr
, "p1 replaced by d1\n");
1487 if (d2
) Domain_Free(d2
);
1489 /* dx = p2->domain */
1494 p2
->F
[i
] |= p1
->F
[i
];
1496 /* Replace p1 with d1 */
1497 Domain_Free(p1
->Domain
);
1500 else { /*d2 is not empty-->d1,d2,dx are distinct */
1503 fprintf(stderr
,"Non-empty d1 and d2\nNew node created\n");
1505 /* Create a new node for dx */
1506 PDNew
= (Param_Domain
*) malloc( sizeof(Param_Domain
) );
1507 PDNew
->F
= (unsigned int *)malloc( nv
*sizeof(int) );
1508 memset(PDNew
->F
,0,nv
*sizeof(int));
1512 PDNew
->F
[i
] = p1
->F
[i
] | p2
->F
[i
];
1514 /* Replace p1 with d1 */
1515 Domain_Free( p1
->Domain
);
1518 /* Replace p2 with d2 */
1519 Domain_Free( p2
->Domain
);
1522 /* Insert new node after p1 */
1523 PDNew
->next
= p1
->next
;
1527 } /* end of p2 scan */
1528 if (p1
->Domain
->next
) {
1529 Polyhedron
*C
= DomainConvex(p1
->Domain
, working_space
);
1530 Domain_Free(p1
->Domain
);
1533 } /* end of p1 scan */
1534 } /* Compute_PDomains */
1537 * Given a polyhedron 'Din' in combined data and parametre space, a context
1538 * polyhedron 'Cin' representing the constraints on the parameter space and
1539 * a working space size 'working_space', return a parametric polyhedron with
1540 * a list of parametric vertices and their defining domains.
1542 Param_Polyhedron
*Polyhedron2Param_Vertices(Polyhedron
*Din
,Polyhedron
*Cin
,int working_space
) {
1544 Param_Polyhedron
*result
;
1546 POL_ENSURE_FACETS(Din
);
1547 POL_ENSURE_VERTICES(Din
);
1548 POL_ENSURE_FACETS(Cin
);
1549 POL_ENSURE_VERTICES(Cin
);
1552 fprintf(stderr
,"Polyhedron2Param_Vertices algorithm starting at : %.2fs\n",
1553 (float)clock()/CLOCKS_PER_SEC
);
1556 /***************** Scan the m-faces ****************/
1557 result
= Find_m_faces(&Din
,Cin
,0,working_space
,NULL
,NULL
);
1560 fprintf(stderr
, "nb of points : %d\n",result
->nbV
);
1564 fprintf(stderr
, "end main loop : %.2fs\n", (float)clock()/CLOCKS_PER_SEC
);
1568 } /* Polyhedron2Param_Vertices */
1571 * Free the memory allocated to a list of parametrized vertices
1573 void Param_Vertices_Free(Param_Vertices
*PV
) {
1575 Param_Vertices
*next_pv
;
1579 if (PV
->Vertex
) Matrix_Free(PV
->Vertex
);
1580 if (PV
->Domain
) Matrix_Free(PV
->Domain
);
1581 if (PV
->Facets
) free(PV
->Facets
);
1585 } /* Param_Vertices_Free */
1588 * Print a list of parametrized vertices *
1590 void Print_Vertex(FILE *DST
, Matrix
*V
, const char **param_names
)
1596 value_init(gcd
); value_init(tmp
);
1599 for(l
=0;l
<V
->NbRows
;++l
){
1604 for(v
=0;v
< V
->NbColumns
-2;++v
) {
1605 if(value_notzero_p(V
->p
[l
][v
])) {
1606 value_gcd(gcd
, V
->p
[l
][v
], V
->p
[l
][V
->NbColumns
-1]);
1607 value_divexact(tmp
, V
->p
[l
][v
], gcd
);
1608 if(value_posz_p(tmp
)) {
1611 if(value_notone_p(tmp
)) {
1612 value_print(DST
,VALUE_FMT
,tmp
);
1615 else { /* V->p[l][v]/gcd<0 */
1616 if(value_mone_p(tmp
))
1619 value_print(DST
,VALUE_FMT
,tmp
);
1622 value_divexact(tmp
, V
->p
[l
][V
->NbColumns
-1], gcd
);
1623 if(value_notone_p(tmp
)) {
1624 fprintf(DST
, "%s/", param_names
[v
]);
1625 value_print(DST
,VALUE_FMT
,tmp
);
1628 fprintf(DST
, "%s", param_names
[v
]);
1634 if(value_notzero_p(V
->p
[l
][v
]) || first
) {
1635 if(value_posz_p(V
->p
[l
][v
]) && !first
)
1637 value_gcd(gcd
, V
->p
[l
][v
], V
->p
[l
][V
->NbColumns
-1]);
1638 value_divexact(tmp
, V
->p
[l
][v
], gcd
);
1639 value_print(DST
,VALUE_FMT
,tmp
);
1640 value_divexact(tmp
, V
->p
[l
][V
->NbColumns
-1], gcd
);
1641 if(value_notone_p(tmp
)) {
1643 value_print(DST
,VALUE_FMT
,tmp
);
1651 value_clear(gcd
); value_clear(tmp
);
1653 } /* Print_Vertex */
1655 /*----------------------------------------------------------------------*/
1657 /* convert a paramvertex from reduced space to normal m-space */
1658 /*----------------------------------------------------------------------*/
1659 Matrix
*VertexCT(Matrix
*V
,Matrix
*CT
) {
1666 /* Have to transform the vertices to original dimension */
1667 Vt
= Matrix_Alloc(V
->NbRows
,CT
->NbColumns
+1);
1668 for(i
=0;i
<V
->NbRows
;++i
) {
1669 value_assign(Vt
->p
[i
][CT
->NbColumns
],V
->p
[i
][V
->NbColumns
-1]);
1670 for(j
=0;j
<CT
->NbColumns
;j
++) {
1671 for(k
=0;k
<CT
->NbRows
;k
++)
1672 if(value_notzero_p(CT
->p
[k
][j
]))
1675 value_assign(Vt
->p
[i
][j
],V
->p
[i
][k
]);
1677 value_set_si(Vt
->p
[i
][j
],0);
1687 * Print the validity Domain 'D' of a parametric polyhedron
1689 void Print_Domain(FILE *DST
, Polyhedron
*D
, const char **pname
)
1694 POL_ENSURE_FACETS(D
);
1695 POL_ENSURE_VERTICES(D
);
1697 for(l
=0;l
<D
->NbConstraints
;++l
) {
1700 for(v
=1;v
<=D
->Dimension
;++v
) {
1701 if(value_notzero_p(D
->Constraint
[l
][v
])) {
1702 if(value_one_p(D
->Constraint
[l
][v
])) {
1704 fprintf(DST
, "%s ", pname
[v
-1]);
1706 fprintf(DST
, "+ %s ", pname
[v
-1] );
1708 else if(value_mone_p(D
->Constraint
[l
][v
]))
1709 fprintf(DST
, "- %s ", pname
[v
-1] );
1711 if(value_pos_p(D
->Constraint
[l
][v
]) && !first
)
1712 fprintf(DST
, "+ " );
1713 value_print(DST
,VALUE_FMT
,D
->Constraint
[l
][v
]);
1714 fprintf(DST
,"%s ",pname
[v
-1]);
1719 if(value_notzero_p(D
->Constraint
[l
][v
])) {
1720 if(value_pos_p(D
->Constraint
[l
][v
]) && !first
)
1723 value_print(DST
,VALUE_FMT
,D
->Constraint
[l
][v
]);
1725 fprintf(DST
,(value_notzero_p(D
->Constraint
[l
][0])) ?" >= 0":" = 0");
1726 fprintf(DST
, "\n" );
1732 fprintf( DST
, "UNION\n" );
1733 Print_Domain( DST
, D
->next
, pname
);
1736 } /* Print_Domain */
1739 * Given a list of parametrized vertices and an array of parameter names, Print
1740 * a list of parametrized vertices in a comprehensible format.
1742 void Param_Vertices_Print(FILE *DST
, Param_Vertices
*PV
, const char **param_names
)
1747 fprintf(DST
, "Vertex :\n" );
1748 Print_Vertex(DST
,PV
->Vertex
,param_names
);
1750 /* Pour le domaine : */
1751 fprintf(DST
, " If :\n" );
1752 poly
= Constraints2Polyhedron(PV
->Domain
,200);
1753 Print_Domain(DST
,poly
,param_names
);
1758 } /* Param_Vertices_Print */
1761 * Given a polyhedron 'Din' in combined data and parametre space, a context
1762 * polyhedron 'Cin' representing the constraints on the parameter space and
1763 * a working space size 'working_space', return a parametric polyhedron with
1764 * a list of distinct validity domains and a complete list of valid vertices
1765 * associated to each validity domain.
1767 Param_Polyhedron
*Polyhedron2Param_Domain(Polyhedron
*Din
,Polyhedron
*Cin
,int working_space
) {
1769 Param_Polyhedron
*result
;
1772 POL_ENSURE_FACETS(Din
);
1773 POL_ENSURE_VERTICES(Din
);
1774 POL_ENSURE_FACETS(Cin
);
1775 POL_ENSURE_VERTICES(Cin
);
1777 if (emptyQ(Din
) || emptyQ(Cin
))
1781 fprintf(stderr
,"Polyhedron2Param_Polyhedron algorithm starting at : %.2fs\n",
1782 (float)clock()/CLOCKS_PER_SEC
);
1785 /* Find the m-faces, keeping the corresponding domains */
1786 /* in the linked list PDomains */
1787 result
= Find_m_faces(&Din
,Cin
,1,working_space
,NULL
,NULL
);
1790 if(result
) fprintf(stderr
, "Number of vertices : %d\n",result
->nbV
);
1791 fprintf(stderr
,"Vertices found at : %.2fs\n",(float)clock()/CLOCKS_PER_SEC
);
1794 /* Processing of PVResult and PDomains */
1795 if(result
&& Cin
->Dimension
>0) /* at least 1 parameter */
1796 Compute_PDomains(result
->D
,result
->nbV
,working_space
);
1797 if(result
&& CEqualities
)
1798 for(D
=result
->D
;D
;D
=D
->next
)
1799 D
->Domain
= Add_CEqualities(D
->Domain
);
1800 Polyhedron_Free(CEqualities
);
1803 fprintf(stderr
, "domains found at : %.2fs\n", (float)clock()/CLOCKS_PER_SEC
);
1807 } /* Polyhedon2Param_Domain */
1812 Param_Polyhedron
*Polyhedron2Param_SimplifiedDomain(Polyhedron
**Din
,Polyhedron
*Cin
,int working_space
,Polyhedron
**CEq
,Matrix
**CT
) {
1814 Param_Polyhedron
*result
;
1816 assert(CEq
!= NULL
);
1819 POL_ENSURE_FACETS(*Din
);
1820 POL_ENSURE_VERTICES(*Din
);
1821 POL_ENSURE_FACETS(Cin
);
1822 POL_ENSURE_VERTICES(Cin
);
1825 fprintf(stderr
,"Polyhedron2Param_Polyhedron algorithm starting at : %.2fs\n",
1826 (float)clock()/CLOCKS_PER_SEC
);
1829 /* Find the m-faces, keeping the corresponding domains */
1830 /* in the linked list PDomains */
1831 result
= Find_m_faces(Din
,Cin
,1,working_space
,CEq
,CT
);
1834 if(result
) fprintf(stderr
, "Number of vertices : %d\n",result
->nbV
);
1835 fprintf(stderr
,"Vertices found at : %.2fs\n",(float)clock()/CLOCKS_PER_SEC
);
1838 /* Processing of PVResult and PDomains */
1839 if(result
&& Cin
->Dimension
>0) /* at least 1 parameter */
1840 Compute_PDomains(result
->D
,result
->nbV
,working_space
);
1842 /* Removed this, Vin100, March 01 */
1843 /* if(result && CEqualities )
1844 for(D=result->D;D;D=D->next)
1845 D->Domain = Add_CEqualities(D->Domain);
1849 fprintf(stderr
, "domains found at : %.2fs\n", (float)clock()/CLOCKS_PER_SEC
);
1853 } /* Polyhedron2Param_SimplifiedDomain */
1856 * Free the memory allocated to a list of validity domain of a parametrized
1859 void Param_Domain_Free(Param_Domain
*PD
) {
1861 Param_Domain
*next_pd
;
1865 Domain_Free(PD
->Domain
);
1871 } /* Param_Domain_Free */
1874 * Free the memory allocated to a parametric polyhedron 'P'
1876 void Param_Polyhedron_Free(Param_Polyhedron
*P
) {
1879 Param_Vertices_Free(P
->V
);
1880 Param_Domain_Free(P
->D
);
1882 Matrix_Free(P
->Constraints
);
1884 Matrix_Free(P
->Rays
);
1887 } /* Param_Polyhedron_Free */
1890 * Scales the parametric polyhedron such that all vertices are integer.
1892 void Param_Polyhedron_Scale_Integer(Param_Polyhedron
*PP
, Polyhedron
**P
,
1893 Value
*det
, unsigned MaxRays
)
1896 int nb_param
, nb_vars
;
1899 Value global_var_lcm
;
1902 value_set_si(*det
, 1);
1906 nb_param
= PP
->D
->Domain
->Dimension
;
1907 nb_vars
= PP
->V
->Vertex
->NbRows
;
1909 /* Scan the vertices and make an orthogonal expansion of the variable
1911 /* a- prepare the array of common denominators */
1912 denoms
= Vector_Alloc(nb_vars
);
1913 value_init(global_var_lcm
);
1915 /* b- scan the vertices and compute the variables' global lcms */
1916 for (V
= PP
->V
; V
; V
= V
->next
)
1917 for (i
= 0; i
< nb_vars
; i
++)
1918 value_lcm(denoms
->p
[i
], denoms
->p
[i
], V
->Vertex
->p
[i
][nb_param
+1]);
1920 value_set_si(global_var_lcm
, 1);
1921 for (i
= 0; i
< nb_vars
; i
++) {
1922 value_multiply(*det
, *det
, denoms
->p
[i
]);
1923 value_lcm(global_var_lcm
, global_var_lcm
, denoms
->p
[i
]);
1926 /* scale vertices */
1927 for (V
= PP
->V
; V
; V
= V
->next
)
1928 for (i
= 0; i
< nb_vars
; i
++) {
1929 Vector_Scale(V
->Vertex
->p
[i
], V
->Vertex
->p
[i
], denoms
->p
[i
], nb_param
+1);
1930 Vector_Normalize(V
->Vertex
->p
[i
], nb_param
+2);
1933 /* the expansion can be actually writen as global_var_lcm.L^{-1} */
1934 /* this is equivalent to multiply the rows of P by denoms_det */
1935 for (i
= 0; i
< nb_vars
; i
++)
1936 value_division(denoms
->p
[i
], global_var_lcm
, denoms
->p
[i
]);
1938 /* OPT : we could use a vector instead of a diagonal matrix here (c- and d-).*/
1939 /* c- make the quick expansion matrix */
1940 expansion
= Matrix_Alloc(nb_vars
+nb_param
+1, nb_vars
+nb_param
+1);
1941 for (i
= 0; i
< nb_vars
; i
++)
1942 value_assign(expansion
->p
[i
][i
], denoms
->p
[i
]);
1943 for (i
= nb_vars
; i
< nb_vars
+nb_param
+1; i
++)
1944 value_assign(expansion
->p
[i
][i
], global_var_lcm
);
1946 /* d- apply the variable expansion to the polyhedron */
1948 *P
= Polyhedron_Preimage(*P
, expansion
, MaxRays
);
1950 Matrix_Free(expansion
);
1951 value_clear(global_var_lcm
);
1952 Vector_Free(denoms
);