polylib 5.22.8
matrix_addon.c
Go to the documentation of this file.
1/**
2 * $Id: matrix_addon.c,v 1.17 2007/03/18 18:49:08 skimo Exp $
3 *
4 * Polylib matrix addons
5 * Mainly, deals with polyhedra represented as a matrix (implicit form)
6 * @author Benoit Meister <meister@icps.u-strasbg.fr>
7 *
8 */
9
11#include <polylib/polylib.h>
12#include <stdlib.h>
13
14/** Creates a view of the constraints of a polyhedron as a Matrix * */
16 Matrix *view = (Matrix *)malloc(sizeof(Matrix));
17 view->NbRows = P->NbConstraints;
18 view->NbColumns = P->Dimension + 2;
19 view->p = P->Constraint;
20 return view;
21}
22
23/** "Frees" a view of the constraints of a polyhedron */
24void constraintsView_Free(Matrix *M) { free(M); }
25
26/**
27 * splits a matrix of constraints M into a matrix of equalities Eqs and a
28 * matrix of inequalities Ineqs allocs the new matrices.
29 * Allocates Eqs and Ineqs.
30 */
31void split_constraints(Matrix const *M, Matrix **Eqs, Matrix **Ineqs) {
32 unsigned int i, j, k_eq, k_ineq, nb_eqs = 0;
33
34 /* 1- count the number of equations */
35 for (i = 0; i < M->NbRows; i++)
36 if (value_zero_p(M->p[i][0]))
37 nb_eqs++;
38
39 /* 2- extract the two matrices of equations */
40 (*Eqs) = Matrix_Alloc(nb_eqs, M->NbColumns);
41 (*Ineqs) = Matrix_Alloc(M->NbRows - nb_eqs, M->NbColumns);
42
43 k_eq = k_ineq = 0;
44 for (i = 0; i < M->NbRows; i++) {
45 if (value_zero_p(M->p[i][0])) {
46 for (j = 0; j < M->NbColumns; j++)
47 value_assign((*Eqs)->p[k_eq][j], M->p[i][j]);
48 k_eq++;
49 } else {
50 for (j = 0; j < M->NbColumns; j++)
51 value_assign((*Ineqs)->p[k_ineq][j], M->p[i][j]);
52 k_ineq++;
53 }
54 }
55}
56
57/* returns the dim-dimensional identity matrix */
58Matrix *Identity_Matrix(unsigned int dim) {
59 Matrix *ret = Matrix_Alloc(dim, dim);
60 unsigned int i, j;
61 for (i = 0; i < dim; i++) {
62 for (j = 0; j < dim; j++) {
63 if (i == j) {
64 value_set_si(ret->p[i][j], 1);
65 } else
66 value_set_si(ret->p[i][j], 0);
67 }
68 }
69 return ret;
70} /* Identity_Matrix */
71
72/**
73 * returns the dim-dimensional identity matrix.
74 * If I is set to NULL, allocates it first.
75 * Else, assumes an existing, allocated Matrix.
76 */
77void Matrix_identity(unsigned int dim, Matrix **I) {
78 int i, j;
79 if (*I == NULL) {
80 (*I) = Identity_Matrix(dim);
81 } else {
82 assert((*I)->NbRows >= dim && (*I)->NbColumns >= dim);
83 for (i = 0; i < dim; i++) {
84 for (j = 0; j < dim; j++) {
85 if (i == j) {
86 value_set_si((*I)->p[i][j], 1);
87 } else {
88 value_set_si((*I)->p[i][j], 0);
89 }
90 }
91 }
92 }
93} /* Matrix_identity */
94
95/** given a n x n integer transformation matrix transf, compute its inverse
96 M/g, where M is a nxn integer matrix. g is a common denominator for
97 elements of (transf^{-1}) */
98void mtransformation_inverse(Matrix *transf, Matrix **inverse, Value *g) {
99 Value factor;
100 unsigned int i, j;
101 Matrix *tmp, *inv;
102
103 value_init(*g);
104 value_set_si(*g, 1);
105
106 /* a - compute the inverse as usual (n x (n+1) matrix) */
107 tmp = Matrix_Copy(transf);
108 inv = Matrix_Alloc(transf->NbRows, transf->NbColumns + 1);
109 MatInverse(tmp, inv);
110 Matrix_Free(tmp);
111
112 /* b - as it is rational, put it to the same denominator*/
113 (*inverse) = Matrix_Alloc(transf->NbRows, transf->NbRows);
114 for (i = 0; i < inv->NbRows; i++)
115 value_lcm(*g, *g, inv->p[i][inv->NbColumns - 1]);
116 for (i = 0; i < inv->NbRows; i++) {
117 value_division(factor, *g, inv->p[i][inv->NbColumns - 1]);
118 for (j = 0; j < (*inverse)->NbColumns; j++)
119 value_multiply((*inverse)->p[i][j], inv->p[i][j], factor);
120 }
121
122 /* c- clean up */
124 Matrix_Free(inv);
125} /* mtransformation_inverse */
126
127/** takes a transformation matrix, and expands it to a higher dimension with
128 the identity matrix regardless of it homogeneousness */
130 Matrix *ret = Identity_Matrix(new_dim);
131 int offset = new_dim - M->NbRows;
132 unsigned int i, j;
133
134 assert(new_dim >= M->NbColumns);
135 assert(M->NbRows == M->NbColumns);
136
137 for (i = 0; i < M->NbRows; i++)
138 for (j = 0; j < M->NbRows; j++)
139 value_assign(ret->p[offset + i][offset + j], M->p[i][j]);
140 return ret;
141} /* mtransformation_expand_left_to_dim */
142
143/** simplify a matrix seen as a polyhedron, by dividing its rows by the gcd of
144 their elements. */
146 int i, j;
147 Value cur_gcd;
148 value_init(cur_gcd);
149 for (i = 0; i < polyh->NbRows; i++) {
150 Vector_Gcd(polyh->p[i] + 1, polyh->NbColumns - 1, &cur_gcd);
151 printf(" gcd[%d] = ", i);
152 value_print(stdout, VALUE_FMT, cur_gcd);
153 printf("\n");
154 Vector_AntiScale(polyh->p[i] + 1, polyh->p[i] + 1, cur_gcd,
155 polyh->NbColumns - 1);
156 }
157 value_clear(cur_gcd);
158} /* mpolyhedron_simplify */
159
160/** inflates a polyhedron (represented as a matrix) P, so that the apx of its
161 Ehrhart Polynomial is an upper bound of the Ehrhart polynomial of P
162 WARNING: this inflation is supposed to be applied on full-dimensional
163 polyhedra. */
164void mpolyhedron_inflate(Matrix *polyh, unsigned int nb_parms) {
165 unsigned int i, j;
166 unsigned nb_vars = polyh->NbColumns - nb_parms - 2;
167 Value infl;
168 value_init(infl);
169 /* subtract the sum of the negative coefficients of each inequality */
170 for (i = 0; i < polyh->NbRows; i++) {
171 value_set_si(infl, 0);
172 for (j = 0; j < nb_vars; j++) {
173 if (value_neg_p(polyh->p[i][1 + j]))
174 value_addto(infl, infl, polyh->p[i][1 + j]);
175 }
176 /* here, we subtract a negative value */
177 value_subtract(polyh->p[i][polyh->NbColumns - 1],
178 polyh->p[i][polyh->NbColumns - 1], infl);
179 }
180 value_clear(infl);
181} /* mpolyhedron_inflate */
182
183/** deflates a polyhedron (represented as a matrix) P, so that the apx of its
184 Ehrhart Polynomial is a lower bound of the Ehrhart polynomial of P WARNING:
185 this deflation is supposed to be applied on full-dimensional polyhedra. */
186void mpolyhedron_deflate(Matrix *polyh, unsigned int nb_parms) {
187 unsigned int i, j;
188 unsigned nb_vars = polyh->NbColumns - nb_parms - 2;
189 Value defl;
190 value_init(defl);
191 /* substract the sum of the negative coefficients of each inequality */
192 for (i = 0; i < polyh->NbRows; i++) {
193 value_set_si(defl, 0);
194 for (j = 0; j < nb_vars; j++) {
195 if (value_pos_p(polyh->p[i][1 + j]))
196 value_addto(defl, defl, polyh->p[i][1 + j]);
197 }
198 /* here, we substract a negative value */
199 value_subtract(polyh->p[i][polyh->NbColumns - 1],
200 polyh->p[i][polyh->NbColumns - 1], defl);
201 }
202 value_clear(defl);
203} /* mpolyhedron_deflate */
204
205/** use an eliminator row to eliminate a variable in a victim row (without
206 * changing the sign of the victim row -> important if it is an inequality).
207 * @param Eliminator the matrix containing the eliminator row
208 * @param eliminator_row the index of the eliminator row in <tt>Eliminator</tt>
209 * @param Victim the matrix containing the row to be eliminated
210 * @param victim_row the row to be eliminated in <tt>Victim</tt>
211 * @param var_to_elim the variable to be eliminated.
212 */
213void eliminate_var_with_constr(Matrix *Eliminator, unsigned int eliminator_row,
214 Matrix *Victim, unsigned int victim_row,
215 unsigned int var_to_elim) {
216 Value cur_lcm, mul_a, mul_b;
217 Value tmp, tmp2;
218 int k;
219
220 value_init(cur_lcm);
221 value_init(mul_a);
222 value_init(mul_b);
223 value_init(tmp);
224 value_init(tmp2);
225 /* if the victim coefficient is not zero */
226 if (value_notzero_p(Victim->p[victim_row][var_to_elim + 1])) {
227 value_lcm(cur_lcm, Eliminator->p[eliminator_row][var_to_elim + 1],
228 Victim->p[victim_row][var_to_elim + 1]);
229 /* multiplication factors */
230 value_division(mul_a, cur_lcm,
231 Eliminator->p[eliminator_row][var_to_elim + 1]);
232 value_division(mul_b, cur_lcm, Victim->p[victim_row][var_to_elim + 1]);
233 /* the multiplicator for the vitim row has to be positive */
234 if (value_pos_p(mul_b)) {
235 value_oppose(mul_a, mul_a);
236 } else {
237 value_oppose(mul_b, mul_b);
238 }
239 value_clear(cur_lcm);
240 /* now we have a.mul_a = -(b.mul_b) and mul_a > 0 */
241 for (k = 1; k < Victim->NbColumns; k++) {
242 value_multiply(tmp, Eliminator->p[eliminator_row][k], mul_a);
243 value_multiply(tmp2, Victim->p[victim_row][k], mul_b);
244 value_addto(Victim->p[victim_row][k], tmp, tmp2);
245 }
246 }
247 value_clear(mul_a);
248 value_clear(mul_b);
249 value_clear(tmp);
250 value_clear(tmp2);
251}
252/* eliminate_var_with_constr */
253
254/* STUFF WITH PARTIAL MAPPINGS (Mappings to a subset of the
255 variables/parameters) : on the first or last variables/parameters */
256
257/** compress the last vars/pars of the polyhedron M expressed as a polylib
258 matrix
259 - adresses the full-rank compressions only
260 - modfies M */
262 unsigned int i, j, k;
263 unsigned int offset = M->NbColumns - compression->NbRows;
264 /* the computations on M will begin on column "offset" */
265
266 Matrix *M_tmp = Matrix_Alloc(1, M->NbColumns);
267 assert(compression->NbRows == compression->NbColumns);
268 /* basic matrix multiplication (using a temporary row instead of a whole
269 temporary matrix), but with a column offset */
270 for (i = 0; i < M->NbRows; i++) {
271 for (j = 0; j < compression->NbRows; j++) {
272 value_set_si(M_tmp->p[0][j], 0);
273 for (k = 0; k < compression->NbRows; k++) {
274 value_addmul(M_tmp->p[0][j], M->p[i][k + offset], compression->p[k][j]);
275 }
276 }
277 for (j = 0; j < compression->NbRows; j++)
278 value_assign(M->p[i][j + offset], M_tmp->p[0][j]);
279 }
280 Matrix_Free(M_tmp);
281} /* mpolyhedron_compress_last_vars */
282
283/** use a set of m equalities Eqs to eliminate m variables in the polyhedron
284 Ineqs represented as a matrix
285 eliminates the m first variables
286 - assumes that Eqs allow to eliminate the m equalities
287 - modifies Eqs and Ineqs */
289 unsigned int i, j, k;
290 /* eliminate one variable (index i) after each other */
291 for (i = 0; i < Eqs->NbRows; i++) {
292 /* find j, the first (non-marked) row of Eqs with a non-zero coefficient */
293 for (j = 0; j < Eqs->NbRows &&
294 (Eqs->p[j][i + 1] == 0 || (!value_cmp_si(Eqs->p[j][0], 2)));
295 j++)
296 ;
297 /* if no row is found in Eqs that allows to eliminate variable i, return an
298 error code (0) */
299 if (j == Eqs->NbRows)
300 return 0;
301 /* else, eliminate variable i in Eqs and Ineqs with the j^th row of Eqs
302 (and mark this row so we don't use it again for an elimination) */
303 for (k = j + 1; k < Eqs->NbRows; k++)
304 eliminate_var_with_constr(Eqs, j, Eqs, k, i);
305 for (k = 0; k < Ineqs->NbRows; k++)
306 eliminate_var_with_constr(Eqs, j, Ineqs, k, i);
307 /* mark the row */
308 value_set_si(Eqs->p[j][0], 2);
309 }
310 /* un-mark all the rows */
311 for (i = 0; i < Eqs->NbRows; i++)
312 value_set_si(Eqs->p[i][0], 0);
313 return 1;
314} /* mpolyhedron_eliminate_first_variables */
315
316/** returns a contiguous submatrix of a matrix.
317 * @param M the input matrix
318 * @param sr the index of the starting row
319 * @param sc the index of the starting column
320 * @param er the index ofthe ending row (excluded)
321 * @param ec the ined of the ending colummn (excluded)
322 * @param sub (returned), the submatrix. Allocated if set to NULL, assumed to
323 * be already allocated else.
324 */
325void Matrix_subMatrix(Matrix *M, unsigned int sr, unsigned int sc,
326 unsigned int er, unsigned int ec, Matrix **sub) {
327 int i;
328 int nbR = er - sr;
329 int nbC = ec - sc;
330 assert(er <= M->NbRows && ec <= M->NbColumns);
331 if ((*sub) == NULL) {
332 (*sub) = Matrix_Alloc(nbR, nbC);
333 }
334 if (nbR == 0 || nbC == 0)
335 return;
336 for (i = 0; i < nbR; i++) {
337 Vector_Copy(&(M->p[i + sr][sc]), (*sub)->p[i], nbC);
338 }
339} /* Matrix_subMatrix */
340
341/**
342 * Cloning function. Similar to Matrix_Copy() but allocates the target matrix
343 * if it is set to NULL.
344 */
345void Matrix_clone(Matrix *M, Matrix **Cl) {
346 Matrix_subMatrix(M, 0, 0, M->NbRows, M->NbColumns, Cl);
347}
348
349/**
350 * Copies a contiguous submatrix of M1 into M2, at the indicated position.
351 * M1 and M2 are assumed t be allocated already.
352 * @param M1 the source matrix
353 * @param sr1 the starting source row
354 * @param sc1 the starting source column
355 * @param nbR the number of rows
356 * @param nbC the number of columns
357 * @param M2 the target matrix
358 * @param sr2 the starting target row
359 * @param sc2 the starting target column
360 */
361void Matrix_copySubMatrix(Matrix *M1, unsigned int sr1, unsigned int sc1,
362 unsigned int nbR, unsigned int nbC, Matrix *M2,
363 unsigned int sr2, unsigned int sc2) {
364 int i;
365 for (i = 0; i < nbR; i++) {
366 Vector_Copy(&(M1->p[i + sr1][sc1]), &(M2->p[i + sr2][sc2]), nbC);
367 }
368} /* Matrix_copySubMatrix */
369
370/**
371 * transforms a matrix M into -M
372 */
374 int i, j;
375 for (i = 0; i < M->NbRows; i++) {
376 for (j = 0; j < M->NbColumns; j++) {
377 value_oppose(M->p[i][j], M->p[i][j]);
378 }
379 }
380}
Matrix * Matrix_Copy(Matrix const *Src)
Definition: Matop.c:98
#define value_pos_p(val)
Definition: arithmetique.h:571
#define value_oppose(ref, val)
Definition: arithmetique.h:552
#define value_notzero_p(val)
Definition: arithmetique.h:576
#define value_lcm(ref, val1, val2)
Definition: arithmetique.h:557
#define value_zero_p(val)
Definition: arithmetique.h:575
#define value_assign(v1, v2)
Definition: arithmetique.h:482
#define value_set_si(val, i)
Definition: arithmetique.h:483
#define value_addmul(ref, val1, val2)
Definition: arithmetique.h:539
#define value_clear(val)
Definition: arithmetique.h:485
#define value_division(ref, val1, val2)
Definition: arithmetique.h:547
#define value_multiply(ref, val1, val2)
Definition: arithmetique.h:543
#define value_print(Dst, fmt, val)
Definition: arithmetique.h:487
#define value_subtract(ref, val1, val2)
Definition: arithmetique.h:544
#define value_addto(ref, val1, val2)
Definition: arithmetique.h:537
#define value_neg_p(val)
Definition: arithmetique.h:572
#define value_init(val)
Definition: arithmetique.h:481
#define value_cmp_si(val, n)
Definition: arithmetique.h:581
#define assert(ex)
Definition: assert.h:16
Matrix * Matrix_Alloc(unsigned NbRows, unsigned NbColumns)
Definition: matrix.c:24
int MatInverse(Matrix *Mat, Matrix *MatInv)
Definition: matrix.c:603
void Matrix_Free(Matrix *Mat)
Definition: matrix.c:71
void mpolyhedron_deflate(Matrix *polyh, unsigned int nb_parms)
deflates a polyhedron (represented as a matrix) P, so that the apx of its Ehrhart Polynomial is a low...
Definition: matrix_addon.c:186
void split_constraints(Matrix const *M, Matrix **Eqs, Matrix **Ineqs)
splits a matrix of constraints M into a matrix of equalities Eqs and a matrix of inequalities Ineqs a...
Definition: matrix_addon.c:31
void Matrix_subMatrix(Matrix *M, unsigned int sr, unsigned int sc, unsigned int er, unsigned int ec, Matrix **sub)
returns a contiguous submatrix of a matrix.
Definition: matrix_addon.c:325
void mpolyhedron_compress_last_vars(Matrix *M, Matrix *compression)
compress the last vars/pars of the polyhedron M expressed as a polylib matrix
Definition: matrix_addon.c:261
Matrix * Identity_Matrix(unsigned int dim)
Definition: matrix_addon.c:58
unsigned int mpolyhedron_eliminate_first_variables(Matrix *Eqs, Matrix *Ineqs)
use a set of m equalities Eqs to eliminate m variables in the polyhedron Ineqs represented as a matri...
Definition: matrix_addon.c:288
void eliminate_var_with_constr(Matrix *Eliminator, unsigned int eliminator_row, Matrix *Victim, unsigned int victim_row, unsigned int var_to_elim)
use an eliminator row to eliminate a variable in a victim row (without changing the sign of the victi...
Definition: matrix_addon.c:213
void Matrix_clone(Matrix *M, Matrix **Cl)
Cloning function.
Definition: matrix_addon.c:345
void constraintsView_Free(Matrix *M)
"Frees" a view of the constraints of a polyhedron
Definition: matrix_addon.c:24
void mtransformation_inverse(Matrix *transf, Matrix **inverse, Value *g)
given a n x n integer transformation matrix transf, compute its inverse M/g, where M is a nxn integer...
Definition: matrix_addon.c:98
Matrix * mtransformation_expand_left_to_dim(Matrix *M, int new_dim)
takes a transformation matrix, and expands it to a higher dimension with the identity matrix regardle...
Definition: matrix_addon.c:129
void mpolyhedron_inflate(Matrix *polyh, unsigned int nb_parms)
inflates a polyhedron (represented as a matrix) P, so that the apx of its Ehrhart Polynomial is an up...
Definition: matrix_addon.c:164
void Matrix_copySubMatrix(Matrix *M1, unsigned int sr1, unsigned int sc1, unsigned int nbR, unsigned int nbC, Matrix *M2, unsigned int sr2, unsigned int sc2)
Copies a contiguous submatrix of M1 into M2, at the indicated position.
Definition: matrix_addon.c:361
void Matrix_oppose(Matrix *M)
transforms a matrix M into -M
Definition: matrix_addon.c:373
void mpolyhedron_simplify(Matrix *polyh)
simplify a matrix seen as a polyhedron, by dividing its rows by the gcd of their elements.
Definition: matrix_addon.c:145
void Matrix_identity(unsigned int dim, Matrix **I)
returns the dim-dimensional identity matrix.
Definition: matrix_addon.c:77
Matrix * constraintsView(Polyhedron *P)
Creates a view of the constraints of a polyhedron as a Matrix *.
Definition: matrix_addon.c:15
Definition: Lattice.c:4
Definition: types.h:75
unsigned NbRows
Definition: types.h:76
Value ** p
Definition: types.h:77
unsigned NbColumns
Definition: types.h:76
unsigned Dimension
Definition: types.h:94
unsigned NbConstraints
Definition: types.h:94
Value ** Constraint
Definition: types.h:95
void Vector_Gcd(Value *p, unsigned length, Value *min)
Definition: vector.c:485
void Vector_AntiScale(Value *p1, Value *p2, Value lambda, unsigned length)
Definition: vector.c:356
void Vector_Copy(Value *p1, Value *p2, unsigned length)
Definition: vector.c:256