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"
25 void set_from_string(T
& v
, const char *s
)
27 std::istringstream
str(s
);
31 int test_evalue_read(struct barvinok_options
*options
)
33 unsigned nvar
, nparam
;
37 e1
= evalue_read_from_str("(1 * aa + 2 * a)",
38 NULL
, &all_vars
, &nvar
, &nparam
, options
->MaxRays
);
39 Free_ParamNames(all_vars
, nvar
+nparam
);
40 e2
= evalue_read_from_str("(3 * aa)",
41 NULL
, &all_vars
, &nvar
, &nparam
, options
->MaxRays
);
42 Free_ParamNames(all_vars
, nvar
+nparam
);
43 assert(!eequal(e1
, e2
));
48 int test_evalue(struct barvinok_options
*options
)
50 unsigned nvar
, nparam
;
54 poly1
= evalue_read_from_str("(1/4 * n^4 + 1/2 * n^3 + 1/4 * n^2)",
55 NULL
, &all_vars
, &nvar
, &nparam
,
57 Free_ParamNames(all_vars
, nvar
+nparam
);
60 evalue_copy(&poly2
, poly1
);
64 assert(EVALUE_IS_ZERO(*poly1
));
66 free_evalue_refs(&poly2
);
69 int test_substitute(struct barvinok_options
*options
)
71 unsigned nvar
, nparam
;
73 const char *vars
= "a,b";
77 e1
= evalue_read_from_str("[ { 1/3 * a } = 0 ] * \n"
78 " ([ { 1/5 * b + 2/5 } = 0 ] * 5) + \n"
79 "[ { 1/3 * a } != 0 ] * 42",
80 vars
, &all_vars
, &nvar
, &nparam
,
82 Free_ParamNames(all_vars
, nvar
+nparam
);
84 subs
[0] = evalue_read_from_str("(2 * b + 5)",
85 vars
, &all_vars
, &nvar
, &nparam
,
87 Free_ParamNames(all_vars
, nvar
+nparam
);
88 subs
[1] = evalue_read_from_str("(a + 1)",
89 vars
, &all_vars
, &nvar
, &nparam
,
91 Free_ParamNames(all_vars
, nvar
+nparam
);
93 evalue_substitute(e1
, subs
);
98 e2
= evalue_read_from_str("[ { 2/3 * b + 2/3 } = 0 ] * \n"
99 " ([ { 1/5 * a + 3/5 } = 0 ] * 5) + \n"
100 "[ { 2/3 * b + 2/3 } != 0 ] * 42",
101 vars
, &all_vars
, &nvar
, &nparam
,
103 Free_ParamNames(all_vars
, nvar
+nparam
);
106 assert(eequal(e1
, e2
));
112 int test_split_periods(struct barvinok_options
*options
)
114 unsigned nvar
, nparam
;
118 e
= evalue_read_from_str("U + 2V + 3 >= 0\n- U -2V >= 0\n- U 10 >= 0\n"
119 "U >= 0\n\n({( 1/3 * U + ( 2/3 * V + 0 ))})",
120 NULL
, &all_vars
, &nvar
, &nparam
,
122 Free_ParamNames(all_vars
, nvar
+nparam
);
124 evalue_split_periods(e
, 2, options
->MaxRays
);
125 assert(value_zero_p(e
->d
));
126 assert(e
->x
.p
->type
== partition
);
127 assert(e
->x
.p
->size
== 4);
128 assert(value_zero_p(e
->x
.p
->arr
[1].d
));
129 assert(e
->x
.p
->arr
[1].x
.p
->type
== polynomial
);
130 assert(value_zero_p(e
->x
.p
->arr
[3].d
));
131 assert(e
->x
.p
->arr
[3].x
.p
->type
== polynomial
);
135 int test_specialization(struct barvinok_options
*options
)
144 assert(value_cmp_si(n
.coeff
->p
[0], 1) == 0);
145 assert(value_cmp_si(n
.coeff
->p
[1], 5) == 0);
146 assert(value_cmp_si(n
.coeff
->p
[2], 10) == 0);
153 assert(value_cmp_si(d
.coeff
->p
[0], 2) == 0);
154 assert(value_cmp_si(d
.coeff
->p
[1], 1) == 0);
155 assert(value_cmp_si(d
.coeff
->p
[2], 0) == 0);
158 mpq_canonicalize(count
);
159 assert(value_cmp_si(mpq_numref(count
), 31) == 0);
160 assert(value_cmp_si(mpq_denref(count
), 8) == 0);
164 assert(value_cmp_si(n2
.coeff
->p
[0], 1) == 0);
165 assert(value_cmp_si(n2
.coeff
->p
[1], -2) == 0);
166 assert(value_cmp_si(n2
.coeff
->p
[2], 3) == 0);
169 mpq_canonicalize(count
);
170 assert(value_cmp_si(mpq_numref(count
), 6) == 0);
171 assert(value_cmp_si(mpq_denref(count
), 1) == 0);
177 int test_lattice_points(struct barvinok_options
*options
)
181 set_from_string(tmp
, "[[0 0 0 0 4][0 0 0 0 4][-1 0 1 0 4]]");
182 V
.Vertex
= zz2matrix(tmp
);
184 set_from_string(lambda
, "[3 5 7]");
186 set_from_string(rays
, "[[0 1 0][4 0 1][0 0 -1]]");
190 unsigned nvar
, nparam
;
192 point
[0] = evalue_read_from_str("( -7/4 * a + ( 7/4 * c + "
193 "( 7 * {( 1/4 * a + ( 3/4 * c + 3/4 ) ) } + -21/4 ) ) )",
194 "a,b,c", &all_vars
, &nvar
, &nparam
, options
->MaxRays
);
195 Free_ParamNames(all_vars
, nvar
+nparam
);
196 point
[1] = evalue_read_from_str("( -7/4 * a + ( 7/4 * c + "
197 "( 7 * {( 1/4 * a + ( 3/4 * c + 1/2 ) ) } + -1/2 ) ) )",
198 "a,b,c", &all_vars
, &nvar
, &nparam
, options
->MaxRays
);
199 Free_ParamNames(all_vars
, nvar
+nparam
);
200 point
[2] = evalue_read_from_str("( -7/4 * a + ( 7/4 * c + "
201 "( 7 * {( 1/4 * a + ( 3/4 * c + 1/4 ) ) } + 17/4 ) ) )",
202 "a,b,c", &all_vars
, &nvar
, &nparam
, options
->MaxRays
);
203 Free_ParamNames(all_vars
, nvar
+nparam
);
204 point
[3] = evalue_read_from_str("( -7/4 * a + ( 7/4 * c + "
205 "( 7 * {( 1/4 * a + ( 3/4 * c + 0 ) ) } + 9 ) ) )",
206 "a,b,c", &all_vars
, &nvar
, &nparam
, options
->MaxRays
);
207 Free_ParamNames(all_vars
, nvar
+nparam
);
209 lattice_point(&V
, rays
, lambda
, &num
, 4, options
);
210 Matrix_Free(V
.Vertex
);
212 for (int i
= 0; i
< 4; ++i
) {
213 assert(eequal(num
.E
[i
], point
[i
]));
214 evalue_free(point
[i
]);
215 free_evalue_refs(num
.E
[i
]);
221 static int test_icounter(struct barvinok_options
*options
)
227 set_from_string(n_coeff
, "[-2/1 1/1]");
228 set_from_string(n_power
, "[[2 6][3 6]]");
229 d_power
.SetDims(0, 2);
230 cnt
.reduce(n_coeff
, n_power
, d_power
);
231 assert(value_cmp_si(mpq_numref(cnt
.count
), -1) == 0);
232 assert(value_cmp_si(mpq_denref(cnt
.count
), 1) == 0);
235 static Matrix
*matrix_read_from_str(const char *s
)
237 std::istringstream
str(s
);
238 return Matrix_Read(str
);
241 static int test_infinite_counter(struct barvinok_options
*options
)
243 Matrix
*M
= matrix_read_from_str("1 3\n 1 1 0\n");
244 Polyhedron
*ctx
= Constraints2Polyhedron(M
, options
->MaxRays
);
247 /* (1 -1/2 x^5 - 1/2 x^7)/(1-x) */
248 infinite_counter
*cnt
= new infinite_counter(1, 1);
253 set_from_string(n_coeff
, "[1/1 -1/2 -1/2]");
254 set_from_string(n_power
, "[[0][5][7]]");
255 set_from_string(d_power
, "[[1]]");
256 cnt
->reduce(n_coeff
, n_power
, d_power
);
257 assert(value_cmp_si(mpq_numref(cnt
->count
[0]), 6) == 0);
258 assert(value_cmp_si(mpq_denref(cnt
->count
[0]), 1) == 0);
259 assert(value_cmp_si(mpq_numref(cnt
->count
[1]), 0) == 0);
260 assert(value_cmp_si(mpq_denref(cnt
->count
[1]), 1) == 0);
262 Polyhedron_Free(ctx
);
264 M
= matrix_read_from_str("2 4\n 1 1 0 0\n 1 0 1 0\n");
265 ctx
= Constraints2Polyhedron(M
, options
->MaxRays
);
268 /* (1 - xy)/((1-x)(1-xy)) */
269 cnt
= new infinite_counter(2, 3);
271 set_from_string(n_coeff
, "[1/1 -1/1]");
272 set_from_string(n_power
, "[[0 0][1 1]]");
273 set_from_string(d_power
, "[[1 0][1 1]]");
274 cnt
->reduce(n_coeff
, n_power
, d_power
);
275 assert(value_cmp_si(mpq_numref(cnt
->count
[1]), 0) != 0);
276 assert(value_cmp_si(mpq_numref(cnt
->count
[2]), 0) == 0);
277 assert(value_cmp_si(mpq_denref(cnt
->count
[2]), 1) == 0);
278 assert(value_cmp_si(mpq_numref(cnt
->count
[3]), 0) == 0);
279 assert(value_cmp_si(mpq_denref(cnt
->count
[3]), 1) == 0);
282 cnt
= new infinite_counter(2, 2);
284 set_from_string(n_coeff
, "[-1/2 1/1 -1/3]");
285 set_from_string(n_power
, "[[2 6][3 6]]");
286 d_power
.SetDims(0, 2);
287 cnt
->reduce(n_coeff
, n_power
, d_power
);
288 assert(value_cmp_si(mpq_numref(cnt
->count
[0]), 1) == 0);
289 assert(value_cmp_si(mpq_denref(cnt
->count
[0]), 6) == 0);
290 assert(value_cmp_si(mpq_numref(cnt
->count
[1]), 0) == 0);
291 assert(value_cmp_si(mpq_denref(cnt
->count
[1]), 1) == 0);
292 assert(value_cmp_si(mpq_numref(cnt
->count
[2]), 0) == 0);
293 assert(value_cmp_si(mpq_denref(cnt
->count
[2]), 1) == 0);
296 cnt
= new infinite_counter(2, 2);
298 set_from_string(n_coeff
, "[1/1]");
299 set_from_string(n_power
, "[[0 11]]");
300 set_from_string(d_power
, "[[0 1]]");
301 cnt
->reduce(n_coeff
, n_power
, d_power
);
302 assert(value_cmp_si(mpq_numref(cnt
->count
[1]), 0) != 0);
303 assert(value_cmp_si(mpq_numref(cnt
->count
[2]), 0) == 0);
304 assert(value_cmp_si(mpq_denref(cnt
->count
[2]), 1) == 0);
307 Polyhedron_Free(ctx
);
312 static int test_series(struct barvinok_options
*options
)
314 Matrix
*M
= matrix_read_from_str(
316 " 0 1 0 0 0 0 0 1 0 0 3 \n"
317 " 0 0 1 0 0 0 0 -1 1 0 -5 \n"
318 " 0 0 0 1 0 0 0 0 -2 -1 6 \n"
319 " 0 0 0 0 1 0 0 1 1 0 5 \n"
320 " 0 0 0 0 0 1 0 0 -1 0 0 \n"
321 " 0 0 0 0 0 0 1 -2 0 -1 -3 \n"
322 " 1 0 0 0 0 0 0 2 0 1 3 \n"
323 " 1 0 0 0 0 0 0 1 -1 0 5 \n"
324 " 1 0 0 0 0 0 0 -1 -1 0 -5 \n"
325 " 1 0 0 0 0 0 0 -1 0 0 -3 \n"
326 " 1 0 0 0 0 0 0 0 2 1 -6 \n"
327 " 1 0 0 0 0 0 0 0 1 0 0 \n");
328 Polyhedron
*P
= Constraints2Polyhedron(M
, options
->MaxRays
);
330 Polyhedron
*C
= Universe_Polyhedron(3);
331 gen_fun
*gf
= barvinok_series_with_options(P
, C
, options
);
336 M
= matrix_read_from_str(
338 " 0 1 1 0 0 1 0 2 \n"
339 " 0 0 0 1 0 -2 0 6 \n"
340 " 0 0 0 0 1 -1 0 -1 \n"
341 " 0 0 0 0 0 0 1 0 \n"
342 " 1 0 1 0 0 0 0 0 \n"
343 " 1 0 -1 0 0 -1 0 -2 \n"
344 " 1 0 0 0 0 1 0 -3 \n");
345 P
= Constraints2Polyhedron(M
, options
->MaxRays
);
347 C
= Universe_Polyhedron(2);
348 gf
= barvinok_series_with_options(P
, C
, options
);
353 M
= matrix_read_from_str(
357 P
= Constraints2Polyhedron(M
, options
->MaxRays
);
359 C
= Universe_Polyhedron(1);
360 gf
= barvinok_series_with_options(P
, C
, options
);
363 gen_fun
*sum
= gf
->summate(1, options
);
370 int test_todd(struct barvinok_options
*options
)
372 tcounter
t(2, options
->max_index
);
373 assert(value_cmp_si(t
.todd
.coeff
->p
[0], 1) == 0);
374 assert(value_cmp_si(t
.todd
.coeff
->p
[1], -3) == 0);
375 assert(value_cmp_si(t
.todd
.coeff
->p
[2], 3) == 0);
376 assert(value_cmp_si(t
.todd_denom
->p
[0], 1) == 0);
377 assert(value_cmp_si(t
.todd_denom
->p
[1], 6) == 0);
378 assert(value_cmp_si(t
.todd_denom
->p
[2], 36) == 0);
381 set_from_string(lambda
, "[1 -1]");
382 zz2values(lambda
, t
.lambda
->p
);
385 set_from_string(rays
, "[[-1 0][-1 1]]");
390 set_from_string(v
, "[2 0 1]");
391 Vector
*vertex
= Vector_Alloc(3);
392 zz2values(v
, vertex
->p
);
394 t
.handle(rays
, vertex
->p
, one
, 1, options
);
395 assert(value_cmp_si(mpq_numref(t
.count
), 71) == 0);
396 assert(value_cmp_si(mpq_denref(t
.count
), 24) == 0);
398 set_from_string(rays
, "[[0 -1][1 -1]]");
399 set_from_string(v
, "[0 2 1]");
400 zz2values(v
, vertex
->p
);
402 t
.handle(rays
, vertex
->p
, one
, 1, options
);
403 assert(value_cmp_si(mpq_numref(t
.count
), 71) == 0);
404 assert(value_cmp_si(mpq_denref(t
.count
), 12) == 0);
406 set_from_string(rays
, "[[1 0][0 1]]");
407 set_from_string(v
, "[0 0 1]");
408 zz2values(v
, vertex
->p
);
410 t
.handle(rays
, vertex
->p
, one
, 1, options
);
411 assert(value_cmp_si(mpq_numref(t
.count
), 6) == 0);
412 assert(value_cmp_si(mpq_denref(t
.count
), 1) == 0);
417 int test_bernoulli(struct barvinok_options
*options
)
419 struct bernoulli_coef
*bernoulli_coef
;
420 struct poly_list
*faulhaber
, *bernoulli
;
421 bernoulli_coef
= bernoulli_coef_compute(2);
422 faulhaber
= faulhaber_compute(4);
423 bernoulli_coef
= bernoulli_coef_compute(8);
424 assert(value_cmp_si(bernoulli_coef
->num
->p
[6], 1) == 0);
425 assert(value_cmp_si(bernoulli_coef
->den
->p
[6], 42) == 0);
426 assert(value_cmp_si(faulhaber
->poly
[3]->p
[0], 0) == 0);
427 assert(value_cmp_si(faulhaber
->poly
[3]->p
[1], 0) == 0);
428 assert(value_cmp_si(faulhaber
->poly
[3]->p
[2], 1) == 0);
429 assert(value_cmp_si(faulhaber
->poly
[3]->p
[3], -2) == 0);
430 assert(value_cmp_si(faulhaber
->poly
[3]->p
[4], 1) == 0);
431 assert(value_cmp_si(faulhaber
->poly
[3]->p
[5], 4) == 0);
433 bernoulli
= bernoulli_compute(6);
434 assert(value_cmp_si(bernoulli
->poly
[6]->p
[0], 1) == 0);
435 assert(value_cmp_si(bernoulli
->poly
[6]->p
[1], 0) == 0);
436 assert(value_cmp_si(bernoulli
->poly
[6]->p
[2], -21) == 0);
437 assert(value_cmp_si(bernoulli
->poly
[6]->p
[3], 0) == 0);
438 assert(value_cmp_si(bernoulli
->poly
[6]->p
[4], 105) == 0);
439 assert(value_cmp_si(bernoulli
->poly
[6]->p
[5], -126) == 0);
440 assert(value_cmp_si(bernoulli
->poly
[6]->p
[6], 42) == 0);
441 assert(value_cmp_si(bernoulli
->poly
[6]->p
[7], 42) == 0);
443 unsigned nvar
, nparam
;
445 evalue
*base
, *sum1
, *sum2
;
446 base
= evalue_read_from_str("(1 * n + 1)", NULL
, &all_vars
, &nvar
, &nparam
,
449 sum1
= evalue_polynomial(faulhaber
->poly
[3], base
);
450 Free_ParamNames(all_vars
, nvar
+nparam
);
452 sum2
= evalue_read_from_str("(1/4 * n^4 + 1/2 * n^3 + 1/4 * n^2)",
453 NULL
, &all_vars
, &nvar
, &nparam
,
455 Free_ParamNames(all_vars
, nvar
+nparam
);
456 assert(eequal(sum1
, sum2
));
462 int test_bernoulli_sum(struct barvinok_options
*options
)
464 unsigned nvar
, nparam
;
466 evalue
*e
, *sum1
, *sum2
;
467 e
= evalue_read_from_str("i + -1 >= 0\n -i + n >= 0\n\n 1 + (-1 *i) + i^2",
468 "i", &all_vars
, &nvar
, &nparam
,
470 Free_ParamNames(all_vars
, nvar
+nparam
);
472 sum1
= Bernoulli_sum_evalue(e
, 1, options
);
473 sum2
= evalue_read_from_str("n -1 >= 0\n\n (1/3 * n^3 + 2/3 * n)",
474 NULL
, &all_vars
, &nvar
, &nparam
,
476 Free_ParamNames(all_vars
, nvar
+nparam
);
480 assert(EVALUE_IS_ZERO(*sum1
));
484 e
= evalue_read_from_str("-i + -1 >= 0\n i + n >= 0\n\n 1 + i + i^2",
485 "i", &all_vars
, &nvar
, &nparam
,
487 Free_ParamNames(all_vars
, nvar
+nparam
);
488 sum1
= Bernoulli_sum_evalue(e
, 1, options
);
492 assert(EVALUE_IS_ZERO(*sum1
));
498 e
= evalue_read_from_str("i + 4 >= 0\n -i + n >= 0\n\n i",
499 "i", &all_vars
, &nvar
, &nparam
,
501 Free_ParamNames(all_vars
, nvar
+nparam
);
502 sum1
= Bernoulli_sum_evalue(e
, 1, options
);
503 sum2
= evalue_read_from_str("n + 0 >= 0\n\n (1/2 * n^2 + 1/2 * n + (-10))\n"
504 "n + 4 >= 0\n -n -1 >= 0\n\n (1/2 * n^2 + 1/2 * n + (-10))",
505 NULL
, &all_vars
, &nvar
, &nparam
,
507 Free_ParamNames(all_vars
, nvar
+nparam
);
511 assert(EVALUE_IS_ZERO(*sum1
));
516 e
= evalue_read_from_str("i -5 >= 0\n -i + n >= 0\n j -1 >= 0\n i -j >= 0\n"
517 "k -1 >= 0\n j -k >= 0\n\n1",
518 "i,j,k", &all_vars
, &nvar
, &nparam
,
520 Free_ParamNames(all_vars
, nvar
+nparam
);
521 sum1
= Bernoulli_sum_evalue(e
, 3, options
);
522 sum2
= evalue_read_from_str("n -5 >= 0\n\n"
523 "1/6 * n^3 + 1/2 * n^2 + 1/3 * n + -20",
524 NULL
, &all_vars
, &nvar
, &nparam
,
526 Free_ParamNames(all_vars
, nvar
+nparam
);
530 assert(EVALUE_IS_ZERO(*sum1
));
536 int test_hilbert(struct barvinok_options
*options
)
539 Matrix
*M
= matrix_read_from_str(
543 Polyhedron
*P
= Constraints2Polyhedron(M
, options
->MaxRays
);
546 M
= Cone_Hilbert_Basis(P
, options
->MaxRays
);
547 assert(M
->NbRows
= 5);
548 assert(M
->NbColumns
= 3);
551 M
= Cone_Integer_Hull(P
, NULL
, 0, options
);
552 assert(M
->NbRows
= 4);
553 assert(M
->NbColumns
= 3);
560 int test_ilp(struct barvinok_options
*options
)
562 Matrix
*M
= matrix_read_from_str(
566 Polyhedron
*P
= Constraints2Polyhedron(M
, options
->MaxRays
);
568 Vector
*obj
= Vector_Alloc(2);
569 value_set_si(obj
->p
[0], 7);
570 value_set_si(obj
->p
[1], -1);
575 value_set_si(min
, 1);
576 value_set_si(max
, 17);
577 Vector
*opt
= Polyhedron_Integer_Minimum(P
, obj
->p
, min
, max
,
580 assert(value_cmp_si(opt
->p
[0], 1) == 0);
581 assert(value_cmp_si(opt
->p
[1], 1) == 0);
582 assert(value_cmp_si(opt
->p
[2], 1) == 0);
591 int test_hull(struct barvinok_options
*options
)
593 Matrix
*M
= matrix_read_from_str(
599 Polyhedron
*P
= Constraints2Polyhedron(M
, options
->MaxRays
);
602 Matrix
*hull
= Polyhedron_Integer_Hull(P
, options
);
604 assert(hull
->NbRows
== 4);
605 M
= Matrix_Alloc(hull
->NbRows
, 1+hull
->NbColumns
);
606 for (int i
= 0; i
< hull
->NbRows
; ++i
) {
607 value_set_si(M
->p
[i
][0], 1);
608 Vector_Copy(hull
->p
[i
], M
->p
[i
]+1, hull
->NbColumns
);
611 Polyhedron
*H
= Constraints2Polyhedron(M
, options
->MaxRays
);
614 M
= matrix_read_from_str(
620 P
= Constraints2Polyhedron(M
, options
->MaxRays
);
622 assert(PolyhedronIncludes(P
, H
) && PolyhedronIncludes(H
, P
));
626 M
= matrix_read_from_str(
631 P
= Constraints2Polyhedron(M
, options
->MaxRays
);
634 hull
= Polyhedron_Integer_Hull(P
, options
);
636 assert(hull
->NbRows
== 0);
640 int main(int argc
, char **argv
)
642 struct barvinok_options
*options
= barvinok_options_new_with_defaults();
643 test_evalue_read(options
);
644 test_evalue(options
);
645 test_substitute(options
);
646 test_split_periods(options
);
647 test_specialization(options
);
648 test_lattice_points(options
);
649 test_icounter(options
);
650 test_infinite_counter(options
);
651 test_series(options
);
653 test_bernoulli(options
);
654 test_bernoulli_sum(options
);
655 test_hilbert(options
);
658 barvinok_options_free(options
);