2 * Copyright 2010 INRIA Saclay
4 * Use of this software is governed by the MIT license
6 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
7 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
11 #include <isl_map_private.h>
13 #include <isl_space_private.h>
17 * Let C be a cone and define
19 * C' := { y | forall x in C : y x >= 0 }
21 * C' contains the coefficients of all linear constraints
22 * that are valid for C.
23 * Furthermore, C'' = C.
25 * If C is defined as { x | A x >= 0 }
26 * then any element in C' must be a non-negative combination
27 * of the rows of A, i.e., y = t A with t >= 0. That is,
29 * C' = { y | exists t >= 0 : y = t A }
31 * If any of the rows in A actually represents an equality, then
32 * also negative combinations of this row are allowed and so the
33 * non-negativity constraint on the corresponding element of t
36 * A polyhedron P = { x | b + A x >= 0 } can be represented
37 * in homogeneous coordinates by the cone
38 * C = { [z,x] | b z + A x >= and z >= 0 }
39 * The valid linear constraints on C correspond to the valid affine
41 * This is essentially Farkas' lemma.
45 * [ w y ] = [t_0 t] [ b A ]
49 * C' = { w, y | exists t_0, t >= 0 : y = t A and w = t_0 + t b }
52 * C' = { w, y | exists t >= 0 : y = t A and w - t b >= 0 }
54 * In practice, we introduce an extra variable (w), shifting all
55 * other variables to the right, and an extra inequality
56 * (w - t b >= 0) corresponding to the positivity constraint on
57 * the homogeneous coordinate.
59 * When going back from coefficients to solutions, we immediately
60 * plug in 1 for z, which corresponds to shifting all variables
61 * to the left, with the leftmost ending up in the constant position.
64 /* Add the given prefix to all named isl_dim_set dimensions in "space".
66 static __isl_give isl_space
*isl_space_prefix(__isl_take isl_space
*space
,
72 size_t prefix_len
= strlen(prefix
);
77 ctx
= isl_space_get_ctx(space
);
78 nvar
= isl_space_dim(space
, isl_dim_set
);
80 return isl_space_free(space
);
82 for (i
= 0; i
< nvar
; ++i
) {
86 name
= isl_space_get_dim_name(space
, isl_dim_set
, i
);
90 prefix_name
= isl_alloc_array(ctx
, char,
91 prefix_len
+ strlen(name
) + 1);
94 memcpy(prefix_name
, prefix
, prefix_len
);
95 strcpy(prefix_name
+ prefix_len
, name
);
97 space
= isl_space_set_dim_name(space
,
98 isl_dim_set
, i
, prefix_name
);
104 isl_space_free(space
);
108 /* Given a dimension specification of the solutions space, construct
109 * a dimension specification for the space of coefficients.
111 * In particular transform
117 * { coefficients[[cst, params] -> S] }
119 * and prefix each dimension name with "c_".
121 static __isl_give isl_space
*isl_space_coefficients(__isl_take isl_space
*space
)
123 isl_space
*space_param
;
127 nvar
= isl_space_dim(space
, isl_dim_set
);
128 nparam
= isl_space_dim(space
, isl_dim_param
);
129 if (nvar
< 0 || nparam
< 0)
130 return isl_space_free(space
);
131 space_param
= isl_space_copy(space
);
132 space_param
= isl_space_drop_dims(space_param
, isl_dim_set
, 0, nvar
);
133 space_param
= isl_space_move_dims(space_param
, isl_dim_set
, 0,
134 isl_dim_param
, 0, nparam
);
135 space_param
= isl_space_prefix(space_param
, "c_");
136 space_param
= isl_space_insert_dims(space_param
, isl_dim_set
, 0, 1);
137 space_param
= isl_space_set_dim_name(space_param
,
138 isl_dim_set
, 0, "c_cst");
139 space
= isl_space_drop_dims(space
, isl_dim_param
, 0, nparam
);
140 space
= isl_space_prefix(space
, "c_");
141 space
= isl_space_join(isl_space_from_domain(space_param
),
142 isl_space_from_range(space
));
143 space
= isl_space_wrap(space
);
144 space
= isl_space_set_tuple_name(space
, isl_dim_set
, "coefficients");
149 /* Drop the given prefix from all named dimensions of type "type" in "space".
151 static __isl_give isl_space
*isl_space_unprefix(__isl_take isl_space
*space
,
152 enum isl_dim_type type
, const char *prefix
)
156 size_t prefix_len
= strlen(prefix
);
158 n
= isl_space_dim(space
, type
);
160 return isl_space_free(space
);
162 for (i
= 0; i
< n
; ++i
) {
165 name
= isl_space_get_dim_name(space
, type
, i
);
168 if (strncmp(name
, prefix
, prefix_len
))
171 space
= isl_space_set_dim_name(space
,
172 type
, i
, name
+ prefix_len
);
178 /* Given a dimension specification of the space of coefficients, construct
179 * a dimension specification for the space of solutions.
181 * In particular transform
183 * { coefficients[[cst, params] -> S] }
189 * and drop the "c_" prefix from the dimension names.
191 static __isl_give isl_space
*isl_space_solutions(__isl_take isl_space
*space
)
195 space
= isl_space_unwrap(space
);
196 space
= isl_space_drop_dims(space
, isl_dim_in
, 0, 1);
197 space
= isl_space_unprefix(space
, isl_dim_in
, "c_");
198 space
= isl_space_unprefix(space
, isl_dim_out
, "c_");
199 nparam
= isl_space_dim(space
, isl_dim_in
);
201 return isl_space_free(space
);
202 space
= isl_space_move_dims(space
,
203 isl_dim_param
, 0, isl_dim_in
, 0, nparam
);
204 space
= isl_space_range(space
);
209 /* Return the rational universe basic set in the given space.
211 static __isl_give isl_basic_set
*rational_universe(__isl_take isl_space
*space
)
215 bset
= isl_basic_set_universe(space
);
216 bset
= isl_basic_set_set_rational(bset
);
221 /* Compute the dual of "bset" by applying Farkas' lemma.
222 * As explained above, we add an extra dimension to represent
223 * the coefficient of the constant term when going from solutions
224 * to coefficients (shift == 1) and we drop the extra dimension when going
225 * in the opposite direction (shift == -1). "space" is the space in which
226 * the dual should be created.
228 * If "bset" is (obviously) empty, then the way this emptiness
229 * is represented by the constraints does not allow for the application
230 * of the standard farkas algorithm. We therefore handle this case
231 * specifically and return the universe basic set.
233 static __isl_give isl_basic_set
*farkas(__isl_take isl_space
*space
,
234 __isl_take isl_basic_set
*bset
, int shift
)
237 isl_basic_set
*dual
= NULL
;
240 if (isl_basic_set_plain_is_empty(bset
)) {
241 isl_basic_set_free(bset
);
242 return rational_universe(space
);
245 total
= isl_basic_set_dim(bset
, isl_dim_all
);
247 space
= isl_space_free(space
);
249 dual
= isl_basic_set_alloc_space(space
, bset
->n_eq
+ bset
->n_ineq
,
250 total
, bset
->n_ineq
+ (shift
> 0));
251 dual
= isl_basic_set_set_rational(dual
);
253 for (i
= 0; i
< bset
->n_eq
+ bset
->n_ineq
; ++i
) {
254 k
= isl_basic_set_alloc_div(dual
);
257 isl_int_set_si(dual
->div
[k
][0], 0);
260 for (i
= 0; i
< total
; ++i
) {
261 k
= isl_basic_set_alloc_equality(dual
);
264 isl_seq_clr(dual
->eq
[k
], 1 + shift
+ total
);
265 isl_int_set_si(dual
->eq
[k
][1 + shift
+ i
], -1);
266 for (j
= 0; j
< bset
->n_eq
; ++j
)
267 isl_int_set(dual
->eq
[k
][1 + shift
+ total
+ j
],
269 for (j
= 0; j
< bset
->n_ineq
; ++j
)
270 isl_int_set(dual
->eq
[k
][1 + shift
+ total
+ bset
->n_eq
+ j
],
271 bset
->ineq
[j
][1 + i
]);
274 for (i
= 0; i
< bset
->n_ineq
; ++i
) {
275 k
= isl_basic_set_alloc_inequality(dual
);
278 isl_seq_clr(dual
->ineq
[k
],
279 1 + shift
+ total
+ bset
->n_eq
+ bset
->n_ineq
);
280 isl_int_set_si(dual
->ineq
[k
][1 + shift
+ total
+ bset
->n_eq
+ i
], 1);
284 k
= isl_basic_set_alloc_inequality(dual
);
287 isl_seq_clr(dual
->ineq
[k
], 2 + total
);
288 isl_int_set_si(dual
->ineq
[k
][1], 1);
289 for (j
= 0; j
< bset
->n_eq
; ++j
)
290 isl_int_neg(dual
->ineq
[k
][2 + total
+ j
],
292 for (j
= 0; j
< bset
->n_ineq
; ++j
)
293 isl_int_neg(dual
->ineq
[k
][2 + total
+ bset
->n_eq
+ j
],
297 dual
= isl_basic_set_remove_divs(dual
);
298 dual
= isl_basic_set_simplify(dual
);
299 dual
= isl_basic_set_finalize(dual
);
301 isl_basic_set_free(bset
);
304 isl_basic_set_free(bset
);
305 isl_basic_set_free(dual
);
309 /* Construct a basic set containing the tuples of coefficients of all
310 * valid affine constraints on the given basic set.
312 __isl_give isl_basic_set
*isl_basic_set_coefficients(
313 __isl_take isl_basic_set
*bset
)
320 isl_die(bset
->ctx
, isl_error_invalid
,
321 "input set not allowed to have local variables",
324 space
= isl_basic_set_get_space(bset
);
325 space
= isl_space_coefficients(space
);
327 return farkas(space
, bset
, 1);
329 isl_basic_set_free(bset
);
333 /* Construct a basic set containing the elements that satisfy all
334 * affine constraints whose coefficient tuples are
335 * contained in the given basic set.
337 __isl_give isl_basic_set
*isl_basic_set_solutions(
338 __isl_take isl_basic_set
*bset
)
345 isl_die(bset
->ctx
, isl_error_invalid
,
346 "input set not allowed to have local variables",
349 space
= isl_basic_set_get_space(bset
);
350 space
= isl_space_solutions(space
);
352 return farkas(space
, bset
, -1);
354 isl_basic_set_free(bset
);
358 /* Construct a basic set containing the tuples of coefficients of all
359 * valid affine constraints on the given set.
361 __isl_give isl_basic_set
*isl_set_coefficients(__isl_take isl_set
*set
)
364 isl_basic_set
*coeff
;
369 isl_space
*space
= isl_set_get_space(set
);
370 space
= isl_space_coefficients(space
);
372 return rational_universe(space
);
375 coeff
= isl_basic_set_coefficients(isl_basic_set_copy(set
->p
[0]));
377 for (i
= 1; i
< set
->n
; ++i
) {
378 isl_basic_set
*bset
, *coeff_i
;
379 bset
= isl_basic_set_copy(set
->p
[i
]);
380 coeff_i
= isl_basic_set_coefficients(bset
);
381 coeff
= isl_basic_set_intersect(coeff
, coeff_i
);
388 /* Wrapper around isl_basic_set_coefficients for use
389 * as a isl_basic_set_list_map callback.
391 static __isl_give isl_basic_set
*coefficients_wrap(
392 __isl_take isl_basic_set
*bset
, void *user
)
394 return isl_basic_set_coefficients(bset
);
397 /* Replace the elements of "list" by the result of applying
398 * isl_basic_set_coefficients to them.
400 __isl_give isl_basic_set_list
*isl_basic_set_list_coefficients(
401 __isl_take isl_basic_set_list
*list
)
403 return isl_basic_set_list_map(list
, &coefficients_wrap
, NULL
);
406 /* Construct a basic set containing the elements that satisfy all
407 * affine constraints whose coefficient tuples are
408 * contained in the given set.
410 __isl_give isl_basic_set
*isl_set_solutions(__isl_take isl_set
*set
)
418 isl_space
*space
= isl_set_get_space(set
);
419 space
= isl_space_solutions(space
);
421 return rational_universe(space
);
424 sol
= isl_basic_set_solutions(isl_basic_set_copy(set
->p
[0]));
426 for (i
= 1; i
< set
->n
; ++i
) {
427 isl_basic_set
*bset
, *sol_i
;
428 bset
= isl_basic_set_copy(set
->p
[i
]);
429 sol_i
= isl_basic_set_solutions(bset
);
430 sol
= isl_basic_set_intersect(sol
, sol_i
);