4 #include <NTL/mat_ZZ.h>
6 #include <barvinok/barvinok.h>
7 #include <barvinok/util.h>
8 #include "conversion.h"
9 #include "decomposer.h"
10 #include "reduce_domain.h"
20 * Returns the largest absolute value in the vector
22 static ZZ
max(vec_ZZ
& v
)
25 for (int i
= 1; i
< v
.length(); ++i
)
31 /* Remove common divisor of elements of cols of B */
32 static void normalize_cols(mat_ZZ
& B
)
35 for (int i
= 0; i
< B
.NumCols(); ++i
) {
37 for (int j
= 1 ; gcd
!= 1 && j
< B
.NumRows(); ++j
)
38 GCD(gcd
, gcd
, B
[j
][i
]);
40 for (int j
= 0; j
< B
.NumRows(); ++j
)
45 /* Remove common divisor of elements of B */
46 static void normalize_matrix(mat_ZZ
& B
)
49 for (int i
= 0; i
< B
.NumCols(); ++i
)
50 for (int j
= 0 ; j
< B
.NumRows(); ++j
) {
51 GCD(gcd
, gcd
, B
[i
][j
]);
55 for (int i
= 0; i
< B
.NumCols(); ++i
)
56 for (int j
= 0; j
< B
.NumRows(); ++j
)
62 cone(const mat_ZZ
& r
, int row
, const vec_ZZ
& w
) {
68 cone(const signed_cone
& sc
) {
71 set_closed(sc
.closed
);
74 det
= determinant(rays
);
76 void set_closed(int *cl
) {
79 closed
= new int[rays
.NumRows()];
80 for (int i
= 0; i
< rays
.NumRows(); ++i
)
84 bool needs_split(barvinok_options
*options
) {
88 if (options
->primal
&& index
<= options
->max_index
)
96 if (!options
->primal
&& options
->max_index
> 1) {
99 index
= abs(determinant(B2
));
100 if (index
<= options
->max_index
)
107 void short_vector(vec_ZZ
& v
, vec_ZZ
& lambda
, barvinok_options
*options
) {
110 long r
= LLL(det2
, B
, U
, options
->LLL_a
, options
->LLL_b
);
114 for (int i
= 1; i
< B
.NumRows(); ++i
) {
127 for (i
= 0; i
< lambda
.length(); ++i
)
130 if (i
== lambda
.length()) {
148 static void decompose(const signed_cone
& sc
, signed_cone_consumer
& scc
,
149 barvinok_options
*options
)
151 vector
<cone
*> nonuni
;
152 cone
* c
= new cone(sc
);
156 if (c
->needs_split(options
)) {
160 options
->stats
->base_cones
++;
161 scc
.handle(signed_cone(sc
.C
, sc
.rays
, sc
.sign
, to_ulong(c
->index
),
162 sc
.closed
), options
);
172 int closed
[c
->rays
.NumRows()];
173 while (!nonuni
.empty()) {
176 c
->short_vector(v
, lambda
, options
);
177 for (int i
= 0; i
< c
->rays
.NumRows(); ++i
) {
180 cone
*pc
= new cone(c
->rays
, i
, v
);
182 for (int j
= 0; j
< c
->rays
.NumRows(); ++j
) {
184 closed
[j
] = c
->closed
[j
];
187 closed
[j
] = c
->closed
[j
];
189 closed
[j
] = !c
->closed
[j
];
190 } else if (sign(lambda
[i
]) == sign(lambda
[j
])) {
191 if (c
->closed
[i
] == c
->closed
[j
])
194 closed
[j
] = c
->closed
[j
];
196 closed
[j
] = c
->closed
[i
] && c
->closed
[j
];
198 pc
->set_closed(closed
);
200 assert (pc
->det
!= 0);
201 if (pc
->needs_split(options
)) {
202 assert(abs(pc
->det
) < abs(c
->det
));
203 nonuni
.push_back(pc
);
206 options
->stats
->base_cones
++;
207 scc
.handle(signed_cone(pc
->rays
, sign(pc
->det
) * s
,
209 pc
->closed
), options
);
214 while (!nonuni
.empty()) {
227 struct polar_signed_cone_consumer
: public signed_cone_consumer
{
228 signed_cone_consumer
& scc
;
230 polar_signed_cone_consumer(signed_cone_consumer
& scc
) : scc(scc
) {}
231 virtual void handle(const signed_cone
& sc
, barvinok_options
*options
) {
232 Polyhedron
*C
= sc
.C
;
234 Matrix
*M
= Matrix_Alloc(sc
.rays
.NumRows()+1, sc
.rays
.NumCols()+2);
235 for (int i
= 0; i
< sc
.rays
.NumRows(); ++i
) {
236 zz2values(sc
.rays
[i
], M
->p
[i
]+1);
237 value_set_si(M
->p
[i
][0], 1);
239 value_set_si(M
->p
[sc
.rays
.NumRows()][0], 1);
240 value_set_si(M
->p
[sc
.rays
.NumRows()][1+sc
.rays
.NumCols()], 1);
241 C
= Rays2Polyhedron(M
, M
->NbRows
+1);
242 assert(C
->NbConstraints
== C
->NbRays
);
245 Polyhedron_Polarize(C
);
247 scc
.handle(signed_cone(C
, r
, sc
.sign
, sc
.det
), options
);
253 /* Remove common divisor of elements of rows of B */
254 static void normalize_rows(mat_ZZ
& B
)
257 for (int i
= 0; i
< B
.NumRows(); ++i
) {
259 for (int j
= 1 ; gcd
!= 1 && j
< B
.NumCols(); ++j
)
260 GCD(gcd
, gcd
, B
[i
][j
]);
262 for (int j
= 0; j
< B
.NumCols(); ++j
)
267 static void polar_decompose(Polyhedron
*cone
, signed_cone_consumer
& scc
,
268 barvinok_options
*options
)
270 POL_ENSURE_VERTICES(cone
);
271 Polyhedron_Polarize(cone
);
272 if (cone
->NbRays
- 1 != cone
->Dimension
) {
273 Polyhedron
*tmp
= cone
;
274 cone
= triangulate_cone_with_options(cone
, options
);
275 Polyhedron_Free(tmp
);
277 polar_signed_cone_consumer
pssc(scc
);
280 for (Polyhedron
*Polar
= cone
; Polar
; Polar
= Polar
->next
) {
283 decompose(signed_cone(Polar
, r
, 1), pssc
, options
);
292 static void primal_decompose(Polyhedron
*cone
, signed_cone_consumer
& scc
,
293 barvinok_options
*options
)
295 POL_ENSURE_VERTICES(cone
);
297 if (cone
->NbRays
- 1 == cone
->Dimension
)
300 parts
= triangulate_cone_with_options(cone
, options
);
301 int closed
[cone
->Dimension
];
302 Vector
*average
= NULL
;
306 average
= inner_point(cone
);
310 for (Polyhedron
*simple
= parts
; simple
; simple
= simple
->next
) {
311 for (int i
= 0, r
= 0; r
< simple
->NbRays
; ++r
) {
312 if (value_notzero_p(simple
->Ray
[r
][1+simple
->Dimension
]))
314 if (simple
== cone
) {
318 for (f
= 0; f
< simple
->NbConstraints
; ++f
) {
319 Inner_Product(simple
->Ray
[r
]+1, simple
->Constraint
[f
]+1,
320 simple
->Dimension
, &tmp
);
321 if (value_notzero_p(tmp
))
324 assert(f
< simple
->NbConstraints
);
325 closed
[i
] = is_internal(average
, simple
->Constraint
[f
]);
330 decompose(signed_cone(simple
, ray
, 1, 0, closed
), scc
, options
);
336 Vector_Free(average
);
343 Vector_Free(average
);
349 void barvinok_decompose(Polyhedron
*C
, signed_cone_consumer
& scc
,
350 barvinok_options
*options
)
353 primal_decompose(C
, scc
, options
);
355 polar_decompose(C
, scc
, options
);
358 void vertex_decomposer::decompose_at_vertex(Param_Vertices
*V
, int _i
,
359 barvinok_options
*options
)
361 Polyhedron
*C
= supporting_cone_p(P
, V
);
365 barvinok_decompose(C
, scc
, options
);
368 struct posneg_collector
: public signed_cone_consumer
{
369 posneg_collector(Polyhedron
*pos
, Polyhedron
*neg
) : pos(pos
), neg(neg
) {}
370 virtual void handle(const signed_cone
& sc
, barvinok_options
*options
) {
371 Polyhedron
*p
= Polyhedron_Copy(sc
.C
);
385 * Barvinok's Decomposition of a simplicial cone
387 * Returns two lists of polyhedra
389 void barvinok_decompose(Polyhedron
*C
, Polyhedron
**ppos
, Polyhedron
**pneg
)
391 barvinok_options
*options
= barvinok_options_new_with_defaults();
392 posneg_collector
pc(*ppos
, *pneg
);
393 POL_ENSURE_VERTICES(C
);
396 decompose(signed_cone(C
, r
, 1), pc
, options
);
399 barvinok_options_free(options
);