2 This file is part of PolyLib.
4 PolyLib is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 PolyLib is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with PolyLib. If not, see <http://www.gnu.org/licenses/>.
19 * $Id: compress_parms.c,v 1.32 2006/11/03 17:34:26 skimo Exp $
21 * The integer points in a parametric linear subspace of Q^n are generally
22 * lying on a sub-lattice of Z^n.
23 * Functions here use and compute validity lattices, i.e. lattices induced on a
24 * set of variables by such equalities involving another set of integer
26 * @author B. Meister 12/2003-2006 meister@icps.u-strasbg.fr
29 * Louis Pasteur University (ULP), Strasbourg, France
33 #include <polylib/polylib.h>
36 * debug flags (2 levels)
39 #define dbgCompParmMore 0
41 #define dbgStart(a) if (dbgCompParmMore) { printf(" -- begin "); \
45 #define dbgEnd(a) if (dbgCompParmMore) { printf(" -- end "); \
52 * Given a full-row-rank nxm matrix M made of m row-vectors), computes the
53 * basis K (made of n-m column-vectors) of the integer kernel of the rows of M
56 Matrix
* int_ker(Matrix
* M
) {
57 Matrix
*U
, *Q
, *H
, *H2
, *K
=NULL
;
62 /* eliminate redundant rows : UM = H*/
63 right_hermite(M
, &H
, &Q
, &U
);
64 for (rk
=H
->NbRows
-1; (rk
>=0) && Vector_IsZero(H
->p
[rk
], H
->NbColumns
); rk
--);
66 if (dbgCompParmMore
) {
67 printf("rank = %d\n", rk
);
70 /* there is a non-null kernel if and only if the dimension m of
71 the space spanned by the rows
72 is inferior to the number n of variables */
73 if (M
->NbColumns
<= rk
) {
77 K
= Matrix_Alloc(M
->NbColumns
, 0);
82 /* fool left_hermite by giving NbRows =rank of M*/
84 /* computes MU = [H 0] */
85 left_hermite(H
, &H2
, &Q
, &U
);
86 if (dbgCompParmMore
) {
87 printf("-- Int. Kernel -- \n");
95 /* the Integer Kernel is made of the last n-rk columns of U */
96 Matrix_subMatrix(U
, 0, rk
, U
->NbRows
, U
->NbColumns
, &K
);
107 * Computes the intersection of two linear lattices, whose base vectors are
108 * respectively represented in A and B.
109 * If I and/or Lb is set to NULL, then the matrix is allocated.
110 * Else, the matrix is assumed to be allocated already.
111 * I and Lb are rk x rk, where rk is the rank of A (or B).
112 * @param A the full-row rank matrix whose column-vectors are the basis for the
113 * first linear lattice.
114 * @param B the matrix whose column-vectors are the basis for the second linear
116 * @param Lb the matrix such that B.Lb = I, where I is the intersection.
117 * @return their intersection.
119 static void linearInter(Matrix
* A
, Matrix
* B
, Matrix
** I
, Matrix
**Lb
) {
122 int a
= A
->NbColumns
;
123 int b
= B
->NbColumns
;
127 /* ensure that the spanning vectors are in the same space */
128 assert(B
->NbRows
==rk
);
129 /* 1- build the matrix
133 AB
= Matrix_Alloc(2*rk
, a
+b
+rk
);
134 Matrix_copySubMatrix(A
, 0, 0, rk
, a
, AB
, 0, 0);
135 Matrix_copySubMatrix(B
, 0, 0, rk
, b
, AB
, rk
, a
);
136 for (i
=0; i
< rk
; i
++) {
137 value_set_si(AB
->p
[i
][a
+b
+i
], 1);
138 value_set_si(AB
->p
[i
+rk
][a
+b
+i
], 1);
144 /* 2- Compute its left Hermite normal form. AB.U = [H 0] */
145 left_hermite(AB
, &H
, &Q
, &U
);
148 /* count the number of non-zero colums in H */
149 for (z
=H
->NbColumns
-1; value_zero_p(H
->p
[H
->NbRows
-1][z
]); z
--);
156 /* if you split U in 9 submatrices, you have:
159 * where the nb of cols of U_{*3} equals the nb of zero-cols of H
160 * U_33 is a (the smallest) combination of col-vectors of A and B at the same
161 * time: their intersection.
163 Matrix_subMatrix(U
, a
+b
, z
, U
->NbColumns
, U
->NbColumns
, I
);
164 Matrix_subMatrix(U
, a
, z
, a
+b
, U
->NbColumns
, Lb
);
173 * Given a system of equalities, looks if it has an integer solution in the
174 * combined space, and if yes, returns one solution.
175 * <p>pre-condition: the equalities are full-row rank (without the constant
177 * @param Eqs the system of equations (as constraints)
178 * @param I a feasible integer solution if it exists, else NULL. Allocated if
179 * initially set to NULL, else reused.
181 void Equalities_integerSolution(Matrix
* Eqs
, Matrix
**I
) {
182 Matrix
* Hm
, *H
=NULL
, *U
, *Q
, *M
=NULL
, *C
=NULL
, *Hi
;
188 if ((*I
)!=NULL
) Matrix_Free(*I
);
192 /* we use: AI = C = (Ha 0).Q.I = (Ha 0)(I' 0)^T */
193 /* with I = Qinv.I' = U.I'*/
194 /* 1- compute I' = Hainv.(-C) */
195 /* HYP: the equalities are full-row rank */
197 Matrix_subMatrix(Eqs
, 0, 1, rk
, Eqs
->NbColumns
-1, &M
);
198 left_hermite(M
, &Hm
, &Q
, &U
);
200 Matrix_subMatrix(Hm
, 0, 0, rk
, rk
, &H
);
201 if (dbgCompParmMore
) {
208 Matrix_subMatrix(Eqs
, 0, Eqs
->NbColumns
-1, rk
, Eqs
->NbColumns
, &C
);
210 Hi
= Matrix_Alloc(rk
, rk
+1);
212 if (dbgCompParmMore
) {
216 /* put the numerator of Hinv back into H */
217 Matrix_subMatrix(Hi
, 0, 0, rk
, rk
, &H
);
218 Ip
= Matrix_Alloc(Eqs
->NbColumns
-2, 1);
219 /* fool Matrix_Product on the size of Ip */
221 Matrix_Product(H
, C
, Ip
);
222 Ip
->NbRows
= Eqs
->NbColumns
-2;
226 for (i
=0; i
< rk
; i
++) {
227 /* if Hinv.C is not integer, return NULL (no solution) */
228 value_pmodulus(mod
, Ip
->p
[i
][0], Hi
->p
[i
][rk
]);
229 if (value_notzero_p(mod
)) {
230 if ((*I
)!=NULL
) Matrix_Free(*I
);
239 value_pdivision(Ip
->p
[i
][0], Ip
->p
[i
][0], Hi
->p
[i
][rk
]);
242 /* fill the rest of I' with zeros */
243 for (i
=rk
; i
< Eqs
->NbColumns
-2; i
++) {
244 value_set_si(Ip
->p
[i
][0], 0);
248 /* 2 - Compute the particular solution I = U.(I' 0) */
249 ensureMatrix((*I
), Eqs
->NbColumns
-2, 1);
250 Matrix_Product(U
, Ip
, (*I
));
260 * Computes the validity lattice of a set of equalities. I.e., the lattice
261 * induced on the last <tt>b</tt> variables by the equalities involving the
262 * first <tt>a</tt> integer existential variables. The submatrix of Eqs that
263 * concerns only the existential variables (so the first a columns) is assumed
264 * to be full-row rank.
265 * @param Eqs the equalities
266 * @param a the number of existential integer variables, placed as first
268 * @param vl the (returned) validity lattice, in homogeneous form. It is
269 * allocated if initially set to null, or reused if already allocated.
271 void Equalities_validityLattice(Matrix
* Eqs
, int a
, Matrix
** vl
) {
272 unsigned int b
= Eqs
->NbColumns
-2-a
;
273 unsigned int r
= Eqs
->NbRows
;
274 Matrix
* A
=NULL
, * B
=NULL
, *I
= NULL
, *Lb
=NULL
, *sol
=NULL
;
279 printf("Computing validity lattice induced by the %d first variables of:"
284 ensureMatrix((*vl
), 1, 1);
285 value_set_si((*vl
)->p
[0][0], 1);
289 /* 1- check that there is an integer solution to the equalities */
290 /* OPT: could change integerSolution's profile to allocate or not*/
291 Equalities_integerSolution(Eqs
, &sol
);
292 /* if there is no integer solution, there is no validity lattice */
294 if ((*vl
)!=NULL
) Matrix_Free(*vl
);
297 Matrix_subMatrix(Eqs
, 0, 1, r
, 1+a
, &A
);
298 Matrix_subMatrix(Eqs
, 0, 1+a
, r
, 1+a
+b
, &B
);
299 linearInter(A
, B
, &I
, &Lb
);
307 /* 2- The linear part of the validity lattice is the left HNF of Lb */
308 left_hermite(Lb
, &H
, &Q
, &U
);
313 /* 3- build the validity lattice */
314 ensureMatrix((*vl
), b
+1, b
+1);
315 Matrix_copySubMatrix(H
, 0, 0, b
, b
, (*vl
), 0,0);
317 for (i
=0; i
< b
; i
++) {
318 value_assign((*vl
)->p
[i
][b
], sol
->p
[0][a
+i
]);
321 Vector_Set((*vl
)->p
[b
],0, b
);
322 value_set_si((*vl
)->p
[b
][b
], 1);
324 } /* validityLattice */
328 * Eliminate the columns corresponding to a list of eliminated parameters.
329 * @param M the constraints matrix whose columns are to be removed
330 * @param nbVars an offset to be added to the ranks of the variables to be
332 * @param elimParms the list of ranks of the variables to be removed
333 * @param newM (output) the matrix without the removed columns
335 void Constraints_removeElimCols(Matrix
* M
, unsigned int nbVars
,
336 unsigned int *elimParms
, Matrix
** newM
) {
337 unsigned int i
, j
, k
;
338 if (elimParms
[0]==0) {
339 Matrix_clone(M
, newM
);
343 (*newM
) = Matrix_Alloc(M
->NbRows
, M
->NbColumns
- elimParms
[0]);
346 assert ((*newM
)->NbColumns
==M
->NbColumns
- elimParms
[0]);
348 for (i
=0; i
< M
->NbRows
; i
++) {
349 value_assign((*newM
)->p
[i
][0], M
->p
[i
][0]); /* kind of cstr */
351 Vector_Copy(&(M
->p
[i
][1]), &((*newM
)->p
[i
][1]), nbVars
);
352 for (j
=0; j
< M
->NbColumns
-2-nbVars
; j
++) {
353 if (j
!=elimParms
[k
+1]) {
354 value_assign((*newM
)->p
[i
][j
-k
+nbVars
+1], M
->p
[i
][j
+nbVars
+1]);
360 value_assign((*newM
)->p
[i
][(*newM
)->NbColumns
-1],
361 M
->p
[i
][M
->NbColumns
-1]); /* cst part */
363 } /* Constraints_removeElimCols */
367 * Eliminates all the equalities in a set of constraints and returns the set of
368 * constraints defining a full-dimensional polyhedron, such that there is a
369 * bijection between integer points of the original polyhedron and these of the
370 * resulting (projected) polyhedron).
371 * If VL is set to NULL, this funciton allocates it. Else, it assumes that
372 * (*VL) points to a matrix of the right size.
373 * <p> The following things are done:
375 * <li> remove equalities involving only parameters, and remove as many
376 * parameters as there are such equalities. From that, the list of
377 * eliminated parameters <i>elimParms</i> is built.
378 * <li> remove equalities that involve variables. This requires a compression
379 * of the parameters and of the other variables that are not eliminated.
380 * The affine compresson is represented by matrix VL (for <i>validity
381 * lattice</i>) and is such that (N I 1)^T = VL.(N' I' 1), where N', I'
382 * are integer (they are the parameters and variables after compression).
386 void Constraints_fullDimensionize(Matrix
** M
, Matrix
** C
, Matrix
** VL
,
387 Matrix
** Eqs
, Matrix
** ParmEqs
,
388 unsigned int ** elimVars
,
389 unsigned int ** elimParms
,
392 Matrix
* A
=NULL
, *B
=NULL
;
394 unsigned int nbVars
= (*M
)->NbColumns
- (*C
)->NbColumns
;
395 unsigned int nbParms
;
397 Matrix
* fullDim
= NULL
;
399 /* variables for permutations */
400 unsigned int * permutation
;
401 Matrix
* permutedEqs
=NULL
, * permutedIneqs
=NULL
;
403 /* 1- Eliminate the equalities involving only parameters. */
404 (*ParmEqs
) = Constraints_removeParmEqs(M
, C
, 0, elimParms
);
405 /* if the polyehdron is empty, return now. */
406 if ((*M
)->NbColumns
==0) return;
407 /* eliminate the columns corresponding to the eliminated parameters */
408 if (elimParms
[0]!=0) {
409 Constraints_removeElimCols(*M
, nbVars
, (*elimParms
), &A
);
412 Constraints_removeElimCols(*C
, 0, (*elimParms
), &B
);
416 printf("After false parameter elimination: \n");
421 nbParms
= (*C
)->NbColumns
-2;
423 /* 2- Eliminate the equalities involving variables */
424 /* a- extract the (remaining) equalities from the poyhedron */
425 split_constraints((*M
), Eqs
, &Ineqs
);
426 nbElimVars
= (*Eqs
)->NbRows
;
427 /* if the polyhedron is already full-dimensional, return */
428 if ((*Eqs
)->NbRows
==0) {
429 Matrix_identity(nbParms
+1, VL
);
432 /* b- choose variables to be eliminated */
433 permutation
= find_a_permutation((*Eqs
), nbParms
);
436 printf("Permuting the vars/parms this way: [ ");
437 for (i
=0; i
< (*Eqs
)->NbColumns
-2; i
++) {
438 printf("%d ", permutation
[i
]);
443 Constraints_permute((*Eqs
), permutation
, &permutedEqs
);
444 Equalities_validityLattice(permutedEqs
, (*Eqs
)->NbRows
, VL
);
447 printf("Validity lattice: ");
450 Constraints_compressLastVars(permutedEqs
, (*VL
));
451 Constraints_permute(Ineqs
, permutation
, &permutedIneqs
);
452 if (dbgCompParmMore
) {
453 show_matrix(permutedIneqs
);
454 show_matrix(permutedEqs
);
458 Constraints_compressLastVars(permutedIneqs
, (*VL
));
460 printf("After compression: ");
461 show_matrix(permutedIneqs
);
463 /* c- eliminate the first variables */
464 assert(Constraints_eliminateFirstVars(permutedEqs
, permutedIneqs
));
465 if (dbgCompParmMore
) {
466 printf("After elimination of the variables: ");
467 show_matrix(permutedIneqs
);
470 /* d- get rid of the first (zero) columns,
471 which are now useless, and put the parameters back at the end */
472 fullDim
= Matrix_Alloc(permutedIneqs
->NbRows
,
473 permutedIneqs
->NbColumns
-nbElimVars
);
474 for (i
=0; i
< permutedIneqs
->NbRows
; i
++) {
475 value_set_si(fullDim
->p
[i
][0], 1);
476 for (j
=0; j
< nbParms
; j
++) {
477 value_assign(fullDim
->p
[i
][j
+fullDim
->NbColumns
-nbParms
-1],
478 permutedIneqs
->p
[i
][j
+nbElimVars
+1]);
480 for (j
=0; j
< permutedIneqs
->NbColumns
-nbParms
-2-nbElimVars
; j
++) {
481 value_assign(fullDim
->p
[i
][j
+1],
482 permutedIneqs
->p
[i
][nbElimVars
+nbParms
+j
+1]);
484 value_assign(fullDim
->p
[i
][fullDim
->NbColumns
-1],
485 permutedIneqs
->p
[i
][permutedIneqs
->NbColumns
-1]);
487 Matrix_Free(permutedIneqs
);
489 } /* Constraints_fullDimensionize */
493 * Given a matrix that defines a full-dimensional affine lattice, returns the
494 * affine sub-lattice spanned in the k first dimensions.
495 * Useful for instance when you only look for the parameters' validity lattice.
496 * @param lat the original full-dimensional lattice
497 * @param subLat the sublattice
499 void Lattice_extractSubLattice(Matrix
* lat
, unsigned int k
, Matrix
** subLat
) {
500 Matrix
* H
, *Q
, *U
, *linLat
= NULL
;
502 dbgStart(Lattice_extractSubLattice
);
503 /* if the dimension is already good, just copy the initial lattice */
504 if (k
==lat
->NbRows
-1) {
506 (*subLat
) = Matrix_Copy(lat
);
509 Matrix_copySubMatrix(lat
, 0, 0, lat
->NbRows
, lat
->NbColumns
, (*subLat
), 0, 0);
513 assert(k
<lat
->NbRows
-1);
514 /* 1- Make the linear part of the lattice triangular to eliminate terms from
516 Matrix_subMatrix(lat
, 0, 0, lat
->NbRows
, lat
->NbColumns
-1, &linLat
);
517 /* OPT: any integer column-vector elimination is ok indeed. */
518 /* OPT: could test if the lattice is already in triangular form. */
519 left_hermite(linLat
, &H
, &Q
, &U
);
520 if (dbgCompParmMore
) {
526 /* if not allocated yet, allocate it */
528 (*subLat
) = Matrix_Alloc(k
+1, k
+1);
530 Matrix_copySubMatrix(H
, 0, 0, k
, k
, (*subLat
), 0, 0);
532 Matrix_copySubMatrix(lat
, 0, lat
->NbColumns
-1, k
, 1, (*subLat
), 0, k
);
533 for (i
=0; i
<k
; i
++) {
534 value_set_si((*subLat
)->p
[k
][i
], 0);
536 value_set_si((*subLat
)->p
[k
][k
], 1);
537 dbgEnd(Lattice_extractSubLattice
);
538 } /* Lattice_extractSubLattice */
542 * Computes the overall period of the variables I for (MI) mod |d|, where M is
543 * a matrix and |d| a vector. Produce a diagonal matrix S = (s_k) where s_k is
544 * the overall period of i_k
545 * @param M the set of affine functions of I (row-vectors)
546 * @param d the column-vector representing the modulos
548 Matrix
* affine_periods(Matrix
* M
, Matrix
* d
) {
552 Value
* periods
= (Value
*)malloc(sizeof(Value
) * M
->NbColumns
);
554 for(i
=0; i
< M
->NbColumns
; i
++) {
555 value_init(periods
[i
]);
556 value_set_si(periods
[i
], 1);
558 for (i
=0; i
<M
->NbRows
; i
++) {
559 for (j
=0; j
< M
->NbColumns
; j
++) {
560 value_gcd(tmp
, d
->p
[i
][0], M
->p
[i
][j
]);
561 value_divexact(tmp
, d
->p
[i
][0], tmp
);
562 value_lcm(periods
[j
], periods
[j
], tmp
);
568 S
= Matrix_Alloc(M
->NbColumns
, M
->NbColumns
);
569 for (i
=0; i
< M
->NbColumns
; i
++)
570 for (j
=0; j
< M
->NbColumns
; j
++)
571 if (i
==j
) value_assign(S
->p
[i
][j
],periods
[j
]);
572 else value_set_si(S
->p
[i
][j
], 0);
575 for(i
=0; i
< M
->NbColumns
; i
++) value_clear(periods
[i
]);
578 } /* affine_periods */
582 * Given an integer matrix B with m rows and integer m-vectors C and d,
583 * computes the basis of the integer solutions to (BN+C) mod d = 0 (1).
584 * This is an affine lattice (G): (N 1)^T= G(N' 1)^T, forall N' in Z^b.
585 * If there is no solution, returns NULL.
586 * @param B B, a (m x b) matrix
587 * @param C C, a (m x 1) integer matrix
588 * @param d d, a (1 x m) integer matrix
589 * @param imb the affine (b+1)x(b+1) basis of solutions, in the homogeneous
590 * form. Allocated if initially set to NULL, reused if not.
592 void Equalities_intModBasis(Matrix
* B
, Matrix
* C
, Matrix
* d
, Matrix
** imb
) {
593 int b
= B
->NbColumns
;
594 /* FIXME: treat the case d=0 as a regular equality B_kN+C_k = 0: */
595 /* OPT: could keep only equalities for which d>1 */
596 int nbEqs
= B
->NbRows
;
599 /* 1- buid the problem DI+BN+C = 0 */
600 Matrix
* eqs
= Matrix_Alloc(nbEqs
, nbEqs
+b
+1);
601 for (i
=0; i
< nbEqs
; i
++) {
602 value_assign(eqs
->p
[i
][i
], d
->p
[0][i
]);
604 Matrix_copySubMatrix(B
, 0, 0, nbEqs
, b
, eqs
, 0, nbEqs
);
605 Matrix_copySubMatrix(C
, 0, 0, nbEqs
, 1, eqs
, 0, nbEqs
+b
);
607 /* 2- the solution is the validity lattice of the equalities */
608 Equalities_validityLattice(eqs
, nbEqs
, imb
);
610 } /* Equalities_intModBasis */
613 /** kept here for backwards compatiblity. Wrapper to Equalities_intModBasis() */
614 Matrix
* int_mod_basis(Matrix
* B
, Matrix
* C
, Matrix
* d
) {
616 Equalities_intModBasis(B
, C
, d
, &imb
);
618 } /* int_mod_basis */
622 * Given a parameterized constraints matrix with m equalities, computes the
623 * compression matrix G such that there is an integer solution in the variables
624 * space for each value of N', with N = G N' (N are the "nb_parms" parameters)
625 * @param E a matrix of parametric equalities @param nb_parms the number of
627 * <b>Note: </b>this function is mostly here for backwards
628 * compatibility. Prefer the use of <tt>Equalities_validityLattice</tt>.
630 Matrix
* compress_parms(Matrix
* E
, int nbParms
) {
632 Equalities_validityLattice(E
, E
->NbColumns
-2-nbParms
, &vl
);
634 }/* compress_parms */
637 /** Removes the equalities that involve only parameters, by eliminating some
638 * parameters in the polyhedron's constraints and in the context.<p>
639 * <b>Updates M and Ctxt.</b>
640 * @param M1 the polyhedron's constraints
641 * @param Ctxt1 the constraints of the polyhedron's context
642 * @param renderSpace tells if the returned equalities must be expressed in the
643 * parameters space (renderSpace=0) or in the combined var/parms space
645 * @param elimParms the list of parameters that have been removed: an array
646 * whose 1st element is the number of elements in the list. (returned)
647 * @return the system of equalities that involve only parameters.
649 Matrix
* Constraints_Remove_parm_eqs(Matrix
** M1
, Matrix
** Ctxt1
,
651 unsigned int ** elimParms
) {
652 int i
, j
, k
, nbEqsParms
=0;
653 int nbEqsM
, nbEqsCtxt
, allZeros
, nbTautoM
= 0, nbTautoCtxt
= 0;
655 Matrix
* Ctxt
= (*Ctxt1
);
656 int nbVars
= M
->NbColumns
-Ctxt
->NbColumns
;
660 /* 1- build the equality matrix(ces) */
662 for (i
=0; i
< M
->NbRows
; i
++) {
663 k
= First_Non_Zero(M
->p
[i
], M
->NbColumns
);
664 /* if it is a tautology, count it as such */
669 /* if it only involves parameters, count it */
670 if (k
>= nbVars
+1) nbEqsM
++;
675 for (i
=0; i
< Ctxt
->NbRows
; i
++) {
676 if (value_zero_p(Ctxt
->p
[i
][0])) {
677 if (First_Non_Zero(Ctxt
->p
[i
], Ctxt
->NbColumns
)==-1) {
685 nbEqsParms
= nbEqsM
+ nbEqsCtxt
;
687 /* nothing to do in this case */
688 if (nbEqsParms
+nbTautoM
+nbTautoCtxt
==0) {
689 (*elimParms
) = (unsigned int*) malloc(sizeof(int));
691 if (renderSpace
==0) {
692 return Matrix_Alloc(0,Ctxt
->NbColumns
);
695 return Matrix_Alloc(0,M
->NbColumns
);
699 Eqs
= Matrix_Alloc(nbEqsParms
, Ctxt
->NbColumns
);
700 EqsMTmp
= Matrix_Alloc(nbEqsParms
, M
->NbColumns
);
702 /* copy equalities from the context */
704 for (i
=0; i
< Ctxt
->NbRows
; i
++) {
705 if (value_zero_p(Ctxt
->p
[i
][0])
706 && First_Non_Zero(Ctxt
->p
[i
], Ctxt
->NbColumns
)!=-1) {
707 Vector_Copy(Ctxt
->p
[i
], Eqs
->p
[k
], Ctxt
->NbColumns
);
708 Vector_Copy(Ctxt
->p
[i
]+1, EqsMTmp
->p
[k
]+nbVars
+1,
713 for (i
=0; i
< M
->NbRows
; i
++) {
714 j
=First_Non_Zero(M
->p
[i
], M
->NbColumns
);
715 /* copy equalities that involve only parameters from M */
717 Vector_Copy(M
->p
[i
]+nbVars
+1, Eqs
->p
[k
]+1, Ctxt
->NbColumns
-1);
718 Vector_Copy(M
->p
[i
]+nbVars
+1, EqsMTmp
->p
[k
]+nbVars
+1,
720 /* mark these equalities for removal */
721 value_set_si(M
->p
[i
][0], 2);
724 /* mark the all-zero equalities for removal */
726 value_set_si(M
->p
[i
][0], 2);
730 /* 2- eliminate parameters until all equalities are used or until we find a
731 contradiction (overconstrained system) */
732 (*elimParms
) = (unsigned int *) malloc((Eqs
->NbRows
+1) * sizeof(int));
735 for (i
=0; i
< Eqs
->NbRows
; i
++) {
736 /* find a variable that can be eliminated */
737 k
= First_Non_Zero(Eqs
->p
[i
], Eqs
->NbColumns
);
738 if (k
!=-1) { /* nothing special to do for tautologies */
740 /* if there is a contradiction, return empty matrices */
741 if (k
==Eqs
->NbColumns
-1) {
742 printf("Contradiction in %dth row of Eqs: ",k
);
745 Matrix_Free(EqsMTmp
);
746 (*M1
) = Matrix_Alloc(0, M
->NbColumns
);
748 (*Ctxt1
) = Matrix_Alloc(0,Ctxt
->NbColumns
);
751 (*elimParms
) = (unsigned int *) malloc(sizeof(int));
753 if (renderSpace
==1) {
754 return Matrix_Alloc(0,(*M1
)->NbColumns
);
757 return Matrix_Alloc(0,(*Ctxt1
)->NbColumns
);
760 /* if we have something we can eliminate, do it in 3 places:
763 k
--; /* k is the rank of the variable, now */
765 (*elimParms
)[(*elimParms
[0])]=k
;
766 for (j
=0; j
< Eqs
->NbRows
; j
++) {
768 eliminate_var_with_constr(Eqs
, i
, Eqs
, j
, k
);
769 eliminate_var_with_constr(EqsMTmp
, i
, EqsMTmp
, j
, k
+nbVars
);
772 for (j
=0; j
< Ctxt
->NbRows
; j
++) {
773 if (value_notzero_p(Ctxt
->p
[i
][0])) {
774 eliminate_var_with_constr(Eqs
, i
, Ctxt
, j
, k
);
777 for (j
=0; j
< M
->NbRows
; j
++) {
778 if (value_cmp_si(M
->p
[i
][0], 2)) {
779 eliminate_var_with_constr(EqsMTmp
, i
, M
, j
, k
+nbVars
);
784 /* if (k==-1): count the tautologies in Eqs to remove them later */
790 /* elimParms may have been overallocated. Now we know how many parms have
791 been eliminated so we can reallocate the right amount of memory. */
792 if (!realloc((*elimParms
), ((*elimParms
)[0]+1)*sizeof(int))) {
793 fprintf(stderr
, "Constraints_Remove_parm_eqs > cannot realloc()");
796 Matrix_Free(EqsMTmp
);
798 /* 3- remove the "bad" equalities from the input matrices
799 and copy the equalities involving only parameters */
800 EqsMTmp
= Matrix_Alloc(M
->NbRows
-nbEqsM
-nbTautoM
, M
->NbColumns
);
802 for (i
=0; i
< M
->NbRows
; i
++) {
803 if (value_cmp_si(M
->p
[i
][0], 2)) {
804 Vector_Copy(M
->p
[i
], EqsMTmp
->p
[k
], M
->NbColumns
);
811 EqsMTmp
= Matrix_Alloc(Ctxt
->NbRows
-nbEqsCtxt
-nbTautoCtxt
, Ctxt
->NbColumns
);
813 for (i
=0; i
< Ctxt
->NbRows
; i
++) {
814 if (value_notzero_p(Ctxt
->p
[i
][0])) {
815 Vector_Copy(Ctxt
->p
[i
], EqsMTmp
->p
[k
], Ctxt
->NbColumns
);
822 if (renderSpace
==0) {/* renderSpace=0: equalities in the parameter space */
823 EqsMTmp
= Matrix_Alloc(Eqs
->NbRows
-allZeros
, Eqs
->NbColumns
);
825 for (i
=0; i
<Eqs
->NbRows
; i
++) {
826 if (First_Non_Zero(Eqs
->p
[i
], Eqs
->NbColumns
)!=-1) {
827 Vector_Copy(Eqs
->p
[i
], EqsMTmp
->p
[k
], Eqs
->NbColumns
);
832 else {/* renderSpace=1: equalities rendered in the combined space */
833 EqsMTmp
= Matrix_Alloc(Eqs
->NbRows
-allZeros
, (*M1
)->NbColumns
);
835 for (i
=0; i
<Eqs
->NbRows
; i
++) {
836 if (First_Non_Zero(Eqs
->p
[i
], Eqs
->NbColumns
)!=-1) {
837 Vector_Copy(Eqs
->p
[i
], &(EqsMTmp
->p
[k
][nbVars
]), Eqs
->NbColumns
);
846 } /* Constraints_Remove_parm_eqs */
849 /** Removes equalities involving only parameters, but starting from a
850 * Polyhedron and its context.
851 * @param P the polyhedron
852 * @param C P's context
853 * @param renderSpace: 0 for the parameter space, =1 for the combined space.
854 * @maxRays Polylib's usual <i>workspace</i>.
856 Polyhedron
* Polyhedron_Remove_parm_eqs(Polyhedron
** P
, Polyhedron
** C
,
858 unsigned int ** elimParms
,
862 Matrix
* M
= Polyhedron2Constraints((*P
));
863 Matrix
* Ct
= Polyhedron2Constraints((*C
));
865 /* if the Minkowski representation is not computed yet, do not compute it in
866 Constraints2Polyhedron */
867 if (F_ISSET((*P
), POL_VALID
| POL_INEQUALITIES
) &&
868 (F_ISSET((*C
), POL_VALID
| POL_INEQUALITIES
))) {
869 FL_INIT(maxRays
, POL_NO_DUAL
);
872 Eqs
= Constraints_Remove_parm_eqs(&M
, &Ct
, renderSpace
, elimParms
);
873 Peqs
= Constraints2Polyhedron(Eqs
, maxRays
);
876 /* particular case: no equality involving only parms is found */
877 if (Eqs
->NbRows
==0) {
884 (*P
) = Constraints2Polyhedron(M
, maxRays
);
885 (*C
) = Constraints2Polyhedron(Ct
, maxRays
);
889 } /* Polyhedron_Remove_parm_eqs */
893 * Given a matrix with m parameterized equations, compress the nb_parms
894 * parameters and n-m variables so that m variables are integer, and transform
895 * the variable space into a n-m space by eliminating the m variables (using
896 * the equalities) the variables to be eliminated are chosen automatically by
898 * <b>Deprecated.</b> Try to use Constraints_fullDimensionize instead.
899 * @param M the constraints
900 * @param the number of parameters
901 * @param validityLattice the the integer lattice underlying the integer
904 Matrix
* full_dimensionize(Matrix
const * M
, int nbParms
,
905 Matrix
** validityLattice
) {
906 Matrix
* Eqs
, * Ineqs
;
907 Matrix
* permutedEqs
, * permutedIneqs
;
909 Matrix
* WVL
; /* The Whole Validity Lattice (vars+parms) */
912 unsigned int * permutation
, * permutationInv
;
913 /* 0- Split the equalities and inequalities from each other */
914 split_constraints(M
, &Eqs
, &Ineqs
);
916 /* 1- if the polyhedron is already full-dimensional, return it */
917 if (Eqs
->NbRows
==0) {
919 (*validityLattice
) = Identity_Matrix(nbParms
+1);
922 nbElimVars
= Eqs
->NbRows
;
924 /* 2- put the vars to be eliminated at the first positions,
925 and compress the other vars/parms
926 -> [ variables to eliminate / parameters / variables to keep ] */
927 permutation
= find_a_permutation(Eqs
, nbParms
);
929 printf("Permuting the vars/parms this way: [ ");
930 for (i
=0; i
< Eqs
->NbColumns
; i
++) {
931 printf("%d ", permutation
[i
]);
935 permutedEqs
= mpolyhedron_permute(Eqs
, permutation
);
936 WVL
= compress_parms(permutedEqs
, Eqs
->NbColumns
-2-Eqs
->NbRows
);
937 /* Check for empty WVL (no solution) */
940 fprintf(stderr
,"full_dimensionize > parameters compression failed.\n");
943 (*validityLattice
) = Identity_Matrix(nbParms
+1);
947 printf("Whole validity lattice: ");
950 mpolyhedron_compress_last_vars(permutedEqs
, WVL
);
951 permutedIneqs
= mpolyhedron_permute(Ineqs
, permutation
);
953 show_matrix(permutedEqs
);
957 mpolyhedron_compress_last_vars(permutedIneqs
, WVL
);
959 printf("After compression: ");
960 show_matrix(permutedIneqs
);
962 /* 3- eliminate the first variables */
963 if (!mpolyhedron_eliminate_first_variables(permutedEqs
, permutedIneqs
)) {
964 fprintf(stderr
,"full_dimensionize > variable elimination failed.\n");
965 Matrix_Free(permutedIneqs
);
966 (*validityLattice
) = Identity_Matrix(nbParms
+1);
970 printf("After elimination of the variables: ");
971 show_matrix(permutedIneqs
);
974 /* 4- get rid of the first (zero) columns,
975 which are now useless, and put the parameters back at the end */
976 Full_Dim
= Matrix_Alloc(permutedIneqs
->NbRows
,
977 permutedIneqs
->NbColumns
-nbElimVars
);
978 for (i
=0; i
< permutedIneqs
->NbRows
; i
++) {
979 value_set_si(Full_Dim
->p
[i
][0], 1);
980 for (j
=0; j
< nbParms
; j
++)
981 value_assign(Full_Dim
->p
[i
][j
+Full_Dim
->NbColumns
-nbParms
-1],
982 permutedIneqs
->p
[i
][j
+nbElimVars
+1]);
983 for (j
=0; j
< permutedIneqs
->NbColumns
-nbParms
-2-nbElimVars
; j
++)
984 value_assign(Full_Dim
->p
[i
][j
+1],
985 permutedIneqs
->p
[i
][nbElimVars
+nbParms
+j
+1]);
986 value_assign(Full_Dim
->p
[i
][Full_Dim
->NbColumns
-1],
987 permutedIneqs
->p
[i
][permutedIneqs
->NbColumns
-1]);
989 Matrix_Free(permutedIneqs
);
991 /* 5- Keep only the the validity lattice restricted to the parameters */
992 *validityLattice
= Matrix_Alloc(nbParms
+1, nbParms
+1);
993 for (i
=0; i
< nbParms
; i
++) {
994 for (j
=0; j
< nbParms
; j
++)
995 value_assign((*validityLattice
)->p
[i
][j
],
997 value_assign((*validityLattice
)->p
[i
][nbParms
],
998 WVL
->p
[i
][WVL
->NbColumns
-1]);
1000 for (j
=0; j
< nbParms
; j
++)
1001 value_set_si((*validityLattice
)->p
[nbParms
][j
], 0);
1002 value_assign((*validityLattice
)->p
[nbParms
][nbParms
],
1003 WVL
->p
[WVL
->NbColumns
-1][WVL
->NbColumns
-1]);
1008 } /* full_dimensionize */
1011 #undef dbgCompParmMore