00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #undef POLY_DEBUG
00055 #undef POLY_RR_DEBUG
00056 #undef POLY_CH_DEBUG
00057
00058 #include <stdio.h>
00059 #include <stdlib.h>
00060 #include <string.h>
00061 #include <assert.h>
00062 #include <polylib/polylib.h>
00063
00064 #ifdef MAC_OS
00065 #define abs __abs
00066 #endif
00067
00068
00069 #define WSIZE (8*sizeof(int))
00070
00071 #define bexchange(a, b, l)\
00072 {\
00073 char *t = (char *)malloc(l*sizeof(char));\
00074 memcpy((t), (char *)(a), (int)(l));\
00075 memcpy((char *)(a), (char *)(b), (int)(l));\
00076 memcpy((char *)(b), (t), (int)(l));\
00077 free(t); \
00078 }
00079
00080 #define exchange(a, b, t)\
00081 { (t)=(a); (a)=(b); (b)=(t); }
00082
00083
00084
00085
00086
00087 void errormsg1(const char *f, const char *msgname, const char *msg);
00088
00089 int Pol_status;
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 typedef struct {
00100 unsigned int NbRows;
00101 unsigned int NbColumns;
00102 int **p;
00103 int *p_init;
00104 } SatMatrix;
00105
00106
00107
00108
00109 static SatMatrix *SMAlloc(int rows,int cols) {
00110
00111 int **q, *p, i;
00112 SatMatrix *result;
00113
00114 result = (SatMatrix *) malloc (sizeof(SatMatrix));
00115 if(!result) {
00116 errormsg1("SMAlloc", "outofmem", "out of memory space");
00117 return 0;
00118 }
00119 result->NbRows = rows;
00120 result->NbColumns = cols;
00121 if(rows == 0 || cols == 0) {
00122 result->p = NULL;
00123 return result;
00124 }
00125 result->p = q = (int **)malloc(rows * sizeof(int *));
00126 if(!result->p) {
00127 errormsg1("SMAlloc", "outofmem", "out of memory space");
00128 return 0;
00129 }
00130 result->p_init = p = (int *)malloc (rows * cols * sizeof (int));
00131 if(!result->p_init) {
00132 errormsg1("SMAlloc", "outofmem", "out of memory space");
00133 return 0;
00134 }
00135 for (i=0; i<rows; i++) {
00136 *q++ = p;
00137 p += cols;
00138 }
00139 return result;
00140 }
00141
00142
00143
00144
00145 static void SMFree (SatMatrix **matrix) {
00146 SatMatrix *SM = *matrix;
00147
00148 if (SM) {
00149 if (SM->p) {
00150 free ((char *) SM->p_init);
00151 free ((char *) SM->p);
00152 }
00153 free ((char *) SM);
00154 *matrix = NULL;
00155 }
00156 }
00157
00158
00159
00160
00161
00162 static void SMPrint (SatMatrix *matrix) {
00163
00164 int *p;
00165 int i, j;
00166 unsigned NbRows, NbColumns;
00167
00168 fprintf(stderr,"%d %d\n",NbRows=matrix->NbRows, NbColumns=matrix->NbColumns);
00169 for (i=0;i<NbRows;i++) {
00170 p = *(matrix->p+i);
00171 for (j=0;j<NbColumns;j++)
00172 fprintf(stderr, " %10X ", *p++);
00173 fprintf(stderr, "\n");
00174 }
00175 }
00176
00177
00178
00179
00180 static void SatVector_OR(int *p1,int *p2,int *p3,unsigned length) {
00181
00182 int *cp1, *cp2, *cp3;
00183 int i;
00184
00185 cp1=p1;
00186 cp2=p2;
00187 cp3=p3;
00188 for (i=0;i<length;i++) {
00189 *cp3 = *cp1 | *cp2;
00190 cp3++;
00191 cp1++;
00192 cp2++;
00193 }
00194 }
00195
00196
00197
00198
00199 #define SMVector_Copy(p1, p2, length) \
00200 memcpy((char *)(p2), (char *)(p1), (int)((length)*sizeof(int)))
00201
00202
00203
00204
00205 #define SMVector_Init(p1, length) \
00206 memset((char *)(p1), 0, (int)((length)*sizeof(int)))
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 static void Combine(Value *p1, Value *p2, Value *p3, int pos, unsigned length) {
00219
00220 Value a1, a2, gcd;
00221 Value abs_a1,abs_a2,neg_a1;
00222
00223
00224 value_init(a1); value_init(a2); value_init(gcd);
00225 value_init(abs_a1); value_init(abs_a2); value_init(neg_a1);
00226
00227
00228 value_assign(a1,p1[pos]);
00229
00230
00231 value_assign(a2,p2[pos]);
00232
00233
00234 value_absolute(abs_a1,a1);
00235
00236
00237 value_absolute(abs_a2,a2);
00238
00239
00240 value_gcd(gcd, abs_a1, abs_a2);
00241
00242
00243 value_divexact(a1, a1, gcd);
00244
00245
00246 value_divexact(a2, a2, gcd);
00247
00248
00249 value_oppose(neg_a1,a1);
00250
00251 Vector_Combine(p1+1,p2+1,p3+1,a2,neg_a1,length);
00252 Vector_Normalize(p3+1,length);
00253
00254
00255 value_clear(a1); value_clear(a2); value_clear(gcd);
00256 value_clear(abs_a1); value_clear(abs_a2); value_clear(neg_a1);
00257
00258 return;
00259 }
00260
00261
00262
00263
00264
00265
00266 static SatMatrix *TransformSat(Matrix *Mat, Matrix *Ray, SatMatrix *Sat) {
00267
00268 int i, j, sat_nbcolumns;
00269 unsigned jx1, jx2, bx1, bx2;
00270 SatMatrix *result;
00271
00272 if (Mat->NbRows != 0)
00273 sat_nbcolumns = (Mat->NbRows-1) /(sizeof(int)*8) + 1;
00274 else
00275 sat_nbcolumns = 0;
00276
00277 result = SMAlloc(Ray->NbRows, sat_nbcolumns);
00278 SMVector_Init(result->p_init, Ray->NbRows * sat_nbcolumns);
00279
00280 for(i=0,jx1=0,bx1=MSB; i<Ray->NbRows; i++) {
00281 for(j=0,jx2=0,bx2=MSB; j<Mat->NbRows; j++) {
00282 if (Sat->p[j][jx1] & bx1)
00283 result->p[i][jx2] |= bx2;
00284 NEXT(jx2,bx2);
00285 }
00286 NEXT(jx1, bx1);
00287 }
00288 return result;
00289 }
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 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) {
00306
00307 int inf_bound;
00308 Value **uni_eq, **uni_sup, **uni_inf;
00309 int **inc_eq, **inc_sup, **inc_inf;
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 *sup_bound = *equal_bound = NbBid;
00321 uni_sup = uni_eq = Ray->p+NbBid;
00322 inc_sup = inc_eq = Sat->p+NbBid;
00323 inf_bound = NbRay;
00324 uni_inf = Ray->p+NbRay;
00325 inc_inf = Sat->p+NbRay;
00326
00327 while (inf_bound>*sup_bound) {
00328 if (value_zero_p(**uni_sup)) {
00329 if (inc_eq != inc_sup) {
00330 Vector_Exchange(*uni_eq,*uni_sup,RowSize1);
00331 bexchange(*inc_eq,*inc_sup,RowSize2);
00332 }
00333 (*equal_bound)++; uni_eq++; inc_eq++;
00334 (*sup_bound)++; uni_sup++; inc_sup++;
00335 }
00336 else {
00337 *((*inc_sup)+jx)|=bx;
00338
00339
00340 if (value_neg_p(**uni_sup)) {
00341 inf_bound--; uni_inf--; inc_inf--;
00342 if (inc_inf != inc_sup) {
00343 Vector_Exchange(*uni_inf,*uni_sup,RowSize1);
00344 bexchange(*inc_inf,*inc_sup,RowSize2);
00345 }
00346 }
00347 else {
00348 (*sup_bound)++; uni_sup++; inc_sup++;
00349 }
00350 }
00351 }
00352 }
00353
00354 static void SatMatrix_Extend(SatMatrix *Sat, Matrix* Mat, unsigned rows)
00355 {
00356 int i;
00357 unsigned cols;
00358 cols = (Mat->NbRows - 1)/(sizeof(int)*8) + 1;
00359
00360 Sat->p = (int **)realloc(Sat->p, rows * sizeof(int *));
00361 if(!Sat->p) {
00362 errormsg1("SatMatrix_Extend", "outofmem", "out of memory space");
00363 return;
00364 }
00365 Sat->p_init = (int *)realloc(Sat->p_init, rows * cols * sizeof (int));
00366 if(!Sat->p_init) {
00367 errormsg1("SatMatrix_Extend", "outofmem", "out of memory space");
00368 return;
00369 }
00370 for (i = 0; i < rows; ++i)
00371 Sat->p[i] = Sat->p_init + (i * cols);
00372 Sat->NbRows = rows;
00373 }
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 static int Chernikova (Matrix *Mat,Matrix *Ray,SatMatrix *Sat, unsigned NbBid, unsigned NbMaxRays, unsigned FirstConstraint,unsigned dual) {
00387
00388 unsigned NbRay, Dimension, NbConstraints, RowSize1, RowSize2, sat_nbcolumns;
00389 int sup_bound, equal_bound, index_non_zero, bound;
00390 int i, j, k, l, redundant, rayonly, nbcommonconstraints;
00391 int *Temp, aux;
00392 int *ip1, *ip2;
00393 unsigned bx, m, jx;
00394 Value *p1, *p2, *p3;
00395
00396 #ifdef POLY_CH_DEBUG
00397 fprintf(stderr, "[Chernikova: Input]\nRay = ");
00398 Matrix_Print(stderr,0,Ray);
00399 fprintf(stderr, "\nConstraints = ");
00400 Matrix_Print(stderr,0,Mat);
00401 fprintf(stderr, "\nSat = ");
00402 SMPrint(Sat);
00403 #endif
00404
00405 NbConstraints=Mat->NbRows;
00406 NbRay = Ray->NbRows;
00407 Dimension = Mat->NbColumns-1;
00408 sat_nbcolumns=Sat->NbColumns;
00409
00410 RowSize1=(Dimension+1);
00411 RowSize2=sat_nbcolumns * sizeof(int);
00412
00413 Temp=(int *)malloc(RowSize2);
00414 if(!Temp) {
00415 errormsg1("Chernikova", "outofmem", "out of memory space");
00416 return 0;
00417 }
00418 CATCH(any_exception_error) {
00419
00420
00421
00422
00423
00424 free(Temp);
00425 RETHROW();
00426 }
00427 TRY {
00428 jx = FirstConstraint/WSIZE;
00429 bx = MSB; bx >>= FirstConstraint%WSIZE;
00430 for (k=FirstConstraint; k<NbConstraints; k++) {
00431
00432
00433
00434
00435
00436
00437 index_non_zero = NbRay;
00438 for (i=0; i<NbRay; i++) {
00439 p1 = Ray->p[i]+1;
00440 p2 = Mat->p[k]+1;
00441 p3 = Ray->p[i];
00442
00443
00444 value_multiply(*p3,*p1,*p2);
00445 p1++; p2++;
00446 for (j=1; j<Dimension; j++) {
00447
00448
00449 value_addmul(*p3, *p1, *p2);
00450 p1++; p2++;
00451 }
00452 if (value_notzero_p(*p3) && (i<index_non_zero))
00453 index_non_zero=i;
00454 }
00455
00456 #ifdef POLY_CH_DEBUG
00457 fprintf(stderr, "[Chernikova: A]\nRay = ");
00458 Matrix_Print(stderr,0,Ray);
00459 fprintf(stderr, "\nConstraints = ");
00460 Matrix_Print(stderr,0,Mat);
00461 fprintf(stderr, "\nSat = ");
00462 SMPrint (Sat);
00463 #endif
00464
00465
00466 if (index_non_zero<NbBid) {
00467
00468
00469 NbBid--;
00470 if (NbBid!=index_non_zero)
00471 Vector_Exchange(Ray->p[index_non_zero],Ray->p[NbBid],RowSize1);
00472
00473 #ifdef POLY_CH_DEBUG
00474 fprintf(stderr,"************\n");
00475 for(i=0;i<RowSize1;i++) {
00476 value_print(stderr,P_VALUE_FMT,Ray->p[index_non_zero][i]);
00477 }
00478 fprintf(stderr,"\n******\n");
00479 for(i=0;i<RowSize1;i++) {
00480 value_print(stderr,P_VALUE_FMT,Ray->p[NbBid][i]);
00481 }
00482 fprintf(stderr,"\n*******\n");
00483 #endif
00484
00485
00486 for (i=0; i<NbBid; i++)
00487 if (value_notzero_p(Ray->p[i][0]))
00488 Combine(Ray->p[i],Ray->p[NbBid],Ray->p[i],0,Dimension);
00489
00490
00491
00492
00493 if (value_neg_p(Ray->p[NbBid][0])) {
00494 p1=Ray->p[NbBid];
00495 for (j=0;j<Dimension+1; j++) {
00496
00497
00498 value_oppose(*p1,*p1);
00499 p1++;
00500 }
00501 }
00502
00503 #ifdef POLY_CH_DEBUG
00504 fprintf(stderr, "[Chernikova: B]\nRay = ");
00505 Ray->NbRows=NbRay;
00506 Matrix_Print(stderr,0,Ray);
00507 fprintf(stderr, "\nConstraints = ");
00508 Matrix_Print(stderr,0,Mat);
00509 fprintf(stderr, "\nSat = ");
00510 SMPrint(Sat);
00511 #endif
00512
00513
00514 for (i=NbBid+1; i<NbRay; i++)
00515 if (value_notzero_p(Ray->p[i][0]))
00516 Combine(Ray->p[i],Ray->p[NbBid],Ray->p[i],0,Dimension);
00517
00518
00519 if (value_notzero_p(Mat->p[k][0])) {
00520 for (j=0;j<sat_nbcolumns;j++) {
00521 Sat->p[NbBid][j] = 0;
00522 }
00523
00524 Sat->p[NbBid][jx] |= bx;
00525 }
00526 else {
00527 if (--NbRay != NbBid) {
00528 Vector_Copy(Ray->p[NbRay],Ray->p[NbBid],Dimension+1);
00529 SMVector_Copy(Sat->p[NbRay],Sat->p[NbBid],sat_nbcolumns);
00530 }
00531 }
00532
00533 #ifdef POLY_CH_DEBUG
00534 fprintf(stderr, "[Chernikova: C]\nRay = ");
00535 Ray->NbRows=NbRay;
00536 Matrix_Print(stderr,0,Ray);
00537 fprintf(stderr, "\nConstraints = ");
00538 Matrix_Print(stderr,0,Mat);
00539 fprintf(stderr, "\nSat = ");
00540 SMPrint (Sat);
00541 #endif
00542
00543 }
00544 else {
00545 RaySort(Ray, Sat, NbBid, NbRay, &equal_bound, &sup_bound,
00546 RowSize1, RowSize2,bx,jx);
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559 #ifdef POLY_CH_DEBUG
00560 fprintf(stderr, "[Chernikova: D]\nRay = ");
00561 Ray->NbRows=NbRay;
00562 Matrix_Print(stderr,0,Ray);
00563 fprintf(stderr, "\nConstraints = ");
00564 Matrix_Print(stderr,0,Mat);
00565 fprintf(stderr, "\nSat = ");
00566 SMPrint (Sat);
00567 #endif
00568
00569
00570 bound=NbRay;
00571 for (i=equal_bound; i<sup_bound; i++)
00572 for(j=sup_bound; j<bound; j++) {
00573
00574
00575
00576
00577
00578
00579 nbcommonconstraints = 0;
00580 for (l=0; l<jx; l++) {
00581 aux = Temp[l] = Sat->p[i][l] | Sat->p[j][l];
00582 for (m=MSB; m!=0; m>>=1)
00583 if (!(aux&m))
00584 nbcommonconstraints++;
00585 }
00586 aux = Temp[jx] = Sat->p[i][jx] | Sat->p[j][jx];
00587 for (m=MSB; m!=bx; m>>=1)
00588 if (!(aux&m))
00589 nbcommonconstraints++;
00590 rayonly = (value_zero_p(Ray->p[i][Dimension]) &&
00591 value_zero_p(Ray->p[j][Dimension]) &&
00592 (dual == 0));
00593 if(rayonly)
00594 nbcommonconstraints++;
00595
00596
00597
00598
00599
00600 if (nbcommonconstraints+NbBid>=Dimension-2) {
00601
00602 redundant=0;
00603 for (m=NbBid; m<bound; m++)
00604 if ((m!=i)&&(m!=j)) {
00605
00606
00607
00608
00609
00610 if (rayonly && value_notzero_p(Ray->p[m][Dimension]))
00611 continue;
00612
00613
00614
00615
00616 ip1 = Temp;
00617 ip2 = Sat->p[m];
00618 for (l=0; l<=jx; l++,ip2++,ip1++)
00619 if (*ip2 & ~*ip1)
00620 break;
00621 if (l>jx) {
00622 redundant=1;
00623 break;
00624 }
00625 }
00626
00627 #ifdef POLY_CH_DEBUG
00628 fprintf(stderr, "[Chernikova: E]\nRay = ");
00629 Ray->NbRows=NbRay;
00630 Matrix_Print(stderr,0,Ray);
00631 fprintf(stderr, "\nConstraints = ");
00632 Matrix_Print(stderr,0,Mat);
00633 fprintf(stderr, "\nSat = ");
00634 SMPrint (Sat);
00635 #endif
00636
00637
00638
00639
00640
00641 if (!redundant) {
00642 if (NbRay==NbMaxRays) {
00643 NbMaxRays *= 2;
00644 Ray->NbRows = NbRay;
00645 Matrix_Extend(Ray, NbMaxRays);
00646 SatMatrix_Extend(Sat, Mat, NbMaxRays);
00647 }
00648
00649
00650 Combine(Ray->p[j],Ray->p[i],Ray->p[NbRay],0,Dimension);
00651 SatVector_OR(Sat->p[j],Sat->p[i],Sat->p[NbRay],sat_nbcolumns);
00652 Sat->p[NbRay][jx] &= ~bx;
00653 NbRay++;
00654 }
00655 }
00656 }
00657
00658 #ifdef POLY_CH_DEBUG
00659 fprintf(stderr,
00660 "[Chernikova: F]\n"
00661 "sup_bound=%d\n"
00662 "equal_bound=%d\n"
00663 "bound=%d\n"
00664 "NbRay=%d\n"
00665 "Dimension = %d\n"
00666 "Ray = ",sup_bound,equal_bound,bound,NbRay,Dimension);
00667 #endif
00668 #ifdef POLY_CH_DEBUG
00669 Ray->NbRows=NbRay;
00670 fprintf(stderr, "[Chernikova: F]:\nRay = ");
00671 Matrix_Print(stderr,0,Ray);
00672 #endif
00673
00674
00675
00676
00677 j = (value_notzero_p(Mat->p[k][0])) ?
00678 sup_bound : equal_bound;
00679
00680 i = NbRay;
00681 #ifdef POLY_CH_DEBUG
00682 fprintf(stderr, "i = %d\nj = %d \n", i, j);
00683 #endif
00684 while ((j<bound)&&(i>bound)) {
00685 i--;
00686 Vector_Copy(Ray->p[i],Ray->p[j],Dimension+1);
00687 SMVector_Copy(Sat->p[i],Sat->p[j],sat_nbcolumns);
00688 j++;
00689 }
00690
00691 #ifdef POLY_CH_DEBUG
00692 fprintf(stderr, "i = %d\nj = %d \n", i, j);
00693 fprintf(stderr,
00694 "[Chernikova: F]\n"
00695 "sup_bound=%d\n"
00696 "equal_bound=%d\n"
00697 "bound=%d\n"
00698 "NbRay=%d\n"
00699 "Dimension = %d\n"
00700 "Ray = ",sup_bound,equal_bound,bound,NbRay, Dimension);
00701 #endif
00702 #ifdef POLY_CH_DEBUG
00703 Ray->NbRows=NbRay;
00704 fprintf(stderr, "[Chernikova: G]\nRay = ");
00705 Matrix_Print(stderr,0,Ray);
00706 #endif
00707 if (j==bound)
00708 NbRay=i;
00709 else
00710 NbRay=j;
00711 }
00712 NEXT(jx,bx);
00713 }
00714 Ray->NbRows=NbRay;
00715 Sat->NbRows=NbRay;
00716
00717 }
00718
00719 UNCATCH(any_exception_error);
00720 free(Temp);
00721
00722 #ifdef POLY_CH_DEBUG
00723 fprintf(stderr, "[Chernikova: Output]\nRay = ");
00724 Matrix_Print(stderr,0,Ray);
00725 fprintf(stderr, "\nConstraints = ");
00726 Matrix_Print(stderr,0,Mat);
00727 fprintf(stderr, "\nSat = ");
00728 SMPrint (Sat);
00729 #endif
00730
00731 return 0;
00732 }
00733
00734 static int Gauss4(Value **p, int NbEq, int NbRows, int Dimension)
00735 {
00736 int i, j, k, pivot, Rank;
00737 int *column_index = NULL;
00738 Value gcd;
00739
00740 value_init(gcd);
00741 column_index=(int *)malloc(Dimension * sizeof(int));
00742 if(!column_index) {
00743 errormsg1("Gauss","outofmem","out of memory space");
00744 value_clear(gcd);
00745 return 0;
00746 }
00747 Rank=0;
00748
00749 CATCH(any_exception_error) {
00750 if (column_index)
00751 free(column_index);
00752 value_clear(gcd);
00753 RETHROW();
00754 }
00755 TRY {
00756
00757 for (j=1; j<=Dimension; j++) {
00758 for (i=Rank; i<NbEq; i++)
00759
00760
00761 if (value_notzero_p(p[i][j]))
00762 break;
00763 if (i!=NbEq) {
00764 if (i!=Rank)
00765 Vector_Exchange(p[Rank]+1,p[i]+1,Dimension);
00766
00767
00768
00769 Vector_Gcd(p[Rank]+1,Dimension,&gcd);
00770
00771 if (value_cmp_si(gcd, 2) >= 0)
00772 Vector_AntiScale(p[Rank]+1, p[Rank]+1, gcd, Dimension);
00773
00774 if (value_neg_p(p[Rank][j]))
00775 Vector_Oppose(p[Rank]+1, p[Rank]+1, Dimension);
00776
00777 pivot=i;
00778 for (i=pivot+1; i<NbEq; i++) {
00779
00780
00781 if (value_notzero_p(p[i][j]))
00782 Combine(p[i],p[Rank],p[i],j,Dimension);
00783 }
00784
00785
00786
00787
00788
00789 column_index[Rank]=j;
00790 Rank++;
00791 }
00792 }
00793
00794
00795 for (k=Rank-1; k>=0; k--) {
00796 j = column_index[k];
00797
00798
00799 for (i=0; i<k; i++) {
00800
00801
00802 if (value_notzero_p(p[i][j]))
00803 Combine(p[i],p[k],p[i],j,Dimension);
00804 }
00805
00806
00807 for (i=NbEq;i<NbRows;i++) {
00808
00809
00810 if (value_notzero_p(p[i][j]))
00811 Combine(p[i],p[k],p[i],j,Dimension);
00812 }
00813 }
00814 }
00815
00816 UNCATCH(any_exception_error);
00817 free(column_index), column_index = NULL;
00818
00819 value_clear(gcd);
00820 return Rank;
00821 }
00822
00823
00824
00825
00826
00827
00828
00829 int Gauss(Matrix *Mat, int NbEq, int Dimension)
00830 {
00831 int Rank;
00832
00833 #ifdef POLY_DEBUG
00834 fprintf(stderr, "[Gauss : Input]\nRay =");
00835 Matrix_Print(stderr,0,Mat);
00836 #endif
00837
00838 Rank = Gauss4(Mat->p, NbEq, Mat->NbRows, Dimension);
00839
00840 #ifdef POLY_DEBUG
00841 fprintf(stderr, "[Gauss : Output]\nRay =");
00842 Matrix_Print(stderr,0,Mat);
00843 #endif
00844
00845 return Rank;
00846 }
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859 static Polyhedron *Remove_Redundants(Matrix *Mat,Matrix *Ray,SatMatrix *Sat,unsigned *Filter) {
00860
00861 int i, j, k;
00862 unsigned Dimension, sat_nbcolumns, NbRay, NbConstraints, RowSize2,
00863 *Trace = NULL, *bx = NULL, *jx = NULL, Dim_RaySpace, b;
00864 unsigned NbBid, NbUni, NbEq, NbIneq;
00865 unsigned NbBid2, NbUni2, NbEq2, NbIneq2;
00866 int Redundant;
00867 int aux, *temp2 = NULL;
00868 Polyhedron *Pol = NULL;
00869 Vector *temp1 = NULL;
00870 unsigned Status;
00871
00872 Dimension = Mat->NbColumns-1;
00873 NbRay = Ray->NbRows;
00874 sat_nbcolumns = Sat->NbColumns;
00875 NbConstraints = Mat->NbRows;
00876 RowSize2=sat_nbcolumns * sizeof(int);
00877
00878 temp1 = Vector_Alloc(Dimension+1);
00879 if (!temp1) {
00880 errormsg1("Remove_Redundants", "outofmem", "out of memory space");
00881 return 0;
00882 }
00883
00884 if (Filter) {
00885 temp2 = (int *)calloc(sat_nbcolumns, sizeof(int));
00886 if (!temp2)
00887 goto oom;
00888 }
00889
00890
00891
00892 bx = (unsigned *)malloc(NbConstraints * sizeof(unsigned));
00893 if (!bx)
00894 goto oom;
00895 jx = (unsigned *)malloc(NbConstraints * sizeof(unsigned));
00896 if (!jx)
00897 goto oom;
00898 CATCH(any_exception_error) {
00899
00900 Vector_Free(temp1);
00901 if (temp2) free(temp2);
00902 if (bx) free(bx);
00903 if (jx) free(jx);
00904 if (Trace) free(Trace);
00905 if (Pol) Polyhedron_Free(Pol);
00906
00907 RETHROW();
00908 }
00909 TRY {
00910
00911
00912
00913
00914
00915
00916 i = 0;
00917 b = MSB;
00918 for (j=0; j<NbConstraints; j++) {
00919 jx[j] = i;
00920 bx[j] = b;
00921 NEXT(i,b);
00922 }
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932 aux = 0;
00933 for (i=0; i<NbRay; i++) {
00934
00935
00936 value_set_si(Ray->p[i][0],0);
00937
00938
00939 if (value_notzero_p(Ray->p[i][Dimension]))
00940 aux++;
00941 }
00942
00943
00944 if (!aux)
00945 goto empty;
00946
00947 #ifdef POLY_RR_DEBUG
00948 fprintf(stderr, "[Remove_redundants : Init]\nConstraints =");
00949 Matrix_Print(stderr,0,Mat);
00950 fprintf(stderr, "\nRays =");
00951 Matrix_Print(stderr,0,Ray);
00952 #endif
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963 NbEq=0;
00964
00965 #ifdef POLY_RR_DEBUG
00966 fprintf (stderr, " j = ");
00967 #endif
00968
00969 for (j=0; j<NbConstraints; j++) {
00970
00971 #ifdef POLY_RR_DEBUG
00972 fprintf (stderr, " %i ", j);
00973 fflush (stderr);
00974 #endif
00975
00976
00977 if (Filter && value_zero_p(Mat->p[j][0]))
00978 temp2[jx[j]] |= bx[j];
00979
00980 value_set_si(Mat->p[j][0],0);
00981
00982
00983 i = First_Non_Zero(Mat->p[j]+1, Dimension-1);
00984
00985 #ifdef POLY_RR_DEBUG
00986 fprintf(stderr, "[Remove_redundants : IntoStep1]\nConstraints =");
00987 Matrix_Print(stderr,0,Mat);
00988 fprintf (stderr, " j = %i \n", j);
00989 #endif
00990
00991
00992
00993
00994
00995 if (i == -1) {
00996 for (i=0; i<NbRay; i++)
00997 if (!(Sat->p[i][jx[j]]&bx[j])) {
00998
00999
01000 value_increment(Mat->p[j][0],Mat->p[j][0]);
01001 }
01002
01003
01004
01005 if ((value_cmp_si(Mat->p[j][0], NbRay) == 0) &&
01006 (value_notzero_p(Mat->p[j][Dimension])))
01007 goto empty;
01008
01009
01010 NbConstraints--;
01011 if (j==NbConstraints) continue;
01012 Vector_Exchange(Mat->p[j], Mat->p[NbConstraints], temp1->Size);
01013 exchange(jx[j], jx[NbConstraints], aux);
01014 exchange(bx[j], bx[NbConstraints], aux);
01015 j--; continue;
01016 }
01017
01018
01019
01020 for (i=0; i<NbRay; i++)
01021 if (!(Sat->p[i][jx[j]]&bx[j])) {
01022
01023
01024 value_increment(Mat->p[j][0],Mat->p[j][0]);
01025
01026
01027 value_increment (Ray->p[i][0],Ray->p[i][0]);
01028 }
01029
01030
01031 if (value_cmp_si(Mat->p[j][0], NbRay) == 0)
01032 NbEq++;
01033 }
01034 Mat->NbRows = NbConstraints;
01035
01036 NbBid=0;
01037 for (i=0; i<NbRay; i++) {
01038
01039
01040 if (value_zero_p(Ray->p[i][Dimension]))
01041
01042
01043 value_increment(Ray->p[i][0],Ray->p[i][0]);
01044
01045
01046
01047
01048
01049
01050 if (value_cmp_si(Ray->p[i][0], NbConstraints+1) == 0)
01051 NbBid++;
01052 }
01053
01054 #ifdef POLY_RR_DEBUG
01055 fprintf(stderr, "[Remove_redundants : Step1]\nConstraints =");
01056 Matrix_Print(stderr,0,Mat);
01057 fprintf(stderr, "\nRay =");
01058 Matrix_Print(stderr,0,Ray);
01059 #endif
01060
01061
01062
01063
01064
01065
01066
01067
01068 for (i=0; i<NbEq; i++) {
01069
01070
01071 if (value_cmp_si(Mat->p[i][0], NbRay) != 0) {
01072
01073
01074 for (k=i+1; value_cmp_si(Mat->p[k][0], NbRay) != 0 && k < NbConstraints; k++)
01075 ;
01076 if (k==NbConstraints) break;
01077
01078
01079
01080 Vector_Copy(Mat->p[k], temp1->p, temp1->Size);
01081 aux = jx[k];
01082 j = bx[k];
01083 for (;k>i;k--) {
01084 Vector_Copy(Mat->p[k-1], Mat->p[k], temp1->Size);
01085 jx[k] = jx[k-1];
01086 bx[k] = bx[k-1];
01087 }
01088 Vector_Copy(temp1->p, Mat->p[i], temp1->Size);
01089 jx[i] = aux;
01090 bx[i] = j;
01091 }
01092 }
01093
01094
01095 if (Filter) {
01096 Value mone;
01097 value_init(mone);
01098 value_set_si(mone, -1);
01099
01100
01101
01102 for (i = 0; i < NbEq; i++) {
01103 int pos = First_Non_Zero(Mat->p[i]+1, Dimension);
01104 if (pos == -1)
01105 continue;
01106 if (value_neg_p(Mat->p[i][1+pos]))
01107 Vector_Scale(Mat->p[i]+1, Mat->p[i]+1, mone, Dimension);
01108 }
01109 value_clear(mone);
01110 for (i=0; i<NbEq; i++) {
01111
01112
01113 Redundant = 0;
01114 for (j=i+1; j<NbEq; j++) {
01115
01116 if (!(temp2[jx[j]] & bx[j]))
01117 continue;
01118
01119 if (Vector_Equal(Mat->p[i]+1, Mat->p[j]+1, Dimension)) {
01120 Redundant=1;
01121 break;
01122 }
01123 }
01124
01125
01126 if (!Redundant) Filter[jx[i]] |= bx[i];
01127 }
01128 }
01129
01130 #ifdef POLY_RR_DEBUG
01131 fprintf(stderr, "[Remove_redundants : Step2]\nConstraints =");
01132 Matrix_Print(stderr,0,Mat);
01133 fprintf(stderr, "\nRay =");
01134 Matrix_Print(stderr,0,Ray);
01135 #endif
01136
01137
01138
01139
01140
01141
01142
01143
01144 NbEq2 = Gauss(Mat,NbEq,Dimension);
01145
01146
01147
01148
01149 if (NbEq2 >= Dimension)
01150 goto empty;
01151
01152 #ifdef POLY_RR_DEBUG
01153 fprintf(stderr, "[Remove_redundants : Step3]\nConstraints =");
01154 Matrix_Print(stderr,0,Mat);
01155 fprintf(stderr, "\nRay =");
01156 Matrix_Print(stderr,0,Ray);
01157 #endif
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167 for (i=0, k=NbRay; i<NbBid && k>i; i++) {
01168
01169 if (value_cmp_si(Ray->p[i][0], NbConstraints+1) != 0) {
01170
01171
01172 while (--k > i && value_cmp_si(Ray->p[k][0], NbConstraints+1) != 0)
01173 ;
01174
01175
01176
01177 Vector_Exchange(Ray->p[i], Ray->p[k], temp1->Size);
01178 bexchange(Sat->p[i], Sat->p[k], RowSize2);
01179 }
01180 }
01181
01182 #ifdef POLY_RR_DEBUG
01183 fprintf(stderr, "[Remove_redundants : Step4]\nConstraints =");
01184 Matrix_Print(stderr,0,Mat);
01185 fprintf(stderr, "\nRay =");
01186 Matrix_Print(stderr,0,Ray);
01187 #endif
01188
01189
01190
01191
01192
01193
01194
01195
01196 NbBid2 = Gauss(Ray, NbBid, Dimension);
01197
01198 #ifdef POLY_RR_DEBUG
01199 fprintf(stderr, "[Remove_redundants : After Gauss]\nRay =");
01200 Matrix_Print(stderr,0,Ray);
01201 #endif
01202
01203
01204
01205 if (NbBid2>=Dimension) {
01206 errormsg1("RemoveRedundants", "rmrdt", "dimension error");
01207 goto empty;
01208 }
01209
01210
01211 Dim_RaySpace = Dimension-1-NbEq2-NbBid2;
01212
01213 #ifdef POLY_RR_DEBUG
01214 fprintf(stderr, "[Remove_redundants : Step5]\nConstraints =");
01215 Matrix_Print(stderr,0,Mat);
01216 fprintf(stderr, "\nRay =");
01217 Matrix_Print(stderr,0,Ray);
01218 #endif
01219
01220
01221
01222
01223
01224
01225
01226
01227 NbIneq=0;
01228 for (j=0; j<NbConstraints; j++) {
01229
01230
01231 i = First_Non_Zero(Mat->p[j]+1, Dimension-1);
01232
01233
01234
01235 if (i == -1) {
01236
01237
01238 if ((value_cmp_si(Mat->p[j][0], NbRay) == 0) &&
01239 (value_notzero_p(Mat->p[j][Dimension])))
01240 goto empty;
01241
01242
01243
01244 value_set_si(Mat->p[j][0],2);
01245 continue;
01246 }
01247
01248 Status = VALUE_TO_INT(Mat->p[j][0]);
01249
01250 if (Status == 0)
01251 value_set_si(Mat->p[j][0], 2);
01252 else if (Status < Dim_RaySpace)
01253 value_set_si(Mat->p[j][0], 2);
01254 else if (Status == NbRay)
01255 value_set_si(Mat->p[j][0], 0);
01256 else {
01257 NbIneq++;
01258 value_set_si(Mat->p[j][0], 1);
01259 }
01260 }
01261
01262 #ifdef POLY_RR_DEBUG
01263 fprintf(stderr, "[Remove_redundants : Step6]\nConstraints =");
01264 Matrix_Print(stderr,0,Mat);
01265 fprintf(stderr, "\nRay =");
01266 Matrix_Print(stderr,0,Ray);
01267 #endif
01268
01269
01270
01271
01272
01273
01274 NbUni=0;
01275 for (j=0; j<NbRay; j++) {
01276 Status = VALUE_TO_INT(Ray->p[j][0]);
01277
01278 if (Status < Dim_RaySpace)
01279 value_set_si(Ray->p[j][0], 2);
01280 else if (Status == NbConstraints+1)
01281 value_set_si(Ray->p[j][0], 0);
01282 else {
01283 NbUni++;
01284 value_set_si(Ray->p[j][0], 1);
01285 }
01286 }
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296 Pol = Polyhedron_Alloc(Dimension-1, NbIneq+NbEq2+1, NbUni+NbBid2);
01297 if (!Pol) {
01298 UNCATCH(any_exception_error);
01299 goto oom;
01300 }
01301 Pol->NbBid = NbBid2;
01302 Pol->NbEq = NbEq2;
01303
01304
01305 if (NbBid2) Vector_Copy(Ray->p[0], Pol->Ray[0], (Dimension+1)*NbBid2);
01306 if (NbEq2) Vector_Copy(Mat->p[0], Pol->Constraint[0], (Dimension+1)*NbEq2);
01307
01308 #ifdef POLY_RR_DEBUG
01309 fprintf(stderr, "[Remove_redundants : Step7]\nConstraints =");
01310 Matrix_Print(stderr,0,Mat);
01311 fprintf(stderr, "\nRay =");
01312 Matrix_Print(stderr,0,Ray);
01313 #endif
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328 Trace=(unsigned *)malloc(sat_nbcolumns * sizeof(unsigned));
01329 if(!Trace) {
01330 UNCATCH(any_exception_error);
01331 goto oom;
01332 }
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355 NbIneq2 = 0;
01356 for (j=NbEq; j<NbConstraints; j++) {
01357
01358
01359 if (value_one_p (Mat->p[j][0])) {
01360 for (k=0; k<sat_nbcolumns; k++) Trace[k]=0;
01361
01362
01363
01364 for (i=NbBid; i<NbRay; i++)
01365
01366
01367 if (value_one_p(Ray->p[i][0])) {
01368 if (!(Sat->p[i][jx[j]]&bx[j]))
01369 for (k=0; k<sat_nbcolumns; k++) Trace[k] |= Sat->p[i][k];
01370 }
01371
01372
01373
01374
01375 Redundant=0;
01376 for (i=NbEq; i<NbConstraints; i++) {
01377
01378
01379 if (value_one_p(Mat->p[i][0]) && (i!=j) && !(Trace[jx[i]] & bx[i])) {
01380 Redundant=1;
01381 break;
01382 }
01383 }
01384 if (Redundant) {
01385 value_set_si(Mat->p[j][0],2);
01386 }
01387 else {
01388 Vector_Copy(Mat->p[j], Pol->Constraint[NbEq2+NbIneq2], Dimension+1);
01389 if (Filter) Filter[jx[j]] |= bx[j];
01390 NbIneq2++;
01391 }
01392 }
01393 }
01394 free(Trace), Trace = NULL;
01395
01396 #ifdef POLY_RR_DEBUG
01397 fprintf(stderr, "[Remove_redundants : Step8]\nConstraints =");
01398 Matrix_Print(stderr,0,Mat);
01399 fprintf(stderr, "\nRay =");
01400 Matrix_Print(stderr,0,Ray);
01401 #endif
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412 Trace=(unsigned *)malloc(NbRay * sizeof(unsigned));
01413 if(!Trace) {
01414 UNCATCH(any_exception_error);
01415 goto oom;
01416 }
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435 NbUni2 = 0;
01436
01437
01438 aux = 0;
01439 for (i=NbBid; i<NbRay; i++) {
01440
01441
01442 if (value_one_p (Ray->p[i][0])) {
01443
01444
01445 if (value_notzero_p (Ray->p[i][Dimension]))
01446 for (k=NbBid; k<NbRay; k++) Trace[k]=0;
01447 else
01448
01449
01450
01451
01452 for (k=NbBid; k<NbRay; k++)
01453
01454
01455 Trace[k] = (value_notzero_p (Ray->p[k][Dimension]));
01456
01457
01458
01459 for (j=NbEq; j<NbConstraints; j++)
01460
01461
01462 if (value_one_p (Mat->p[j][0])) {
01463 if (!(Sat->p[i][jx[j]]&bx[j]))
01464 for (k=NbBid; k<NbRay; k++) Trace[k] |= Sat->p[k][jx[j]]&bx[j];
01465 }
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475 Redundant = 0;
01476 for (j=NbBid; j<NbRay; j++) {
01477
01478
01479 if (value_one_p (Ray->p[j][0]) && (i!=j) && !Trace[j]) {
01480 Redundant=1;
01481 break;
01482 }
01483 }
01484 if (Redundant)
01485 value_set_si(Ray->p[i][0],2);
01486 else {
01487 Vector_Copy(Ray->p[i], Pol->Ray[NbBid2+NbUni2], Dimension+1);
01488 NbUni2++;
01489
01490
01491 if (value_zero_p (Ray->p[i][Dimension]))
01492 aux++;
01493 }
01494 }
01495 }
01496
01497
01498 if (aux>=Dim_RaySpace) {
01499 Vector_Set(Pol->Constraint[NbEq2+NbIneq2],0,Dimension+1);
01500 value_set_si(Pol->Constraint[NbEq2+NbIneq2][0],1);
01501 value_set_si(Pol->Constraint[NbEq2+NbIneq2][Dimension],1);
01502 NbIneq2++;
01503 }
01504 }
01505
01506 UNCATCH(any_exception_error);
01507
01508 #ifdef POLY_RR_DEBUG
01509 fprintf(stderr, "[Remove_redundants : Step9]\nConstraints =");
01510 Matrix_Print(stderr,0,Mat);
01511 fprintf(stderr, "\nRay =");
01512 Matrix_Print(stderr,0,Ray);
01513 #endif
01514
01515 free(Trace);
01516 free(bx);
01517 free(jx);
01518 if (temp2)
01519 free(temp2);
01520
01521 Pol->NbConstraints = NbEq2 + NbIneq2;
01522 Pol->NbRays = NbBid2 + NbUni2;
01523
01524 Vector_Free(temp1);
01525 F_SET(Pol,
01526 POL_VALID | POL_INEQUALITIES | POL_FACETS | POL_POINTS | POL_VERTICES);
01527 return Pol;
01528
01529 oom:
01530 errormsg1("Remove_Redundants", "outofmem", "out of memory space");
01531
01532 Vector_Free(temp1);
01533 if (temp2)
01534 free(temp2);
01535 if (bx)
01536 free(bx);
01537 if (jx)
01538 free(jx);
01539 return NULL;
01540
01541 empty:
01542 Vector_Free(temp1);
01543 if (temp2)
01544 free(temp2);
01545 if (bx)
01546 free(bx);
01547 if (jx)
01548 free(jx);
01549 UNCATCH(any_exception_error);
01550 return Empty_Polyhedron(Dimension-1);
01551 }
01552
01553
01554
01555
01556 Polyhedron* Polyhedron_Alloc(unsigned Dimension,unsigned NbConstraints,unsigned NbRays) {
01557
01558 Polyhedron *Pol;
01559 unsigned NbRows,NbColumns;
01560 int i,j;
01561 Value *p, **q;
01562
01563 Pol=(Polyhedron *)malloc(sizeof(Polyhedron));
01564 if(!Pol) {
01565 errormsg1("Polyhedron_Alloc", "outofmem", "out of memory space");
01566 return 0;
01567 }
01568
01569 Pol->next = (Polyhedron *)0;
01570 Pol->Dimension = Dimension;
01571 Pol->NbConstraints = NbConstraints;
01572 Pol->NbRays = NbRays;
01573 Pol->NbEq = 0;
01574 Pol->NbBid = 0;
01575 Pol->flags = 0;
01576 NbRows = NbConstraints + NbRays;
01577 NbColumns = Dimension + 2;
01578
01579 q = (Value **)malloc(NbRows * sizeof(Value *));
01580 if(!q) {
01581 errormsg1("Polyhedron_Alloc", "outofmem", "out of memory space");
01582 return 0;
01583 }
01584 p = value_alloc(NbRows*NbColumns, &Pol->p_Init_size);
01585 if(!p) {
01586 free(q);
01587 errormsg1("Polyhedron_Alloc", "outofmem", "out of memory space");
01588 return 0;
01589 }
01590 Pol->Constraint = q;
01591 Pol->Ray = q + NbConstraints;
01592 Pol->p_Init = p;
01593 for (i=0;i<NbRows;i++) {
01594 *q++ = p;
01595 p += NbColumns;
01596 }
01597 return Pol;
01598 }
01599
01600
01601
01602
01603 void Polyhedron_Free(Polyhedron *Pol)
01604 {
01605 if(!Pol)
01606 return;
01607 value_free(Pol->p_Init, Pol->p_Init_size);
01608 free(Pol->Constraint);
01609 free(Pol);
01610 return;
01611 }
01612
01613
01614
01615
01616 void Domain_Free(Polyhedron *Pol)
01617 {
01618 Polyhedron *Next;
01619
01620 for (; Pol; Pol = Next) {
01621 Next = Pol->next;
01622 Polyhedron_Free(Pol);
01623 }
01624 return;
01625 }
01626
01627
01628
01629
01630 void Polyhedron_Print(FILE *Dst, const char *Format, const Polyhedron *Pol)
01631 {
01632 unsigned Dimension, NbConstraints, NbRays;
01633 int i, j;
01634 Value *p;
01635
01636 if (!Pol) {
01637 fprintf(Dst, "<null polyhedron>\n");
01638 return;
01639 }
01640
01641 Dimension = Pol->Dimension + 2;
01642 NbConstraints = Pol->NbConstraints;
01643 NbRays = Pol->NbRays;
01644 fprintf(Dst, "POLYHEDRON Dimension:%d\n", Pol->Dimension);
01645 fprintf(Dst," Constraints:%d Equations:%d Rays:%d Lines:%d\n",
01646 Pol->NbConstraints, Pol->NbEq, Pol->NbRays, Pol->NbBid);
01647 fprintf(Dst,"Constraints %d %d\n", NbConstraints, Dimension);
01648
01649 for (i=0;i<NbConstraints;i++) {
01650 p=Pol->Constraint[i];
01651
01652
01653 if (value_notzero_p (*p))
01654 fprintf(Dst,"Inequality: [");
01655 else
01656 fprintf(Dst,"Equality: [");
01657 p++;
01658 for (j=1;j<Dimension;j++) {
01659 value_print(Dst,Format,*p++);
01660 }
01661 (void)fprintf(Dst," ]\n");
01662 }
01663
01664 (void)fprintf(Dst, "Rays %d %d\n", NbRays, Dimension);
01665 for (i=0;i<NbRays;i++) {
01666 p=Pol->Ray[i];
01667
01668
01669 if (value_notzero_p (*p)) {
01670 p++;
01671
01672
01673 if (value_notzero_p (p[Dimension-2]))
01674 fprintf(Dst, "Vertex: [");
01675 else
01676 fprintf(Dst, "Ray: [");
01677 }
01678 else {
01679 p++;
01680 fprintf(Dst, "Line: [");
01681 }
01682 for (j=1; j < Dimension-1; j++) {
01683 value_print(Dst,Format,*p++);
01684 }
01685
01686
01687 if (value_notzero_p (*p)) {
01688 fprintf( Dst, " ]/" );
01689 value_print(Dst,VALUE_FMT,*p);
01690 fprintf( Dst, "\n" );
01691 }
01692 else
01693 fprintf(Dst, " ]\n");
01694 }
01695 if (Pol->next) {
01696 fprintf(Dst, "UNION ");
01697 Polyhedron_Print(Dst,Format,Pol->next);
01698 }
01699 }
01700
01701
01702
01703
01704 void PolyPrint (Polyhedron *Pol) {
01705 Polyhedron_Print(stderr,"%4d",Pol);
01706 }
01707
01708
01709
01710
01711
01712
01713
01714
01715 Polyhedron *Empty_Polyhedron(unsigned Dimension) {
01716
01717 Polyhedron *Pol;
01718 int i;
01719
01720 Pol = Polyhedron_Alloc(Dimension, Dimension+1, 0);
01721 if (!Pol) {
01722 errormsg1("Empty_Polyhedron", "outofmem", "out of memory space");
01723 return 0;
01724 }
01725 Vector_Set(Pol->Constraint[0],0,(Dimension+1)*(Dimension+2));
01726 for (i=0; i<=Dimension; i++) {
01727
01728
01729 value_set_si(Pol->Constraint[i][i+1],1);
01730 }
01731 Pol->NbEq = Dimension+1;
01732 Pol->NbBid = 0;
01733 F_SET(Pol,
01734 POL_VALID | POL_INEQUALITIES | POL_FACETS | POL_POINTS | POL_VERTICES);
01735 return Pol;
01736 }
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748 Polyhedron *Universe_Polyhedron(unsigned Dimension) {
01749
01750 Polyhedron *Pol;
01751 int i;
01752
01753 Pol = Polyhedron_Alloc(Dimension,1,Dimension+1);
01754 if (!Pol) {
01755 errormsg1("Universe_Polyhedron", "outofmem", "out of memory space");
01756 return 0;
01757 }
01758 Vector_Set(Pol->Constraint[0],0,(Dimension+2));
01759
01760
01761 value_set_si(Pol->Constraint[0][0],1);
01762
01763
01764 value_set_si(Pol->Constraint[0][Dimension+1],1);
01765 Vector_Set(Pol->Ray[0],0,(Dimension+1)*(Dimension+2));
01766 for (i=0;i<=Dimension;i++) {
01767
01768
01769 value_set_si(Pol->Ray[i][i+1],1);
01770 }
01771
01772
01773 value_set_si(Pol->Ray[Dimension][0],1);
01774 Pol->NbEq = 0;
01775 Pol->NbBid = Dimension;
01776 F_SET(Pol,
01777 POL_VALID | POL_INEQUALITIES | POL_FACETS | POL_POINTS | POL_VERTICES);
01778 return Pol;
01779 }
01780
01781
01782
01783
01784
01785
01786 static void SortConstraints(Matrix *Constraints, unsigned NbEq)
01787 {
01788 int i, j, k;
01789 for (i = NbEq; i < Constraints->NbRows; ++i) {
01790 int max = i;
01791 for (k = i+1; k < Constraints->NbRows; ++k) {
01792 for (j = 1; j < Constraints->NbColumns-1; ++j) {
01793 if (value_eq(Constraints->p[k][j],
01794 Constraints->p[max][j]))
01795 continue;
01796 if (value_abs_lt(Constraints->p[k][j],
01797 Constraints->p[max][j]))
01798 break;
01799 if (value_abs_eq(Constraints->p[k][j],
01800 Constraints->p[max][j]) &&
01801 value_pos_p(Constraints->p[max][j]))
01802 break;
01803 max = k;
01804 break;
01805 }
01806
01807
01808
01809 if (j == Constraints->NbColumns-1) {
01810 if (value_lt(Constraints->p[k][j], Constraints->p[max][j]))
01811 Vector_Exchange(Constraints->p[k],
01812 Constraints->p[max],
01813 Constraints->NbColumns);
01814 Constraints->NbRows--;
01815 if (k < Constraints->NbRows)
01816 Vector_Exchange(Constraints->p[k],
01817 Constraints->p[Constraints->NbRows],
01818 Constraints->NbColumns);
01819 k--;
01820 }
01821 }
01822 if (max != i)
01823 Vector_Exchange(Constraints->p[max], Constraints->p[i],
01824 Constraints->NbColumns);
01825 }
01826 }
01827
01828
01829
01830
01831
01832
01833
01834
01835 static int ImplicitEqualities(Matrix *Constraints, unsigned NbEq)
01836 {
01837 int row, nrow, k;
01838 int found = 0;
01839 Value tmp;
01840 for (row = NbEq; row < Constraints->NbRows; ++row) {
01841 int d = First_Non_Zero(Constraints->p[row]+1, Constraints->NbColumns-2);
01842 if (d == -1) {
01843
01844 if (value_neg_p(Constraints->p[row][Constraints->NbColumns-1])) {
01845 value_set_si(Constraints->p[row][0], 0);
01846 found = 1;
01847 }
01848 break;
01849 }
01850 if (value_neg_p(Constraints->p[row][1+d]))
01851 continue;
01852 for (nrow = row+1; nrow < Constraints->NbRows; ++nrow) {
01853 if (value_zero_p(Constraints->p[nrow][1+d]))
01854 break;
01855 if (value_pos_p(Constraints->p[nrow][1+d]))
01856 continue;
01857 for (k = d; k < Constraints->NbColumns-1; ++k) {
01858 if (value_abs_ne(Constraints->p[row][1+k],
01859 Constraints->p[nrow][1+k]))
01860 break;
01861 if (value_zero_p(Constraints->p[row][1+k]))
01862 continue;
01863 if (value_eq(Constraints->p[row][1+k], Constraints->p[nrow][1+k]))
01864 break;
01865 }
01866 if (k == Constraints->NbColumns-1) {
01867 value_set_si(Constraints->p[row][0], 0);
01868 value_set_si(Constraints->p[nrow][0], 0);
01869 found = 1;
01870 break;
01871 }
01872 if (k != Constraints->NbColumns-2)
01873 continue;
01874
01875
01876
01877 value_init(tmp);
01878 value_addto(tmp, Constraints->p[row][1+k],
01879 Constraints->p[nrow][1+k]);
01880 if (value_sign(tmp) < 0) {
01881 Vector_Set(Constraints->p[row], 0, Constraints->NbColumns-1);
01882 Vector_Set(Constraints->p[nrow], 0, Constraints->NbColumns-1);
01883 value_set_si(Constraints->p[row][1+k], 1);
01884 value_set_si(Constraints->p[nrow][1+k], 1);
01885 found = 1;
01886 }
01887 value_clear(tmp);
01888 if (found)
01889 break;
01890 }
01891 }
01892 return found;
01893 }
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906 Polyhedron *Constraints2Polyhedron(Matrix *Constraints,unsigned NbMaxRays) {
01907
01908 Polyhedron *Pol = NULL;
01909 Matrix *Ray = NULL;
01910 SatMatrix *Sat = NULL;
01911 unsigned Dimension, nbcolumns;
01912 int i;
01913
01914 Dimension = Constraints->NbColumns - 1;
01915 if (Dimension < 1) {
01916 errormsg1("Constraints2Polyhedron","invalidpoly","invalid polyhedron dimension");
01917 return 0;
01918 }
01919
01920
01921
01922 if (Constraints->NbRows==0) {
01923 Pol = Universe_Polyhedron(Dimension-1);
01924 return Pol;
01925 }
01926
01927 if (POL_ISSET(NbMaxRays, POL_NO_DUAL)) {
01928 unsigned NbEq;
01929 unsigned Rank;
01930 Value tmp;
01931 if (POL_ISSET(NbMaxRays, POL_INTEGER))
01932 value_init(tmp);
01933 do {
01934 NbEq = 0;
01935
01936 for (i = 0; i < Constraints->NbRows; ++i)
01937 if (value_zero_p(Constraints->p[i][0])) {
01938 if (POL_ISSET(NbMaxRays, POL_INTEGER) &&
01939 ConstraintSimplify(Constraints->p[i],
01940 Constraints->p[i], Dimension+1, &tmp)) {
01941 value_clear(tmp);
01942 return Empty_Polyhedron(Dimension-1);
01943 }
01944
01945 if (First_Non_Zero(Constraints->p[i]+1, Dimension-1) == -1 &&
01946 value_notzero_p(Constraints->p[i][Dimension])) {
01947 if (POL_ISSET(NbMaxRays, POL_INTEGER))
01948 value_clear(tmp);
01949 return Empty_Polyhedron(Dimension-1);
01950 }
01951 if (i != NbEq)
01952 ExchangeRows(Constraints, i, NbEq);
01953 ++NbEq;
01954 }
01955 Rank = Gauss(Constraints, NbEq, Dimension);
01956 if (POL_ISSET(NbMaxRays, POL_INTEGER))
01957 for (i = NbEq; i < Constraints->NbRows; ++i)
01958 ConstraintSimplify(Constraints->p[i],
01959 Constraints->p[i], Dimension+1, &tmp);
01960 SortConstraints(Constraints, NbEq);
01961 } while (ImplicitEqualities(Constraints, NbEq));
01962 if (POL_ISSET(NbMaxRays, POL_INTEGER))
01963 value_clear(tmp);
01964 Pol = Polyhedron_Alloc(Dimension-1, Constraints->NbRows - (NbEq-Rank), 0);
01965 if (Rank > 0)
01966 Vector_Copy(Constraints->p[0], Pol->Constraint[0],
01967 Rank * Constraints->NbColumns);
01968 if (Constraints->NbRows > NbEq)
01969 Vector_Copy(Constraints->p[NbEq], Pol->Constraint[Rank],
01970 (Constraints->NbRows - NbEq) * Constraints->NbColumns);
01971 Pol->NbEq = Rank;
01972
01973 Pol->Ray = 0;
01974 F_SET(Pol, POL_VALID | POL_INEQUALITIES);
01975 return Pol;
01976 }
01977
01978 if (Dimension > NbMaxRays)
01979 NbMaxRays = Dimension;
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991 Ray = Matrix_Alloc(NbMaxRays, Dimension+1);
01992 if(!Ray) {
01993 errormsg1("Constraints2Polyhedron","outofmem","out of memory space");
01994 return 0;
01995 }
01996 Vector_Set(Ray->p_Init,0, NbMaxRays * (Dimension+1));
01997 for (i=0; i<Dimension; i++) {
01998
01999
02000 value_set_si(Ray->p[i][i+1],1);
02001 }
02002
02003
02004 value_set_si(Ray->p[Dimension-1][0],1);
02005 Ray->NbRows = Dimension;
02006
02007
02008 nbcolumns = (Constraints->NbRows - 1)/(sizeof(int)*8) + 1;
02009 Sat = SMAlloc(NbMaxRays, nbcolumns);
02010 SMVector_Init(Sat->p_init,Dimension*nbcolumns);
02011 Sat->NbRows = Dimension;
02012
02013 CATCH(any_exception_error) {
02014
02015
02016 if (Sat) SMFree(&Sat);
02017 if (Ray) Matrix_Free(Ray);
02018 if (Pol) Polyhedron_Free(Pol);
02019 RETHROW();
02020 }
02021 TRY {
02022
02023
02024 Chernikova(Constraints,Ray,Sat,Dimension-1,NbMaxRays,0,0);
02025
02026 #ifdef POLY_DEBUG
02027 fprintf(stderr, "[constraints2polyhedron]\nConstraints = ");
02028 Matrix_Print(stderr,0,Constraints);
02029 fprintf(stderr, "\nRay = ");
02030 Matrix_Print(stderr,0,Ray);
02031 fprintf(stderr, "\nSat = ");
02032 SMPrint(Sat);
02033 #endif
02034
02035
02036 Pol = Remove_Redundants(Constraints,Ray,Sat,0);
02037 }
02038
02039 UNCATCH(any_exception_error);
02040
02041 #ifdef POLY_DEBUG
02042 fprintf(stderr, "\nPol = ");
02043 Polyhedron_Print(stderr,"%4d",Pol);
02044 #endif
02045
02046 SMFree(&Sat), Sat = NULL;
02047 Matrix_Free(Ray), Ray = NULL;
02048 return Pol;
02049 }
02050
02051 #undef POLY_DEBUG
02052
02053
02054
02055
02056 Matrix *Polyhedron2Constraints(Polyhedron *Pol) {
02057
02058 Matrix *Mat;
02059 unsigned NbConstraints,Dimension;
02060
02061 POL_ENSURE_INEQUALITIES(Pol);
02062
02063 NbConstraints = Pol->NbConstraints;
02064 Dimension = Pol->Dimension+2;
02065 Mat = Matrix_Alloc(NbConstraints,Dimension);
02066 if(!Mat) {
02067 errormsg1("Polyhedron2Constraints", "outofmem", "out of memory space");
02068 return 0;
02069 }
02070 Vector_Copy(Pol->Constraint[0],Mat->p_Init,NbConstraints * Dimension);
02071 return Mat;
02072 }
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083 Polyhedron *Rays2Polyhedron(Matrix *Ray,unsigned NbMaxConstrs) {
02084
02085 Polyhedron *Pol = NULL;
02086 Matrix *Mat = NULL;
02087 SatMatrix *Sat = NULL, *SatTranspose = NULL;
02088 unsigned Dimension, nbcolumns;
02089 int i;
02090
02091 Dimension = Ray->NbColumns-1;
02092 Sat = NULL;
02093 SatTranspose = NULL;
02094 Mat = NULL;
02095
02096 if (Ray->NbRows==0) {
02097
02098
02099 Pol = Empty_Polyhedron(Dimension-1);
02100 return(Pol);
02101 }
02102
02103
02104 if (POL_ISSET(NbMaxConstrs, POL_NO_DUAL))
02105 NbMaxConstrs = 0;
02106
02107 if (Dimension > NbMaxConstrs)
02108 NbMaxConstrs = Dimension;
02109
02110
02111 Mat = Matrix_Alloc(NbMaxConstrs,Dimension+1);
02112 if(!Mat) {
02113 errormsg1("Rays2Polyhedron","outofmem","out of memory space");
02114 return 0;
02115 }
02116
02117
02118 Vector_Set(Mat->p_Init,0,NbMaxConstrs * (Dimension+1));
02119 for (i=0; i<Dimension; i++) {
02120
02121
02122 value_set_si(Mat->p[i][i+1],1);
02123 }
02124
02125
02126
02127 Mat->NbRows = Dimension;
02128 nbcolumns = (Ray->NbRows -1)/(sizeof(int)*8) + 1;
02129 SatTranspose = SMAlloc(NbMaxConstrs,nbcolumns);
02130 SMVector_Init(SatTranspose->p[0],Dimension * nbcolumns);
02131 SatTranspose->NbRows = Dimension;
02132
02133 #ifdef POLY_DEBUG
02134 fprintf(stderr, "[ray2polyhedron: Before]\nRay = ");
02135 Matrix_Print(stderr,0,Ray);
02136 fprintf(stderr, "\nConstraints = ");
02137 Matrix_Print(stderr,0,Mat);
02138 fprintf(stderr, "\nSatTranspose = ");
02139 SMPrint (SatTranspose);
02140 #endif
02141
02142 CATCH(any_exception_error) {
02143
02144
02145
02146
02147 if (SatTranspose) SMFree(&SatTranspose);
02148 if (Sat) SMFree(&Sat);
02149 if (Mat) Matrix_Free(Mat);
02150 if (Pol) Polyhedron_Free(Pol);
02151 RETHROW();
02152 }
02153 TRY {
02154
02155
02156 Chernikova(Ray,Mat,SatTranspose,Dimension,NbMaxConstrs,0,1);
02157
02158 #ifdef POLY_DEBUG
02159 fprintf(stderr, "[ray2polyhedron: After]\nRay = ");
02160 Matrix_Print(stderr,0,Ray);
02161 fprintf(stderr, "\nConstraints = ");
02162 Matrix_Print(stderr,0,Mat);
02163 fprintf(stderr, "\nSatTranspose = ");
02164 SMPrint (SatTranspose);
02165 #endif
02166
02167
02168
02169 Sat = TransformSat(Mat,Ray,SatTranspose);
02170
02171 #ifdef POLY_DEBUG
02172 fprintf(stderr, "\nSat =");
02173 SMPrint(Sat);
02174 #endif
02175
02176 SMFree(&SatTranspose), SatTranspose = NULL;
02177
02178
02179 Pol = Remove_Redundants(Mat,Ray,Sat,0);
02180 }
02181
02182 UNCATCH(any_exception_error);
02183
02184 #ifdef POLY_DEBUG
02185 fprintf(stderr, "\nPol = ");
02186 Polyhedron_Print(stderr,"%4d",Pol);
02187 #endif
02188
02189 SMFree(&Sat);
02190 Matrix_Free(Mat);
02191 return Pol;
02192 }
02193
02194
02195
02196
02197
02198 void Polyhedron_Compute_Dual(Polyhedron *P)
02199 {
02200 if (!F_ISSET(P, POL_VALID))
02201 return;
02202
02203 if (F_ISSET(P, POL_FACETS | POL_VERTICES))
02204 return;
02205
02206 if (F_ISSET(P, POL_INEQUALITIES)) {
02207 Matrix M;
02208 Polyhedron tmp, *Q;
02209
02210 M.NbRows = P->NbConstraints;
02211 M.NbColumns = P->Dimension+2;
02212 M.p_Init = P->p_Init;
02213 M.p = P->Constraint;
02214 Q = Constraints2Polyhedron(&M, 0);
02215
02216
02217 tmp = *Q;
02218 *Q = *P;
02219 *P = tmp;
02220
02221 P->next = Q->next;
02222 Polyhedron_Free(Q);
02223 return;
02224 }
02225
02226
02227 assert(0);
02228 }
02229
02230
02231
02232
02233
02234
02235
02236
02237 static SatMatrix *BuildSat(Matrix *Mat,Matrix *Ray,unsigned NbConstraints,unsigned NbMaxRays) {
02238
02239 SatMatrix *Sat = NULL;
02240 int i, j, k, jx;
02241 Value *p1, *p2, *p3;
02242 unsigned Dimension, NbRay, bx, nbcolumns;
02243
02244 CATCH(any_exception_error) {
02245 if (Sat)
02246 SMFree(&Sat);
02247 RETHROW();
02248 }
02249 TRY {
02250 NbRay = Ray->NbRows;
02251 Dimension = Mat->NbColumns-1;
02252
02253
02254 nbcolumns = (Mat->NbRows - 1)/(sizeof(int)*8) + 1;
02255 Sat = SMAlloc(NbMaxRays,nbcolumns);
02256 Sat->NbRows = NbRay;
02257 SMVector_Init(Sat->p_init, nbcolumns * NbRay);
02258 jx=0; bx=MSB;
02259 for (k=0; k<NbConstraints; k++) {
02260 for (i=0; i<NbRay; i++) {
02261
02262
02263
02264 p1 = Ray->p[i]+1;
02265 p2 = Mat->p[k]+1;
02266 p3 = Ray->p[i];
02267 value_set_si(*p3,0);
02268 for (j=0; j<Dimension; j++) {
02269 value_addmul(*p3, *p1, *p2);
02270 p1++; p2++;
02271 }
02272 }
02273 for (j=0; j<NbRay; j++) {
02274
02275
02276
02277 if (value_notzero_p(Ray->p[j][0]))
02278 Sat->p[j][jx]|=bx;
02279 }
02280 NEXT(jx, bx);
02281 }
02282 }
02283
02284 UNCATCH(any_exception_error);
02285 return Sat;
02286 }
02287
02288
02289
02290
02291
02292
02293 Polyhedron *AddConstraints(Value *Con,unsigned NbConstraints,Polyhedron *Pol,unsigned NbMaxRays) {
02294
02295 Polyhedron *NewPol = NULL;
02296 Matrix *Mat = NULL, *Ray = NULL;
02297 SatMatrix *Sat = NULL;
02298 unsigned NbRay, NbCon, Dimension;
02299
02300 if (NbConstraints == 0)
02301 return Polyhedron_Copy(Pol);
02302
02303 POL_ENSURE_INEQUALITIES(Pol);
02304 Dimension = Pol->Dimension + 2;
02305
02306 if (POL_ISSET(NbMaxRays, POL_NO_DUAL)) {
02307 NbCon = Pol->NbConstraints + NbConstraints;
02308
02309 Mat = Matrix_Alloc(NbCon, Dimension);
02310 if (!Mat) {
02311 errormsg1("AddConstraints", "outofmem", "out of memory space");
02312 return NULL;
02313 }
02314 Vector_Copy(Pol->Constraint[0], Mat->p[0], Pol->NbConstraints * Dimension);
02315 Vector_Copy(Con, Mat->p[Pol->NbConstraints], NbConstraints * Dimension);
02316 NewPol = Constraints2Polyhedron(Mat, NbMaxRays);
02317 Matrix_Free(Mat);
02318 return NewPol;
02319 }
02320
02321 POL_ENSURE_VERTICES(Pol);
02322
02323 CATCH(any_exception_error) {
02324 if (NewPol) Polyhedron_Free(NewPol);
02325 if (Mat) Matrix_Free(Mat);
02326 if (Ray) Matrix_Free(Ray);
02327 if (Sat) SMFree(&Sat);
02328 RETHROW();
02329 }
02330 TRY {
02331 NbRay = Pol->NbRays;
02332 NbCon = Pol->NbConstraints + NbConstraints;
02333
02334 if (NbRay > NbMaxRays)
02335 NbMaxRays = NbRay;
02336
02337 Mat = Matrix_Alloc(NbCon, Dimension);
02338 if(!Mat) {
02339 errormsg1("AddConstraints", "outofmem", "out of memory space");
02340 UNCATCH(any_exception_error);
02341 return 0;
02342 }
02343
02344
02345 Vector_Copy(Pol->Constraint[0], Mat->p[0], Pol->NbConstraints * Dimension);
02346
02347
02348 Vector_Copy(Con, Mat->p[Pol->NbConstraints], NbConstraints * Dimension);
02349
02350
02351 Ray = Matrix_Alloc(NbMaxRays, Dimension);
02352 if(!Ray) {
02353 errormsg1("AddConstraints", "outofmem", "out of memory space");
02354 UNCATCH(any_exception_error);
02355 return 0;
02356 }
02357 Ray->NbRows = NbRay;
02358
02359
02360 if (NbRay)
02361 Vector_Copy(Pol->Ray[0], Ray->p[0], NbRay * Dimension);
02362
02363
02364
02365 Sat = BuildSat(Mat, Ray, Pol->NbConstraints, NbMaxRays);
02366
02367
02368 Pol_status = Chernikova(Mat, Ray, Sat, Pol->NbBid, NbMaxRays, Pol->NbConstraints,0);
02369
02370
02371 NewPol = Remove_Redundants(Mat, Ray, Sat, 0);
02372
02373 }
02374
02375 UNCATCH(any_exception_error);
02376 SMFree(&Sat);
02377 Matrix_Free(Ray);
02378 Matrix_Free(Mat);
02379 return NewPol;
02380 }
02381
02382
02383
02384
02385
02386
02387
02388 int PolyhedronIncludes(Polyhedron *Pol1,Polyhedron *Pol2) {
02389
02390 int Dimension = Pol1->Dimension + 1;
02391 int i, j, k;
02392 Value *p1, *p2, p3;
02393
02394 POL_ENSURE_FACETS(Pol1);
02395 POL_ENSURE_VERTICES(Pol1);
02396 POL_ENSURE_FACETS(Pol2);
02397 POL_ENSURE_VERTICES(Pol2);
02398
02399 value_init(p3);
02400 for (k=0; k<Pol1->NbConstraints; k++) {
02401 for (i=0;i<Pol2->NbRays;i++) {
02402
02403
02404 p1 = Pol2->Ray[i]+1;
02405 p2 = Pol1->Constraint[k]+1;
02406 value_set_si(p3,0);
02407 for(j=0;j<Dimension;j++) {
02408 value_addmul(p3, *p1,*p2);
02409 p1++; p2++;
02410 }
02411
02412
02413
02414 if(value_neg_p(p3) ||
02415 (value_notzero_p(p3)
02416 && (value_zero_p(Pol1->Constraint[k][0]) || (value_zero_p(Pol2->Ray[i][0])) ) )) {
02417 value_clear(p3);
02418 return 0;
02419 }
02420 }
02421 }
02422 value_clear(p3);
02423 return 1;
02424 }
02425
02426
02427
02428
02429
02430
02431
02432 Polyhedron *AddPolyToDomain(Polyhedron *Pol,Polyhedron *PolDomain) {
02433
02434 Polyhedron *p, *pnext, *p_domain_end = (Polyhedron *) 0;
02435 int Redundant;
02436
02437 if (!Pol)
02438 return PolDomain;
02439 if (!PolDomain)
02440 return Pol;
02441
02442 POL_ENSURE_FACETS(Pol);
02443 POL_ENSURE_VERTICES(Pol);
02444
02445
02446 if (emptyQ(Pol)) {
02447 Polyhedron_Free(Pol);
02448 return PolDomain;
02449 }
02450
02451 POL_ENSURE_FACETS(PolDomain);
02452 POL_ENSURE_VERTICES(PolDomain);
02453
02454
02455 if (emptyQ(PolDomain)) {
02456 Polyhedron_Free(PolDomain);
02457 return Pol;
02458 }
02459
02460
02461 Redundant = 0;
02462 for (p=PolDomain,PolDomain=(Polyhedron *)0; p; p=pnext) {
02463
02464
02465 if (PolyhedronIncludes(Pol, p))
02466 {
02467
02468 pnext = p->next;
02469 Polyhedron_Free( p );
02470 continue;
02471 }
02472
02473
02474 if (!PolDomain) PolDomain = p; else p_domain_end->next = p;
02475 p_domain_end = p;
02476
02477
02478 if (PolyhedronIncludes(p,Pol)) {
02479 Redundant = 1;
02480 break;
02481 }
02482 pnext = p->next;
02483 }
02484 if (!Redundant) {
02485
02486
02487
02488 if (!PolDomain) PolDomain = Pol; else p_domain_end->next = Pol;
02489 }
02490 else {
02491
02492
02493 Polyhedron_Free(Pol);
02494 }
02495 return PolDomain;
02496 }
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508 Polyhedron *SubConstraint(Value *Con,Polyhedron *Pol,unsigned NbMaxRays,int Pass) {
02509
02510 Polyhedron *NewPol = NULL;
02511 Matrix *Mat = NULL, *Ray = NULL;
02512 SatMatrix *Sat = NULL;
02513 unsigned NbRay, NbCon, NbEle1, Dimension;
02514 int i;
02515
02516 POL_ENSURE_FACETS(Pol);
02517 POL_ENSURE_VERTICES(Pol);
02518
02519 CATCH(any_exception_error) {
02520 if (NewPol) Polyhedron_Free(NewPol);
02521 if (Mat) Matrix_Free(Mat);
02522 if (Ray) Matrix_Free(Ray);
02523 if (Sat) SMFree(&Sat);
02524 RETHROW();
02525 }
02526 TRY {
02527
02528
02529 Dimension = Pol->Dimension+1;
02530 for (i=1; i<Dimension; i++)
02531 if (value_notzero_p(Con[i])) break;
02532 if (i==Dimension) {
02533 UNCATCH(any_exception_error);
02534 return (Polyhedron *) 0;
02535 }
02536
02537 NbRay = Pol->NbRays;
02538 NbCon = Pol->NbConstraints;
02539 Dimension = Pol->Dimension+2;
02540 NbEle1 = NbCon * Dimension;
02541
02542
02543 if (POL_ISSET(NbMaxRays, POL_NO_DUAL))
02544 NbMaxRays = 0;
02545
02546 if (NbRay > NbMaxRays)
02547 NbMaxRays = NbRay;
02548
02549 Mat = Matrix_Alloc(NbCon + 1, Dimension);
02550 if(!Mat) {
02551 errormsg1("SubConstraint", "outofmem", "out of memory space");
02552 UNCATCH(any_exception_error);
02553 return 0;
02554 }
02555
02556
02557 Vector_Copy(Pol->Constraint[0], Mat->p[0], NbEle1);
02558
02559
02560 value_set_si(Mat->p[NbCon][0],1);
02561 if (!(Pass&1))
02562 for(i=1; i<Dimension; i++)
02563 value_oppose(Mat->p[NbCon][i],Con[i]);
02564 else
02565 for(i=1; i<Dimension; i++)
02566 value_assign(Mat->p[NbCon][i],Con[i]);
02567 if (!(Pass&2))
02568 value_decrement(Mat->p[NbCon][Dimension-1],Mat->p[NbCon][Dimension-1]);
02569
02570
02571 Ray = Matrix_Alloc(NbMaxRays, Dimension);
02572 if(!Ray) {
02573 errormsg1("SubConstraint", "outofmem", "out of memory space");
02574 UNCATCH(any_exception_error);
02575 return 0;
02576 }
02577
02578
02579 Ray->NbRows = NbRay;
02580 if (NbRay)
02581 Vector_Copy(Pol->Ray[0], Ray->p[0], NbRay * Dimension);
02582
02583
02584
02585 Sat = BuildSat(Mat, Ray, NbCon, NbMaxRays);
02586
02587
02588 Pol_status = Chernikova(Mat, Ray, Sat, Pol->NbBid, NbMaxRays, NbCon,0);
02589
02590
02591 NewPol = Remove_Redundants(Mat, Ray, Sat, 0);
02592
02593 }
02594
02595 UNCATCH(any_exception_error);
02596
02597 SMFree(&Sat);
02598 Matrix_Free(Ray);
02599 Matrix_Free(Mat);
02600 return NewPol;
02601 }
02602
02603
02604
02605
02606
02607 Polyhedron *DomainIntersection(Polyhedron *Pol1,Polyhedron *Pol2,unsigned NbMaxRays) {
02608
02609 Polyhedron *p1, *p2, *p3, *d;
02610
02611 if (!Pol1 || !Pol2) return (Polyhedron*) 0;
02612 if (Pol1->Dimension != Pol2->Dimension) {
02613 errormsg1( "DomainIntersection", "diffdim",
02614 "operation on different dimensions");
02615 return (Polyhedron*) 0;
02616 }
02617
02618
02619
02620
02621 d = (Polyhedron *)0;
02622 for (p1=Pol1; p1; p1=p1->next) {
02623 for (p2=Pol2; p2; p2=p2->next) {
02624 p3 = AddConstraints(p2->Constraint[0],
02625 p2->NbConstraints, p1, NbMaxRays);
02626 d = AddPolyToDomain(p3,d);
02627 }
02628 }
02629 if (!d)
02630 return Empty_Polyhedron(Pol1->Dimension);
02631 else
02632 return d;
02633
02634 }
02635
02636
02637
02638
02639 Matrix *Polyhedron2Rays(Polyhedron *Pol) {
02640
02641 Matrix *Ray;
02642 unsigned NbRays, Dimension;
02643
02644 POL_ENSURE_POINTS(Pol);
02645
02646 NbRays = Pol->NbRays;
02647 Dimension = Pol->Dimension+2;
02648 Ray = Matrix_Alloc(NbRays, Dimension);
02649 if(!Ray) {
02650 errormsg1("Polyhedron2Rays", "outofmem", "out of memory space");
02651 return 0;
02652 }
02653 Vector_Copy(Pol->Ray[0], Ray->p_Init, NbRays*Dimension);
02654 return Ray;
02655 }
02656
02657
02658
02659
02660
02661 Polyhedron *AddRays(Value *AddedRays,unsigned NbAddedRays,Polyhedron *Pol,unsigned NbMaxConstrs) {
02662
02663 Polyhedron *NewPol = NULL;
02664 Matrix *Mat = NULL, *Ray = NULL;
02665 SatMatrix *Sat = NULL, *SatTranspose = NULL;
02666 unsigned NbCon, NbRay,NbEle1, Dimension;
02667
02668 POL_ENSURE_FACETS(Pol);
02669 POL_ENSURE_VERTICES(Pol);
02670
02671 CATCH(any_exception_error) {
02672 if (NewPol) Polyhedron_Free(NewPol);
02673 if (Mat) Matrix_Free(Mat);
02674 if (Ray) Matrix_Free(Ray);
02675 if (Sat) SMFree(&Sat);
02676 if (SatTranspose) SMFree(&SatTranspose);
02677 RETHROW();
02678 }
02679 TRY {
02680
02681 NbCon = Pol->NbConstraints;
02682 NbRay = Pol->NbRays;
02683 Dimension = Pol->Dimension + 2;
02684 NbEle1 = NbRay * Dimension;
02685
02686 Ray = Matrix_Alloc(NbAddedRays + NbRay, Dimension);
02687 if(!Ray) {
02688 errormsg1("AddRays", "outofmem", "out of memory space");
02689 UNCATCH(any_exception_error);
02690 return 0;
02691 }
02692
02693
02694 if (NbRay)
02695 Vector_Copy(Pol->Ray[0], Ray->p_Init, NbEle1);
02696
02697
02698 Vector_Copy(AddedRays, Ray->p_Init+NbEle1, NbAddedRays * Dimension);
02699
02700
02701 if (POL_ISSET(NbMaxConstrs, POL_NO_DUAL))
02702 NbMaxConstrs = 0;
02703
02704
02705 if (NbMaxConstrs < NbCon)
02706 NbMaxConstrs = NbCon;
02707
02708
02709 Mat = Matrix_Alloc(NbMaxConstrs, Dimension);
02710 if(!Mat) {
02711 errormsg1("AddRays", "outofmem", "out of memory space");
02712 UNCATCH(any_exception_error);
02713 return 0;
02714 }
02715 Mat->NbRows = NbCon;
02716
02717
02718 Vector_Copy(Pol->Constraint[0], Mat->p_Init, NbCon*Dimension);
02719
02720
02721
02722
02723 SatTranspose = BuildSat(Ray, Mat, NbRay, NbMaxConstrs);
02724
02725
02726 Pol_status = Chernikova(Ray, Mat, SatTranspose, Pol->NbEq, NbMaxConstrs, NbRay,1);
02727
02728
02729
02730 Sat = TransformSat(Mat, Ray, SatTranspose);
02731 SMFree(&SatTranspose), SatTranspose = NULL;
02732
02733
02734 NewPol = Remove_Redundants(Mat, Ray, Sat, 0);
02735
02736 SMFree(&Sat), Sat = NULL;
02737 Matrix_Free(Mat), Mat = NULL;
02738 Matrix_Free(Ray), Ray = NULL;
02739 }
02740
02741 UNCATCH(any_exception_error);
02742 return NewPol;
02743 }
02744
02745
02746
02747
02748
02749
02750 Polyhedron *DomainAddRays(Polyhedron *Pol,Matrix *Ray,unsigned NbMaxConstrs) {
02751
02752 Polyhedron *PolA, *PolEndA, *p1, *p2, *p3;
02753 int Redundant;
02754
02755 if (!Pol) return (Polyhedron*) 0;
02756 if (!Ray || Ray->NbRows == 0)
02757 return Domain_Copy(Pol);
02758 if (Pol->Dimension != Ray->NbColumns-2) {
02759 errormsg1(
02760 "DomainAddRays", "diffdim", "operation on different dimensions");
02761 return (Polyhedron*) 0;
02762 }
02763
02764
02765 PolA = PolEndA = (Polyhedron *)0;
02766 for (p1=Pol; p1; p1=p1->next) {
02767 p3 = AddRays(Ray->p[0], Ray->NbRows, p1, NbMaxConstrs);
02768
02769
02770 Redundant = 0;
02771 for (p2=PolA; p2; p2=p2->next) {
02772 if (PolyhedronIncludes(p2, p3)) {
02773 Redundant = 1;
02774 break;
02775 }
02776 }
02777
02778
02779 if (Redundant)
02780 Polyhedron_Free(p3);
02781 else {
02782 if (!PolEndA)
02783 PolEndA = PolA = p3;
02784 else {
02785 PolEndA->next = p3;
02786 PolEndA = PolEndA->next;
02787 }
02788 }
02789 }
02790 return PolA;
02791 }
02792
02793
02794
02795
02796 Polyhedron *Polyhedron_Copy(Polyhedron *Pol) {
02797
02798 Polyhedron *Pol1;
02799
02800 if (!Pol) return (Polyhedron *)0;
02801
02802
02803 Pol1 = Polyhedron_Alloc(Pol->Dimension, Pol->NbConstraints, Pol->NbRays);
02804 if (!Pol1) {
02805 errormsg1("Polyhedron_Copy", "outofmem", "out of memory space");
02806 return 0;
02807 }
02808 if( Pol->NbConstraints )
02809 Vector_Copy(Pol->Constraint[0], Pol1->Constraint[0],
02810 Pol->NbConstraints*(Pol->Dimension+2));
02811 if( Pol->NbRays )
02812 Vector_Copy(Pol->Ray[0], Pol1->Ray[0],
02813 Pol->NbRays*(Pol->Dimension+2));
02814 Pol1->NbBid = Pol->NbBid;
02815 Pol1->NbEq = Pol->NbEq;
02816 Pol1->flags = Pol->flags;
02817 return Pol1;
02818 }
02819
02820
02821
02822
02823 Polyhedron *Domain_Copy(Polyhedron *Pol) {
02824
02825 Polyhedron *Pol1;
02826
02827 if (!Pol) return (Polyhedron *) 0;
02828 Pol1 = Polyhedron_Copy(Pol);
02829 if (Pol->next) Pol1->next = Domain_Copy(Pol->next);
02830 return Pol1;
02831 }
02832
02833
02834
02835
02836
02837
02838
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861 static void addToFilter(int k, unsigned *Filter, SatMatrix *Sat,Value *tmpR,Value *tmpC,int NbRays,int NbConstraints) {
02862
02863 int kj, i,j, jx;
02864 unsigned kb, bx;
02865
02866
02867 kj = k/WSIZE; kb = MSB; kb >>= k%WSIZE;
02868 Filter[kj]|=kb;
02869 value_set_si(tmpC[k],-1);
02870
02871
02872 for(i=0; i<NbRays; i++)
02873 if (value_posz_p(tmpR[i])) {
02874 if (Sat->p[i][kj]&kb)
02875 value_decrement(tmpR[i],tmpR[i]);
02876 else {
02877
02878
02879 value_set_si(tmpR[i],-1);
02880
02881
02882 jx=0; bx=MSB;
02883 for(j=0; j<NbConstraints; j++) {
02884 if (value_posz_p(tmpC[j]) && (Sat->p[i][jx]&bx) )
02885 value_decrement(tmpC[j],tmpC[j]);
02886 NEXT(jx,bx);
02887 }
02888 }
02889 }
02890 }
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902 static void FindSimple(Polyhedron *P1,Polyhedron *P2,unsigned *Filter,unsigned NbMaxRays) {
02903
02904 Matrix *Mat = NULL;
02905 SatMatrix *Sat = NULL;
02906 int i, j, k, jx, found;
02907 Value *p1, *p2, p3;
02908 unsigned Dimension, NbRays, NbConstraints, bx, nc;
02909 Value NbConstraintsLeft, tmp;
02910 Value *tmpC = NULL, *tmpR = NULL;
02911 Polyhedron *Pol = NULL, *Pol2 = NULL;
02912
02913
02914 value_init(p3); value_init(NbConstraintsLeft);
02915 value_init(tmp);
02916
02917 CATCH(any_exception_error) {
02918 if (tmpC) free(tmpC);
02919 if (tmpR) free(tmpR);
02920 if (Mat) Matrix_Free(Mat);
02921 if (Sat) SMFree(&Sat);
02922 if (Pol2 && Pol2!=P2) Polyhedron_Free(Pol2);
02923 if (Pol && Pol!=Pol2 && Pol!=P2) Polyhedron_Free(Pol);
02924
02925
02926 value_clear(p3); value_clear(NbConstraintsLeft);
02927 value_clear(tmp);
02928 RETHROW();
02929 }
02930 TRY {
02931
02932 Dimension = P1->Dimension+2;
02933 Mat = Matrix_Alloc(P1->NbConstraints, Dimension);
02934 if(!Mat) {
02935 errormsg1("FindSimple", "outofmem", "out of memory space");
02936 UNCATCH(any_exception_error);
02937
02938
02939 value_clear(p3); value_clear(NbConstraintsLeft); value_clear(tmp);
02940 return;
02941 }
02942
02943
02944 jx = 0; bx = MSB; Mat->NbRows=0;
02945 value_set_si(NbConstraintsLeft,0);
02946 for (k=0; k<P1->NbConstraints; k++) {
02947 if (Filter[jx]&bx) {
02948 Vector_Copy(P1->Constraint[k], Mat->p[Mat->NbRows], Dimension);
02949 Mat->NbRows++;
02950 }
02951 else
02952 value_increment(NbConstraintsLeft,NbConstraintsLeft);
02953 NEXT(jx,bx);
02954 }
02955 Pol2 = P2;
02956
02957 for (;;) {
02958 if (Mat->NbRows==0)
02959 Pol = Polyhedron_Copy(Pol2);
02960 else {
02961 Pol = AddConstraints(Mat->p_Init, Mat->NbRows, Pol2, NbMaxRays);
02962 if (Pol2 != P2) Polyhedron_Free(Pol2), Pol2 = NULL;
02963 }
02964 if (emptyQ(Pol)) {
02965 Matrix_Free(Mat), Mat = NULL;
02966 Polyhedron_Free(Pol), Pol = NULL;
02967 UNCATCH(any_exception_error);
02968
02969
02970 value_clear(p3); value_clear(NbConstraintsLeft); value_clear(tmp);
02971 return;
02972 }
02973 Mat->NbRows = 0;
02974 Pol2 = Pol;
02975
02976
02977 Dimension = Pol->Dimension+1;
02978 NbRays = Pol->NbRays;
02979 NbConstraints = P1->NbConstraints;
02980 tmpR = (Value *)malloc(NbRays*sizeof(Value));
02981 if(!tmpR) {
02982 errormsg1("FindSimple", "outofmem", "out of memory space");
02983 UNCATCH(any_exception_error);
02984
02985
02986 value_clear(p3); value_clear(NbConstraintsLeft); value_clear(tmp);
02987 return;
02988 }
02989 for(i=0;i<NbRays;i++)
02990 value_init(tmpR[i]);
02991 tmpC = (Value *)malloc(NbConstraints*sizeof(Value));
02992 if(!tmpC) {
02993 errormsg1("FindSimple", "outofmem", "out of memory space");
02994 UNCATCH(any_exception_error);
02995
02996
02997 value_clear(p3); value_clear(NbConstraintsLeft);
02998 for(i=0;i<NbRays;i++)
02999 value_clear(tmpR[i]);
03000 free(tmpR);
03001 return;
03002 }
03003 for(i=0;i<NbConstraints;i++)
03004 value_init(tmpC[i]);
03005 Vector_Set(tmpR,0,NbRays);
03006 Vector_Set(tmpC,0,NbConstraints);
03007
03008
03009 nc = (NbConstraints - 1) / (sizeof(int)*8) + 1;
03010 Sat = SMAlloc(NbRays, nc);
03011 Sat->NbRows = NbRays;
03012 SMVector_Init(Sat->p_init, nc*NbRays);
03013
03014 jx=0; bx=MSB;
03015 for (k=0; k<NbConstraints; k++) {
03016 if (Filter[jx]&bx)
03017 value_set_si(tmpC[k],-1);
03018 else
03019 for (i=0; i<NbRays; i++) {
03020 p1 = Pol->Ray[i]+1;
03021 p2 = P1->Constraint[k]+1;
03022 value_set_si(p3,0);
03023 for (j=0; j<Dimension; j++) {
03024 value_addmul(p3, *p1, *p2);
03025 p1++; p2++;
03026 }
03027 if(value_zero_p(p3) ||
03028 (value_pos_p(p3) && value_notzero_p(P1->Constraint[k][0]))) {
03029 Sat->p[i][jx]|=bx;
03030 value_increment(tmpR[i],tmpR[i]);
03031 value_increment(tmpC[k],tmpC[k]);
03032 }
03033 }
03034 NEXT(jx, bx);
03035 }
03036
03037 do {
03038 found = 0;
03039 for(i=0; i<NbRays; i++)
03040 if(value_posz_p(tmpR[i])) {
03041 value_add_int(tmp,tmpR[i],1);
03042 if(value_eq(tmp,NbConstraintsLeft)) {
03043
03044
03045 jx = 0; bx = MSB;
03046 for(k=0; k<NbConstraints; k++) {
03047 if(value_posz_p(tmpC[k]) && ((Sat->p[i][jx]&bx)==0)) {
03048 addToFilter(k, Filter, Sat, tmpR, tmpC,
03049 NbRays, NbConstraints);
03050 Vector_Copy(P1->Constraint[k],
03051 Mat->p[Mat->NbRows],Dimension+1);
03052 Mat->NbRows++;
03053 value_decrement(NbConstraintsLeft,NbConstraintsLeft);
03054 found=1;
03055 break;
03056 }
03057 NEXT(jx,bx);
03058 }
03059 break;
03060 }
03061 }
03062 }
03063 while (found);
03064
03065 if (!Mat->NbRows) {
03066
03067 Value cmax;
03068 value_init(cmax);
03069
03070 #ifndef LINEAR_VALUE_IS_CHARS
03071 value_set_si(cmax,(NbRays * NbConstraints+1));
03072 #else
03073 value_set_si(cmax,1);
03074 #endif
03075
03076 j = -1;
03077 for(k=0; k<NbConstraints; k++)
03078 if (value_posz_p(tmpC[k])) {
03079 if (value_gt(cmax,tmpC[k])) {
03080 value_assign(cmax,tmpC[k]);
03081 j = k;
03082 }
03083 }
03084 value_clear(cmax);
03085 if (j<0) {
03086 errormsg1("DomSimplify","logerror","logic error");
03087 }
03088 else {
03089 addToFilter(j, Filter, Sat, tmpR, tmpC, NbRays, NbConstraints);
03090 Vector_Copy(P1->Constraint[j],Mat->p[Mat->NbRows],Dimension+1);
03091 Mat->NbRows++;
03092 value_decrement(NbConstraintsLeft,NbConstraintsLeft);
03093 }
03094 }
03095 SMFree(&Sat), Sat = NULL;
03096 free(tmpC), tmpC = NULL;
03097 free(tmpR), tmpR = NULL;
03098 }
03099 }
03100
03101
03102 value_clear(p3); value_clear(NbConstraintsLeft);
03103 value_clear(tmp);
03104 for(i=0;i<NbRays;i++)
03105 value_clear(tmpR[i]);
03106 for(i=0;i<NbRays;i++)
03107 value_clear(tmpC[i]);
03108
03109 UNCATCH(any_exception_error);
03110 }
03111
03112
03113
03114
03115
03116
03117
03118
03119
03120 static int SimplifyConstraints(Polyhedron *Pol1,Polyhedron *Pol2,unsigned *Filter,unsigned NbMaxRays) {
03121
03122 Polyhedron *Pol = NULL;
03123 Matrix *Mat = NULL, *Ray = NULL;
03124 SatMatrix *Sat = NULL;
03125 unsigned NbRay, NbCon, NbCon1, NbCon2, NbEle1, Dimension, notempty;
03126
03127 CATCH(any_exception_error) {
03128 if (Pol) Polyhedron_Free(Pol);
03129 if (Mat) Matrix_Free(Mat);
03130 if (Ray) Matrix_Free(Ray);
03131 if (Sat) SMFree(&Sat);
03132 RETHROW();
03133 }
03134 TRY {
03135
03136 NbRay = Pol1->NbRays;
03137 NbCon1 = Pol1->NbConstraints;
03138 NbCon2 = Pol2->NbConstraints;
03139 NbCon = NbCon1 + NbCon2;
03140 Dimension = Pol1->Dimension+2;
03141 NbEle1 = NbCon1*Dimension;
03142
03143
03144 if (POL_ISSET(NbMaxRays, POL_NO_DUAL))
03145 NbMaxRays = 0;
03146
03147 if (NbRay > NbMaxRays)
03148 NbMaxRays = NbRay;
03149
03150
03151 Mat = Matrix_Alloc(NbCon, Dimension);
03152 if(!Mat) {
03153 errormsg1("SimplifyConstraints", "outofmem", "out of memory space");
03154 UNCATCH(any_exception_error);
03155 return 0;
03156 }
03157
03158
03159 Vector_Copy(Pol1->Constraint[0], Mat->p_Init, NbEle1);
03160
03161
03162 Vector_Copy(Pol2->Constraint[0], Mat->p_Init+NbEle1, NbCon2*Dimension);
03163
03164
03165 Ray = Matrix_Alloc(NbMaxRays, Dimension);
03166 if(!Ray) {
03167 errormsg1("SimplifyConstraints", "outofmem", "out of memory space");
03168 UNCATCH(any_exception_error);
03169 return 0;
03170 }
03171 Ray->NbRows = NbRay;
03172
03173
03174 Vector_Copy(Pol1->Ray[0], Ray->p_Init, NbRay*Dimension);
03175
03176
03177
03178 Sat = BuildSat(Mat, Ray, NbCon1, NbMaxRays);
03179
03180
03181 Pol_status = Chernikova(Mat, Ray, Sat, Pol1->NbBid, NbMaxRays, NbCon1,0);
03182
03183
03184 Pol = Remove_Redundants(Mat, Ray, Sat, Filter);
03185 notempty = 1;
03186 if (Filter && emptyQ(Pol)) {
03187 notempty = 0;
03188 FindSimple(Pol1, Pol2, Filter, NbMaxRays);
03189 }
03190
03191
03192 Polyhedron_Free(Pol), Pol = NULL;
03193 SMFree(&Sat), Sat = NULL;
03194 Matrix_Free(Ray), Ray = NULL;
03195 Matrix_Free(Mat), Mat = NULL;
03196
03197 }
03198
03199 UNCATCH(any_exception_error);
03200 return notempty;
03201 }
03202
03203
03204
03205
03206
03207 static void SimplifyEqualities(Polyhedron *Pol1, Polyhedron *Pol2, unsigned *Filter) {
03208
03209 int i,j;
03210 unsigned ix, bx, NbEqn, NbEqn1, NbEqn2, NbEle2, Dimension;
03211 Matrix *Mat;
03212
03213 NbEqn1 = Pol1->NbEq;
03214 NbEqn2 = Pol2->NbEq;
03215 NbEqn = NbEqn1 + NbEqn2;
03216 Dimension = Pol1->Dimension+2;
03217 NbEle2 = NbEqn2*Dimension;
03218
03219 Mat = Matrix_Alloc(NbEqn, Dimension);
03220 if (!Mat) {
03221 errormsg1("SimplifyEqualities", "outofmem", "out of memory space");
03222 Pol_status = 1;
03223 return;
03224 }
03225
03226
03227 Vector_Copy(Pol2->Constraint[0], Mat->p_Init, NbEle2);
03228
03229
03230 Vector_Copy(Pol1->Constraint[0], Mat->p_Init+NbEle2, NbEqn1*Dimension);
03231
03232 Gauss(Mat, NbEqn2, Dimension-1);
03233
03234 ix = 0;
03235 bx = MSB;
03236 for (i=NbEqn2; i<NbEqn; i++) {
03237 for (j=1; j<Dimension; j++) {
03238 if (value_notzero_p(Mat->p[i][j])) {
03239
03240
03241
03242 Filter[ix] |= bx;
03243 break;
03244 }
03245 }
03246 NEXT(ix,bx);
03247 }
03248 Matrix_Free(Mat);
03249 return;
03250 }
03251
03252
03253
03254
03255
03256
03257
03258
03259
03260 Polyhedron *DomainSimplify(Polyhedron *Pol1, Polyhedron *Pol2, unsigned NbMaxRays) {
03261
03262 Polyhedron *p1, *p2, *p3, *d;
03263 unsigned k, jx, bx, nbentries, NbConstraints, Dimension, NbCon, empty;
03264 unsigned *Filter;
03265 Matrix *Constraints;
03266
03267
03268 if (!Pol1 || !Pol2) return Pol1;
03269 if (Pol1->Dimension != Pol2->Dimension) {
03270 errormsg1("DomSimplify","diffdim","operation on different dimensions");
03271 Pol_status = 1;
03272 return 0;
03273 }
03274 POL_ENSURE_VERTICES(Pol1);
03275 POL_ENSURE_VERTICES(Pol2);
03276 if (emptyQ(Pol1)||emptyQ(Pol2))
03277 return Empty_Polyhedron(Pol1->Dimension);
03278
03279
03280
03281 NbCon = 0;
03282 for (p2=Pol2; p2; p2=p2->next)
03283 if (p2->NbConstraints > NbCon)
03284 NbCon = p2->NbConstraints;
03285
03286 Dimension = Pol1->Dimension+2;
03287 d = (Polyhedron *)0;
03288 for (p1=Pol1; p1; p1=p1->next) {
03289
03290 POL_ENSURE_VERTICES(p1);
03291
03292
03293
03294
03295
03296
03297 NbConstraints = p1->NbConstraints;
03298 nbentries = (NbConstraints + NbCon - 1) / (sizeof(int)*8) + 1;
03299
03300
03301 Filter = (unsigned *)malloc(nbentries * sizeof(int));
03302 if (!Filter) {
03303 errormsg1("DomSimplify", "outofmem", "out of memory space\n");
03304 Pol_status = 1;
03305 return 0;
03306 }
03307
03308
03309 SMVector_Init(Filter, nbentries);
03310
03311
03312 empty = 1;
03313 for (p2=Pol2; p2; p2=p2->next) {
03314
03315 POL_ENSURE_VERTICES(p2);
03316
03317
03318
03319
03320
03321
03322 SimplifyEqualities(p1, p2, Filter);
03323 if (SimplifyConstraints(p1, p2, Filter, NbMaxRays))
03324 empty=0;
03325
03326
03327 }
03328
03329 if (!empty) {
03330
03331
03332 Constraints = Matrix_Alloc(NbConstraints, Dimension);
03333 if (!Constraints) {
03334 errormsg1("DomSimplify", "outofmem", "out of memory space\n");
03335 Pol_status = 1;
03336 return 0;
03337 }
03338 Constraints->NbRows = 0;
03339 for (k=0, jx=0, bx=MSB; k<NbConstraints; k++) {
03340
03341
03342
03343 if (Filter[jx]&bx) {
03344 Vector_Copy(p1->Constraint[k],
03345 Constraints->p[Constraints->NbRows],
03346 Dimension);
03347 Constraints->NbRows++;
03348 }
03349 NEXT(jx,bx);
03350 }
03351
03352
03353
03354 p3 = Constraints2Polyhedron(Constraints,NbMaxRays);
03355 Matrix_Free(Constraints);
03356
03357
03358 d = AddPolyToDomain (p3, d);
03359 p3 = NULL;
03360 }
03361 free(Filter);
03362 }
03363 if (!d)
03364 return Empty_Polyhedron(Pol1->Dimension);
03365 else return d;
03366
03367 }
03368
03369
03370
03371
03372 Polyhedron *Stras_DomainSimplify(Polyhedron *Pol1,Polyhedron *Pol2,unsigned NbMaxRays) {
03373
03374 Polyhedron *p1, *p2, *p3 = NULL, *d = NULL;
03375 unsigned k, jx, bx, nbentries, NbConstraints, Dimension, NbCon, empty;
03376 unsigned *Filter = NULL;
03377 Matrix *Constraints = NULL;
03378
03379 CATCH(any_exception_error) {
03380 if (Constraints) Matrix_Free(Constraints);
03381 if (Filter) free(Filter);
03382 if (d) Polyhedron_Free(d);
03383 if (p2) Polyhedron_Free(p3);
03384 RETHROW();
03385 }
03386 TRY {
03387 if (!Pol1 || !Pol2) {
03388 UNCATCH(any_exception_error);
03389 return Pol1;
03390 }
03391 if (Pol1->Dimension != Pol2->Dimension) {
03392 errormsg1("DomainSimplify","diffdim","operation on different dimensions");
03393 UNCATCH(any_exception_error);
03394 return 0;
03395 }
03396 POL_ENSURE_VERTICES(Pol1);
03397 POL_ENSURE_VERTICES(Pol2);
03398 if (emptyQ(Pol1)||emptyQ(Pol2)) {
03399 UNCATCH(any_exception_error);
03400 return Empty_Polyhedron(Pol1->Dimension);
03401 }
03402
03403
03404
03405 NbCon = 0;
03406 for (p2=Pol2; p2; p2=p2->next)
03407 if (p2->NbConstraints > NbCon)
03408 NbCon = p2->NbConstraints;
03409
03410 Dimension = Pol1->Dimension+2;
03411 d = (Polyhedron *)0;
03412 for (p1=Pol1; p1; p1=p1->next) {
03413
03414
03415
03416
03417
03418
03419 NbConstraints = p1->NbConstraints;
03420 nbentries = (NbConstraints + NbCon - 1)/(sizeof(int)*8) + 1;
03421
03422
03423 Filter = (unsigned *)malloc(nbentries * sizeof(int));
03424 if(!Filter) {
03425 errormsg1("DomainSimplify", "outofmem", "out of memory space");
03426 UNCATCH(any_exception_error);
03427 return 0;
03428 }
03429
03430
03431 SMVector_Init(Filter, nbentries);
03432
03433
03434 empty = 1;
03435 for (p2=Pol2; p2; p2=p2->next) {
03436
03437
03438
03439
03440
03441
03442 if (SimplifyConstraints(p1, p2, Filter, NbMaxRays))
03443 empty=0;
03444 }
03445
03446 if (!empty) {
03447
03448
03449 Constraints = Matrix_Alloc(NbConstraints,Dimension);
03450 if(!Constraints) {
03451 errormsg1("DomainSimplify", "outofmem", "out of memory space");
03452 UNCATCH(any_exception_error);
03453 return 0;
03454 }
03455 Constraints->NbRows = 0;
03456 for (k=0, jx=0, bx=MSB; k<NbConstraints; k++) {
03457
03458
03459
03460 if (Filter[jx]&bx) {
03461 Vector_Copy(p1->Constraint[k],
03462 Constraints->p[Constraints->NbRows],
03463 Dimension);
03464 Constraints->NbRows++;
03465 }
03466 NEXT(jx,bx);
03467 }
03468
03469
03470
03471 p3 = Constraints2Polyhedron(Constraints,NbMaxRays);
03472 Matrix_Free(Constraints), Constraints = NULL;
03473
03474
03475 d = AddPolyToDomain (p3, d);
03476 p3 = NULL;
03477 }
03478 free(Filter), Filter = NULL;
03479 }
03480 }
03481
03482 UNCATCH(any_exception_error);
03483 if (!d)
03484 return Empty_Polyhedron(Pol1->Dimension);
03485 else
03486 return d;
03487 }
03488
03489
03490
03491
03492
03493 Polyhedron *DomainUnion(Polyhedron *Pol1,Polyhedron *Pol2,unsigned NbMaxRays) {
03494
03495 Polyhedron *PolA, *PolEndA, *PolB, *PolEndB, *p1, *p2;
03496 int Redundant;
03497
03498 if (!Pol1 || !Pol2) return (Polyhedron *) 0;
03499 if (Pol1->Dimension != Pol2->Dimension) {
03500 errormsg1("DomainUnion","diffdim","operation on different dimensions");
03501 return (Polyhedron*) 0;
03502 }
03503
03504
03505
03506
03507
03508
03509
03510 PolA = PolEndA = (Polyhedron *)0;
03511 for (p1=Pol1; p1; p1=p1->next) {
03512
03513
03514 Redundant = 0;
03515 for (p2=Pol2; p2; p2=p2->next) {
03516 if (PolyhedronIncludes(p2, p1) ) {
03517 Redundant = 1;
03518
03519
03520 break;
03521
03522 }
03523 }
03524 if (!Redundant) {
03525
03526
03527 if (!PolEndA)
03528 PolEndA = PolA = Polyhedron_Copy(p1);
03529 else {
03530 PolEndA->next = Polyhedron_Copy(p1);
03531 PolEndA = PolEndA->next;
03532 }
03533
03534 }
03535 }
03536
03537
03538 PolB = PolEndB = (Polyhedron *)0;
03539 for (p2=Pol2; p2; p2=p2->next) {
03540
03541
03542 Redundant = 0;
03543 for (p1=PolA; p1; p1=p1->next) {
03544 if (PolyhedronIncludes(p1, p2)) {
03545 Redundant = 1;
03546 break;
03547 }
03548 }
03549 if (!Redundant) {
03550
03551
03552 if (!PolEndB)
03553 PolEndB = PolB = Polyhedron_Copy(p2);
03554 else {
03555 PolEndB->next = Polyhedron_Copy(p2);
03556 PolEndB = PolEndB->next;
03557 }
03558
03559
03560 }
03561 }
03562
03563 if (!PolA) return PolB;
03564 PolEndA->next = PolB;
03565 return PolA;
03566 }
03567
03568
03569
03570
03571
03572
03573
03574 Polyhedron *DomainConvex(Polyhedron *Pol,unsigned NbMaxConstrs) {
03575
03576 Polyhedron *p, *q, *NewPol = NULL;
03577
03578 CATCH(any_exception_error) {
03579 if (NewPol) Polyhedron_Free(NewPol);
03580 RETHROW();
03581 }
03582 TRY {
03583
03584 if (!Pol) {
03585 UNCATCH(any_exception_error);
03586 return (Polyhedron*) 0;
03587 }
03588
03589 POL_ENSURE_VERTICES(Pol);
03590 NewPol = Polyhedron_Copy(Pol);
03591 for (p=Pol->next; p; p=p->next) {
03592 POL_ENSURE_VERTICES(p);
03593 q = AddRays(p->Ray[0], p->NbRays, NewPol, NbMaxConstrs);
03594 Polyhedron_Free(NewPol);
03595 NewPol = q;
03596 }
03597 }
03598
03599 UNCATCH(any_exception_error);
03600
03601 return NewPol;
03602 }
03603
03604
03605
03606
03607
03608 Polyhedron *DomainDifference(Polyhedron *Pol1,Polyhedron *Pol2,unsigned NbMaxRays) {
03609
03610 Polyhedron *p1, *p2, *p3, *d;
03611 int i;
03612
03613 if (!Pol1 || !Pol2) return (Polyhedron*) 0;
03614 if (Pol1->Dimension != Pol2->Dimension) {
03615 errormsg1("DomainDifference",
03616 "diffdim", "operation on different dimensions");
03617 return (Polyhedron*) 0;
03618 }
03619 POL_ENSURE_FACETS(Pol1);
03620 POL_ENSURE_VERTICES(Pol1);
03621 POL_ENSURE_FACETS(Pol2);
03622 POL_ENSURE_VERTICES(Pol2);
03623 if (emptyQ(Pol1) || emptyQ(Pol2))
03624 return (Domain_Copy(Pol1));
03625 d = (Polyhedron *)0;
03626 for (p2=Pol2; p2; p2=p2->next) {
03627 for (p1=Pol1; p1; p1=p1->next) {
03628 for (i=0; i<p2->NbConstraints; i++) {
03629
03630
03631
03632 p3 = SubConstraint(p2->Constraint[i], p1, NbMaxRays,0);
03633
03634
03635 d = AddPolyToDomain (p3, d);
03636
03637
03638
03639
03640
03641 if( value_notzero_p(p2->Constraint[i][0]) )
03642 continue;
03643 p3 = SubConstraint(p2->Constraint[i], p1, NbMaxRays,1);
03644
03645
03646 d = AddPolyToDomain (p3, d);
03647 }
03648 }
03649 if (p2 != Pol2)
03650 Domain_Free(Pol1);
03651 Pol1 = d;
03652 d = (Polyhedron *)0;
03653 }
03654 if (!Pol1)
03655 return Empty_Polyhedron(Pol2->Dimension);
03656 else
03657 return Pol1;
03658 }
03659
03660
03661
03662
03663
03664
03665 Polyhedron *align_context(Polyhedron *Pol,int align_dimension,int NbMaxRays) {
03666
03667 int i, j, k;
03668 Polyhedron *p = NULL, **next, *result = NULL;
03669 unsigned dim;
03670
03671 CATCH(any_exception_error) {
03672 if (result) Polyhedron_Free(result);
03673 RETHROW();
03674 }
03675 TRY {
03676
03677 if (!Pol) return Pol;
03678 dim = Pol->Dimension;
03679 if (align_dimension < Pol->Dimension) {
03680 errormsg1("align_context", "diffdim", "context dimension exceeds data");
03681 UNCATCH(any_exception_error);
03682 return NULL;
03683 }
03684 if (align_dimension == Pol->Dimension) {
03685 UNCATCH(any_exception_error);
03686 return Domain_Copy(Pol);
03687 }
03688
03689
03690 k = align_dimension - Pol->Dimension;
03691 next = &result;
03692
03693
03694 for (; Pol; Pol=Pol->next) {
03695 int have_cons = !F_ISSET(Pol, POL_VALID) || F_ISSET(Pol, POL_INEQUALITIES);
03696 int have_rays = !F_ISSET(Pol, POL_VALID) || F_ISSET(Pol, POL_POINTS);
03697 unsigned NbCons = have_cons ? Pol->NbConstraints : 0;
03698 unsigned NbRays = have_rays ? Pol->NbRays + k : 0;
03699
03700 if (Pol->Dimension != dim) {
03701 Domain_Free(result);
03702 errormsg1("align_context", "diffdim", "context not of uniform dimension");
03703 UNCATCH(any_exception_error);
03704 return NULL;
03705 }
03706
03707 p = Polyhedron_Alloc(align_dimension, NbCons, NbRays);
03708 if (have_cons) {
03709 for (i = 0; i < NbCons; ++i) {
03710 value_assign(p->Constraint[i][0], Pol->Constraint[i][0]);
03711 Vector_Copy(Pol->Constraint[i]+1, p->Constraint[i]+k+1, Pol->Dimension+1);
03712 }
03713 p->NbEq = Pol->NbEq;
03714 }
03715
03716 if (have_rays) {
03717 for (i = 0; i < k; ++i)
03718 value_set_si(p->Ray[i][1+i], 1);
03719 for (i = 0; i < Pol->NbRays; ++i) {
03720 value_assign(p->Ray[k+i][0], Pol->Ray[i][0]);
03721 Vector_Copy(Pol->Ray[i]+1, p->Ray[i+k]+k+1, Pol->Dimension+1);
03722 }
03723 p->NbBid = Pol->NbBid + k;
03724 }
03725 p->flags = Pol->flags;
03726
03727 *next = p;
03728 next = &p->next;
03729 }
03730 }
03731
03732 UNCATCH(any_exception_error);
03733 return result;
03734 }
03735
03736
03737
03738
03739
03740
03741
03742
03743 Polyhedron *Polyhedron_Scan(Polyhedron *D, Polyhedron *C,unsigned NbMaxRays) {
03744
03745 int i, j, dim ;
03746 Matrix *Mat;
03747 Polyhedron *C1, *C2, *D1, *D2;
03748 Polyhedron *res, *last, *tmp;
03749
03750 dim = D->Dimension - C->Dimension;
03751 res = last = (Polyhedron *) 0;
03752 if (dim==0) return (Polyhedron *)0;
03753
03754 assert(!D->next);
03755
03756 POL_ENSURE_FACETS(D);
03757 POL_ENSURE_VERTICES(D);
03758 POL_ENSURE_FACETS(C);
03759 POL_ENSURE_VERTICES(C);
03760
03761
03762 Mat = Matrix_Alloc(D->Dimension, D->Dimension+2);
03763 if(!Mat) {
03764 errormsg1("Polyhedron_Scan", "outofmem", "out of memory space");
03765 return 0;
03766 }
03767 C1 = align_context(C,D->Dimension,NbMaxRays);
03768 if(!C1) {
03769 return 0;
03770 }
03771
03772 D2 = DomainIntersection( C1, D, NbMaxRays);
03773
03774 for (i=0; i<dim; i++)
03775 {
03776 Vector_Set(Mat->p_Init,0,D2->Dimension*(D2->Dimension + 2));
03777 for (j=i+1; j<dim; j++) {
03778 value_set_si(Mat->p[j-i-1][j+1],1);
03779 }
03780 Mat->NbRows = dim-i-1;
03781 D1 = Mat->NbRows ? DomainAddRays(D2, Mat, NbMaxRays) : D2;
03782 tmp = DomainSimplify(D1, C1, NbMaxRays);
03783 if (!last) res = last = tmp;
03784 else { last->next = tmp; last = tmp; }
03785 C2 = DomainIntersection(C1, D1, NbMaxRays);
03786 Domain_Free(C1);
03787 C1 = C2;
03788 if (Mat->NbRows) Domain_Free(D1);
03789 }
03790 Domain_Free(D2);
03791 Domain_Free(C1);
03792 Matrix_Free(Mat);
03793 return res;
03794 }
03795
03796
03797
03798
03799
03800
03801
03802
03803
03804
03805 int lower_upper_bounds(int pos,Polyhedron *P,Value *context,Value *LBp,Value *UBp) {
03806
03807 Value LB, UB;
03808 int flag, i;
03809 Value n, n1, d, tmp;
03810
03811 POL_ENSURE_FACETS(P);
03812 POL_ENSURE_VERTICES(P);
03813
03814
03815 value_init(LB); value_init(UB); value_init(tmp);
03816 value_init(n); value_init(n1); value_init(d);
03817
03818 value_set_si(LB,0);
03819 value_set_si(UB,0);
03820
03821
03822 flag = LB_INFINITY | UB_INFINITY;
03823 for (i=0; i<P->NbConstraints; i++) {
03824 value_assign(d,P->Constraint[i][pos]);
03825 Inner_Product(&context[1],&(P->Constraint[i][1]),P->Dimension+1,&n);
03826 if (value_zero_p(d)) {
03827
03828 if (value_neg_p(n) ||
03829 (value_zero_p(P->Constraint[i][0]) && value_notzero_p(n)))
03830 goto empty_loop;
03831 continue;
03832 }
03833 value_oppose(n,n);
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845
03846
03847 if(value_zero_p(P->Constraint[i][0])) {
03848 value_modulus(tmp,n,d);
03849
03850
03851 if (value_notzero_p(tmp))
03852 goto empty_loop;
03853
03854 value_division(n1,n,d);
03855
03856
03857 if((flag&LB_INFINITY) || value_gt(n1,LB))
03858 value_assign(LB,n1);
03859 if((flag&UB_INFINITY) || value_lt(n1,UB))
03860 value_assign(UB,n1);
03861 flag = 0;
03862 }
03863
03864 if (value_pos_p(d)) {
03865 value_modulus(tmp,n,d);
03866
03867
03868 if (value_pos_p(n) && value_notzero_p(tmp)) {
03869 value_division(n1,n,d);
03870 value_add_int(n1,n1,1);
03871 }
03872 else
03873 value_division(n1,n,d);
03874 if (flag&LB_INFINITY) {
03875 value_assign(LB,n1);
03876 flag^=LB_INFINITY;
03877 }
03878 else if(value_gt(n1,LB))
03879 value_assign(LB,n1);
03880 }
03881
03882 if (value_neg_p(d)) {
03883 value_modulus(tmp,n,d);
03884
03885
03886 if (value_pos_p(n) && value_notzero_p(tmp)) {
03887 value_division(n1,n,d);
03888 value_sub_int(n1,n1,1);
03889 }
03890 else
03891 value_division(n1,n,d);
03892
03893 if (flag&UB_INFINITY) {
03894 value_assign(UB,n1);
03895 flag^=UB_INFINITY;
03896 }
03897 else if (value_lt(n1,UB))
03898 value_assign(UB, n1);
03899 }
03900 }
03901 if ((flag & LB_INFINITY)==0) value_assign(*LBp,LB);
03902 if ((flag & UB_INFINITY)==0) value_assign(*UBp,UB);
03903
03904 if (0) {
03905 empty_loop:
03906 flag = 0;
03907 value_set_si(*LBp, 1);
03908 value_set_si(*UBp, 0);
03909 }
03910
03911
03912 value_clear(LB); value_clear(UB); value_clear(tmp);
03913 value_clear(n); value_clear(n1); value_clear(d);
03914 return flag;
03915 }
03916
03917
03918
03919
03920 static void Rays_Mult(Value **A, Matrix *B, Value **C, unsigned NbRays)
03921 {
03922 int i, j, k;
03923 unsigned Dimension1, Dimension2;
03924 Value Sum, tmp;
03925
03926 value_init(Sum); value_init(tmp);
03927
03928 CATCH(any_exception_error) {
03929 value_clear(Sum); value_clear(tmp);
03930 RETHROW();
03931 }
03932 TRY {
03933 Dimension1 = B->NbRows;
03934 Dimension2 = B->NbColumns;
03935
03936 for (i=0; i<NbRays; i++) {
03937 value_assign(C[i][0],A[i][0]);
03938 for (j=0; j<Dimension2; j++) {
03939 value_set_si(Sum,0);
03940 for (k=0; k<Dimension1; k++) {
03941
03942
03943 value_addmul(Sum, A[i][k+1], B->p[k][j]);
03944 }
03945 value_assign(C[i][j+1],Sum);
03946 }
03947 Vector_Gcd(C[i]+1, Dimension2, &tmp);
03948 if (value_notone_p(tmp))
03949 Vector_AntiScale(C[i]+1, C[i]+1, tmp, Dimension2);
03950 }
03951 }
03952 UNCATCH(any_exception_error);
03953 value_clear(Sum); value_clear(tmp);
03954 }
03955
03956
03957
03958
03959 static void Rays_Mult_Transpose(Value **A, Matrix *B, Value **C,
03960 unsigned NbRays)
03961 {
03962 int i, j, k;
03963 unsigned Dimension1, Dimension2;
03964 Value Sum, tmp;
03965
03966 value_init(Sum); value_init(tmp);
03967
03968 CATCH(any_exception_error) {
03969 value_clear(Sum); value_clear(tmp);
03970 RETHROW();
03971 }
03972 TRY {
03973 Dimension1 = B->NbColumns;
03974 Dimension2 = B->NbRows;
03975
03976 for (i=0; i<NbRays; i++) {
03977 value_assign(C[i][0],A[i][0]);
03978 for (j=0; j<Dimension2; j++) {
03979 value_set_si(Sum,0);
03980 for (k=0; k<Dimension1; k++) {
03981
03982
03983 value_addmul(Sum, A[i][k+1], B->p[j][k]);
03984 }
03985 value_assign(C[i][j+1],Sum);
03986 }
03987 Vector_Gcd(C[i]+1, Dimension2, &tmp);
03988 if (value_notone_p(tmp))
03989 Vector_AntiScale(C[i]+1, C[i]+1, tmp, Dimension2);
03990 }
03991 }
03992 UNCATCH(any_exception_error);
03993 value_clear(Sum); value_clear(tmp);
03994 }
03995
03996
03997
03998
03999
04000
04001
04002 Polyhedron *Polyhedron_Preimage(Polyhedron *Pol,Matrix *Func,unsigned NbMaxRays) {
04003
04004 Matrix *Constraints = NULL;
04005 Polyhedron *NewPol = NULL;
04006 unsigned NbConstraints, Dimension1, Dimension2;
04007
04008 POL_ENSURE_INEQUALITIES(Pol);
04009
04010 CATCH(any_exception_error) {
04011 if (Constraints) Matrix_Free(Constraints);
04012 if (NewPol) Polyhedron_Free(NewPol);
04013 RETHROW();
04014 }
04015 TRY {
04016
04017 NbConstraints = Pol->NbConstraints;
04018 Dimension1 = Pol->Dimension+1;
04019 Dimension2 = Func->NbColumns;
04020 if (Dimension1!=(Func->NbRows)) {
04021 errormsg1("Polyhedron_Preimage", "dimincomp", "incompatable dimensions");
04022 UNCATCH(any_exception_error);
04023 return Empty_Polyhedron(Dimension2-1);
04024 }
04025
04026
04027
04028
04029
04030
04031
04032
04033
04034 Constraints = Matrix_Alloc(NbConstraints, Dimension2+1);
04035 if (!Constraints) {
04036 errormsg1("Polyhedron_Preimage", "outofmem", "out of memory space\n");
04037 Pol_status = 1;
04038 UNCATCH(any_exception_error);
04039 return 0;
04040 }
04041
04042
04043
04044 Rays_Mult(Pol->Constraint, Func, Constraints->p, NbConstraints);
04045 NewPol = Constraints2Polyhedron(Constraints, NbMaxRays);
04046 Matrix_Free(Constraints), Constraints = NULL;
04047
04048 }
04049
04050 UNCATCH(any_exception_error);
04051
04052 return NewPol;
04053 }
04054
04055
04056
04057
04058
04059
04060
04061 Polyhedron *DomainPreimage(Polyhedron *Pol,Matrix *Func,unsigned NbMaxRays) {
04062
04063 Polyhedron *p, *q, *d = NULL;
04064
04065 CATCH(any_exception_error) {
04066 if (d) Polyhedron_Free(d);
04067 RETHROW();
04068 }
04069 TRY {
04070 if (!Pol || !Func) {
04071 UNCATCH(any_exception_error);
04072 return (Polyhedron *) 0;
04073 }
04074 d = (Polyhedron *) 0;
04075 for (p=Pol; p; p=p->next) {
04076 q = Polyhedron_Preimage(p, Func, NbMaxRays);
04077 d = AddPolyToDomain (q, d);
04078 }
04079 }
04080 UNCATCH(any_exception_error);
04081 return d;
04082 }
04083
04084
04085
04086
04087
04088
04089 Polyhedron *Polyhedron_Image(Polyhedron *Pol, Matrix *Func,unsigned NbMaxConstrs) {
04090
04091 Matrix *Rays = NULL;
04092 Polyhedron *NewPol = NULL;
04093 unsigned NbRays, Dimension1, Dimension2;
04094
04095 POL_ENSURE_FACETS(Pol);
04096 POL_ENSURE_VERTICES(Pol);
04097
04098 CATCH(any_exception_error) {
04099 if (Rays) Matrix_Free(Rays);
04100 if (NewPol) Polyhedron_Free(NewPol);
04101 RETHROW();
04102 }
04103 TRY {
04104
04105 NbRays = Pol->NbRays;
04106 Dimension1 = Pol->Dimension+1;
04107 Dimension2 = Func->NbRows;
04108 if (Dimension1!=Func->NbColumns) {
04109 errormsg1("Polyhedron_Image", "dimincomp", "incompatible dimensions");
04110 UNCATCH(any_exception_error);
04111 return Empty_Polyhedron(Dimension2-1);
04112 }
04113
04114
04115
04116
04117
04118
04119
04120
04121
04122
04123 if (Dimension1 == Dimension2) {
04124 Matrix *M, *M2;
04125 int ok;
04126 M = Matrix_Copy(Func);
04127 M2 = Matrix_Alloc(Dimension2, Dimension1);
04128 if (!M2) {
04129 errormsg1("Polyhedron_Image", "outofmem", "out of memory space\n");
04130 UNCATCH(any_exception_error);
04131 return 0;
04132 }
04133
04134 ok = Matrix_Inverse(M, M2);
04135 Matrix_Free(M);
04136 if (ok) {
04137 NewPol = Polyhedron_Alloc(Pol->Dimension, Pol->NbConstraints,
04138 Pol->NbRays);
04139 if (!NewPol) {
04140 errormsg1("Polyhedron_Image", "outofmem",
04141 "out of memory space\n");
04142 UNCATCH(any_exception_error);
04143 return 0;
04144 }
04145 Rays_Mult_Transpose(Pol->Ray, Func, NewPol->Ray, NbRays);
04146 Rays_Mult(Pol->Constraint, M2, NewPol->Constraint,
04147 Pol->NbConstraints);
04148 NewPol->NbEq = Pol->NbEq;
04149 NewPol->NbBid = Pol->NbBid;
04150 if (NewPol->NbEq)
04151 Gauss4(NewPol->Constraint, NewPol->NbEq, NewPol->NbConstraints,
04152 NewPol->Dimension+1);
04153 if (NewPol->NbBid)
04154 Gauss4(NewPol->Ray, NewPol->NbBid, NewPol->NbRays,
04155 NewPol->Dimension+1);
04156 }
04157 Matrix_Free(M2);
04158 }
04159
04160 if (!NewPol) {
04161
04162 Rays = Matrix_Alloc(NbRays, Dimension2+1);
04163 if (!Rays) {
04164 errormsg1("Polyhedron_Image", "outofmem", "out of memory space\n");
04165 UNCATCH(any_exception_error);
04166 return 0;
04167 }
04168
04169
04170
04171 Rays_Mult_Transpose(Pol->Ray, Func, Rays->p, NbRays);
04172 NewPol = Rays2Polyhedron(Rays, NbMaxConstrs);
04173 Matrix_Free(Rays), Rays = NULL;
04174 }
04175
04176 }
04177
04178 UNCATCH(any_exception_error);
04179 return NewPol;
04180 }
04181
04182
04183
04184
04185
04186
04187 Polyhedron *DomainImage(Polyhedron *Pol,Matrix *Func,unsigned NbMaxConstrs) {
04188
04189 Polyhedron *p, *q, *d = NULL;
04190
04191 CATCH(any_exception_error) {
04192 if (d) Polyhedron_Free(d);
04193 RETHROW();
04194 }
04195 TRY {
04196
04197 if (!Pol || !Func) {
04198 UNCATCH(any_exception_error);
04199 return (Polyhedron *) 0;
04200 }
04201 d = (Polyhedron *) 0;
04202 for (p=Pol; p; p=p->next) {
04203 q = Polyhedron_Image(p, Func, NbMaxConstrs);
04204 d = AddPolyToDomain (q, d);
04205 }
04206 }
04207
04208 UNCATCH(any_exception_error);
04209
04210 return d;
04211 }
04212
04213
04214
04215
04216
04217
04218
04219
04220
04221
04222
04223 Interval *DomainCost(Polyhedron *Pol,Value *Cost) {
04224
04225 int i, j, NbRay, Dim;
04226 Value *p1, *p2, p3, d, status;
04227 Value tmp1, tmp2, tmp3;
04228 Value **Ray;
04229 Interval *I = NULL;
04230
04231 value_init(p3); value_init(d); value_init(status);
04232 value_init(tmp1); value_init(tmp2); value_init(tmp3);
04233
04234 POL_ENSURE_FACETS(Pol);
04235 POL_ENSURE_VERTICES(Pol);
04236
04237 CATCH(any_exception_error) {
04238 if (I) free(I);
04239 RETHROW();
04240 value_clear(p3); value_clear(d); value_clear(status);
04241 value_clear(tmp1); value_clear(tmp2); value_clear(tmp3);
04242 }
04243 TRY {
04244
04245 Ray = Pol->Ray;
04246 NbRay = Pol->NbRays;
04247 Dim = Pol->Dimension+1;
04248 I = (Interval *) malloc (sizeof(Interval));
04249 if (!I) {
04250 errormsg1("DomainCost", "outofmem", "out of memory space\n");
04251 UNCATCH(any_exception_error);
04252 value_clear(p3); value_clear(d); value_clear(status);
04253 value_clear(tmp1); value_clear(tmp2); value_clear(tmp3);
04254 return 0;
04255 }
04256
04257
04258
04259
04260
04261
04262
04263
04264 value_set_si(I->MaxN,-1);
04265 value_set_si(I->MaxD,0);
04266 I->MaxI = -1;
04267 value_set_si(I->MinN,1);
04268 value_set_si(I->MinD,0);
04269 I->MinI = -1;
04270
04271
04272 for (i=0; i<NbRay; i++) {
04273 p1 = Ray[i];
04274 value_assign(status, *p1);
04275 p1++;
04276 p2 = Cost;
04277
04278
04279 value_multiply(p3,*p1,*p2);
04280 p1++; p2++;
04281 for (j=1; j<Dim; j++) {
04282 value_multiply(tmp1,*p1,*p2);
04283
04284
04285 value_addto(p3,p3,tmp1);
04286 p1++; p2++;
04287 }
04288
04289
04290 p1--;
04291 value_assign(d,*p1);
04292 value_multiply(tmp1,p3,I->MaxD);
04293 value_multiply(tmp2,I->MaxN,d);
04294 value_set_si(tmp3,1);
04295
04296
04297 if (I->MaxI==-1 ||
04298 value_gt(tmp1,tmp2) ||
04299 (value_eq(tmp1,tmp2) &&
04300 value_eq(d,tmp3) && value_ne(I->MaxD,tmp3))) {
04301 value_assign(I->MaxN,p3);
04302 value_assign(I->MaxD,d);
04303 I->MaxI = i;
04304 }
04305 value_multiply(tmp1,p3,I->MinD);
04306 value_multiply(tmp2,I->MinN,d);
04307 value_set_si(tmp3,1);
04308
04309
04310 if (I->MinI==-1 ||
04311 value_lt(tmp1,tmp2) ||
04312 (value_eq(tmp1,tmp2) &&
04313 value_eq(d,tmp3) && value_ne(I->MinD,tmp3))) {
04314 value_assign(I->MinN, p3);
04315 value_assign(I->MinD, d);
04316 I->MinI = i;
04317 }
04318 value_multiply(tmp1,p3,I->MaxD);
04319 value_set_si(tmp2,0);
04320
04321
04322 if (value_zero_p(status)) {
04323 if (value_lt(tmp1,tmp2)) {
04324 value_oppose(I->MaxN,p3);
04325 value_set_si(I->MaxD,0);
04326 I->MaxI = i;
04327 }
04328 value_multiply(tmp1,p3,I->MinD);
04329 value_set_si(tmp2,0);
04330
04331 if (value_gt(tmp1,tmp2)) {
04332 value_oppose(I->MinN,p3);
04333 value_set_si(I->MinD,0);
04334 I->MinI = i;
04335 }
04336 }
04337 }
04338 }
04339
04340 UNCATCH(any_exception_error);
04341 value_clear(p3); value_clear(d); value_clear(status);
04342 value_clear(tmp1); value_clear(tmp2); value_clear(tmp3);
04343 return I;
04344 }
04345
04346
04347
04348
04349
04350
04351 Polyhedron *DomainAddConstraints(Polyhedron *Pol,Matrix *Mat,unsigned NbMaxRays) {
04352
04353 Polyhedron *PolA, *PolEndA, *p1, *p2, *p3;
04354 int Redundant;
04355
04356 if (!Pol) return (Polyhedron*) 0;
04357 if (!Mat) return Pol;
04358 if (Pol->Dimension != Mat->NbColumns-2) {
04359 errormsg1("DomainAddConstraints",
04360 "diffdim", "operation on different dimensions");
04361 return (Polyhedron*) 0;
04362 }
04363
04364
04365 PolA = PolEndA = (Polyhedron *)0;
04366 for (p1=Pol; p1; p1=p1->next) {
04367 p3 = AddConstraints(Mat->p_Init, Mat->NbRows, p1, NbMaxRays);
04368
04369
04370 Redundant = 0;
04371 for (p2=PolA; p2; p2=p2->next) {
04372 if (PolyhedronIncludes(p2, p3)) {
04373 Redundant = 1;
04374 break;
04375 }
04376 }
04377
04378
04379 if (Redundant)
04380 Polyhedron_Free(p3);
04381 else {
04382 if (!PolEndA)
04383 PolEndA = PolA = p3;
04384 else {
04385 PolEndA->next = p3;
04386 PolEndA = PolEndA->next;
04387 }
04388 }
04389 }
04390 return PolA;
04391 }
04392
04393
04394
04395
04396
04397
04398
04399
04400
04401
04402
04403
04404 Polyhedron *Disjoint_Domain( Polyhedron *P, int flag, unsigned NbMaxRays )
04405 {
04406 Polyhedron *lP, *tmp, *Result, *lR, *prec, *reste;
04407 Polyhedron *p1, *p2, *p3, *Pol1, *dx, *d1, *d2, *pi, *newpi;
04408 int i;
04409
04410 if( flag!=0 && flag!=1 )
04411 {
04412 errormsg1("Disjoint_Domain",
04413 "invalidarg", "flag should be equal to 0 or 1");
04414 return (Polyhedron*) 0;
04415 }
04416 if(!P) return (Polyhedron*) 0;
04417 if(!P->next) return Polyhedron_Copy(P);
04418
04419 Result = (Polyhedron *)0;
04420
04421 for(lP=P;lP;lP=lP->next)
04422 {
04423 reste = Polyhedron_Copy(lP);
04424 prec = (Polyhedron *)0;
04425
04426 lR=Result;
04427 while( lR && reste )
04428 {
04429
04430 dx = (Polyhedron *)0;
04431 for( p1=reste; p1; p1=p1->next )
04432 {
04433 p3 = AddConstraints(lR->Constraint[0], lR->NbConstraints, p1,
04434 NbMaxRays);
04435 dx = AddPolyToDomain(p3,dx);
04436 }
04437
04438
04439 if(!dx)
04440 { prec = lR;
04441 lR=lR->next;
04442 continue;
04443 }
04444 if (emptyQ(dx)) {
04445 Domain_Free(dx);
04446 prec = lR;
04447 lR=lR->next;
04448 continue;
04449 }
04450
04451
04452
04453
04454
04455
04456
04457
04458 d1 = (Polyhedron *)0;
04459 for (p1=reste; p1; p1=p1->next)
04460 {
04461 pi = p1;
04462 for (i=0; i<P->NbConstraints && pi ; i++)
04463 {
04464
04465
04466
04467 p3 = SubConstraint(P->Constraint[i], pi, NbMaxRays,2*flag);
04468
04469 d1 = AddPolyToDomain (p3, d1);
04470
04471
04472
04473
04474 if( value_zero_p(P->Constraint[i][0]) )
04475 {
04476 p3 = SubConstraint(P->Constraint[i], pi, NbMaxRays,1+2*flag);
04477
04478 d1 = AddPolyToDomain (p3, d1);
04479
04480
04481 newpi = AddConstraints( P->Constraint[i], 1, pi, NbMaxRays);
04482 }
04483 else
04484 {
04485
04486 newpi = SubConstraint(P->Constraint[i], pi, NbMaxRays,3);
04487 }
04488 if( newpi && emptyQ( newpi ) )
04489 {
04490 Domain_Free( newpi );
04491 newpi = (Polyhedron *)0;
04492 }
04493 if( pi != p1 )
04494 Domain_Free( pi );
04495 pi = newpi;
04496 }
04497 if( pi != p1 )
04498 Domain_Free( pi );
04499 }
04500
04501
04502 Pol1 = Polyhedron_Copy( lR );
04503 for (p2=reste; p2; p2=p2->next)
04504 {
04505 d2 = (Polyhedron *)0;
04506 for (p1=Pol1; p1; p1=p1->next)
04507 {
04508 pi = p1;
04509 for (i=0; i<p2->NbConstraints && pi ; i++)
04510 {
04511
04512
04513
04514 p3 = SubConstraint(p2->Constraint[i], pi, NbMaxRays,2*flag);
04515
04516 d2 = AddPolyToDomain (p3, d2);
04517
04518
04519
04520
04521 if( value_zero_p(p2->Constraint[i][0]) )
04522 {
04523 p3 = SubConstraint(p2->Constraint[i], pi, NbMaxRays,1+2*flag);
04524
04525 d2 = AddPolyToDomain (p3, d2);
04526
04527
04528 newpi = AddConstraints( p2->Constraint[i], 1, pi, NbMaxRays);
04529 }
04530 else
04531 {
04532
04533 newpi = SubConstraint(p2->Constraint[i], pi, NbMaxRays,3);
04534 }
04535 if( newpi && emptyQ( newpi ) )
04536 {
04537 Domain_Free( newpi );
04538 newpi = (Polyhedron *)0;
04539 }
04540 if( pi != p1 )
04541 Domain_Free( pi );
04542 pi = newpi;
04543 }
04544 if( pi && pi!=p1 )
04545 Domain_Free( pi );
04546 }
04547 if( Pol1 )
04548 Domain_Free( Pol1 );
04549 Pol1 = d2;
04550 }
04551
04552
04553
04554 if( d1 && emptyQ(d1) )
04555 {
04556 Domain_Free( d1 );
04557 d1 = NULL;
04558 }
04559 if( d2 && emptyQ(d2) )
04560 {
04561 Domain_Free( d2 );
04562 d2 = NULL;
04563 }
04564
04565
04566 Domain_Free( reste );
04567 reste = d1;
04568
04569
04570 if( d2 )
04571 {
04572 for( tmp=d2 ; tmp->next ; tmp=tmp->next )
04573 ;
04574 tmp->next = Result;
04575 Result = d2;
04576 if( !prec )
04577 prec = tmp;
04578 }
04579
04580
04581 for( tmp=dx ; tmp->next ; tmp=tmp->next )
04582 ;
04583 tmp->next = Result;
04584 Result = dx;
04585 if( !prec )
04586 prec = tmp;
04587
04588
04589 if( !prec )
04590 errormsg1( "Disjoint_Domain","internalerror","internal error");
04591 prec->next = lR->next;
04592 Polyhedron_Free( lR );
04593 lR = prec->next;
04594 }
04595
04596
04597 if(reste)
04598 {
04599 if(emptyQ(reste))
04600 {
04601 Domain_Free( reste );
04602 reste = NULL;
04603 }
04604 else
04605 {
04606 Polyhedron *tnext;
04607 for( tmp=reste ; tmp ; tmp=tnext )
04608 {
04609 tnext = tmp->next;
04610 tmp->next = NULL;
04611 Result = AddPolyToDomain(tmp, Result);
04612 }
04613 }
04614 }
04615 }
04616
04617 return( Result );
04618 }
04619
04620
04621
04622
04623 void Polyhedron_PrintConstraints(FILE *Dst, const char *Format, Polyhedron *Pol)
04624 {
04625 int i,j;
04626
04627 fprintf( Dst, "%d %d\n", Pol->NbConstraints, Pol->Dimension+2 );
04628 for( i=0 ; i<Pol->NbConstraints ; i++ )
04629 {
04630 for( j=0 ; j<Pol->Dimension+2 ; j++ )
04631 value_print( Dst, Format, Pol->Constraint[i][j] );
04632 fprintf( Dst, "\n" );
04633 }
04634
04635 }
04636
04637
04638 void Domain_PrintConstraints(FILE *Dst, const char *Format, Polyhedron *Pol)
04639 {
04640 Polyhedron *Q;
04641 for (Q = Pol; Q; Q = Q->next)
04642 Polyhedron_PrintConstraints(Dst, Format, Q);
04643 }
04644
04645 static Polyhedron *p_simplify_constraints(Polyhedron *P, Vector *row,
04646 Value *g, unsigned MaxRays)
04647 {
04648 Polyhedron *T, *R = P;
04649 int len = P->Dimension+2;
04650 int r;
04651
04652
04653
04654
04655
04656 for (r = 0; r < R->NbConstraints; ++r) {
04657 if (ConstraintSimplify(R->Constraint[r], row->p, len, g)) {
04658 T = R;
04659 if (value_zero_p(R->Constraint[r][0])) {
04660 R = Empty_Polyhedron(R->Dimension);
04661 r = R->NbConstraints;
04662 } else if (POL_ISSET(MaxRays, POL_NO_DUAL)) {
04663 R = Polyhedron_Copy(R);
04664 F_CLR(R, POL_FACETS | POL_VERTICES | POL_POINTS);
04665 Vector_Copy(row->p+1, R->Constraint[r]+1, R->Dimension+1);
04666 } else {
04667 R = AddConstraints(row->p, 1, R, MaxRays);
04668 r = -1;
04669 }
04670 if (T != P)
04671 Polyhedron_Free(T);
04672 }
04673 }
04674 if (R != P)
04675 Polyhedron_Free(P);
04676 return R;
04677 }
04678
04679
04680
04681
04682
04683
04684
04685 Polyhedron *DomainConstraintSimplify(Polyhedron *P, unsigned MaxRays)
04686 {
04687 Polyhedron **prev;
04688 int len = P->Dimension+2;
04689 Vector *row = Vector_Alloc(len);
04690 Value g;
04691 Polyhedron *R = P, *N;
04692 value_set_si(row->p[0], 1);
04693 value_init(g);
04694
04695 for (prev = &R; P; P = N) {
04696 Polyhedron *T;
04697 N = P->next;
04698 T = p_simplify_constraints(P, row, &g, MaxRays);
04699
04700 if (emptyQ(T) && prev != &R) {
04701 Polyhedron_Free(T);
04702 *prev = NULL;
04703 continue;
04704 }
04705
04706 if (T != P)
04707 T->next = N;
04708 *prev = T;
04709 prev = &T->next;
04710 }
04711
04712 if (R->next && emptyQ(R)) {
04713 N = R->next;
04714 Polyhedron_Free(R);
04715 R = N;
04716 }
04717
04718 value_clear(g);
04719 Vector_Free(row);
04720 return R;
04721 }