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