00001
00002
00003
00004
00005
00006 #include <polylib/polylib.h>
00007
00008
00009
00010
00011
00012 void b_modulo(Value g, Value a, Value b) {
00013 if (value_zero_p(b)) {value_assign(g,a); return;}
00014 if (value_neg_p(b)) value_oppose(b, b);
00015 if (value_posz_p(a)) {
00016 value_division(g,a,b);
00017 value_multiply(g,g,b);
00018 value_subtract(g, a, g);
00019 return;
00020 }
00021 else {
00022 value_division(g, a, b);
00023 value_decrement(g, g);
00024 value_multiply(g, g, b);
00025 value_subtract(g, a, g);
00026
00027 if (value_eq(g,b)) value_set_si(g,0);
00028 }
00029 }
00030
00031
00032
00033
00034
00035 Matrix * int_ker(Matrix * M) {
00036 Matrix *U, *Q, *H, *K;
00037 int i, j;
00038
00039
00040
00041 if (M->NbColumns <= M->NbRows) {
00042 K = Matrix_Alloc(M->NbColumns, 0);
00043 return K;
00044 }
00045
00046 left_hermite(M, &H, &Q, &U);
00047
00048
00049 K=Matrix_Alloc(U->NbRows, U->NbColumns-M->NbRows);
00050 for (i=0; i< U->NbRows; i++)
00051 for(j=0; j< U->NbColumns-M->NbRows; j++)
00052 value_assign(K->p[i][j], U->p[i][M->NbRows+j]);
00053
00054
00055 Matrix_Free(H);
00056 Matrix_Free(U);
00057 Matrix_Free(Q);
00058 return K;
00059 }
00060
00061
00062
00063
00064 Matrix * affine_periods(Matrix * M, Matrix * d) {
00065 Matrix * S;
00066 unsigned int i,j;
00067 Value tmp;
00068 value_init(tmp);
00069
00070 Value * periods = (Value *)malloc(sizeof(Value) * M->NbColumns);
00071 for(i=0; i< M->NbColumns; i++) {
00072 value_init(periods[i]);
00073 value_set_si(periods[i], 1);
00074 }
00075 for (i=0; i<M->NbRows; i++) {
00076 for (j=0; j< M->NbColumns; j++) {
00077 Gcd(d->p[i][0], M->p[i][j], &tmp);
00078 value_division(tmp, d->p[i][0], tmp);
00079 Lcm3(periods[j], tmp, &(periods[j]));
00080 }
00081 }
00082 value_clear(tmp);
00083
00084
00085 S = Matrix_Alloc(M->NbColumns, M->NbColumns);
00086 for (i=0; i< M->NbColumns; i++)
00087 for (j=0; j< M->NbColumns; j++)
00088 if (i==j) value_assign(S->p[i][j],periods[j]);
00089 else value_set_si(S->p[i][j], 0);
00090
00091
00092 for(i=0; i< M->NbColumns; i++) value_clear(periods[i]);
00093 free(periods);
00094 return S;
00095 }
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 Matrix * int_mod_basis(Matrix * Bp, Matrix * Cp, Matrix * d) {
00107 int nb_eqs = Bp->NbRows;
00108 unsigned int nb_parms=Bp->NbColumns;
00109 unsigned int i, j;
00110
00111
00112 Matrix * K = int_ker(Bp);
00113 Matrix * S = affine_periods(Bp, d);
00114
00115
00116
00117
00118
00119
00120
00121 Matrix * KS = Matrix_Alloc(nb_parms, K->NbColumns+ nb_parms);
00122 for(i=0; i< KS->NbRows; i++) {
00123 for(j=0; j< K->NbColumns; j++) value_assign(KS->p[i][j], K->p[i][j]);
00124 for(j=0; j< S->NbColumns; j++) value_assign(KS->p[i][j+K->NbColumns], S->p[i][j]);
00125 }
00126
00127
00128
00129
00130 Matrix * H, * U, * Q;
00131 left_hermite(KS, &H, &U, &Q);
00132 Matrix_Free(KS);
00133 Matrix_Free(U);
00134 Matrix_Free(Q);
00135
00136
00137
00138
00139 for (i=0; i< nb_parms; i++) {
00140 for (j=0; j< nb_parms; j++)
00141 value_assign(S->p[i][j], H->p[i][j]);
00142
00143
00144 }
00145 Matrix_Free(H);
00146
00147
00148 Matrix * M = Matrix_Alloc(nb_eqs, nb_parms+nb_eqs);
00149
00150
00151
00152
00153 for (i=0; i< nb_eqs; i++) {
00154 for (j=0; j< nb_parms; j++) {
00155 value_assign(M->p[i][j], Bp->p[i][j]);
00156 }
00157
00158 for (j=0; j< nb_eqs; j++) {
00159 if (i==j) value_assign(M->p[i][j+nb_parms], d->p[i][0]);
00160 else value_set_si(M->p[i][j+nb_parms], 0);
00161 }
00162 }
00163
00164
00165 left_hermite(M, &H, &Q, &U);
00166 Matrix * inv_H_M=Matrix_Alloc(nb_eqs, nb_eqs+1);
00167
00168 Matrix * Ha = Matrix_Alloc(nb_eqs, nb_eqs);
00169 for(i=0; i< nb_eqs; i++) {
00170 for(j=0; j< nb_eqs; j++) {
00171 value_assign(Ha->p[i][j], H->p[i][j]);
00172 }
00173 }
00174 MatInverse(Ha, inv_H_M);
00175 Matrix_Free(Ha);
00176 Matrix_Free(H);
00177 Matrix_Free(Q);
00178
00179
00180 Matrix * Cp_mod_d = Matrix_Alloc(nb_eqs, 1);
00181 for (i=0; i< nb_eqs; i++) {
00182 value_oppose(Cp->p[i][0], Cp->p[i][0]);
00183 b_modulo(Cp_mod_d->p[i][0], Cp->p[i][0], d->p[i][0]);
00184
00185 }
00186
00187
00188
00189 Matrix * Np_0= Matrix_Alloc(U->NbColumns, 1);
00190 for(i=0; i< nb_eqs; i++)
00191 {
00192 value_set_si(Np_0->p[i][0], 0);
00193 for(j=0; j< nb_eqs; j++) {
00194 value_addmul(Np_0->p[i][0], inv_H_M->p[i][j], Cp_mod_d->p[j][0]);
00195 }
00196 }
00197 for(i=nb_eqs; i< U->NbColumns; i++) value_set_si(Np_0->p[i][0], 0);
00198
00199
00200
00201
00202 for (i=0; i< nb_eqs; i++) {
00203
00204 #ifdef GNUMP
00205 if (mpz_divisible_p(Np_0->p[i][0], inv_H_M->p[i][nb_eqs])) mpz_divexact(Np_0->p[i][0], Np_0->p[i][0], inv_H_M->p[i][nb_eqs]);
00206 #else
00207 if (!(Np_0->p[i][0]%inv_H_M->p[i][nb_eqs])) Np_0->p[i][0]/=inv_H_M->p[i][nb_eqs];
00208 #endif
00209 else {
00210 Matrix_Free(S);
00211 Matrix_Free(inv_H_M);
00212 Matrix_Free(Np_0);
00213 fprintf(stderr, "int_mod_basis > No particular solution: polyhedron without integer points.\n");
00214 return NULL;
00215 }
00216 }
00217
00218
00219
00220 Matrix * N_0 = Matrix_Alloc(U->NbColumns, 1);
00221
00222 Matrix_Product(U, Np_0, N_0);
00223
00224 Matrix_Free(Np_0);
00225 Matrix_Free(U);
00226
00227
00228 Matrix * G = Matrix_Alloc(S->NbRows+1, S->NbRows+1);
00229 for (i=0; i< S->NbRows; i++) {
00230 for(j=0; j< S->NbRows; j++)
00231 value_assign(G->p[i][j], S->p[i][j]);
00232 value_assign(G->p[i][S->NbRows], N_0->p[i][0]);
00233 }
00234
00235 for (j=0; j< S->NbRows; j++) value_set_si(G->p[S->NbRows][j],0);
00236 value_set_si(G->p[S->NbRows][S->NbRows],1);
00237
00238
00239 Matrix_Free(S);
00240 Matrix_Free(N_0);
00241 return G;
00242 }
00243
00244
00245
00246 Matrix * get_linear_part(Matrix const * E, int nb_parms){
00247 unsigned int i,j, k, nb_eqs=E->NbRows;
00248 int nb_vars=E->NbColumns - nb_parms -2;
00249 Matrix * A = Matrix_Alloc(nb_eqs, nb_vars);
00250 k=0;
00251 for (i=0; i< E->NbRows; i++) {
00252 for (j=0; j< nb_vars; j++)
00253 value_assign(A->p[i][j],E->p[i][j+1]);
00254 }
00255 return A;
00256 }
00257
00258
00259 Matrix * get_parameter_part(Matrix const * E, int nb_parms) {
00260 unsigned int i,j, k, nb_eqs=E->NbRows;
00261 int nb_vars=E->NbColumns - nb_parms -2;
00262 Matrix * B = Matrix_Alloc(nb_eqs,nb_parms);
00263 k=0;
00264
00265 for(i=0; i< E->NbRows; i++) {
00266 for(j=0; j< nb_parms; j++)
00267 value_assign(B->p[i][j], E->p[i][1+nb_vars+j]);
00268 }
00269 return B;
00270 }
00271
00272
00273 Matrix * get_constant_part(Matrix const * E, int nb_parms) {
00274 unsigned int i,j, k, nb_eqs=E->NbRows;
00275 int nb_vars=E->NbColumns - nb_parms -2;
00276 Matrix * C = Matrix_Alloc(nb_eqs,1);
00277 k=0;
00278 for(i=0; i< E->NbRows; i++) {
00279 value_assign(C->p[i][0], E->p[i][E->NbColumns-1]);
00280 }
00281 return C;
00282 }
00283
00284
00285
00286
00287
00288
00289
00290 Matrix * extract_funny_stuff(Matrix const * E, int nb_parms, Matrix ** Bp, Matrix **Cp, Matrix **d) {
00291 unsigned int i,j, k, nb_eqs=E->NbRows;
00292 int nb_vars=E->NbColumns - nb_parms -2;
00293 Matrix * A, * Ap, * Ha, * U, * Q, * H, *B, *C;
00294
00295
00296 if (nb_eqs==0) {
00297 *Bp = Matrix_Alloc(0, E->NbColumns);
00298 *Cp = Matrix_Alloc(0, E->NbColumns);
00299 *d = NULL;
00300 return NULL;
00301 }
00302
00303
00304 A = get_linear_part(E, nb_parms);
00305
00306
00307
00308
00309 left_hermite(A, &H, &Q, &U);
00310 Matrix_Free(A);
00311 Matrix_Free(Q);
00312
00313
00314 Ha = Matrix_Alloc(nb_eqs, nb_eqs);
00315 for (i=0; i< nb_eqs; i++) {
00316 for (j=0; j< nb_eqs; j++) {
00317 value_assign(Ha->p[i][j],H->p[i][j]);
00318 }
00319 }
00320 Matrix_Free(H);
00321
00322
00323
00324
00325 Matrix * Ha_pre_inv = Matrix_Alloc(nb_eqs, nb_eqs+1);
00326 if(!MatInverse(Ha, Ha_pre_inv)) {
00327 fprintf(stderr,"extract_funny_stuff > Matrix Ha is non-invertible.");
00328 }
00329
00330 for(i=0; i< nb_eqs; i++) {
00331 for(j=0; j< nb_eqs; j++) {
00332 value_assign(Ha->p[i][j],Ha_pre_inv->p[i][j]);
00333 }
00334 }
00335
00336
00337 (*d) = Matrix_Alloc(Ha_pre_inv->NbRows, 1);
00338
00339 for (i=0; i< Ha_pre_inv->NbRows; i++) value_assign((*d)->p[i][0], Ha_pre_inv->p[i][Ha_pre_inv->NbColumns-1]);
00340
00341
00342
00343 Matrix_Free(Ha_pre_inv);
00344
00345
00346
00347 B = get_parameter_part(E, nb_parms);
00348 (*Bp) = Matrix_Alloc(B->NbRows,B->NbColumns);
00349
00350 Matrix_Product(Ha, B, (*Bp));
00351
00352 Matrix_Free(B);
00353
00354
00355 C = get_constant_part(E, nb_parms);
00356
00357 (*Cp) = Matrix_Alloc(nb_eqs, 1);
00358 Matrix_Product(Ha, C, (*Cp));
00359
00360 Matrix_Free(C);
00361
00362 Matrix_Free(Ha);
00363 return U;
00364 }
00365
00366
00367
00368
00369
00370 Matrix * compress_parms(Matrix * E, int nb_parms) {
00371 unsigned int i,j, k, nb_eqs=0;
00372 int nb_vars=E->NbColumns - nb_parms -2;
00373 Matrix *U, *d, *Bp, *Cp;
00374
00375
00376 if (E->NbRows==0) return Identity_Matrix(nb_parms+1);
00377
00378 U = extract_funny_stuff(E, nb_parms, &Bp, & Cp, &d);
00379
00380 Matrix_Free(U);
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 Matrix * G = int_mod_basis(Bp, Cp, d);
00392 Matrix_Free(Bp);
00393 Matrix_Free(Cp);
00394 Matrix_Free(d);
00395 return G;
00396 }
00397
00398
00399
00400
00401 Matrix * full_dimensionize(Matrix const * M, int nb_parms, Matrix ** Validity_Lattice) {
00402 Matrix * Eqs, * Ineqs;
00403 Matrix * Permuted_Eqs, * Permuted_Ineqs;
00404 Matrix * Full_Dim;
00405 Matrix * Whole_Validity_Lattice;
00406 unsigned int i,j;
00407 int nb_elim_vars;
00408 int * permutation, * permutation_inv;
00409
00410 split_constraints(M, &Eqs, &Ineqs);
00411
00412
00413 if (Eqs->NbRows==0) {
00414 Matrix_Free(Eqs);
00415 (*Validity_Lattice) = Identity_Matrix(nb_parms+1);
00416 return Ineqs;
00417 }
00418 nb_elim_vars = Eqs->NbRows;
00419
00420
00421
00422 permutation = find_a_permutation(Eqs, nb_parms);
00423 Permuted_Eqs = mpolyhedron_permute(Eqs, permutation);
00424 Whole_Validity_Lattice = compress_parms(Permuted_Eqs, Eqs->NbColumns-2-Eqs->NbRows);
00425 mpolyhedron_compress_last_vars(Permuted_Eqs, Whole_Validity_Lattice);
00426 Permuted_Ineqs = mpolyhedron_permute(Ineqs, permutation);
00427 Matrix_Free(Eqs);
00428 Matrix_Free(Ineqs);
00429 mpolyhedron_compress_last_vars(Permuted_Ineqs, Whole_Validity_Lattice);
00430
00431
00432
00433 if (!mpolyhedron_eliminate_first_variables(Permuted_Eqs, Permuted_Ineqs)) {
00434 fprintf(stderr,"full-dimensionize > variable elimination failed. \n");
00435 return NULL;
00436 }
00437
00438
00439
00440
00441 Full_Dim = Matrix_Alloc(Permuted_Ineqs->NbRows, Permuted_Ineqs->NbColumns-nb_elim_vars);
00442 for (i=0; i< Permuted_Ineqs->NbRows; i++) {
00443 value_set_si(Full_Dim->p[i][0], 1);
00444 for (j=0; j< nb_parms; j++)
00445 value_assign(Full_Dim->p[i][j+Full_Dim->NbColumns-nb_parms-1], Permuted_Ineqs->p[i][j+nb_elim_vars+1]);
00446 for (j=0; j< Permuted_Ineqs->NbColumns-nb_parms-2-nb_elim_vars; j++)
00447 value_assign(Full_Dim->p[i][j+1], Permuted_Ineqs->p[i][nb_elim_vars+nb_parms+j+1]);
00448 value_assign(Full_Dim->p[i][Full_Dim->NbColumns-1], Permuted_Ineqs->p[i][Permuted_Ineqs->NbColumns-1]);
00449 }
00450 Matrix_Free(Permuted_Ineqs);
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 *Validity_Lattice = Matrix_Alloc(nb_parms+1, nb_parms+1);
00464 for (i=0; i< nb_parms; i++) {
00465 for (j=0; j< nb_parms; j++)
00466 value_assign((*Validity_Lattice)->p[i][j], Whole_Validity_Lattice->p[i][j]);
00467 value_assign((*Validity_Lattice)->p[i][nb_parms], Whole_Validity_Lattice->p[i][Whole_Validity_Lattice->NbColumns-1]);
00468 }
00469 for (j=0; j< nb_parms; j++) value_set_si((*Validity_Lattice)->p[nb_parms][j], 0);
00470 value_assign((*Validity_Lattice)->p[nb_parms][nb_parms], Whole_Validity_Lattice->p[Whole_Validity_Lattice->NbColumns-1][Whole_Validity_Lattice->NbColumns-1]);
00471
00472
00473 Matrix_Free(Whole_Validity_Lattice);
00474 return Full_Dim;
00475
00476 }
00477