7 #include <NTL/vec_ZZ.h>
8 #include <NTL/mat_ZZ.h>
10 #include <barvinok/barvinok.h>
11 #include <barvinok/util.h>
12 #include "conversion.h"
13 #include "decomposer.h"
14 #include "param_util.h"
15 #include "reduce_domain.h"
23 * Returns the largest absolute value in the vector
25 static ZZ
max(vec_ZZ
& v
)
28 for (int i
= 1; i
< v
.length(); ++i
)
34 /* Remove common divisor of elements of cols of B */
35 static void normalize_cols(mat_ZZ
& B
)
38 for (int i
= 0; i
< B
.NumCols(); ++i
) {
40 for (int j
= 1 ; gcd
!= 1 && j
< B
.NumRows(); ++j
)
41 GCD(gcd
, gcd
, B
[j
][i
]);
43 for (int j
= 0; j
< B
.NumRows(); ++j
)
48 /* Remove common divisor of elements of B */
49 static void normalize_matrix(mat_ZZ
& B
)
52 for (int i
= 0; i
< B
.NumCols(); ++i
)
53 for (int j
= 0 ; j
< B
.NumRows(); ++j
) {
54 GCD(gcd
, gcd
, B
[i
][j
]);
58 for (int i
= 0; i
< B
.NumCols(); ++i
)
59 for (int j
= 0; j
< B
.NumRows(); ++j
)
65 cone(const mat_ZZ
& r
, int row
, const vec_ZZ
& w
, int s
) {
71 cone(const signed_cone
& sc
) {
77 det
= determinant(rays
);
80 bool needs_split(barvinok_options
*options
) {
84 if (options
->primal
&& index
<= options
->max_index
)
92 if (!options
->primal
&& options
->max_index
> 1) {
95 index
= abs(determinant(B2
));
96 if (index
<= options
->max_index
)
103 void short_vector(vec_ZZ
& v
, vec_ZZ
& lambda
, barvinok_options
*options
) {
107 LLL(det2
, B
, U
, options
->LLL_a
, options
->LLL_b
);
111 for (int i
= 1; i
< B
.NumRows(); ++i
) {
124 for (i
= 0; i
< lambda
.length(); ++i
)
127 if (i
== lambda
.length()) {
140 std::ostream
& operator<<(std::ostream
& os
, const cone
& c
)
142 os
<< c
.rays
<< endl
;
143 os
<< "det: " << c
.det
<< endl
;
144 os
<< "sign: " << c
.sgn
<< endl
;
148 static void decompose(const signed_cone
& sc
, signed_cone_consumer
& scc
,
149 bool primal
, barvinok_options
*options
)
151 vector
<cone
*> nonuni
;
152 cone
*c
= new cone(sc
);
153 if (c
->needs_split(options
)) {
157 options
->stats
->base_cones
++;
158 scc
.handle(signed_cone(sc
.C
, sc
.rays
, sc
.sign
, to_ulong(c
->index
)),
169 while (!nonuni
.empty()) {
172 c
->short_vector(v
, lambda
, options
);
173 for (int i
= 0; i
< c
->rays
.NumRows(); ++i
) {
176 cone
*pc
= new cone(c
->rays
, i
, v
, sign(lambda
[i
]) * c
->sgn
);
178 for (int j
= 0; j
<= i
; ++j
) {
179 if ((j
== i
&& sign(lambda
[i
]) < 0) ||
180 (j
< i
&& sign(lambda
[i
]) == sign(lambda
[j
]))) {
181 pc
->rays
[j
] = -pc
->rays
[j
];
186 if (pc
->needs_split(options
)) {
187 assert(abs(pc
->det
) < abs(c
->det
));
188 nonuni
.push_back(pc
);
191 options
->stats
->base_cones
++;
192 scc
.handle(signed_cone(pc
->rays
, pc
->sgn
,
193 to_ulong(pc
->index
)),
199 while (!nonuni
.empty()) {
212 struct polar_signed_cone_consumer
: public signed_cone_consumer
{
213 signed_cone_consumer
& scc
;
215 polar_signed_cone_consumer(signed_cone_consumer
& scc
) : scc(scc
) {}
216 virtual void handle(const signed_cone
& sc
, barvinok_options
*options
) {
217 Polyhedron
*C
= sc
.C
;
219 Matrix
*M
= Matrix_Alloc(sc
.rays
.NumRows()+1, sc
.rays
.NumCols()+2);
220 for (int i
= 0; i
< sc
.rays
.NumRows(); ++i
) {
221 zz2values(sc
.rays
[i
], M
->p
[i
]+1);
222 value_set_si(M
->p
[i
][0], 1);
224 value_set_si(M
->p
[sc
.rays
.NumRows()][0], 1);
225 value_set_si(M
->p
[sc
.rays
.NumRows()][1+sc
.rays
.NumCols()], 1);
226 C
= Rays2Polyhedron(M
, M
->NbRows
+1);
227 assert(C
->NbConstraints
== C
->NbRays
);
230 Polyhedron_Polarize(C
);
233 scc
.handle(signed_cone(C
, r
, sc
.sign
, sc
.det
), options
);
244 /* Remove common divisor of elements of rows of B */
245 static void normalize_rows(mat_ZZ
& B
)
248 for (int i
= 0; i
< B
.NumRows(); ++i
) {
250 for (int j
= 1 ; gcd
!= 1 && j
< B
.NumCols(); ++j
)
251 GCD(gcd
, gcd
, B
[i
][j
]);
253 for (int j
= 0; j
< B
.NumCols(); ++j
)
258 static void polar_decompose(Polyhedron
*cone
, signed_cone_consumer
& scc
,
259 barvinok_options
*options
)
261 POL_ENSURE_VERTICES(cone
);
262 Polyhedron_Polarize(cone
);
263 if (cone
->NbRays
- 1 != cone
->Dimension
) {
264 Polyhedron
*tmp
= cone
;
265 cone
= triangulate_cone_with_options(cone
, options
);
266 Polyhedron_Free(tmp
);
268 polar_signed_cone_consumer
pssc(scc
);
271 for (Polyhedron
*Polar
= cone
; Polar
; Polar
= Polar
->next
) {
274 decompose(signed_cone(Polar
, r
, 1), pssc
, false, options
);
283 static void primal_decompose(Polyhedron
*cone
, signed_cone_consumer
& scc
,
284 barvinok_options
*options
)
286 POL_ENSURE_VERTICES(cone
);
288 if (cone
->NbRays
- 1 == cone
->Dimension
)
291 parts
= triangulate_cone_with_options(cone
, options
);
292 Vector
*average
= NULL
;
296 average
= inner_point(cone
);
300 for (Polyhedron
*simple
= parts
; simple
; simple
= simple
->next
) {
302 Matrix
*Rays
= rays2(simple
);
303 for (int i
= 0; i
< Rays
->NbRows
; ++i
) {
304 if (simple
== cone
) {
308 for (f
= 0; f
< simple
->NbConstraints
; ++f
) {
309 Inner_Product(Rays
->p
[i
], simple
->Constraint
[f
]+1,
310 simple
->Dimension
, &tmp
);
311 if (value_notzero_p(tmp
))
314 assert(f
< simple
->NbConstraints
);
315 if (!is_internal(average
, simple
->Constraint
[f
])) {
316 Vector_Oppose(Rays
->p
[i
], Rays
->p
[i
], Rays
->NbColumns
);
321 matrix2zz(Rays
, ray
, Rays
->NbRows
, Rays
->NbColumns
);
323 decompose(signed_cone(simple
, ray
, sign
), scc
, true, options
);
329 Vector_Free(average
);
336 Vector_Free(average
);
342 void barvinok_decompose(Polyhedron
*C
, signed_cone_consumer
& scc
,
343 barvinok_options
*options
)
345 POL_ENSURE_VERTICES(C
);
347 primal_decompose(C
, scc
, options
);
349 polar_decompose(C
, scc
, options
);
352 void vertex_decomposer::decompose_at_vertex(Param_Vertices
*V
, int _i
,
353 barvinok_options
*options
)
355 Polyhedron
*C
= Param_Vertex_Cone(PP
, V
, options
);
359 barvinok_decompose(C
, scc
, options
);
362 struct posneg_collector
: public signed_cone_consumer
{
363 posneg_collector(Polyhedron
*pos
, Polyhedron
*neg
) : pos(pos
), neg(neg
) {}
364 virtual void handle(const signed_cone
& sc
, barvinok_options
*options
) {
365 Polyhedron
*p
= Polyhedron_Copy(sc
.C
);
379 * Barvinok's Decomposition of a simplicial cone
381 * Returns two lists of polyhedra
383 void barvinok_decompose(Polyhedron
*C
, Polyhedron
**ppos
, Polyhedron
**pneg
)
385 barvinok_options
*options
= barvinok_options_new_with_defaults();
386 posneg_collector
pc(*ppos
, *pneg
);
387 POL_ENSURE_VERTICES(C
);
390 decompose(signed_cone(C
, r
, 1), pc
, false, options
);
393 barvinok_options_free(options
);