8 #include <barvinok/barvinok.h>
9 #include <barvinok/util.h>
14 namespace polymake
{ namespace polytope
{
17 * The h^*-vector and the Ehrhart polynomial f(t) of a lattice polytope are
20 * f(t) = \sum_{i=0}^d h^*_i { t+d-i \choose d }
25 * with c and h^* column vectors,
26 * f(t) = \sum_{i=0}^d c_i t^i,
27 * and column i of M the coefficients of the polynomial { t+d-i \choose d }
29 * Since it is actually easier for us to compute the Ehrhart polynomial,
30 * we compute the h^*-vector from this Ehrhart polynomial as
34 * All coefficients are ordered from index 0 to d.
36 void h_star_vector(Poly
& p
)
38 Matrix
<Rational
> F
= p
.give("FACETS | INEQUALITIES");
39 ::Matrix
*M
= polymake_constraints2polylib(F
);
40 Polyhedron
*A
= Constraints2Polyhedron(M
, 0);
42 for (unsigned i
= 0; i
< A
->NbRays
; ++i
) {
43 if (value_zero_p(A
->Ray
[i
][0]) || value_zero_p(A
->Ray
[i
][1+A
->Dimension
])) {
45 throw std::runtime_error("polyhedron must be bounded");
47 if (value_notone_p(A
->Ray
[i
][1+A
->Dimension
])) {
49 throw std::runtime_error("polytope must have integer vertices");
52 Polyhedron
*C
= Cone_over_Polyhedron(A
);
54 Polyhedron
*U
= Universe_Polyhedron(1);
55 evalue
*EP
= barvinok_enumerate_ev(C
, U
, MAXRAYS
);
59 assert(value_zero_p(EP
->d
));
60 assert(EP
->x
.p
->type
== partition
);
61 assert(EP
->x
.p
->size
== 2);
62 evalue
*poly
= &EP
->x
.p
->arr
[1];
63 if (value_notzero_p(poly
->d
)) {
64 assert(value_one_p(poly
->d
));
65 p
.take("H_STAR_VECTOR") << Integer(poly
->x
.n
);
67 assert(poly
->x
.p
->type
== polynomial
);
68 int d
= poly
->x
.p
->size
- 1;
69 ::Matrix
*M
= Matrix_Alloc(d
+2, d
+2);
70 ::Vector
*V
= Vector_Alloc(d
+2);
71 ::Vector
*h
= Vector_Alloc(d
+2);
78 for (int i
= 0; i
<= d
; ++i
) {
79 Vector_Set(V
->p
, 0, d
+2);
80 value_set_si(V
->p
[d
], 1);
81 for (int j
= d
; j
> 0; --j
) {
83 Vector_Combine(V
->p
+ j
-1, V
->p
+ j
, V
->p
+ j
-1, k
, one
, d
-j
+2);
85 for (int j
= 0; j
<= d
; ++j
)
86 value_assign(M
->p
[j
][i
], V
->p
[d
-j
]);
91 Factorial(d
, &M
->p
[d
+1][d
+1]);
92 ::Matrix
*inv
= Matrix_Alloc(d
+2, d
+2);
93 int ok
= Matrix_Inverse(M
, inv
);
96 for (int i
= 0; i
<= d
; ++i
) {
97 assert(value_one_p(poly
->x
.p
->arr
[i
].d
));
98 value_assign(V
->p
[i
], poly
->x
.p
->arr
[i
].x
.n
);
100 value_set_si(V
->p
[d
+1], 1);
101 Matrix_Vector_Product(inv
, V
->p
, h
->p
);
104 assert(value_one_p(h
->p
[d
+1]));
106 Vector
<Integer
> h_star(d
+1);
107 for (int i
= 0; i
<= d
; ++i
)
108 h_star
[i
] = Integer(h
->p
[i
]);
110 p
.take("H_STAR_VECTOR") << h_star
;
117 using namespace polymake
;
119 int main(int argc
, const char *argv
[])
125 Poly
p(argv
[1], ios::in
| ios::out
);
126 polytope::h_star_vector(p
);
127 } catch (const std::exception
& e
) {
128 cerr
<< e
.what() << endl
;