add exported isl_multi_aff_involves_locals
[isl.git] / isl_farkas.c
blob111cd51f77577febd1933302081d2ab658c50574
1 /*
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,
8 * 91893 Orsay, France
9 */
11 #include <isl_map_private.h>
12 #include <isl/set.h>
13 #include <isl_space_private.h>
14 #include <isl_seq.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
34 * can be dropped.
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
40 * constraints on P.
41 * This is essentially Farkas' lemma.
43 * Since
44 * [ 1 0 ]
45 * [ w y ] = [t_0 t] [ b A ]
47 * we have
49 * C' = { w, y | exists t_0, t >= 0 : y = t A and w = t_0 + t b }
50 * or
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,
67 const char *prefix)
69 int i;
70 isl_ctx *ctx;
71 isl_size nvar;
72 size_t prefix_len = strlen(prefix);
74 if (!space)
75 return NULL;
77 ctx = isl_space_get_ctx(space);
78 nvar = isl_space_dim(space, isl_dim_set);
79 if (nvar < 0)
80 return isl_space_free(space);
82 for (i = 0; i < nvar; ++i) {
83 const char *name;
84 char *prefix_name;
86 name = isl_space_get_dim_name(space, isl_dim_set, i);
87 if (!name)
88 continue;
90 prefix_name = isl_alloc_array(ctx, char,
91 prefix_len + strlen(name) + 1);
92 if (!prefix_name)
93 goto error;
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);
99 free(prefix_name);
102 return space;
103 error:
104 isl_space_free(space);
105 return NULL;
108 /* Given a dimension specification of the solutions space, construct
109 * a dimension specification for the space of coefficients.
111 * In particular transform
113 * [params] -> { S }
115 * to
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;
124 isl_size nvar;
125 isl_size nparam;
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");
146 return space;
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)
154 int i;
155 isl_size n;
156 size_t prefix_len = strlen(prefix);
158 n = isl_space_dim(space, type);
159 if (n < 0)
160 return isl_space_free(space);
162 for (i = 0; i < n; ++i) {
163 const char *name;
165 name = isl_space_get_dim_name(space, type, i);
166 if (!name)
167 continue;
168 if (strncmp(name, prefix, prefix_len))
169 continue;
171 space = isl_space_set_dim_name(space,
172 type, i, name + prefix_len);
175 return space;
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] }
185 * to
187 * [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)
193 isl_size nparam;
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);
200 if (nparam < 0)
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);
206 return 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)
213 isl_basic_set *bset;
215 bset = isl_basic_set_universe(space);
216 bset = isl_basic_set_set_rational(bset);
218 return 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). "dim" 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)
236 int i, j, k;
237 isl_basic_set *dual = NULL;
238 isl_size total;
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);
246 if (total < 0)
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);
255 if (k < 0)
256 goto error;
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);
262 if (k < 0)
263 goto error;
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],
268 bset->eq[j][1 + i]);
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);
276 if (k < 0)
277 goto error;
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);
283 if (shift > 0) {
284 k = isl_basic_set_alloc_inequality(dual);
285 if (k < 0)
286 goto error;
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],
291 bset->eq[j][0]);
292 for (j = 0; j < bset->n_ineq; ++j)
293 isl_int_neg(dual->ineq[k][2 + total + bset->n_eq + j],
294 bset->ineq[j][0]);
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);
302 return dual;
303 error:
304 isl_basic_set_free(bset);
305 isl_basic_set_free(dual);
306 return NULL;
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)
315 isl_space *space;
317 if (!bset)
318 return NULL;
319 if (bset->n_div)
320 isl_die(bset->ctx, isl_error_invalid,
321 "input set not allowed to have local variables",
322 goto error);
324 space = isl_basic_set_get_space(bset);
325 space = isl_space_coefficients(space);
327 return farkas(space, bset, 1);
328 error:
329 isl_basic_set_free(bset);
330 return NULL;
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)
340 isl_space *space;
342 if (!bset)
343 return NULL;
344 if (bset->n_div)
345 isl_die(bset->ctx, isl_error_invalid,
346 "input set not allowed to have local variables",
347 goto error);
349 space = isl_basic_set_get_space(bset);
350 space = isl_space_solutions(space);
352 return farkas(space, bset, -1);
353 error:
354 isl_basic_set_free(bset);
355 return NULL;
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)
363 int i;
364 isl_basic_set *coeff;
366 if (!set)
367 return NULL;
368 if (set->n == 0) {
369 isl_space *space = isl_set_get_space(set);
370 space = isl_space_coefficients(space);
371 isl_set_free(set);
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);
384 isl_set_free(set);
385 return coeff;
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)
412 int i;
413 isl_basic_set *sol;
415 if (!set)
416 return NULL;
417 if (set->n == 0) {
418 isl_space *space = isl_set_get_space(set);
419 space = isl_space_solutions(space);
420 isl_set_free(set);
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);
433 isl_set_free(set);
434 return sol;