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(const signed_cone
& sc
) {
37 Cone
= Polyhedron_Copy(sc
.C
);
40 set_closed(sc
.closed
);
44 matrix2zz(Rays
, A
, Rays
->NbRows
- 1, Rays
->NbColumns
- 1);
47 void set_closed(int *cl
) {
50 closed
= new int[Rays
->NbRows
-1];
51 for (int i
= 0; i
< Rays
->NbRows
-1; ++i
)
56 Vector
* short_vector(vec_ZZ
& lambda
, barvinok_options
*options
) {
57 Matrix
*M
= Matrix_Copy(Rays
);
58 Matrix
*inv
= Matrix_Alloc(M
->NbRows
, M
->NbColumns
);
59 int ok
= Matrix_Inverse(M
, inv
);
66 matrix2zz(inv
, B
, inv
->NbRows
- 1, inv
->NbColumns
- 1);
67 long r
= LLL(det2
, B
, U
, options
->LLL_a
, options
->LLL_b
);
71 for (int i
= 1; i
< B
.NumRows(); ++i
) {
83 Vector
*z
= Vector_Alloc(U
[index
].length()+1);
85 zz2values(U
[index
], z
->p
);
86 value_set_si(z
->p
[U
[index
].length()], 0);
88 Polyhedron
*C
= poly();
90 for (i
= 0; i
< lambda
.length(); ++i
)
93 if (i
== lambda
.length()) {
96 value_set_si(tmp
, -1);
97 Vector_Scale(z
->p
, z
->p
, tmp
, z
->Size
-1);
105 Polyhedron_Free(Cone
);
113 Matrix
*M
= Matrix_Alloc(Rays
->NbRows
+1, Rays
->NbColumns
+1);
114 for (int i
= 0; i
< Rays
->NbRows
; ++i
) {
115 Vector_Copy(Rays
->p
[i
], M
->p
[i
]+1, Rays
->NbColumns
);
116 value_set_si(M
->p
[i
][0], 1);
118 Vector_Set(M
->p
[Rays
->NbRows
]+1, 0, Rays
->NbColumns
-1);
119 value_set_si(M
->p
[Rays
->NbRows
][0], 1);
120 value_set_si(M
->p
[Rays
->NbRows
][Rays
->NbColumns
], 1);
121 Cone
= Rays2Polyhedron(M
, M
->NbRows
+1);
122 assert(Cone
->NbConstraints
== Cone
->NbRays
);
134 static void decompose(const signed_cone
& sc
, signed_cone_consumer
& scc
,
135 barvinok_options
*options
)
137 vector
<cone
*> nonuni
;
138 cone
* c
= new cone(sc
);
146 options
->stats
.unimodular_cones
++;
156 int closed
[c
->Rays
->NbRows
-1];
157 while (!nonuni
.empty()) {
160 Vector
* v
= c
->short_vector(lambda
, options
);
161 for (int i
= 0; i
< c
->Rays
->NbRows
- 1; ++i
) {
164 Matrix
* M
= Matrix_Copy(c
->Rays
);
165 Vector_Copy(v
->p
, M
->p
[i
], v
->Size
);
166 cone
* pc
= new cone(M
);
168 bool same_sign
= sign(c
->det
) * sign(pc
->det
) > 0;
169 for (int j
= 0; j
< c
->Rays
->NbRows
- 1; ++j
) {
171 closed
[j
] = c
->closed
[j
];
174 closed
[j
] = c
->closed
[j
];
176 closed
[j
] = !c
->closed
[j
];
177 } else if (sign(lambda
[i
]) * sign(lambda
[j
]) > 0) {
178 if (c
->closed
[i
] == c
->closed
[j
])
181 closed
[j
] = c
->closed
[j
];
183 closed
[j
] = c
->closed
[i
] && c
->closed
[j
];
185 pc
->set_closed(closed
);
187 assert (pc
->det
!= 0);
188 if (abs(pc
->det
) > 1) {
189 assert(abs(pc
->det
) < abs(c
->det
));
190 nonuni
.push_back(pc
);
193 options
->stats
.unimodular_cones
++;
195 scc
.handle(signed_cone(pc
->poly(), sign(pc
->det
) * s
,
198 scc
.handle(signed_cone(pc
->poly(), sign(pc
->det
) * s
));
203 while (!nonuni
.empty()) {
220 struct polar_signed_cone_consumer
: public signed_cone_consumer
{
221 signed_cone_consumer
& scc
;
222 polar_signed_cone_consumer(signed_cone_consumer
& scc
) : scc(scc
) {}
223 virtual void handle(const signed_cone
& sc
) {
224 Polyhedron_Polarize(sc
.C
);
229 static void polar_decompose(Polyhedron
*cone
, signed_cone_consumer
& scc
,
230 barvinok_options
*options
)
232 POL_ENSURE_VERTICES(cone
);
233 Polyhedron_Polarize(cone
);
234 if (cone
->NbRays
- 1 != cone
->Dimension
) {
235 Polyhedron
*tmp
= cone
;
236 cone
= triangulate_cone(cone
, options
->MaxRays
);
237 Polyhedron_Free(tmp
);
239 polar_signed_cone_consumer
pssc(scc
);
241 for (Polyhedron
*Polar
= cone
; Polar
; Polar
= Polar
->next
)
242 decompose(signed_cone(Polar
, 1), pssc
, options
);
250 static void primal_decompose(Polyhedron
*cone
, signed_cone_consumer
& scc
,
251 barvinok_options
*options
)
253 POL_ENSURE_VERTICES(cone
);
255 if (cone
->NbRays
- 1 == cone
->Dimension
)
258 parts
= triangulate_cone(cone
, options
->MaxRays
);
259 int closed
[cone
->Dimension
];
260 Vector
*average
= NULL
;
264 average
= Vector_Alloc(cone
->Dimension
);
265 for (int i
= 0; i
< cone
->NbRays
; ++i
) {
266 if (value_notzero_p(cone
->Ray
[i
][1+cone
->Dimension
]))
268 Vector_Add(average
->p
, cone
->Ray
[i
]+1, average
->p
, cone
->Dimension
);
272 for (Polyhedron
*simple
= parts
; simple
; simple
= simple
->next
) {
273 for (int i
= 0, r
= 0; r
< simple
->NbRays
; ++r
) {
274 if (value_notzero_p(simple
->Ray
[r
][1+simple
->Dimension
]))
276 if (simple
== cone
) {
280 for (f
= 0; f
< simple
->NbConstraints
; ++f
) {
281 Inner_Product(simple
->Ray
[r
]+1, simple
->Constraint
[f
]+1,
282 simple
->Dimension
, &tmp
);
283 if (value_notzero_p(tmp
))
286 assert(f
< simple
->NbConstraints
);
287 Inner_Product(simple
->Constraint
[f
]+1, average
->p
,
288 simple
->Dimension
, &tmp
);
289 if (value_notzero_p(tmp
))
290 closed
[i
] = value_pos_p(tmp
);
292 int p
= First_Non_Zero(simple
->Constraint
[f
]+1,
294 closed
[i
] = value_pos_p(simple
->Constraint
[f
][1+p
]);
299 decompose(signed_cone(simple
, 1, closed
), scc
, options
);
305 Vector_Free(average
);
312 Vector_Free(average
);
318 void barvinok_decompose(Polyhedron
*C
, signed_cone_consumer
& scc
,
319 barvinok_options
*options
)
322 primal_decompose(C
, scc
, options
);
324 polar_decompose(C
, scc
, options
);
327 void vertex_decomposer::decompose_at_vertex(Param_Vertices
*V
, int _i
,
328 barvinok_options
*options
)
330 Polyhedron
*C
= supporting_cone_p(P
, V
);
334 barvinok_decompose(C
, scc
, options
);
337 struct posneg_collector
: public signed_cone_consumer
{
338 posneg_collector(Polyhedron
*pos
, Polyhedron
*neg
) : pos(pos
), neg(neg
) {}
339 virtual void handle(const signed_cone
& sc
) {
340 Polyhedron
*p
= Polyhedron_Copy(sc
.C
);
354 * Barvinok's Decomposition of a simplicial cone
356 * Returns two lists of polyhedra
358 void barvinok_decompose(Polyhedron
*C
, Polyhedron
**ppos
, Polyhedron
**pneg
)
360 barvinok_options
*options
= barvinok_options_new_with_defaults();
361 posneg_collector
pc(*ppos
, *pneg
);
362 POL_ENSURE_VERTICES(C
);
363 decompose(signed_cone(C
, 1), pc
, options
);