Makefile.am: check-evalue: print name of each test file
[barvinok.git] / reducer.cc
blob51b0a3178fa93220e72c05be8d658c46260f6e8f
1 #include <vector>
2 #include <barvinok/util.h>
3 #include "reducer.h"
4 #include "lattice_point.h"
6 using std::vector;
7 using std::cerr;
8 using std::endl;
10 struct OrthogonalException Orthogonal;
12 void np_base::handle(const signed_cone& sc, barvinok_options *options)
14 assert(sc.rays.NumRows() == dim);
15 factor.n *= sc.sign;
16 handle(sc.rays, current_vertex, factor, sc.det, options);
17 factor.n *= sc.sign;
20 void np_base::start(Polyhedron *P, barvinok_options *options)
22 QQ factor(1, 1);
23 for (;;) {
24 try {
25 init(P);
26 for (int i = 0; i < P->NbRays; ++i) {
27 if (!value_pos_p(P->Ray[i][dim+1]))
28 continue;
30 Polyhedron *C = supporting_cone(P, i);
31 do_vertex_cone(factor, C, P->Ray[i]+1, options);
33 break;
34 } catch (OrthogonalException &e) {
35 reset();
40 /* input:
41 * f: the powers in the denominator for the remaining vars
42 * each row refers to a factor
43 * den_s: for each factor, the power of (s+1)
44 * sign
45 * num_s: powers in the numerator corresponding to the summed vars
46 * num_p: powers in the numerator corresponding to the remaining vars
47 * number of rays in cone: "dim" = "k"
48 * length of each ray: "dim" = "d"
49 * for now, it is assumed: k == d
50 * output:
51 * den_p: for each factor
52 * 0: independent of remaining vars
53 * 1: power corresponds to corresponding row in f
55 * all inputs are subject to change
57 void normalize(ZZ& sign, vec_ZZ& num_s, mat_ZZ& num_p, vec_ZZ& den_s, vec_ZZ& den_p,
58 mat_ZZ& f)
60 unsigned dim = f.NumRows();
61 unsigned nparam = num_p.NumCols();
62 unsigned nvar = dim - nparam;
64 int change = 0;
66 for (int j = 0; j < den_s.length(); ++j) {
67 if (den_s[j] == 0) {
68 den_p[j] = 1;
69 continue;
71 int k;
72 for (k = 0; k < nparam; ++k)
73 if (f[j][k] != 0)
74 break;
75 if (k < nparam) {
76 den_p[j] = 1;
77 if (den_s[j] > 0) {
78 f[j] = -f[j];
79 for (int i = 0; i < num_p.NumRows(); ++i)
80 num_p[i] += f[j];
82 } else
83 den_p[j] = 0;
84 if (den_s[j] > 0)
85 change ^= 1;
86 else {
87 den_s[j] = abs(den_s[j]);
88 for (int i = 0; i < num_p.NumRows(); ++i)
89 num_s[i] += den_s[j];
93 if (change)
94 sign = -sign;
97 void reducer::base(const vec_QQ& c, const mat_ZZ& num, const mat_ZZ& den_f)
99 for (int i = 0; i < num.NumRows(); ++i)
100 base(c[i], num[i], den_f);
103 struct dpoly_r_scanner {
104 const dpoly_r *rc;
105 const dpoly * const *num;
106 int n;
107 int dim;
108 dpoly_r_term_list::iterator *iter;
109 vector<int> powers;
110 vec_ZZ coeff;
112 dpoly_r_scanner(const dpoly * const *num, int n, const dpoly_r *rc, int dim)
113 : num(num), rc(rc), n(n), dim(dim), powers(dim, 0) {
114 coeff.SetLength(n);
115 iter = new dpoly_r_term_list::iterator[rc->len];
116 for (int i = 0; i < rc->len; ++i) {
117 int k;
118 for (k = 0; k < n; ++k)
119 if (value_notzero_p(num[k]->coeff->p[rc->len-1-i]))
120 break;
121 if (k < n)
122 iter[i] = rc->c[i].begin();
123 else
124 iter[i] = rc->c[i].end();
127 bool next() {
128 int pos[rc->len];
129 int len = 0;
131 for (int i = 0; i < rc->len; ++i) {
132 if (iter[i] == rc->c[i].end())
133 continue;
134 if (!len)
135 pos[len++] = i;
136 else {
137 if ((*iter[i])->powers < (*iter[pos[0]])->powers) {
138 pos[0] = i;
139 len = 1;
140 } else if ((*iter[i])->powers == (*iter[pos[0]])->powers)
141 pos[len++] = i;
145 if (!len)
146 return false;
148 powers = (*iter[pos[0]])->powers;
149 for (int k = 0; k < n; ++k) {
150 value2zz(num[k]->coeff->p[rc->len-1-pos[0]], tmp);
151 mul(coeff[k], (*iter[pos[0]])->coeff, tmp);
153 ++iter[pos[0]];
154 for (int i = 1; i < len; ++i) {
155 for (int k = 0; k < n; ++k) {
156 value2zz(num[k]->coeff->p[rc->len-1-pos[i]], tmp);
157 mul(tmp, (*iter[pos[i]])->coeff, tmp);
158 add(coeff[k], coeff[k], tmp);
160 ++iter[pos[i]];
163 return true;
165 ~dpoly_r_scanner() {
166 delete [] iter;
168 private:
169 ZZ tmp;
172 void reducer::reduce_canonical(const vec_QQ& c, const mat_ZZ& num,
173 const mat_ZZ& den_f)
175 vec_QQ c2 = c;
176 mat_ZZ num2 = num;
178 for (int i = 0; i < c2.length(); ++i) {
179 c2[i].canonicalize();
180 if (c2[i].n != 0)
181 continue;
183 if (i < c2.length()-1) {
184 num2[i] = num2[c2.length()-1];
185 c2[i] = c2[c2.length()-1];
187 num2.SetDims(num2.NumRows()-1, num2.NumCols());
188 c2.SetLength(c2.length()-1);
189 --i;
191 reduce(c2, num2, den_f);
194 void reducer::reduce(const vec_QQ& c, const mat_ZZ& num, const mat_ZZ& den_f)
196 assert(c.length() == num.NumRows());
197 unsigned len = den_f.NumRows(); // number of factors in den
198 vec_QQ c2 = c;
200 if (num.NumCols() == lower) {
201 base(c, num, den_f);
202 return;
204 assert(num.NumCols() > 1);
205 assert(num.NumRows() > 0);
207 vec_ZZ den_s;
208 mat_ZZ den_r;
209 vec_ZZ num_s;
210 mat_ZZ num_p;
212 split(num, num_s, num_p, den_f, den_s, den_r);
214 vec_ZZ den_p;
215 den_p.SetLength(len);
217 ZZ sign(INIT_VAL, 1);
218 normalize(sign, num_s, num_p, den_s, den_p, den_r);
219 c2 *= sign;
221 int only_param = 0; // k-r-s from text
222 int no_param = 0; // r from text
223 for (int k = 0; k < len; ++k) {
224 if (den_p[k] == 0)
225 ++no_param;
226 else if (den_s[k] == 0)
227 ++only_param;
229 if (no_param == 0) {
230 reduce(c2, num_p, den_r);
231 } else {
232 int k, l;
233 mat_ZZ pden;
234 pden.SetDims(only_param, den_r.NumCols());
236 for (k = 0, l = 0; k < len; ++k)
237 if (den_s[k] == 0)
238 pden[l++] = den_r[k];
240 for (k = 0; k < len; ++k)
241 if (den_p[k] == 0)
242 break;
244 dpoly *n[num_s.length()];
245 for (int i = 0; i < num_s.length(); ++i) {
246 zz2value(num_s[i], tz);
247 n[i] = new dpoly(no_param, tz);
248 /* Search for other numerator (j) with same num_p.
249 * If found, replace a[j]/b[j] * n[j] and a[i]/b[i] * n[i]
250 * by 1/(b[j]*b[i]/g) * (a[j]*b[i]/g * n[j] + a[i]*b[j]/g * n[i])
251 * where g = gcd(b[i], b[j].
253 for (int j = 0; j < i; ++j) {
254 if (num_p[i] != num_p[j])
255 continue;
256 ZZ g = GCD(c2[i].d, c2[j].d);
257 zz2value(c2[j].n * c2[i].d/g, tz);
258 *n[j] *= tz;
259 zz2value(c2[i].n * c2[j].d/g, tz);
260 *n[i] *= tz;
261 *n[j] += *n[i];
262 c2[j].n = 1;
263 c2[j].d *= c2[i].d/g;
264 delete n[i];
265 if (i < num_s.length()-1) {
266 num_s[i] = num_s[num_s.length()-1];
267 num_p[i] = num_p[num_s.length()-1];
268 c2[i] = c2[num_s.length()-1];
270 num_s.SetLength(num_s.length()-1);
271 c2.SetLength(c2.length()-1);
272 num_p.SetDims(num_p.NumRows()-1, num_p.NumCols());
273 --i;
274 break;
277 zz2value(den_s[k], tz);
278 dpoly D(no_param, tz, 1);
279 for ( ; ++k < len; )
280 if (den_p[k] == 0) {
281 zz2value(den_s[k], tz);
282 dpoly fact(no_param, tz, 1);
283 D *= fact;
286 if (no_param + only_param == len) {
287 vec_QQ q;
288 q.SetLength(num_s.length());
289 for (int i = 0; i < num_s.length(); ++i) {
290 mpq_set_si(tcount, 0, 1);
291 n[i]->div(D, tcount, 1);
293 value2zz(mpq_numref(tcount), q[i].n);
294 value2zz(mpq_denref(tcount), q[i].d);
295 q[i] *= c2[i];
297 for (int i = q.length()-1; i >= 0; --i) {
298 if (q[i].n == 0) {
299 q[i] = q[q.length()-1];
300 num_p[i] = num_p[q.length()-1];
301 q.SetLength(q.length()-1);
302 num_p.SetDims(num_p.NumRows()-1, num_p.NumCols());
306 if (q.length() != 0)
307 reduce(q, num_p, pden);
308 } else {
309 value_set_si(tz, 0);
310 dpoly one(no_param, tz);
311 dpoly_r *r = NULL;
313 for (k = 0; k < len; ++k) {
314 if (den_s[k] == 0 || den_p[k] == 0)
315 continue;
317 zz2value(den_s[k], tz);
318 dpoly pd(no_param-1, tz, 1);
320 int l;
321 for (l = 0; l < k; ++l)
322 if (den_r[l] == den_r[k])
323 break;
325 if (!r)
326 r = new dpoly_r(one, pd, l, len);
327 else {
328 dpoly_r *nr = new dpoly_r(r, pd, l, len);
329 delete r;
330 r = nr;
334 vec_QQ factor;
335 factor.SetLength(c2.length());
336 int common = pden.NumRows();
337 dpoly_r *rc = r->div(D);
338 for (int i = 0; i < num_s.length(); ++i) {
339 factor[i].d = c2[i].d;
340 factor[i].d *= rc->denom;
343 dpoly_r_scanner scanner(n, num_s.length(), rc, len);
344 int rows;
345 while (scanner.next()) {
346 int i;
347 for (i = 0; i < num_s.length(); ++i)
348 if (scanner.coeff[i] != 0)
349 break;
350 if (i == num_s.length())
351 continue;
352 rows = common;
353 pden.SetDims(rows, pden.NumCols());
354 for (int k = 0; k < rc->dim; ++k) {
355 int n = scanner.powers[k];
356 if (n == 0)
357 continue;
358 pden.SetDims(rows+n, pden.NumCols());
359 for (int l = 0; l < n; ++l)
360 pden[rows+l] = den_r[k];
361 rows += n;
363 /* The denominators in factor are kept constant
364 * over all iterations of the enclosing while loop.
365 * The rational numbers in factor may therefore not be
366 * canonicalized. Some may even be zero.
368 for (int i = 0; i < num_s.length(); ++i) {
369 factor[i].n = c2[i].n;
370 factor[i].n *= scanner.coeff[i];
372 reduce_canonical(factor, num_p, pden);
375 delete rc;
376 delete r;
378 for (int i = 0; i < num_s.length(); ++i)
379 delete n[i];
383 void reducer::handle(const mat_ZZ& den, Value *V, const QQ& c,
384 unsigned long det, barvinok_options *options)
386 vec_QQ vc;
388 Matrix *points = Matrix_Alloc(det, dim);
389 Matrix* Rays = zz2matrix(den);
390 lattice_points_fixed(V, V, Rays, Rays, points, det);
391 Matrix_Free(Rays);
392 matrix2zz(points, vertex, points->NbRows, points->NbColumns);
393 Matrix_Free(points);
395 vc.SetLength(vertex.NumRows());
396 for (int i = 0; i < vc.length(); ++i)
397 vc[i] = c;
399 reduce(vc, vertex, den);
402 void split_one(const mat_ZZ& num, vec_ZZ& num_s, mat_ZZ& num_p,
403 const mat_ZZ& den_f, vec_ZZ& den_s, mat_ZZ& den_r)
405 unsigned len = den_f.NumRows(); // number of factors in den
406 unsigned d = num.NumCols() - 1;
408 den_s.SetLength(len);
409 den_r.SetDims(len, d);
411 for (int r = 0; r < len; ++r) {
412 den_s[r] = den_f[r][0];
413 for (int k = 1; k <= d; ++k)
414 den_r[r][k-1] = den_f[r][k];
417 num_s.SetLength(num.NumRows());
418 num_p.SetDims(num.NumRows(), d);
419 for (int i = 0; i < num.NumRows(); ++i) {
420 num_s[i] = num[i][0];
421 for (int k = 1 ; k <= d; ++k)
422 num_p[i][k-1] = num[i][k];
426 void normalize(ZZ& sign, ZZ& num, vec_ZZ& den)
428 unsigned dim = den.length();
430 int change = 0;
432 for (int j = 0; j < den.length(); ++j) {
433 if (den[j] > 0)
434 change ^= 1;
435 else {
436 den[j] = abs(den[j]);
437 num += den[j];
440 if (change)
441 sign = -sign;
444 void icounter::base(const QQ& c, const vec_ZZ& num, const mat_ZZ& den_f)
446 int r;
447 unsigned len = den_f.NumRows(); // number of factors in den
448 vec_ZZ den_s;
449 den_s.SetLength(len);
450 assert(num.length() == 1);
451 ZZ num_s = num[0];
452 for (r = 0; r < len; ++r)
453 den_s[r] = den_f[r][0];
454 ZZ sign = ZZ(INIT_VAL, 1);
455 normalize(sign, num_s, den_s);
457 zz2value(num_s, tz);
458 dpoly n(len, tz);
459 zz2value(den_s[0], tz);
460 dpoly D(len, tz, 1);
461 for (int k = 1; k < len; ++k) {
462 zz2value(den_s[k], tz);
463 dpoly fact(len, tz, 1);
464 D *= fact;
466 mpq_set_si(tcount, 0, 1);
467 n.div(D, tcount, 1);
468 zz2value(c.n, tn);
469 if (sign == -1)
470 value_oppose(tn, tn);
471 zz2value(c.d, td);
472 mpz_mul(mpq_numref(tcount), mpq_numref(tcount), tn);
473 mpz_mul(mpq_denref(tcount), mpq_denref(tcount), td);
474 mpq_canonicalize(tcount);
475 mpq_add(count, count, tcount);
478 void infinite_icounter::base(const QQ& c, const vec_ZZ& num, const mat_ZZ& den_f)
480 int r;
481 unsigned len = den_f.NumRows(); // number of factors in den
482 vec_ZZ den_s;
483 den_s.SetLength(len);
484 assert(num.length() == 1);
485 ZZ num_s = num[0];
487 for (r = 0; r < len; ++r)
488 den_s[r] = den_f[r][0];
489 ZZ sign = ZZ(INIT_VAL, 1);
490 normalize(sign, num_s, den_s);
492 zz2value(num_s, tz);
493 dpoly n(len, tz);
494 zz2value(den_s[0], tz);
495 dpoly D(len, tz, 1);
496 for (int k = 1; k < len; ++k) {
497 zz2value(den_s[k], tz);
498 dpoly fact(len, tz, 1);
499 D *= fact;
502 Value tmp;
503 mpq_t factor;
504 mpq_init(factor);
505 value_init(tmp);
506 zz2value(c.n, tmp);
507 if (sign == -1)
508 value_oppose(tmp, tmp);
509 value_assign(mpq_numref(factor), tmp);
510 zz2value(c.d, tmp);
511 value_assign(mpq_denref(factor), tmp);
513 n.div(D, count, factor);
515 value_clear(tmp);
516 mpq_clear(factor);