3 #include <barvinok/barvinok.h>
4 #include <barvinok/set.h>
5 #include <barvinok/options.h>
6 #include <barvinok/evalue.h>
7 #include <barvinok/util.h>
8 #include "conversion.h"
9 #include "evalue_read.h"
11 #include "lattice_point.h"
13 #include "bernoulli.h"
17 #include "matrix_read.h"
24 void set_from_string(T
& v
, const char *s
)
26 std::istringstream
str(s
);
30 int test_evalue(struct barvinok_options
*options
)
32 unsigned nvar
, nparam
;
36 poly1
= evalue_read_from_str("(1/4 * n^4 + 1/2 * n^3 + 1/4 * n^2)",
37 NULL
, &all_vars
, &nvar
, &nparam
,
39 Free_ParamNames(all_vars
, nvar
+nparam
);
42 evalue_copy(&poly2
, poly1
);
46 assert(EVALUE_IS_ZERO(*poly1
));
48 free_evalue_refs(&poly2
);
51 int test_split_periods(struct barvinok_options
*options
)
53 unsigned nvar
, nparam
;
57 e
= evalue_read_from_str("U + 2V + 3 >= 0\n- U -2V >= 0\n- U 10 >= 0\n"
58 "U >= 0\n\n({( 1/3 * U + ( 2/3 * V + 0 ))})",
59 NULL
, &all_vars
, &nvar
, &nparam
,
61 Free_ParamNames(all_vars
, nvar
+nparam
);
63 evalue_split_periods(e
, 2, options
->MaxRays
);
64 assert(value_zero_p(e
->d
));
65 assert(e
->x
.p
->type
== partition
);
66 assert(e
->x
.p
->size
== 4);
67 assert(value_zero_p(e
->x
.p
->arr
[1].d
));
68 assert(e
->x
.p
->arr
[1].x
.p
->type
== polynomial
);
69 assert(value_zero_p(e
->x
.p
->arr
[3].d
));
70 assert(e
->x
.p
->arr
[3].x
.p
->type
== polynomial
);
74 int test_specialization(struct barvinok_options
*options
)
83 assert(value_cmp_si(n
.coeff
->p
[0], 1) == 0);
84 assert(value_cmp_si(n
.coeff
->p
[1], 5) == 0);
85 assert(value_cmp_si(n
.coeff
->p
[2], 10) == 0);
92 assert(value_cmp_si(d
.coeff
->p
[0], 2) == 0);
93 assert(value_cmp_si(d
.coeff
->p
[1], 1) == 0);
94 assert(value_cmp_si(d
.coeff
->p
[2], 0) == 0);
97 mpq_canonicalize(count
);
98 assert(value_cmp_si(mpq_numref(count
), 31) == 0);
99 assert(value_cmp_si(mpq_denref(count
), 8) == 0);
103 assert(value_cmp_si(n2
.coeff
->p
[0], 1) == 0);
104 assert(value_cmp_si(n2
.coeff
->p
[1], -2) == 0);
105 assert(value_cmp_si(n2
.coeff
->p
[2], 3) == 0);
108 mpq_canonicalize(count
);
109 assert(value_cmp_si(mpq_numref(count
), 6) == 0);
110 assert(value_cmp_si(mpq_denref(count
), 1) == 0);
116 int test_lattice_points(struct barvinok_options
*options
)
120 set_from_string(tmp
, "[[0 0 0 0 4][0 0 0 0 4][-1 0 1 0 4]]");
121 V
.Vertex
= zz2matrix(tmp
);
123 set_from_string(lambda
, "[3 5 7]");
125 set_from_string(rays
, "[[0 1 0][4 0 1][0 0 -1]]");
129 unsigned nvar
, nparam
;
131 point
[0] = evalue_read_from_str("( -7/4 * a + ( 7/4 * c + "
132 "( 7 * {( 1/4 * a + ( 3/4 * c + 3/4 ) ) } + -21/4 ) ) )",
133 "a,b,c", &all_vars
, &nvar
, &nparam
, options
->MaxRays
);
134 Free_ParamNames(all_vars
, nvar
+nparam
);
135 point
[1] = evalue_read_from_str("( -7/4 * a + ( 7/4 * c + "
136 "( 7 * {( 1/4 * a + ( 3/4 * c + 1/2 ) ) } + -1/2 ) ) )",
137 "a,b,c", &all_vars
, &nvar
, &nparam
, options
->MaxRays
);
138 Free_ParamNames(all_vars
, nvar
+nparam
);
139 point
[2] = evalue_read_from_str("( -7/4 * a + ( 7/4 * c + "
140 "( 7 * {( 1/4 * a + ( 3/4 * c + 1/4 ) ) } + 17/4 ) ) )",
141 "a,b,c", &all_vars
, &nvar
, &nparam
, options
->MaxRays
);
142 Free_ParamNames(all_vars
, nvar
+nparam
);
143 point
[3] = evalue_read_from_str("( -7/4 * a + ( 7/4 * c + "
144 "( 7 * {( 1/4 * a + ( 3/4 * c + 0 ) ) } + 9 ) ) )",
145 "a,b,c", &all_vars
, &nvar
, &nparam
, options
->MaxRays
);
146 Free_ParamNames(all_vars
, nvar
+nparam
);
148 lattice_point(&V
, rays
, lambda
, &num
, 4, options
);
149 Matrix_Free(V
.Vertex
);
151 for (int i
= 0; i
< 4; ++i
) {
152 assert(eequal(num
.E
[i
], point
[i
]));
153 evalue_free(point
[i
]);
154 free_evalue_refs(num
.E
[i
]);
160 static int test_icounter(struct barvinok_options
*options
)
166 set_from_string(n_coeff
, "[-2/1 1/1]");
167 set_from_string(n_power
, "[[2 6][3 6]]");
168 d_power
.SetDims(0, 2);
169 cnt
.reduce(n_coeff
, n_power
, d_power
);
170 assert(value_cmp_si(mpq_numref(cnt
.count
), -1) == 0);
171 assert(value_cmp_si(mpq_denref(cnt
.count
), 1) == 0);
174 static Matrix
*matrix_read_from_str(const char *s
)
176 std::istringstream
str(s
);
177 return Matrix_Read(str
);
180 static int test_infinite_counter(struct barvinok_options
*options
)
182 Matrix
*M
= matrix_read_from_str("1 3\n 1 1 0\n");
183 Polyhedron
*ctx
= Constraints2Polyhedron(M
, options
->MaxRays
);
186 /* (1 -1/2 x^5 - 1/2 x^7)/(1-x) */
187 infinite_counter
*cnt
= new infinite_counter(1, 1);
192 set_from_string(n_coeff
, "[1/1 -1/2 -1/2]");
193 set_from_string(n_power
, "[[0][5][7]]");
194 set_from_string(d_power
, "[[1]]");
195 cnt
->reduce(n_coeff
, n_power
, d_power
);
196 assert(value_cmp_si(mpq_numref(cnt
->count
[0]), 6) == 0);
197 assert(value_cmp_si(mpq_denref(cnt
->count
[0]), 1) == 0);
198 assert(value_cmp_si(mpq_numref(cnt
->count
[1]), 0) == 0);
199 assert(value_cmp_si(mpq_denref(cnt
->count
[1]), 1) == 0);
201 Polyhedron_Free(ctx
);
203 M
= matrix_read_from_str("2 4\n 1 1 0 0\n 1 0 1 0\n");
204 ctx
= Constraints2Polyhedron(M
, options
->MaxRays
);
207 /* (1 - xy)/((1-x)(1-xy)) */
208 cnt
= new infinite_counter(2, 3);
210 set_from_string(n_coeff
, "[1/1 -1/1]");
211 set_from_string(n_power
, "[[0 0][1 1]]");
212 set_from_string(d_power
, "[[1 0][1 1]]");
213 cnt
->reduce(n_coeff
, n_power
, d_power
);
214 assert(value_cmp_si(mpq_numref(cnt
->count
[1]), 0) != 0);
215 assert(value_cmp_si(mpq_numref(cnt
->count
[2]), 0) == 0);
216 assert(value_cmp_si(mpq_denref(cnt
->count
[2]), 1) == 0);
217 assert(value_cmp_si(mpq_numref(cnt
->count
[3]), 0) == 0);
218 assert(value_cmp_si(mpq_denref(cnt
->count
[3]), 1) == 0);
221 cnt
= new infinite_counter(2, 2);
223 set_from_string(n_coeff
, "[-1/2 1/1 -1/3]");
224 set_from_string(n_power
, "[[2 6][3 6]]");
225 d_power
.SetDims(0, 2);
226 cnt
->reduce(n_coeff
, n_power
, d_power
);
227 assert(value_cmp_si(mpq_numref(cnt
->count
[0]), 1) == 0);
228 assert(value_cmp_si(mpq_denref(cnt
->count
[0]), 6) == 0);
229 assert(value_cmp_si(mpq_numref(cnt
->count
[1]), 0) == 0);
230 assert(value_cmp_si(mpq_denref(cnt
->count
[1]), 1) == 0);
231 assert(value_cmp_si(mpq_numref(cnt
->count
[2]), 0) == 0);
232 assert(value_cmp_si(mpq_denref(cnt
->count
[2]), 1) == 0);
235 cnt
= new infinite_counter(2, 2);
237 set_from_string(n_coeff
, "[1/1]");
238 set_from_string(n_power
, "[[0 11]]");
239 set_from_string(d_power
, "[[0 1]]");
240 cnt
->reduce(n_coeff
, n_power
, d_power
);
241 assert(value_cmp_si(mpq_numref(cnt
->count
[1]), 0) != 0);
242 assert(value_cmp_si(mpq_numref(cnt
->count
[2]), 0) == 0);
243 assert(value_cmp_si(mpq_denref(cnt
->count
[2]), 1) == 0);
246 Polyhedron_Free(ctx
);
251 static int test_series(struct barvinok_options
*options
)
253 Matrix
*M
= matrix_read_from_str(
255 " 0 1 0 0 0 0 0 1 0 0 3 \n"
256 " 0 0 1 0 0 0 0 -1 1 0 -5 \n"
257 " 0 0 0 1 0 0 0 0 -2 -1 6 \n"
258 " 0 0 0 0 1 0 0 1 1 0 5 \n"
259 " 0 0 0 0 0 1 0 0 -1 0 0 \n"
260 " 0 0 0 0 0 0 1 -2 0 -1 -3 \n"
261 " 1 0 0 0 0 0 0 2 0 1 3 \n"
262 " 1 0 0 0 0 0 0 1 -1 0 5 \n"
263 " 1 0 0 0 0 0 0 -1 -1 0 -5 \n"
264 " 1 0 0 0 0 0 0 -1 0 0 -3 \n"
265 " 1 0 0 0 0 0 0 0 2 1 -6 \n"
266 " 1 0 0 0 0 0 0 0 1 0 0 \n");
267 Polyhedron
*P
= Constraints2Polyhedron(M
, options
->MaxRays
);
269 Polyhedron
*C
= Universe_Polyhedron(3);
270 gen_fun
*gf
= barvinok_series_with_options(P
, C
, options
);
275 M
= matrix_read_from_str(
277 " 0 1 1 0 0 1 0 2 \n"
278 " 0 0 0 1 0 -2 0 6 \n"
279 " 0 0 0 0 1 -1 0 -1 \n"
280 " 0 0 0 0 0 0 1 0 \n"
281 " 1 0 1 0 0 0 0 0 \n"
282 " 1 0 -1 0 0 -1 0 -2 \n"
283 " 1 0 0 0 0 1 0 -3 \n");
284 P
= Constraints2Polyhedron(M
, options
->MaxRays
);
286 C
= Universe_Polyhedron(2);
287 gf
= barvinok_series_with_options(P
, C
, options
);
292 M
= matrix_read_from_str(
296 P
= Constraints2Polyhedron(M
, options
->MaxRays
);
298 C
= Universe_Polyhedron(1);
299 gf
= barvinok_series_with_options(P
, C
, options
);
302 gen_fun
*sum
= gf
->summate(1, options
);
309 int test_todd(struct barvinok_options
*options
)
311 tcounter
t(2, options
->max_index
);
312 assert(value_cmp_si(t
.todd
.coeff
->p
[0], 1) == 0);
313 assert(value_cmp_si(t
.todd
.coeff
->p
[1], -3) == 0);
314 assert(value_cmp_si(t
.todd
.coeff
->p
[2], 3) == 0);
315 assert(value_cmp_si(t
.todd_denom
->p
[0], 1) == 0);
316 assert(value_cmp_si(t
.todd_denom
->p
[1], 6) == 0);
317 assert(value_cmp_si(t
.todd_denom
->p
[2], 36) == 0);
320 set_from_string(lambda
, "[1 -1]");
321 zz2values(lambda
, t
.lambda
->p
);
324 set_from_string(rays
, "[[-1 0][-1 1]]");
329 set_from_string(v
, "[2 0 1]");
330 Vector
*vertex
= Vector_Alloc(3);
331 zz2values(v
, vertex
->p
);
333 t
.handle(rays
, vertex
->p
, one
, 1, options
);
334 assert(value_cmp_si(mpq_numref(t
.count
), 71) == 0);
335 assert(value_cmp_si(mpq_denref(t
.count
), 24) == 0);
337 set_from_string(rays
, "[[0 -1][1 -1]]");
338 set_from_string(v
, "[0 2 1]");
339 zz2values(v
, vertex
->p
);
341 t
.handle(rays
, vertex
->p
, one
, 1, options
);
342 assert(value_cmp_si(mpq_numref(t
.count
), 71) == 0);
343 assert(value_cmp_si(mpq_denref(t
.count
), 12) == 0);
345 set_from_string(rays
, "[[1 0][0 1]]");
346 set_from_string(v
, "[0 0 1]");
347 zz2values(v
, vertex
->p
);
349 t
.handle(rays
, vertex
->p
, one
, 1, options
);
350 assert(value_cmp_si(mpq_numref(t
.count
), 6) == 0);
351 assert(value_cmp_si(mpq_denref(t
.count
), 1) == 0);
356 int test_bernoulli(struct barvinok_options
*options
)
358 struct bernoulli_coef
*bernoulli_coef
;
359 struct poly_list
*faulhaber
, *bernoulli
;
360 bernoulli_coef
= bernoulli_coef_compute(2);
361 faulhaber
= faulhaber_compute(4);
362 bernoulli_coef
= bernoulli_coef_compute(8);
363 assert(value_cmp_si(bernoulli_coef
->num
->p
[6], 1) == 0);
364 assert(value_cmp_si(bernoulli_coef
->den
->p
[6], 42) == 0);
365 assert(value_cmp_si(faulhaber
->poly
[3]->p
[0], 0) == 0);
366 assert(value_cmp_si(faulhaber
->poly
[3]->p
[1], 0) == 0);
367 assert(value_cmp_si(faulhaber
->poly
[3]->p
[2], 1) == 0);
368 assert(value_cmp_si(faulhaber
->poly
[3]->p
[3], -2) == 0);
369 assert(value_cmp_si(faulhaber
->poly
[3]->p
[4], 1) == 0);
370 assert(value_cmp_si(faulhaber
->poly
[3]->p
[5], 4) == 0);
372 bernoulli
= bernoulli_compute(6);
373 assert(value_cmp_si(bernoulli
->poly
[6]->p
[0], 1) == 0);
374 assert(value_cmp_si(bernoulli
->poly
[6]->p
[1], 0) == 0);
375 assert(value_cmp_si(bernoulli
->poly
[6]->p
[2], -21) == 0);
376 assert(value_cmp_si(bernoulli
->poly
[6]->p
[3], 0) == 0);
377 assert(value_cmp_si(bernoulli
->poly
[6]->p
[4], 105) == 0);
378 assert(value_cmp_si(bernoulli
->poly
[6]->p
[5], -126) == 0);
379 assert(value_cmp_si(bernoulli
->poly
[6]->p
[6], 42) == 0);
380 assert(value_cmp_si(bernoulli
->poly
[6]->p
[7], 42) == 0);
382 unsigned nvar
, nparam
;
384 evalue
*base
, *sum1
, *sum2
;
385 base
= evalue_read_from_str("(1 * n + 1)", NULL
, &all_vars
, &nvar
, &nparam
,
388 sum1
= evalue_polynomial(faulhaber
->poly
[3], base
);
389 Free_ParamNames(all_vars
, nvar
+nparam
);
391 sum2
= evalue_read_from_str("(1/4 * n^4 + 1/2 * n^3 + 1/4 * n^2)",
392 NULL
, &all_vars
, &nvar
, &nparam
,
394 Free_ParamNames(all_vars
, nvar
+nparam
);
395 assert(eequal(sum1
, sum2
));
401 int test_bernoulli_sum(struct barvinok_options
*options
)
403 unsigned nvar
, nparam
;
405 evalue
*e
, *sum1
, *sum2
;
406 e
= evalue_read_from_str("i + -1 >= 0\n -i + n >= 0\n\n 1 + (-1 *i) + i^2",
407 "i", &all_vars
, &nvar
, &nparam
,
409 Free_ParamNames(all_vars
, nvar
+nparam
);
411 sum1
= Bernoulli_sum_evalue(e
, 1, options
);
412 sum2
= evalue_read_from_str("n -1 >= 0\n\n (1/3 * n^3 + 2/3 * n)",
413 NULL
, &all_vars
, &nvar
, &nparam
,
415 Free_ParamNames(all_vars
, nvar
+nparam
);
419 assert(EVALUE_IS_ZERO(*sum1
));
423 e
= evalue_read_from_str("-i + -1 >= 0\n i + n >= 0\n\n 1 + i + i^2",
424 "i", &all_vars
, &nvar
, &nparam
,
426 Free_ParamNames(all_vars
, nvar
+nparam
);
427 sum1
= Bernoulli_sum_evalue(e
, 1, options
);
431 assert(EVALUE_IS_ZERO(*sum1
));
437 e
= evalue_read_from_str("i + 4 >= 0\n -i + n >= 0\n\n i",
438 "i", &all_vars
, &nvar
, &nparam
,
440 Free_ParamNames(all_vars
, nvar
+nparam
);
441 sum1
= Bernoulli_sum_evalue(e
, 1, options
);
442 sum2
= evalue_read_from_str("n + 0 >= 0\n\n (1/2 * n^2 + 1/2 * n + (-10))\n"
443 "n + 4 >= 0\n -n -1 >= 0\n\n (1/2 * n^2 + 1/2 * n + (-10))",
444 NULL
, &all_vars
, &nvar
, &nparam
,
446 Free_ParamNames(all_vars
, nvar
+nparam
);
450 assert(EVALUE_IS_ZERO(*sum1
));
455 e
= evalue_read_from_str("i -5 >= 0\n -i + n >= 0\n j -1 >= 0\n i -j >= 0\n"
456 "k -1 >= 0\n j -k >= 0\n\n1",
457 "i,j,k", &all_vars
, &nvar
, &nparam
,
459 Free_ParamNames(all_vars
, nvar
+nparam
);
460 sum1
= Bernoulli_sum_evalue(e
, 3, options
);
461 sum2
= evalue_read_from_str("n -5 >= 0\n\n"
462 "1/6 * n^3 + 1/2 * n^2 + 1/3 * n + -20",
463 NULL
, &all_vars
, &nvar
, &nparam
,
465 Free_ParamNames(all_vars
, nvar
+nparam
);
469 assert(EVALUE_IS_ZERO(*sum1
));
475 int test_hilbert(struct barvinok_options
*options
)
477 Matrix
*M
= matrix_read_from_str(
481 Polyhedron
*P
= Constraints2Polyhedron(M
, options
->MaxRays
);
484 M
= Cone_Hilbert_Basis(P
, options
->MaxRays
);
485 assert(M
->NbRows
= 5);
486 assert(M
->NbColumns
= 3);
489 M
= Cone_Integer_Hull(P
, NULL
, 0, options
);
490 assert(M
->NbRows
= 4);
491 assert(M
->NbColumns
= 3);
497 int test_ilp(struct barvinok_options
*options
)
499 Matrix
*M
= matrix_read_from_str(
503 Polyhedron
*P
= Constraints2Polyhedron(M
, options
->MaxRays
);
505 Vector
*obj
= Vector_Alloc(2);
506 value_set_si(obj
->p
[0], 7);
507 value_set_si(obj
->p
[1], -1);
512 value_set_si(min
, 1);
513 value_set_si(max
, 17);
514 Vector
*opt
= Polyhedron_Integer_Minimum(P
, obj
->p
, min
, max
,
517 assert(value_cmp_si(opt
->p
[0], 1) == 0);
518 assert(value_cmp_si(opt
->p
[1], 1) == 0);
519 assert(value_cmp_si(opt
->p
[2], 1) == 0);
528 int test_hull(struct barvinok_options
*options
)
530 Matrix
*M
= matrix_read_from_str(
536 Polyhedron
*P
= Constraints2Polyhedron(M
, options
->MaxRays
);
539 Matrix
*hull
= Polyhedron_Integer_Hull(P
, options
);
541 assert(hull
->NbRows
== 4);
542 M
= Matrix_Alloc(hull
->NbRows
, 1+hull
->NbColumns
);
543 for (int i
= 0; i
< hull
->NbRows
; ++i
) {
544 value_set_si(M
->p
[i
][0], 1);
545 Vector_Copy(hull
->p
[i
], M
->p
[i
]+1, hull
->NbColumns
);
548 Polyhedron
*H
= Constraints2Polyhedron(M
, options
->MaxRays
);
551 M
= matrix_read_from_str(
557 P
= Constraints2Polyhedron(M
, options
->MaxRays
);
559 assert(PolyhedronIncludes(P
, H
) && PolyhedronIncludes(H
, P
));
563 M
= matrix_read_from_str(
568 P
= Constraints2Polyhedron(M
, options
->MaxRays
);
571 hull
= Polyhedron_Integer_Hull(P
, options
);
573 assert(hull
->NbRows
== 0);
577 int main(int argc
, char **argv
)
579 struct barvinok_options
*options
= barvinok_options_new_with_defaults();
580 test_evalue(options
);
581 test_split_periods(options
);
582 test_specialization(options
);
583 test_lattice_points(options
);
584 test_icounter(options
);
585 test_infinite_counter(options
);
586 test_series(options
);
588 test_bernoulli(options
);
589 test_bernoulli_sum(options
);
590 test_hilbert(options
);
593 barvinok_options_free(options
);