barvinok.cc: ienumerator::ienumerator: drop redundant argument
[barvinok.git] / series.cc
blob692be04ed305dd65a5037e9886a722031d4f0f0e
1 #include <assert.h>
2 #include <barvinok/barvinok.h>
3 #include <barvinok/util.h>
4 #include "genfun_constructor.h"
5 #include "lattice_width.h"
6 #include "remove_equalities.h"
8 using std::cerr;
9 using std::endl;
11 static gen_fun *enumerate_series(Polyhedron *P, unsigned nparam,
12 barvinok_options *options)
14 Matrix *CP = NULL;
15 gen_fun *gf;
16 Polyhedron *P_orig = P;
18 if (emptyQ2(P))
19 return new gen_fun(Empty_Polyhedron(nparam));
21 if (P->NbEq != 0)
22 remove_all_equalities(&P, NULL, &CP, NULL, nparam, options->MaxRays);
23 assert(emptyQ2(P) || P->NbEq == 0);
24 if (CP)
25 nparam = CP->NbColumns-1;
27 if (nparam == 0) {
28 Value c;
29 value_init(c);
30 barvinok_count_with_options(P, &c, options);
31 gf = new gen_fun(c);
32 value_clear(c);
33 } else {
34 POL_ENSURE_VERTICES(P);
35 if (P->NbEq)
36 gf = enumerate_series(P, nparam, options);
37 else {
38 gf_base *red;
39 red = gf_base::create(Polyhedron_Project(P, nparam),
40 P->Dimension, nparam, options);
41 red->start_gf(P, options);
42 gf = red->gf;
43 delete red;
46 if (CP) {
47 gf->substitute(CP);
48 Matrix_Free(CP);
50 if (P != P_orig)
51 Polyhedron_Free(P);
52 return gf;
55 gen_fun *barvinok_enumerate_series(Polyhedron *P, unsigned nparam,
56 barvinok_options *options)
58 if (emptyQ2(P))
59 return new gen_fun(Empty_Polyhedron(nparam));
61 assert(!Polyhedron_is_unbounded(P, nparam, options->MaxRays));
62 assert(P->NbBid == 0);
63 assert(Polyhedron_has_revlex_positive_rays(P, nparam));
64 return enumerate_series(P, nparam, options);
67 gen_fun * barvinok_series_with_options(Polyhedron *P, Polyhedron* C,
68 barvinok_options *options)
70 Polyhedron *CA;
71 unsigned nparam = C->Dimension;
72 gen_fun *gf;
74 CA = align_context(C, P->Dimension, options->MaxRays);
75 P = DomainIntersection(P, CA, options->MaxRays);
76 Polyhedron_Free(CA);
78 gf = barvinok_enumerate_series(P, nparam, options);
79 Polyhedron_Free(P);
81 return gf;
84 gen_fun * barvinok_series(Polyhedron *P, Polyhedron* C, unsigned MaxRays)
86 gen_fun *gf;
87 barvinok_options *options = barvinok_options_new_with_defaults();
88 options->MaxRays = MaxRays;
89 gf = barvinok_series_with_options(P, C, options);
90 barvinok_options_free(options);
91 return gf;
94 gen_fun* barvinok_enumerate_union_series_with_options(Polyhedron *D, Polyhedron* C,
95 barvinok_options *options)
97 Polyhedron *CA;
98 gen_fun *gf = NULL, *gf2;
99 unsigned nparam = C->Dimension;
101 CA = align_context(C, D->Dimension, options->MaxRays);
102 D = DomainIntersection(D, CA, options->MaxRays);
103 Polyhedron_Free(CA);
105 for (Polyhedron *P = D; P; P = P->next) {
106 assert(P->Dimension == D->Dimension);
107 gen_fun *P_gf;
109 P_gf = barvinok_enumerate_series(P, P->Dimension, options);
110 if (!gf)
111 gf = P_gf;
112 else {
113 gf->add_union(P_gf, options);
114 delete P_gf;
117 /* we actually only need the convex union of the parameter space
118 * but the reducer classes currently expect a polyhedron in
119 * the combined space
121 Polyhedron_Free(gf->context);
122 gf->context = DomainConvex(D, options->MaxRays);
124 gf2 = gf->summate(D->Dimension - nparam, options);
126 delete gf;
127 Domain_Free(D);
128 return gf2;
131 gen_fun* barvinok_enumerate_union_series(Polyhedron *D, Polyhedron* C,
132 unsigned MaxRays)
134 gen_fun *gf;
135 barvinok_options *options = barvinok_options_new_with_defaults();
136 options->MaxRays = MaxRays;
137 gf = barvinok_enumerate_union_series_with_options(D, C, options);
138 barvinok_options_free(options);
139 return gf;
142 /* Unimodularly transform the polyhedron P, such that
143 * the direction specified by dir corresponds to the last
144 * variable in the transformed polyhedron.
145 * The number of variables is given by the length of dir.
147 static Polyhedron *put_direction_last(Polyhedron *P, Vector *dir,
148 unsigned MaxRays)
150 Polyhedron *R;
151 Matrix *T;
152 int n = dir->Size;
154 T = Matrix_Alloc(P->Dimension+1, P->Dimension+1);
155 T->NbColumns = T->NbRows = n;
156 Vector_Copy(dir->p, T->p[0], n);
157 unimodular_complete(T, 1);
158 Vector_Exchange(T->p[0], T->p[n-1], n);
159 T->NbColumns = T->NbRows = P->Dimension+1;
160 for (int j = n; j < P->Dimension+1; ++j)
161 value_set_si(T->p[j][j], 1);
163 R = Polyhedron_Image(P, T, MaxRays);
164 Matrix_Free(T);
166 return R;
169 /* Do we need to continue shifting and subtracting?
170 * i is the number of times we shifted so far
171 * n is the number of coordinates projected out
173 static bool more_shifts_needed(int j, int n,
174 gen_fun *S, gen_fun *S_divide, const vec_ZZ& up,
175 barvinok_options *options)
177 bool empty;
178 gen_fun *hp;
180 /* For the 2-dimensional case, we need to subtract at most once */
181 if (n == 2 && j > 0)
182 return false;
184 S_divide->shift(up);
186 /* Assume that we have to subtract at least once */
187 if (j == 0)
188 return true;
190 hp = S->Hadamard_product(S_divide, options);
192 empty = hp->is_zero();
193 delete hp;
195 return !empty;
198 static gen_fun *project(Polyhedron *P, unsigned n, barvinok_options *options,
199 int free_P);
201 /* Return gf of P projected on last dim(P)-n coordinates, i.e.,
202 * project out the first n coordinates.
204 * Assumes P has no equalities.
206 static gen_fun *project_full_dim(Polyhedron *P, unsigned n,
207 barvinok_options *options)
209 QQ one(1, 1);
210 QQ mone(-1, 1);
211 vec_ZZ up;
212 gen_fun *gf = NULL;
213 struct width_direction_array *dirs;
214 Polyhedron *U;
216 if (n == 0)
217 return barvinok_enumerate_series(P, P->Dimension, options);
219 up.SetLength(P->Dimension - (n-1));
220 up[0] = 1;
221 for (int i = 1; i < P->Dimension - (n-1); ++i)
222 up[i] = 0;
224 if (n == 1) {
225 gen_fun *S, *S_shift, *hp;
227 S = barvinok_enumerate_series(P, P->Dimension, options);
228 S_shift = new gen_fun(S);
229 S_shift->shift(up);
230 hp = S->Hadamard_product(S_shift, options);
231 S->add(mone, hp, options);
232 delete S_shift;
233 delete hp;
235 gf = S->summate(1, options);
236 delete S;
238 return gf;
241 U = Universe_Polyhedron(P->Dimension - n);
242 dirs = Polyhedron_Lattice_Width_Directions(P, U, options);
243 Polyhedron_Free(U);
245 for (int i = 0; i < dirs->n; ++i) {
246 Polyhedron *Pi, *R;
247 Polyhedron *CA;
248 gen_fun *S, *S_shift, *S_divide, *sum;
250 CA = align_context(dirs->wd[i].domain, P->Dimension, options->MaxRays);
251 R = DomainIntersection(P, CA, options->MaxRays);
252 Polyhedron_Free(CA);
253 assert(dirs->wd[i].dir->Size == n);
254 Pi = put_direction_last(R, dirs->wd[i].dir, options->MaxRays);
255 Polyhedron_Free(R);
257 S = project(Pi, n-1, options, 1);
259 S_shift = new gen_fun(S);
260 S_divide = new gen_fun(S);
261 S_divide->divide(up);
263 for (int j = 0; more_shifts_needed(j, n, S, S_divide, up, options); ++j) {
264 gen_fun *hp;
266 S_shift->shift(up);
267 hp = S->Hadamard_product(S_shift, options);
268 S->add(mone, hp, options);
270 delete hp;
273 sum = S->summate(1, options);
275 delete S_shift;
276 delete S_divide;
277 delete S;
279 if (!gf)
280 gf = sum;
281 else {
282 gf->add(one, sum, options);
283 delete sum;
286 free_width_direction_array(dirs);
288 return gf;
291 /* Return gf of P projected on last dim(P)-n coordinates, i.e.,
292 * project out the first n coordinates.
294 static gen_fun *project(Polyhedron *P, unsigned n, barvinok_options *options,
295 int free_P)
297 Matrix *CP = NULL;
298 gen_fun *proj;
299 unsigned nparam = P->Dimension - n;
301 if (P->NbEq != 0) {
302 Polyhedron *Q = P;
303 remove_all_equalities(&P, NULL, &CP, NULL, nparam, options->MaxRays);
304 if (CP)
305 nparam = CP->NbColumns - 1;
306 n = P->Dimension - nparam;
307 if (free_P)
308 Polyhedron_Free(Q);
309 free_P = 1;
312 if (emptyQ(P))
313 proj = new gen_fun(Empty_Polyhedron(nparam));
314 else
315 proj = project_full_dim(P, n, options);
316 if (CP) {
317 proj->substitute(CP);
318 Matrix_Free(CP);
321 if (free_P)
322 Polyhedron_Free(P);
324 return proj;
327 gen_fun *barvinok_enumerate_e_series(Polyhedron *P,
328 unsigned exist, unsigned nparam, barvinok_options *options)
330 Polyhedron *P_orig = P;
331 gen_fun *gf, *proj;
332 unsigned nvar = P->Dimension - exist - nparam;
334 if (exist == 0)
335 return barvinok_enumerate_series(P, nparam, options);
337 if (emptyQ(P))
338 return new gen_fun(Empty_Polyhedron(nparam));
340 assert(!Polyhedron_is_unbounded(P, nparam, options->MaxRays));
341 assert(P->NbBid == 0);
342 assert(Polyhedron_has_revlex_positive_rays(P, nparam));
344 /* Move existentially quantified variables to the front.*/
345 if (nvar) {
346 Matrix *T;
347 T = Matrix_Alloc(exist+nvar+nparam+1, nvar+exist+nparam+1);
348 for (int i = 0; i < exist; ++i)
349 value_set_si(T->p[i][nvar+i], 1);
350 for (int i = 0; i < nvar; ++i)
351 value_set_si(T->p[exist+i][i], 1);
352 for (int i = 0; i < nparam+1; ++i)
353 value_set_si(T->p[exist+nvar+i][nvar+exist+i], 1);
354 P = Polyhedron_Image(P, T, options->MaxRays);
355 Matrix_Free(T);
357 proj = project(P, exist, options, P != P_orig);
359 if (!nvar)
360 gf = proj;
361 else {
362 gf = proj->summate(nvar, options);
363 delete proj;
365 return gf;