3 #include <NTL/vec_ZZ.h>
4 #include <NTL/mat_ZZ.h>
5 #include <barvinok/polylib.h>
6 #include <barvinok/util.h>
8 #include "lattice_point.h"
10 /* Computes the integer points in the fundamental parallelepiped and
11 * passes them along (in num) to the counter specific (i.e., specialization
12 * specific) add_lattice_points.
14 void counter_base::handle(const mat_ZZ
& rays
, Value
*V
, const QQ
& c
,
15 unsigned long det
, barvinok_options
*options
)
17 Matrix
* Rays
= zz2matrix(rays
);
20 assert(c
.n
== 1 || c
.n
== -1);
21 int sign
= to_int(c
.n
);
23 Matrix_Vector_Product(Rays
, lambda
->p
, den
->p_Init
);
24 for (int k
= 0; k
< dim
; ++k
)
25 if (value_zero_p(den
->p_Init
[k
])) {
29 Inner_Product(lambda
->p
, V
, dim
, &tmp
);
30 lattice_points_fixed(V
, &tmp
, Rays
, den
, num
, det
);
37 add_lattice_points(sign
);
40 static void add_falling_powers(dpoly
& n
, Value degree
)
42 value_increment(n
.coeff
->p
[0], n
.coeff
->p
[0]);
43 if (n
.coeff
->Size
== 1)
46 int min
= n
.coeff
->Size
-1;
47 if (value_posz_p(degree
) && value_cmp_si(degree
, min
) < 0)
48 min
= VALUE_TO_INT(degree
);
52 value_assign(tmp
, degree
);
53 value_addto(n
.coeff
->p
[1], n
.coeff
->p
[1], tmp
);
54 for (int i
= 2; i
<= min
; ++i
) {
55 value_decrement(degree
, degree
);
56 value_multiply(tmp
, tmp
, degree
);
57 mpz_divexact_ui(tmp
, tmp
, i
);
58 value_addto(n
.coeff
->p
[i
], n
.coeff
->p
[i
], tmp
);
63 void counter::add_lattice_points(int sign
)
66 for (int k
= 0; k
< num
->NbRows
; ++k
)
67 add_falling_powers(d
, num
->p_Init
[k
]);
68 dpoly
n(dim
, den
->p_Init
[0], 1);
69 for (int k
= 1; k
< dim
; ++k
) {
70 dpoly
fact(dim
, den
->p_Init
[k
], 1);
73 d
.div(n
, count
, sign
);
79 void tcounter::setup_todd(unsigned dim
)
81 value_set_si(todd
.coeff
->p
[0], 1);
84 value_set_si(d
.coeff
->p
[dim
], 1);
85 for (int i
= dim
-1; i
>= 0; --i
)
86 mpz_mul_ui(d
.coeff
->p
[i
], d
.coeff
->p
[i
+1], i
+2);
88 todd_denom
= todd
.div(d
);
89 /* shift denominators up -> divide by (dim+1)! */
90 for (int i
= todd
.coeff
->Size
-1; i
>= 1; --i
)
91 value_assign(todd_denom
->p
[i
], todd_denom
->p
[i
-1]);
92 value_set_si(todd_denom
->p
[0], 1);
95 void tcounter::adapt_todd(dpoly
& t
, const Value c
)
97 if (t
.coeff
->Size
<= 1)
100 value_multiply(t
.coeff
->p
[1], t
.coeff
->p
[1], tmp
);
101 for (int i
= 2; i
< t
.coeff
->Size
; ++i
) {
102 value_multiply(tmp
, tmp
, c
);
103 value_multiply(t
.coeff
->p
[i
], t
.coeff
->p
[i
], tmp
);
107 void tcounter::add_powers(dpoly
& n
, const Value c
)
109 value_increment(n
.coeff
->p
[0], n
.coeff
->p
[0]);
110 if (n
.coeff
->Size
== 1)
112 value_assign(tmp
, c
);
113 value_addto(n
.coeff
->p
[1], n
.coeff
->p
[1], tmp
);
114 for (int i
= 2; i
< n
.coeff
->Size
; ++i
) {
115 value_multiply(tmp
, tmp
, c
);
116 value_addto(n
.coeff
->p
[i
], n
.coeff
->p
[i
], tmp
);
120 void tcounter::add_lattice_points(int sign
)
123 value_assign(denom
, den
->p_Init
[0]);
124 adapt_todd(t
, den
->p_Init
[0]);
125 for (int k
= 1; k
< dim
; ++k
) {
127 value_multiply(denom
, denom
, den
->p_Init
[k
]);
128 adapt_todd(fact
, den
->p_Init
[k
]);
133 for (int k
= 0; k
< num
->NbRows
; ++k
)
134 add_powers(n
, num
->p_Init
[k
]);
136 for (int i
= 0; i
< n
.coeff
->Size
; ++i
)
137 value_multiply(n
.coeff
->p
[i
], n
.coeff
->p
[i
], todd_denom
->p
[i
]);
138 value_multiply(denom
, denom
, todd_denom
->p
[todd_denom
->Size
-1]);
140 value_set_si(tmp
, 1);
141 for (int i
= 2; i
< n
.coeff
->Size
; ++i
) {
142 mpz_mul_ui(tmp
, tmp
, i
);
143 mpz_divexact(n
.coeff
->p
[i
], n
.coeff
->p
[i
], tmp
);
146 value_multiply(tmp
, t
.coeff
->p
[0], n
.coeff
->p
[n
.coeff
->Size
-1]);
147 for (int i
= 1; i
< n
.coeff
->Size
; ++i
)
148 value_addmul(tmp
, t
.coeff
->p
[i
], n
.coeff
->p
[n
.coeff
->Size
-1-i
]);
150 value_assign(mpq_numref(tcount
), tmp
);
151 value_assign(mpq_denref(tcount
), denom
);
152 mpq_canonicalize(tcount
);
154 mpq_sub(count
, count
, tcount
);
156 mpq_add(count
, count
, tcount
);
161 * Set lambda to a random vector that has a positive inner product
162 * with all the rays of the context { x | A x + b >= 0 }.
164 * To do so, we take d rows A' from the constraint matrix A.
165 * For every ray, we have
167 * We compute a random positive row vector x' and set x = x' A'.
168 * We then have, for each ray r,
170 * Although we can take any d rows from A, we choose linearly
171 * independent rows from A to avoid the elements of the transformed
172 * random vector to have simple linear relations, which would
173 * increase the risk of the vector being orthogonal to one of
174 * powers in the denominator of one of the terms in the generating
177 void infinite_counter::init(Polyhedron
*context
, int n_try
)
179 Matrix
*M
, *H
, *Q
, *U
;
182 randomvector(context
, lambda
, context
->Dimension
, n_try
);
184 M
= Matrix_Alloc(context
->NbConstraints
, context
->Dimension
);
185 for (int i
= 0; i
< context
->NbConstraints
; ++i
)
186 Vector_Copy(context
->Constraint
[i
]+1, M
->p
[i
], context
->Dimension
);
187 left_hermite(M
, &H
, &Q
, &U
);
191 for (int col
= 0, row
= 0; col
< H
->NbColumns
; ++col
, ++row
) {
192 for (; row
< H
->NbRows
; ++row
)
193 if (value_notzero_p(H
->p
[row
][col
]))
195 assert(row
< H
->NbRows
);
196 Vector_Copy(M
->p
[row
], M
->p
[col
], M
->NbColumns
);
198 matrix2zz(M
, A
, context
->Dimension
, context
->Dimension
);
202 for (int i
= 0; i
< lambda
.length(); ++i
)
203 lambda
[i
] = abs(lambda
[i
]);
207 static ZZ
LCM(const ZZ
& a
, const ZZ
& b
)
209 return a
* b
/ GCD(a
, b
);
212 /* Normalize the powers in the denominator to be positive
213 * and return -1 is the sign has to be changed.
215 static int normalized_sign(vec_ZZ
& num
, vec_ZZ
& den
)
219 for (int j
= 0; j
< den
.length(); ++j
) {
223 den
[j
] = abs(den
[j
]);
224 for (int k
= 0; k
< num
.length(); ++k
)
228 return change
? -1 : 1;
231 void infinite_counter::reduce(const vec_QQ
& c
, const mat_ZZ
& num
,
236 unsigned len
= den_f
.NumRows();
239 for (int i
= 1; i
< c
.length(); ++i
)
240 lcm
= LCM(lcm
, c
[i
].d
);
243 coeff
.SetLength(c
.length());
244 for (int i
= 0; i
< c
.length(); ++i
)
245 coeff
[i
] = c
[i
].n
* lcm
/c
[i
].d
;
248 for (int i
= 0; i
< c
.length(); ++i
) {
249 zz2value(coeff
[i
], tz
);
250 value_addto(mpq_numref(factor
), mpq_numref(factor
), tz
);
253 value_assign(mpq_denref(factor
), tz
);
254 mpq_add(count
[0], count
[0], factor
);
259 vec_ZZ num_s
= num
* lambda
;
260 vec_ZZ den_s
= den_f
* lambda
;
261 for (int i
= 0; i
< den_s
.length(); ++i
)
262 assert(den_s
[i
] != 0);
263 int sign
= normalized_sign(num_s
, den_s
);
268 zz2value(num_s
[0], tz
);
269 add_falling_powers(n
, tz
);
270 zz2value(coeff
[0], tz
);
272 for (int i
= 1; i
< c
.length(); ++i
) {
274 zz2value(num_s
[i
], tz
);
275 add_falling_powers(t
, tz
);
276 zz2value(coeff
[i
], tz
);
280 zz2value(den_s
[0], tz
);
282 for (int i
= 1; i
< len
; ++i
) {
283 zz2value(den_s
[i
], tz
);
284 dpoly
fact(len
, tz
, 1);
287 value_set_si(mpq_numref(factor
), 1);
289 value_assign(mpq_denref(factor
), tz
);
290 n
.div(d
, count
, factor
);