polylib 5.22.8
matrix_permutations.c
Go to the documentation of this file.
1/**
2 * $Id: matrix_permutations.c,v 1.8 2006/10/01 02:10:46 meister Exp $
3 *
4 * Permutations on matrices Matrices are seen either as transformations
5 * (mtransformation) or as polyhedra (mpolyhedron)
6 * @author B. Meister
7 * LSIIT -ICPS
8 * UMR 7005 CNRS
9 * Louis Pasteur University (ULP), Strasbourg, France
10 *
11 * Permutations are just indirection vectors: the k^th element of a permutation
12 * vector is the position of the k^th variable in the permuted object.
13 */
14
16#include <stdlib.h>
17
18/** utility function : bit count (i know, there are faster methods) */
19unsigned int nb_bits(unsigned long long int x) {
20 unsigned int i, n = 0;
21 unsigned long long int y = x;
22 for (i = 0; i < 64; i++) {
23 n += y % 2;
24 y >>= 1;
25 }
26 return n;
27}
28
29/** Gives the inverse permutation vector of a permutation vector
30 * @param perm the permutation vector
31 * @param
32 */
33unsigned int *permutation_inverse(unsigned int *perm, unsigned int nb_elems) {
34 int i;
35 unsigned int *inv_perm =
36 (unsigned int *)malloc(sizeof(unsigned int) * nb_elems);
37 for (i = 0; i < nb_elems; i++)
38 inv_perm[perm[i]] = i;
39 return inv_perm;
40}
41
42/**
43 * Given a linear tranformation on initial variables, and a variable
44 * permutation, computes the tranformation for the permuted variables. perm is
45 * a vector giving the new "position of the k^th variable, k \in [1..n] we can
46 * call it a "permutation vector" if you wish transf[x][y] ->
47 * permuted[permutation(x)][permutation(y)]
48 */
49Matrix *mtransformation_permute(Matrix *transf, unsigned int *permutation) {
50 Matrix *permuted;
51 unsigned int i, j;
52 /* the transformation is supposed to be from Q^n to Q^n, so a square matrix.
53 */
54 assert(transf->NbRows == transf->NbColumns);
55 permuted = Matrix_Alloc(transf->NbRows, transf->NbRows);
56 for (i = 0; i < transf->NbRows; i++) {
57 for (j = 0; j < transf->NbRows; j++) {
58 value_assign(permuted->p[permutation[i]][permutation[j]],
59 transf->p[i][j]);
60 }
61 }
62 return permuted;
63}
64
65/** permutes the variables of the constraints of a polyhedron
66 * @param polyh the constraints of the polyhedron
67 * @param permutation a permutation vector
68 */
69Matrix *mpolyhedron_permute(Matrix *polyh, unsigned int *permutation) {
70 unsigned int i, j;
71 Matrix *permuted = Matrix_Alloc(polyh->NbRows, polyh->NbColumns);
72 for (i = 0; i < polyh->NbRows; i++) {
73 value_assign(permuted->p[i][0], polyh->p[i][0]);
74 for (j = 1; j < polyh->NbColumns; j++) {
75 value_assign(permuted->p[i][permutation[j - 1] + 1], polyh->p[i][j]);
76 }
77 }
78 return permuted;
79}
80
81/** permutes the variables of the constraints of a polyhedron
82 * @param C the original set of constraints
83 * @param perm a permutation vector
84 * @param Cp (returned) the set of constraints whose variables are
85 * permuted. Allocated if set to NULL, assumed to be already allocated if not.
86 */
87void Constraints_permute(Matrix *C, unsigned int *perm, Matrix **Cp) {
88 unsigned int i, j;
89 if ((*Cp) == NULL) {
90 (*Cp) = Matrix_Alloc(C->NbRows, C->NbColumns);
91 } else {
92 assert((*Cp)->NbRows == C->NbRows && (*Cp)->NbColumns == C->NbColumns);
93 }
94 for (i = 0; i < C->NbRows; i++) {
95 value_assign((*Cp)->p[i][0], C->p[i][0]);
96 for (j = 1; j < C->NbColumns; j++) {
97 value_assign((*Cp)->p[i][perm[j - 1] + 1], C->p[i][j]);
98 }
99 }
100} /* Constraints_permute */
101
102/** Given a set of <i>equalities</i>, find a set of variables that can be
103 * eliminated using these equalities. The variables that we agree to eliminate
104 * are in a zone of contiguous variables (or parameters). <p>
105 * Notes:
106 <ul>
107 <li>brute force, surely enhanceable algorithm</li>
108 <li>limited number of variables in the zone: limit = bitwidth of long long
109 </ul>
110 * @param Eqs the matrix of equalities.
111 * @param start the rank of the first variable (inclusive) of the zone in Eqs
112 * @param end the rank of the last variable (inclusive) of the zone
113 * return a bitfield where bits set to one define the variables to eliminate
114*/
115unsigned long long int eliminable_vars(Matrix *Eqs, unsigned start,
116 unsigned end) {
117 unsigned long long int combination;
118 unsigned int i, j, k;
119 Matrix *M, *H, *Q, *U;
120 Matrix *Square_Mat, *Eqs2;
121 unsigned nb_vars = end - start + 1;
122 Polyhedron *OverConstrained;
123
124 assert(start > 0 && end < Eqs->NbColumns - 1);
125
126 /* if the affine hull is overconstrained, return 0 */
127 if (Eqs->NbRows > nb_vars) {
128 /* FIXME: there is a magic maximum number of rays here */
129 Eqs2 = Matrix_Copy(Eqs);
130 OverConstrained =
131 Constraints2Polyhedron(Eqs2, Eqs->NbColumns * Eqs->NbColumns);
132 Matrix_Free(Eqs2);
133 if (emptyQ(OverConstrained)) {
134 Polyhedron_Free(OverConstrained);
135 return 0;
136 }
137 Polyhedron_Free(OverConstrained);
138 }
139
140 /* do not accept 0 = 0 equalities */
141 for (i = 0; i < Eqs->NbRows; i++) {
142 assert(!Vector_IsZero(Eqs->p[i], Eqs->NbColumns));
143 }
144
145 Square_Mat = Matrix_Alloc(Eqs->NbRows, Eqs->NbRows);
146
147 /* There are Eqs->NbRows variables to eliminate.
148 Generate all the combinations of Eqs->NbRows variables (-> bits to 1 in
149 the word "combination") among nb_vars WARNING : we assume here that we
150 have not more than 64 variables. You may convert it to use GNU MP to
151 set it to an infinite number of bits
152 */
153 for (combination = ((unsigned long long int)1 << (Eqs->NbRows)) - 1;
154 (combination < ((unsigned long long int)1 << nb_vars)); combination++) {
155 if (nb_bits(combination) == Eqs->NbRows) {
156 k = 0;
157 /* 1- put the m colums in a square matrix */
158 for (j = 0; j < nb_vars; j++) {
159 if ((combination >> j) % 2) {
160 for (i = 0; i < Eqs->NbRows; i++) {
161 value_assign(Square_Mat->p[i][k], Eqs->p[i][j + start]);
162 }
163 k++;
164 }
165 }
166 /* 2- see if the matrix is full-row-rank */
167 right_hermite(Square_Mat, &H, &Q, &U);
168 Matrix_Free(Q);
169 Matrix_Free(U);
170
171 /* if it is full-row-rank, we have found a set of variables that can be
172 eliminated. */
173 if (value_notzero_p((H->p[Eqs->NbRows - 1][Eqs->NbRows - 1]))) {
174 Matrix_Free(Square_Mat);
175 Matrix_Free(H);
176 return combination;
177 }
178 Matrix_Free(H);
179 }
180 }
181 Matrix_Free(Square_Mat);
182 return (unsigned long long int)0;
183} /* eliminable_vars */
184
185/**
186 * finds a valid permutation : for a set of m equations, find m variables that
187 * will be put at the beginning (to be eliminated).
188 * Note: inherits the limited the number of variables from
189 * <i>eliminable_vars</i>
190 */
191unsigned int *find_a_permutation(Matrix *Eqs, unsigned int nb_parms) {
192 unsigned int i, j, k;
193 int nb_vars = Eqs->NbColumns - nb_parms - 2;
194 unsigned long long int combination;
195 unsigned int *permutation =
196 (unsigned int *)malloc(sizeof(unsigned int) * Eqs->NbColumns - 1);
197
198 /* 1- find a set of variables to eliminate */
199 if ((combination = eliminable_vars(Eqs, 1, nb_vars)) == 0) {
200 /* if it is impossible to eliminate enough variables, return error code */
201 return NULL;
202 }
203
204 /* 2- make the permutation matrix
205 * a- deal with the variables */
206 k = 0;
207 for (i = 0; i < nb_vars; i++) {
208 /* if the variable has to be eliminated, put them at the beginning */
209 if (combination % 2) {
210 permutation[i] = k;
211 k++;
212 }
213 /* if not, put the variables at the end */
214 else
215 permutation[i] = Eqs->NbRows + nb_parms + i - k;
216 combination >>= 1;
217 }
218 /* b- deal with the parameters */
219 for (i = 0; i < nb_parms; i++) {
220 permutation[nb_vars + i] = Eqs->NbRows + i;
221 }
222 /* c- deal with the constant */
223 permutation[Eqs->NbColumns - 2] = Eqs->NbColumns - 2;
224
225 return permutation;
226} /* find_a_permutation */
227
228/** computes the permutation of variables and parameters, according to some
229 * variables to keep. put the variables not to be kept at the beginning, then
230 * the parameters and finally the variables to be kept. strongly related to
231 * the function compress_to_full_dim2
232 */
233unsigned int *permutation_for_full_dim2(unsigned int *vars_to_keep,
234 unsigned int nb_keep,
235 unsigned int nb_vars_parms,
236 unsigned int nb_parms) {
237 unsigned int *permutation =
238 (unsigned int *)malloc(sizeof(unsigned int) * nb_vars_parms + 1);
239 unsigned int i;
240 int cur_keep = 0,
241 cur_go = 0; /*current number of variables to eliminate/keep*/
242 for (i = 0; i < nb_vars_parms - nb_parms; i++) {
243 if (i == vars_to_keep[cur_keep]) {
244 permutation[i] = nb_vars_parms - nb_keep + cur_keep;
245 cur_keep++;
246 } else {
247 permutation[i] = cur_go;
248 cur_go++;
249 }
250 }
251 /* parameters are just left-shifted */
252 for (i = 0; i < nb_parms; i++)
253 permutation[i + nb_vars_parms - nb_parms] =
254 i + nb_vars_parms - nb_parms - nb_keep;
255
256 /* contants stay where they are */
257 permutation[nb_vars_parms] = nb_vars_parms;
258 return permutation;
259} /* permutation_for_full_dim2 */
Matrix * Matrix_Copy(Matrix const *Src)
Definition: Matop.c:98
#define value_notzero_p(val)
Definition: arithmetique.h:576
#define value_assign(v1, v2)
Definition: arithmetique.h:482
#define assert(ex)
Definition: assert.h:16
Matrix * Matrix_Alloc(unsigned NbRows, unsigned NbColumns)
Definition: matrix.c:24
void right_hermite(Matrix *A, Matrix **Hp, Matrix **Up, Matrix **Qp)
Definition: matrix.c:449
void Matrix_Free(Matrix *Mat)
Definition: matrix.c:71
void Constraints_permute(Matrix *C, unsigned int *perm, Matrix **Cp)
permutes the variables of the constraints of a polyhedron
unsigned int * permutation_inverse(unsigned int *perm, unsigned int nb_elems)
Gives the inverse permutation vector of a permutation vector.
unsigned long long int eliminable_vars(Matrix *Eqs, unsigned start, unsigned end)
Given a set of equalities, find a set of variables that can be eliminated using these equalities.
Matrix * mpolyhedron_permute(Matrix *polyh, unsigned int *permutation)
permutes the variables of the constraints of a polyhedron
Matrix * mtransformation_permute(Matrix *transf, unsigned int *permutation)
Given a linear tranformation on initial variables, and a variable permutation, computes the tranforma...
unsigned int nb_bits(unsigned long long int x)
utility function : bit count (i know, there are faster methods)
unsigned int * find_a_permutation(Matrix *Eqs, unsigned int nb_parms)
finds a valid permutation : for a set of m equations, find m variables that will be put at the beginn...
unsigned int * permutation_for_full_dim2(unsigned int *vars_to_keep, unsigned int nb_keep, unsigned int nb_vars_parms, unsigned int nb_parms)
computes the permutation of variables and parameters, according to some variables to keep.
void Polyhedron_Free(Polyhedron *Pol)
Definition: polyhedron.c:1614
Polyhedron * Constraints2Polyhedron(Matrix *Constraints, unsigned NbMaxRays)
Given a matrix of constraints ('Constraints'), construct and return a polyhedron.
Definition: polyhedron.c:1905
static int n
Definition: polyparam.c:276
Definition: types.h:75
unsigned NbRows
Definition: types.h:76
Value ** p
Definition: types.h:77
unsigned NbColumns
Definition: types.h:76
#define emptyQ(P)
Definition: types.h:118
int Vector_IsZero(Value *v, unsigned length)
Definition: vector.c:724