4 #include <NTL/mat_ZZ.h>
6 #include <barvinok/barvinok.h>
7 #include <barvinok/util.h>
8 #include "conversion.h"
9 #include "decomposer.h"
17 * Returns the largest absolute value in the vector
19 static ZZ
max(vec_ZZ
& v
)
22 for (int i
= 1; i
< v
.length(); ++i
)
32 Rays
= Matrix_Copy(M
);
36 Cone
= Polyhedron_Copy(C
);
42 matrix2zz(Rays
, A
, Rays
->NbRows
- 1, Rays
->NbColumns
- 1);
46 Vector
* short_vector(vec_ZZ
& lambda
, barvinok_options
*options
) {
47 Matrix
*M
= Matrix_Copy(Rays
);
48 Matrix
*inv
= Matrix_Alloc(M
->NbRows
, M
->NbColumns
);
49 int ok
= Matrix_Inverse(M
, inv
);
56 matrix2zz(inv
, B
, inv
->NbRows
- 1, inv
->NbColumns
- 1);
57 long r
= LLL(det2
, B
, U
, options
->LLL_a
, options
->LLL_b
);
61 for (int i
= 1; i
< B
.NumRows(); ++i
) {
73 Vector
*z
= Vector_Alloc(U
[index
].length()+1);
75 zz2values(U
[index
], z
->p
);
76 value_set_si(z
->p
[U
[index
].length()], 0);
78 Polyhedron
*C
= poly();
80 for (i
= 0; i
< lambda
.length(); ++i
)
83 if (i
== lambda
.length()) {
86 value_set_si(tmp
, -1);
87 Vector_Scale(z
->p
, z
->p
, tmp
, z
->Size
-1);
94 Polyhedron_Free(Cone
);
100 Matrix
*M
= Matrix_Alloc(Rays
->NbRows
+1, Rays
->NbColumns
+1);
101 for (int i
= 0; i
< Rays
->NbRows
; ++i
) {
102 Vector_Copy(Rays
->p
[i
], M
->p
[i
]+1, Rays
->NbColumns
);
103 value_set_si(M
->p
[i
][0], 1);
105 Vector_Set(M
->p
[Rays
->NbRows
]+1, 0, Rays
->NbColumns
-1);
106 value_set_si(M
->p
[Rays
->NbRows
][0], 1);
107 value_set_si(M
->p
[Rays
->NbRows
][Rays
->NbColumns
], 1);
108 Cone
= Rays2Polyhedron(M
, M
->NbRows
+1);
109 assert(Cone
->NbConstraints
== Cone
->NbRays
);
120 static void primal_decompose(Polyhedron
*C
, signed_cone_consumer
& scc
,
121 barvinok_options
*options
)
123 vector
<cone
*> nonuni
;
124 cone
* c
= new cone(C
);
132 options
->stats
.unimodular_cones
++;
133 scc
.handle(signed_cone(C
, 1));
141 while (!nonuni
.empty()) {
144 Vector
* v
= c
->short_vector(lambda
, options
);
145 for (int i
= 0; i
< c
->Rays
->NbRows
- 1; ++i
) {
148 Matrix
* M
= Matrix_Copy(c
->Rays
);
149 Vector_Copy(v
->p
, M
->p
[i
], v
->Size
);
150 cone
* pc
= new cone(M
);
151 assert (pc
->det
!= 0);
152 if (abs(pc
->det
) > 1) {
153 assert(abs(pc
->det
) < abs(c
->det
));
154 nonuni
.push_back(pc
);
157 options
->stats
.unimodular_cones
++;
158 scc
.handle(signed_cone(pc
->poly(), sign(pc
->det
) * s
));
163 while (!nonuni
.empty()) {
180 struct polar_signed_cone_consumer
: public signed_cone_consumer
{
181 signed_cone_consumer
& scc
;
182 polar_signed_cone_consumer(signed_cone_consumer
& scc
) : scc(scc
) {}
183 virtual void handle(const signed_cone
& sc
) {
184 Polyhedron_Polarize(sc
.C
);
189 static void polar_decompose(Polyhedron
*cone
, signed_cone_consumer
& scc
,
190 barvinok_options
*options
)
192 POL_ENSURE_VERTICES(cone
);
193 Polyhedron_Polarize(cone
);
194 if (cone
->NbRays
- 1 != cone
->Dimension
) {
195 Polyhedron
*tmp
= cone
;
196 cone
= triangulate_cone(cone
, options
->MaxRays
);
197 Polyhedron_Free(tmp
);
199 polar_signed_cone_consumer
pssc(scc
);
201 for (Polyhedron
*Polar
= cone
; Polar
; Polar
= Polar
->next
)
202 primal_decompose(Polar
, pssc
, options
);
210 void barvinok_decompose(Polyhedron
*C
, signed_cone_consumer
& scc
,
211 barvinok_options
*options
)
213 polar_decompose(C
, scc
, options
);
216 void vertex_decomposer::decompose_at_vertex(Param_Vertices
*V
, int _i
,
217 barvinok_options
*options
)
219 Polyhedron
*C
= supporting_cone_p(P
, V
);
223 barvinok_decompose(C
, scc
, options
);
227 * Barvinok's Decomposition of a simplicial cone
229 * Returns two lists of polyhedra
231 void barvinok_decompose(Polyhedron
*C
, Polyhedron
**ppos
, Polyhedron
**pneg
)
233 barvinok_options
*options
= barvinok_options_new_with_defaults();
234 Polyhedron
*pos
= *ppos
, *neg
= *pneg
;
235 vector
<cone
*> nonuni
;
236 cone
* c
= new cone(C
);
243 Polyhedron
*p
= Polyhedron_Copy(c
->Cone
);
249 while (!nonuni
.empty()) {
252 Vector
* v
= c
->short_vector(lambda
, options
);
253 for (int i
= 0; i
< c
->Rays
->NbRows
- 1; ++i
) {
256 Matrix
* M
= Matrix_Copy(c
->Rays
);
257 Vector_Copy(v
->p
, M
->p
[i
], v
->Size
);
258 cone
* pc
= new cone(M
);
259 assert (pc
->det
!= 0);
260 if (abs(pc
->det
) > 1) {
261 assert(abs(pc
->det
) < abs(c
->det
));
262 nonuni
.push_back(pc
);
264 Polyhedron
*p
= pc
->poly();
266 if (sign(pc
->det
) == s
) {