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
)
47 cone(const mat_ZZ
& r
, int row
, const vec_ZZ
& w
) {
53 cone(const signed_cone
& sc
) {
56 set_closed(sc
.closed
);
59 det
= determinant(rays
);
61 void set_closed(int *cl
) {
64 closed
= new int[rays
.NumRows()];
65 for (int i
= 0; i
< rays
.NumRows(); ++i
)
69 bool needs_split(barvinok_options
*options
) {
73 if (options
->primal
&& index
<= options
->max_index
)
76 Matrix
*M
= rays2matrix(rays
);
77 Matrix
*inv
= Matrix_Alloc(M
->NbRows
, M
->NbColumns
);
78 int ok
= Matrix_Inverse(M
, inv
);
82 matrix2zz(inv
, B
, inv
->NbRows
- 1, inv
->NbColumns
- 1);
85 if (!options
->primal
&& options
->max_index
> 1) {
88 index
= abs(determinant(B2
));
89 if (index
<= options
->max_index
)
96 void short_vector(vec_ZZ
& v
, vec_ZZ
& lambda
, barvinok_options
*options
) {
99 long r
= LLL(det2
, B
, U
, options
->LLL_a
, options
->LLL_b
);
103 for (int i
= 1; i
< B
.NumRows(); ++i
) {
116 for (i
= 0; i
< lambda
.length(); ++i
)
119 if (i
== lambda
.length()) {
137 static void decompose(const signed_cone
& sc
, signed_cone_consumer
& scc
,
138 barvinok_options
*options
)
140 vector
<cone
*> nonuni
;
141 cone
* c
= new cone(sc
);
145 if (c
->needs_split(options
)) {
149 options
->stats
->base_cones
++;
150 scc
.handle(signed_cone(sc
.C
, sc
.rays
, sc
.sign
, to_ulong(c
->index
),
151 sc
.closed
), options
);
161 int closed
[c
->rays
.NumRows()];
162 while (!nonuni
.empty()) {
165 c
->short_vector(v
, lambda
, options
);
166 for (int i
= 0; i
< c
->rays
.NumRows(); ++i
) {
169 cone
*pc
= new cone(c
->rays
, i
, v
);
171 for (int j
= 0; j
< c
->rays
.NumRows(); ++j
) {
173 closed
[j
] = c
->closed
[j
];
176 closed
[j
] = c
->closed
[j
];
178 closed
[j
] = !c
->closed
[j
];
179 } else if (sign(lambda
[i
]) == sign(lambda
[j
])) {
180 if (c
->closed
[i
] == c
->closed
[j
])
183 closed
[j
] = c
->closed
[j
];
185 closed
[j
] = c
->closed
[i
] && c
->closed
[j
];
187 pc
->set_closed(closed
);
189 assert (pc
->det
!= 0);
190 if (pc
->needs_split(options
)) {
191 assert(abs(pc
->det
) < abs(c
->det
));
192 nonuni
.push_back(pc
);
195 options
->stats
->base_cones
++;
196 scc
.handle(signed_cone(pc
->rays
, sign(pc
->det
) * s
,
198 pc
->closed
), options
);
203 while (!nonuni
.empty()) {
216 struct polar_signed_cone_consumer
: public signed_cone_consumer
{
217 signed_cone_consumer
& scc
;
219 polar_signed_cone_consumer(signed_cone_consumer
& scc
) : scc(scc
) {}
220 virtual void handle(const signed_cone
& sc
, barvinok_options
*options
) {
221 Polyhedron
*C
= sc
.C
;
223 Matrix
*M
= Matrix_Alloc(sc
.rays
.NumRows()+1, sc
.rays
.NumCols()+2);
224 for (int i
= 0; i
< sc
.rays
.NumRows(); ++i
) {
225 zz2values(sc
.rays
[i
], M
->p
[i
]+1);
226 value_set_si(M
->p
[i
][0], 1);
228 value_set_si(M
->p
[sc
.rays
.NumRows()][0], 1);
229 value_set_si(M
->p
[sc
.rays
.NumRows()][1+sc
.rays
.NumCols()], 1);
230 C
= Rays2Polyhedron(M
, M
->NbRows
+1);
231 assert(C
->NbConstraints
== C
->NbRays
);
234 Polyhedron_Polarize(C
);
236 scc
.handle(signed_cone(C
, r
, sc
.sign
, sc
.det
), options
);
242 /* Remove common divisor of elements of rows of B */
243 static void normalize_rows(mat_ZZ
& B
)
246 for (int i
= 0; i
< B
.NumRows(); ++i
) {
248 for (int j
= 1 ; gcd
!= 1 && j
< B
.NumCols(); ++j
)
249 GCD(gcd
, gcd
, B
[i
][j
]);
251 for (int j
= 0; j
< B
.NumCols(); ++j
)
256 static void polar_decompose(Polyhedron
*cone
, signed_cone_consumer
& scc
,
257 barvinok_options
*options
)
259 POL_ENSURE_VERTICES(cone
);
260 Polyhedron_Polarize(cone
);
261 if (cone
->NbRays
- 1 != cone
->Dimension
) {
262 Polyhedron
*tmp
= cone
;
263 cone
= triangulate_cone(cone
, options
->MaxRays
);
264 Polyhedron_Free(tmp
);
266 polar_signed_cone_consumer
pssc(scc
);
269 for (Polyhedron
*Polar
= cone
; Polar
; Polar
= Polar
->next
) {
272 decompose(signed_cone(Polar
, r
, 1), pssc
, options
);
281 static void primal_decompose(Polyhedron
*cone
, signed_cone_consumer
& scc
,
282 barvinok_options
*options
)
284 POL_ENSURE_VERTICES(cone
);
286 if (cone
->NbRays
- 1 == cone
->Dimension
)
289 parts
= triangulate_cone(cone
, options
->MaxRays
);
290 int closed
[cone
->Dimension
];
291 Vector
*average
= NULL
;
295 average
= inner_point(cone
);
299 for (Polyhedron
*simple
= parts
; simple
; simple
= simple
->next
) {
300 for (int i
= 0, r
= 0; r
< simple
->NbRays
; ++r
) {
301 if (value_notzero_p(simple
->Ray
[r
][1+simple
->Dimension
]))
303 if (simple
== cone
) {
307 for (f
= 0; f
< simple
->NbConstraints
; ++f
) {
308 Inner_Product(simple
->Ray
[r
]+1, simple
->Constraint
[f
]+1,
309 simple
->Dimension
, &tmp
);
310 if (value_notzero_p(tmp
))
313 assert(f
< simple
->NbConstraints
);
314 closed
[i
] = is_internal(average
, simple
->Constraint
[f
]);
319 decompose(signed_cone(simple
, ray
, 1, 0, closed
), scc
, options
);
325 Vector_Free(average
);
332 Vector_Free(average
);
338 void barvinok_decompose(Polyhedron
*C
, signed_cone_consumer
& scc
,
339 barvinok_options
*options
)
342 primal_decompose(C
, scc
, options
);
344 polar_decompose(C
, scc
, options
);
347 void vertex_decomposer::decompose_at_vertex(Param_Vertices
*V
, int _i
,
348 barvinok_options
*options
)
350 Polyhedron
*C
= supporting_cone_p(P
, V
);
354 barvinok_decompose(C
, scc
, options
);
357 struct posneg_collector
: public signed_cone_consumer
{
358 posneg_collector(Polyhedron
*pos
, Polyhedron
*neg
) : pos(pos
), neg(neg
) {}
359 virtual void handle(const signed_cone
& sc
, barvinok_options
*options
) {
360 Polyhedron
*p
= Polyhedron_Copy(sc
.C
);
374 * Barvinok's Decomposition of a simplicial cone
376 * Returns two lists of polyhedra
378 void barvinok_decompose(Polyhedron
*C
, Polyhedron
**ppos
, Polyhedron
**pneg
)
380 barvinok_options
*options
= barvinok_options_new_with_defaults();
381 posneg_collector
pc(*ppos
, *pneg
);
382 POL_ENSURE_VERTICES(C
);
385 decompose(signed_cone(C
, r
, 1), pc
, options
);
388 barvinok_options_free(options
);