3 #include <polylib/polylib.h>
7 Both this software and its documentation are
9 Copyright 1993 by IRISA /Universite de Rennes I - France,
10 Copyright 1995,1996 by BYU, Provo, Utah
13 Permission is granted to copy, use, and distribute
14 for any commercial or noncommercial purpose under the terms
15 of the GNU General Public license, version 2, June 1991
16 (see file : LICENSING).
23 /*---------------------------------------------------------------------*/
24 /* int exist_points(pos,P,context) */
25 /* pos : index position of current loop index (0..hdim-1) */
27 /* context : context values for fixed indices */
28 /* recursive procedure, recurs for each imbriquation */
29 /* returns 1 if there exists any integer points in this polyhedron */
30 /* returns 0 if there are none */
31 /*---------------------------------------------------------------------*/
32 static int exist_points(int pos
,Polyhedron
*Pol
,Value
*context
) {
36 value_init(LB
); value_init(UB
);
37 value_init(k
); value_init(tmp
);
41 /* Problem if UB or LB is INFINITY */
42 if (lower_upper_bounds(pos
,Pol
,context
,&LB
,&UB
) !=0) {
43 errormsg1("exist_points", "infdom", "infinite domain");
50 value_set_si(context
[pos
],0);
59 value_substract(tmp
,UB
,LB
);
60 value_increment(tmp
,tmp
);
64 return (value_pos_p(tmp
));
67 for (value_assign(k
,LB
);value_le(k
,UB
);value_increment(k
,k
)) {
69 /* insert k in context */
70 value_assign(context
[pos
],k
);
71 if (exist_points(pos
+1,Pol
->next
,context
) > 0 ) {
72 value_clear(LB
); value_clear(UB
);
73 value_clear(k
); value_clear(tmp
);
78 value_set_si(context
[pos
],0);
79 value_clear(UB
); value_clear(LB
);
80 value_clear(k
); value_clear(tmp
);
84 /*--------------------------------------------------------------*/
85 /* Test to see if there are any integral points in a polyhedron */
86 /*--------------------------------------------------------------*/
87 int Polyhedron_Not_Empty(Polyhedron
*P
,Polyhedron
*C
,int MAXRAYS
) {
93 /* Create a context vector size dim+2 and set it to all zeros */
94 context
= (Value
*) malloc((P
->Dimension
+2)*sizeof(Value
));
96 /* Initialize array 'context' */
97 for (i
=0;i
<(P
->Dimension
+2);i
++)
98 value_init(context
[i
]);
100 Vector_Set(context
,0,(P
->Dimension
+2));
102 /* Set context[P->Dimension+1] = 1 (the constant) */
103 value_set_si(context
[P
->Dimension
+1],1);
105 L
= Polyhedron_Scan(P
,C
,MAXRAYS
);
106 res
= exist_points(1,L
,context
);
109 /* Clear array 'context' */
110 for (i
=0;i
<(P
->Dimension
+2);i
++)
111 value_clear(context
[i
]);
116 /* PolyhedronLTQ ( P1, P2 ) */
117 /* P1 and P2 must be simple polyhedra */
118 /* result = 0 --> not comparable */
119 /* result = -1 --> P1 < P2 */
120 /* result = 1 --> P1 > P2 */
121 int PolyhedronLTQ (Polyhedron
*Pol1
,Polyhedron
*Pol2
,int NbMaxConstrs
) {
123 int res
, dim
, i
, j
, k
;
124 Polyhedron
*Q1
, *Q2
, *Q3
, *Q
;
129 if (Pol1
->next
|| Pol2
->next
) {
130 errormsg1("PolyhedronLTQ", "compoly", "Can only compare polyhedra");
133 if (Pol1
->Dimension
!= Pol2
->Dimension
) {
134 errormsg1("PolyhedronLTQ","diffdim","Polyhedra are not same dimension");
137 dim
= Pol1
->Dimension
+2;
140 fprintf(stdout
, "P1\n");
141 Polyhedron_Print(stdout
,P_VALUE_FMT
,Pol1
);
142 fprintf(stdout
, "P2\n");
143 Polyhedron_Print(stdout
,P_VALUE_FMT
,Pol2
);
146 /* Create the Line to add */
147 Mat
= Matrix_Alloc(1,dim
);
148 Vector_Set(Mat
->p_Init
,0,dim
);
149 value_set_si(Mat
->p
[0][INDEX
],1); /* line in INDEX dimension */
151 Q1
= AddRays(Mat
->p
[0],1,Pol1
,NbMaxConstrs
);
152 Q2
= AddRays(Mat
->p
[0],1,Pol2
,NbMaxConstrs
);
155 fprintf(stdout
, "Q1\n");
156 Polyhedron_Print(stdout
,P_VALUE_FMT
,Q1
);
157 fprintf(stdout
, "Q2\n");
158 Polyhedron_Print(stdout
,P_VALUE_FMT
,Q2
);
162 Q
= DomainIntersection(Q1
,Q2
,NbMaxConstrs
);
165 fprintf(stdout
, "Q\n");
166 Polyhedron_Print(stdout
,P_VALUE_FMT
,Q
);
172 if (emptyQ(Q
)) res
= 0; /* not comparable */
174 Q1
= DomainIntersection(Pol1
,Q
,NbMaxConstrs
);
175 Q2
= DomainIntersection(Pol2
,Q
,NbMaxConstrs
);
178 fprintf(stdout
, "Q1\n");
179 Polyhedron_Print(stdout
,P_VALUE_FMT
,Q1
);
180 fprintf(stdout
, "Q2\n");
181 Polyhedron_Print(stdout
,P_VALUE_FMT
,Q2
);
184 /* Test if Q1 < Q2 */
185 /* Build a constraint array for >= Q1 and <= Q2 */
186 Mat
= Matrix_Alloc(2,dim
);
187 Vector_Set(Mat
->p_Init
,0,2*dim
);
189 /* Choose a contraint from Q1 */
190 for (i
=0; i
<Q1
->NbConstraints
; i
++) {
191 if (value_zero_p(Q1
->Constraint
[i
][0])) {
194 if (value_zero_p(Q1
->Constraint
[i
][INDEX
])) {
196 /* Ignore side constraint (they are in Q) */
199 else if (value_neg_p(Q1
->Constraint
[i
][INDEX
])) {
201 /* copy -constraint to Mat */
202 value_set_si(Mat
->p
[0][0],1);
203 for (k
=1; k
<dim
; k
++)
204 value_oppose(Mat
->p
[0][k
],Q1
->Constraint
[i
][k
]);
208 /* Copy constraint to Mat */
210 value_set_si(Mat
->p
[0][0],1);
211 for (k
=1; k
<dim
; k
++)
212 value_assign(Mat
->p
[0][k
],Q1
->Constraint
[i
][k
]);
215 else if(value_neg_p(Q1
->Constraint
[i
][INDEX
])) {
217 /* Upper bound -- make a lower bound from it */
218 value_set_si(Mat
->p
[0][0],1);
219 for (k
=1; k
<dim
; k
++)
220 value_oppose(Mat
->p
[0][k
],Q1
->Constraint
[i
][k
]);
224 /* Lower or side bound -- ignore it */
228 /* Choose a constraint from Q2 */
229 for (j
=0; j
<Q2
->NbConstraints
; j
++) {
230 if (value_zero_p(Q2
->Constraint
[j
][0])) { /* equality */
231 if (value_zero_p(Q2
->Constraint
[j
][INDEX
])) {
233 /* Ignore side constraint (they are in Q) */
236 else if (value_pos_p(Q2
->Constraint
[j
][INDEX
])) {
238 /* Copy -constraint to Mat */
239 value_set_si(Mat
->p
[1][0],1);
240 for (k
=1; k
<dim
; k
++)
241 value_oppose(Mat
->p
[1][k
],Q2
->Constraint
[j
][k
]);
245 /* Copy constraint to Mat */
246 value_set_si(Mat
->p
[1][0],1);
247 for (k
=1; k
<dim
; k
++)
248 value_assign(Mat
->p
[1][k
],Q2
->Constraint
[j
][k
]);
251 else if (value_pos_p(Q2
->Constraint
[j
][INDEX
])) {
253 /* Lower bound -- make an upper bound from it */
254 value_set_si(Mat
->p
[1][0],1);
256 value_oppose(Mat
->p
[1][k
],Q2
->Constraint
[j
][k
]);
260 /* Upper or side bound -- ignore it */
265 fprintf(stdout
, "i=%d j=%d M=\n", i
+1, j
+1);
266 Matrix_Print(stdout
,P_VALUE_FMT
,Mat
);
269 /* Add Mat to Q and see if anything is made */
270 Q3
= AddConstraints(Mat
->p
[0],2,Q
,NbMaxConstrs
);
273 fprintf(stdout
, "Q3\n");
274 Polyhedron_Print(stdout
,P_VALUE_FMT
,Q3
);
281 fprintf(stdout
, "not empty\n");
287 fprintf(stdout
,"empty\n");
301 fprintf(stdout
, "res = %d\n", res
);
305 } /* PolyhedronLTQ */
308 Given Mat1, a matrix of equalities, performs Gaussian elimination.
309 Find a minimum basis, Returns the rank.
310 Mat1 is context, Mat2 is reduced in context of Mat1
312 int GaussSimplify(Matrix
*Mat1
,Matrix
*Mat2
) {
314 int NbRows
= Mat1
->NbRows
;
315 int NbCols
= Mat1
->NbColumns
;
317 int i
, j
, k
, n
, pivot
, Rank
;
320 column_index
=(int *)malloc(NbCols
* sizeof(int));
322 errormsg1("GaussSimplify", "outofmem", "out of memory space\n");
327 /* Initialize all the 'Value' variables */
328 value_init(gcd
); value_init(tmp
);
331 for (j
=0; j
<NbCols
; j
++) { /* for each column starting at */
332 for (i
=Rank
; i
<NbRows
; i
++) /* diagonal, look down to find */
333 if (value_notzero_p(Mat1
->p
[i
][j
])) /* the first non-zero entry */
335 if (i
!=NbRows
) { /* was one found ? */
336 if (i
!=Rank
) /* was it found below the diagonal?*/
337 Vector_Exchange(Mat1
->p
[Rank
],Mat1
->p
[i
],NbCols
);
339 /* Normalize the pivot row */
340 Vector_Gcd(Mat1
->p
[Rank
],NbCols
,&gcd
);
344 if (value_ge(gcd
,tmp
)) {
346 for (k
=0; k
<NbCols
; k
++,cp
++)
347 value_division(*cp
,*cp
,gcd
);
349 if (value_neg_p(Mat1
->p
[Rank
][j
])) {
351 for (k
=0; k
<NbCols
; k
++,cp
++)
352 value_oppose(*cp
,*cp
);
354 /* End of normalize */
357 for (i
=0;i
<NbRows
;i
++) /* Zero out the rest of the column */
359 if (value_notzero_p(Mat1
->p
[i
][j
])) {
361 value_init(a
); value_init(a1
); value_init(a2
);
362 value_absolute(a1
,Mat1
->p
[i
][j
]);
363 value_absolute(a2
,Mat1
->p
[Rank
][j
]);
365 value_division(a1
,a1
,a
);
366 value_division(a2
,a2
,a
);
368 Vector_Combine(Mat1
->p
[i
],Mat1
->p
[Rank
],Mat1
->p
[i
],a2
,
370 Vector_Normalize(Mat1
->p
[i
],NbCols
);
371 value_clear(a
); value_clear(a1
); value_clear(a2
);
374 column_index
[Rank
]=j
;
377 } /* end of Gauss elimination */
379 if (Mat2
) { /* Mat2 is a transformation matrix (i,j->f(i,j))....
380 can't scale it because can't scale both sides of -> */
381 /* normalizes an affine transformation */
382 /* priority of forms */
383 /* 1. i' -> i (identity) */
384 /* 2. i' -> i + constant (uniform) */
385 /* 3. i' -> constant (broadcast) */
386 /* 4. i' -> j (permutation) */
387 /* 5. i' -> j + constant ( ) */
388 /* 6. i' -> i + j + constant (non-uniform) */
389 for (k
=0; k
<Rank
; k
++) {
391 for (i
=0; i
<(Mat2
->NbRows
-1);i
++) { /* all but the last row 0...0 1 */
392 if ((i
!=j
) && value_notzero_p(Mat2
->p
[i
][j
])) {
394 /* Remove dependency of i' on j */
396 value_init(a
); value_init(a1
); value_init(a2
);
397 value_absolute(a1
,Mat2
->p
[i
][j
]);
398 value_absolute(a2
,Mat2
->p
[k
][j
]);
400 value_division(a1
,a1
,a
);
401 value_division(a2
,a2
,a
);
403 if (value_one_p(a2
)) {
404 Vector_Combine(Mat2
->p
[i
],Mat1
->p
[k
],Mat2
->p
[i
],a2
,
407 /* Vector_Normalize(Mat2->p[i],NbCols); -- can't do T */
408 } /* otherwise, can't do it without mult lhs prod (2i,3j->...) */
409 value_clear(a
); value_clear(a1
); value_clear(a2
);
411 else if ((i
==j
) && value_zero_p(Mat2
->p
[i
][j
])) {
413 /* 'i' does not depend on j */
414 for (n
=j
+1; n
< (NbCols
-1); n
++) {
415 if (value_notzero_p(Mat2
->p
[i
][n
])) { /* i' depends on some n */
417 Vector_Combine(Mat2
->p
[i
],Mat1
->p
[k
],Mat2
->p
[i
],tmp
,
420 } /* if 'i' depends on just a constant, then leave it alone.*/
426 /* Check last row of transformation Mat2 */
427 for (j
=0; j
<(NbCols
-1); j
++)
428 if (value_notzero_p(Mat2
->p
[Mat2
->NbRows
-1][j
])) {
429 errormsg1("GaussSimplify", "corrtrans", "Corrupted transformation\n");
433 if (value_notone_p(Mat2
->p
[Mat2
->NbRows
-1][NbCols
-1])) {
434 errormsg1("GaussSimplify", "corrtrans", "Corrupted transformation\n");
437 value_clear(gcd
); value_clear(tmp
);
440 } /* GaussSimplify */
446 Matrix
*a
=NULL
, *b
=NULL
, *c
, *d
, *e
, *f
;
447 Polyhedron
*A
, *B
, *C
, *D
, *last
, *tmp
;
448 int i
, nbPol
, nbMat
, func
;
450 fgets(s
, 128, stdin
);
453 ((sscanf(s
, "D %d", &nbPol
)<1) && (sscanf(s
, "M %d", &nbMat
)<1)) )
454 fgets(s
, 128, stdin
);
456 for (i
=0, A
=last
=(Polyhedron
*)0; i
<nbPol
; i
++) {
458 tmp
= Constraints2Polyhedron(a
,600);
460 if (!last
) A
= last
= tmp
;
473 ((sscanf(s
, "D %d", &nbPol
)<1) && (sscanf(s
, "M %d", &nbMat
)<1)) )
474 fgets(s
, 128, stdin
);
476 for (i
=0, B
=last
=(Polyhedron
*)0; i
<nbPol
; i
++) {
478 tmp
= Constraints2Polyhedron(b
,200);
480 if (!last
) B
= last
= tmp
;
490 fgets(s
, 128, stdin
);
491 while ((*s
=='#') || (sscanf(s
, "F %d", &func
)<1))
492 fgets(s
, 128, stdin
);
496 C
= DomainUnion(A
, B
, 200);
497 D
= DomainConvex(C
, 200);
498 d
= Polyhedron2Constraints(D
);
499 Matrix_Print(stdout
,P_VALUE_FMT
,d
);
505 D
= DomainSimplify(A
, B
, 200);
506 d
= Polyhedron2Constraints(D
);
507 Matrix_Print(stdout
,P_VALUE_FMT
,d
);
512 a
= Polyhedron2Constraints(A
);
513 Matrix_Print(stdout
,P_VALUE_FMT
,a
);
514 b
= Polyhedron2Constraints(B
);
515 Matrix_Print(stdout
,P_VALUE_FMT
,b
);
518 a
= Polyhedron2Rays(A
);
519 Matrix_Print(stdout
,P_VALUE_FMT
,a
);
523 /* a = ec , da = c , ed = 1 */
524 right_hermite(a
,&c
,&d
,&e
);
525 Matrix_Print(stdout
,P_VALUE_FMT
,c
);
526 Matrix_Print(stdout
,P_VALUE_FMT
,d
);
527 Matrix_Print(stdout
,P_VALUE_FMT
,e
);
528 f
= Matrix_Alloc(e
->NbRows
,c
->NbColumns
);
529 Matrix_Product(e
,c
,f
);
530 Matrix_Print(stdout
,P_VALUE_FMT
,f
);
532 f
= Matrix_Alloc(d
->NbRows
,a
->NbColumns
);
533 Matrix_Product(d
,a
,f
);
534 Matrix_Print(stdout
,P_VALUE_FMT
,f
);
536 f
= Matrix_Alloc(e
->NbRows
, d
->NbColumns
);
537 Matrix_Product(e
,d
,f
);
538 Matrix_Print(stdout
,P_VALUE_FMT
,f
);
542 /* a = ce , ad = c , de = 1 */
543 left_hermite(a
,&c
,&d
,&e
);
544 Matrix_Print(stdout
,P_VALUE_FMT
,c
);
545 Matrix_Print(stdout
,P_VALUE_FMT
,d
);
546 Matrix_Print(stdout
,P_VALUE_FMT
,e
);
547 f
= Matrix_Alloc(c
->NbRows
, e
->NbColumns
);
548 Matrix_Product(c
,e
,f
);
549 Matrix_Print(stdout
,P_VALUE_FMT
,f
);
551 f
= Matrix_Alloc(a
->NbRows
, d
->NbColumns
);
552 Matrix_Product(a
,d
,f
);
553 Matrix_Print(stdout
,P_VALUE_FMT
,f
);
555 f
= Matrix_Alloc(d
->NbRows
, e
->NbColumns
);
556 Matrix_Product(d
,e
,f
);
557 Matrix_Print(stdout
,P_VALUE_FMT
,f
);
561 /* Polyhedron_Print(stdout,"%5d", A); */
562 /* Matrix_Print(stdout,"%4d", b); */
564 C
= Polyhedron_Image(A
, b
, 400);
565 Polyhedron_Print(stdout
,P_VALUE_FMT
,C
);
570 Polyhedron_Not_Empty(A
,B
,600) ? "Not Empty" : "Empty");
574 i
= PolyhedronLTQ(A
,B
,600);
576 i
==-1 ? "A<B" : i
==1 ? "A>B" : i
==0 ? "A><B" : "error");
577 i
= PolyhedronLTQ(B
,A
,600);
579 i
==-1 ? "A<B" : i
==1 ? "A>B" : i
==0 ? "A><B" : "error");
582 printf("? unknown function\n");