3 #define Vector ZSolveVector
4 #define Matrix ZSolveMatrix
5 #include "zsolve/libzsolve.h"
8 #include <barvinok/options.h>
9 #include <barvinok/util.h>
13 static ZSolveMatrix
Matrix2zsolve(Matrix
*M
)
18 zmatrix
= createMatrix(M
->NbColumns
-2, M
->NbRows
);
19 for (i
= 0; i
< M
->NbRows
; ++i
)
20 for (j
= 0; j
< M
->NbColumns
-2; ++j
) {
21 assert(mpz_cmp_si(M
->p
[i
][1+j
], -MAXINT
) > 0);
22 assert(mpz_cmp_si(M
->p
[i
][1+j
], MAXINT
) < 0);
23 zmatrix
->Data
[i
*zmatrix
->Width
+j
] = mpz_get_si(M
->p
[i
][1+j
]);
29 static Matrix
*VectorArray2Matrix(VectorArray array
, unsigned cols
)
32 Matrix
*M
= Matrix_Alloc(array
->Size
, cols
+1);
34 for (i
= 0; i
< array
->Size
; ++i
) {
35 for (j
= 0; j
< cols
; ++j
)
36 value_set_si(M
->p
[i
][j
], array
->Data
[i
][j
]);
37 value_set_si(M
->p
[i
][cols
], 1);
42 static void Polyhedron_Remove_Positivity_Constraint(Polyhedron
*P
)
46 for (i
= 0; i
< P
->NbConstraints
; ++i
) {
47 if (First_Non_Zero(P
->Constraint
[i
]+1, P
->Dimension
) != -1)
49 if (i
< P
->NbConstraints
-1)
50 Vector_Exchange(P
->Constraint
[i
],
51 P
->Constraint
[P
->NbConstraints
-1],
62 static Matrix
*homogenize(Matrix
*T
)
65 Matrix
*H
= Matrix_Alloc(T
->NbRows
+1, T
->NbColumns
+1);
67 for (i
= 0; i
< T
->NbRows
; ++i
)
68 Vector_Copy(T
->p
[i
], H
->p
[i
], T
->NbColumns
);
69 value_set_si(H
->p
[T
->NbRows
][T
->NbColumns
], 1);
73 static Matrix
*Polyhedron2standard_form(Polyhedron
*P
, Matrix
**T
)
77 unsigned dim
= P
->Dimension
;
82 Polyhedron_Remove_Positivity_Constraint(P
);
83 for (i
= 0; i
< P
->NbConstraints
; ++i
)
84 assert(value_zero_p(P
->Constraint
[i
][1+dim
]));
86 H
= standard_constraints(P
, 0, &rows
, &U
);
90 M2
= Matrix_Alloc(rows
, 2+dim
+rows
);
92 for (i
= dim
; i
< H
->NbRows
; ++i
) {
93 Vector_Copy(H
->p
[i
], M2
->p
[i
-dim
]+1, dim
);
94 value_set_si(M2
->p
[i
-dim
][1+i
], -1);
96 for (i
= 0, j
= H
->NbRows
-dim
; i
< dim
; ++i
) {
97 if (First_Non_Zero(H
->p
[i
], i
) == -1)
99 Vector_Oppose(H
->p
[i
], M2
->p
[j
]+1, dim
);
100 value_set_si(M2
->p
[j
][1+j
+dim
], 1);
107 /* Assumes C is a linear cone (i.e. with apex zero).
108 * All equalities are removed first to speed up the computation
111 Matrix
*Cone_Hilbert_Basis(Polyhedron
*C
, unsigned MaxRays
)
117 LinearSystem initialsystem
;
122 remove_all_equalities(&C
, NULL
, NULL
, &CV
, 0, MaxRays
);
125 for (i
= 0; i
< C
->NbConstraints
; ++i
)
126 assert(value_zero_p(C
->Constraint
[i
][1+dim
]) ||
127 First_Non_Zero(C
->Constraint
[i
]+1, dim
) == -1);
129 M2
= Polyhedron2standard_form(C
, &T
);
130 matrix
= Matrix2zsolve(M2
);
133 rhs
= createVector(matrix
->Height
);
134 for (i
= 0; i
< matrix
->Height
; i
++)
137 initialsystem
= createLinearSystem();
138 setLinearSystemMatrix(initialsystem
, matrix
);
139 deleteMatrix(matrix
);
141 setLinearSystemRHS(initialsystem
, rhs
);
144 setLinearSystemLimit(initialsystem
, -1, 0, MAXINT
, 0);
145 setLinearSystemEquationType(initialsystem
, -1, EQUATION_EQUAL
, 0);
147 ctx
= createZSolveContextFromSystem(initialsystem
, NULL
, 0, 0, NULL
, NULL
);
148 zsolveSystem(ctx
, 0);
150 M2
= VectorArray2Matrix(ctx
->Homs
, C
->Dimension
);
151 deleteZSolveContext(ctx
, 1);
152 Matrix_Transposition(T
);
153 M3
= Matrix_Alloc(M2
->NbRows
, M2
->NbColumns
);
154 Matrix_Product(M2
, T
, M3
);
161 M
= Matrix_Alloc(M3
->NbRows
, T
->NbColumns
);
162 Matrix_Product(M3
, T
, M
);
173 /* Assumes no two arrays of values are the same, so we can just
174 * look for the first different elements, without knowing the
175 * length of the arrays.
177 static int lex_cmp(const void *va
, const void *vb
)
180 const Value
*a
= *(const Value
**)va
;
181 const Value
*b
= *(const Value
**)vb
;
184 int sign
= mpz_cmp(a
[i
], b
[i
]);
190 /* Compute integer hull of truncated linear cone C, i.e., of C with
191 * the origin removed.
192 * Here, we do this by first computing the Hilbert basis of C
193 * and then discarding elements from this basis that are rational
194 * overconvex combinations of other elements in the basis.
196 Matrix
*Cone_Hilbert_Integer_Hull(Polyhedron
*C
,
197 struct barvinok_options
*options
)
200 Matrix
*hilbert
= Cone_Hilbert_Basis(C
, options
->MaxRays
);
202 unsigned dim
= C
->Dimension
;
204 unsigned MaxRays
= options
->MaxRays
;
206 /* When checking for redundant points below, we want to
207 * check if there are any _rational_ solutions.
209 POL_UNSET(options
->MaxRays
, POL_INTEGER
);
211 POL_ENSURE_VERTICES(C
);
212 rays
= Matrix_Alloc(C
->NbRays
-1, C
->Dimension
);
213 for (i
= 0, j
= 0; i
< C
->NbRays
; ++i
) {
214 if (value_notzero_p(C
->Ray
[i
][1+C
->Dimension
]))
216 Vector_Copy(C
->Ray
[i
]+1, rays
->p
[j
++], C
->Dimension
);
219 /* We only sort the pointers into the big Value array */
220 qsort(rays
->p
, rays
->NbRows
, sizeof(Value
*), lex_cmp
);
221 qsort(hilbert
->p
, hilbert
->NbRows
, sizeof(Value
*), lex_cmp
);
223 /* Remove rays from Hilbert basis */
224 for (i
= 0, j
= 0, k
= 0; i
< hilbert
->NbRows
&& j
< rays
->NbRows
; ++i
) {
225 if (Vector_Equal(hilbert
->p
[i
], rays
->p
[j
], C
->Dimension
))
228 hilbert
->p
[k
++] = hilbert
->p
[i
];
232 /* Now remove points that are overconvex combinations of other points */
234 for (i
= 0; hilbert
->NbRows
> 1 && i
< hilbert
->NbRows
; ++i
) {
237 int nray
= rays
->NbRows
;
238 int npoint
= hilbert
->NbRows
;
239 enum lp_result result
;
241 LP
= Matrix_Alloc(dim
+ 1 + nray
+ (npoint
-1), 2 + nray
+ (npoint
-1));
242 for (j
= 0; j
< dim
; ++j
) {
243 for (k
= 0; k
< nray
; ++k
)
244 value_assign(LP
->p
[j
][k
+1], rays
->p
[k
][j
]);
245 for (k
= 0; k
< npoint
; ++k
) {
247 value_oppose(LP
->p
[j
][1+nray
+npoint
-1], hilbert
->p
[k
][j
]);
249 value_assign(LP
->p
[j
][1+nray
+k
-(k
>i
)], hilbert
->p
[k
][j
]);
252 value_set_si(LP
->p
[dim
][0], 1);
253 for (k
= 0; k
< nray
+npoint
-1; ++k
)
254 value_set_si(LP
->p
[dim
][1+k
], 1);
255 value_set_si(LP
->p
[dim
][LP
->NbColumns
-1], -1);
256 for (k
= 0; k
< LP
->NbColumns
-2; ++k
) {
257 value_set_si(LP
->p
[dim
+1+k
][0], 1);
258 value_set_si(LP
->p
[dim
+1+k
][1+k
], 1);
261 /* Somewhat arbitrary objective function. */
262 obj
= Vector_Alloc(LP
->NbColumns
-1);
263 value_set_si(obj
->p
[0], 1);
264 value_set_si(obj
->p
[obj
->Size
-1], 1);
266 result
= constraints_opt(LP
, obj
->p
, obj
->p
[0], lp_min
, &tmp
,
269 /* If the LP is not empty, the point can be discarded */
270 if (result
!= lp_empty
) {
272 if (i
< hilbert
->NbRows
)
273 hilbert
->p
[i
] = hilbert
->p
[hilbert
->NbRows
];
282 hull
= Matrix_Alloc(rays
->NbRows
+ hilbert
->NbRows
, dim
+1);
283 for (i
= 0; i
< rays
->NbRows
; ++i
) {
284 Vector_Copy(rays
->p
[i
], hull
->p
[i
], dim
);
285 value_set_si(hull
->p
[i
][dim
], 1);
287 for (i
= 0; i
< hilbert
->NbRows
; ++i
) {
288 Vector_Copy(hilbert
->p
[i
], hull
->p
[rays
->NbRows
+i
], dim
);
289 value_set_si(hull
->p
[rays
->NbRows
+i
][dim
], 1);
292 Matrix_Free(hilbert
);
294 options
->MaxRays
= MaxRays
;