isl_tab_lexopt_templ.c
7.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
/*
* Copyright 2008-2009 Katholieke Universiteit Leuven
* Copyright 2010 INRIA Saclay
* Copyright 2011 Sven Verdoolaege
*
* Use of this software is governed by the MIT license
*
* Written by Sven Verdoolaege, K.U.Leuven, Departement
* Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
* and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
* ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
*/
#define xSF(TYPE,SUFFIX) TYPE ## SUFFIX
#define SF(TYPE,SUFFIX) xSF(TYPE,SUFFIX)
/* Given a basic map with at least two parallel constraints (as found
* by the function parallel_constraints), first look for more constraints
* parallel to the two constraint and replace the found list of parallel
* constraints by a single constraint with as "input" part the minimum
* of the input parts of the list of constraints. Then, recursively call
* basic_map_partial_lexopt (possibly finding more parallel constraints)
* and plug in the definition of the minimum in the result.
*
* As in parallel_constraints, only inequality constraints that only
* involve input variables that do not occur in any other inequality
* constraints are considered.
*
* More specifically, given a set of constraints
*
* a x + b_i(p) >= 0
*
* Replace this set by a single constraint
*
* a x + u >= 0
*
* with u a new parameter with constraints
*
* u <= b_i(p)
*
* Any solution to the new system is also a solution for the original system
* since
*
* a x >= -u >= -b_i(p)
*
* Moreover, m = min_i(b_i(p)) satisfies the constraints on u and can
* therefore be plugged into the solution.
*/
static TYPE *SF(basic_map_partial_lexopt_symm,SUFFIX)(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, int max, int first, int second)
{
int i, n, k;
int *list = NULL;
isl_size bmap_in, bmap_param, bmap_all;
unsigned n_in, n_out, n_div;
isl_ctx *ctx;
isl_vec *var = NULL;
isl_mat *cst = NULL;
isl_space *map_space, *set_space;
map_space = isl_basic_map_get_space(bmap);
set_space = empty ? isl_basic_set_get_space(dom) : NULL;
bmap_in = isl_basic_map_dim(bmap, isl_dim_in);
bmap_param = isl_basic_map_dim(bmap, isl_dim_param);
bmap_all = isl_basic_map_dim(bmap, isl_dim_all);
if (bmap_in < 0 || bmap_param < 0 || bmap_all < 0)
goto error;
n_in = bmap_param + bmap_in;
n_out = bmap_all - n_in;
ctx = isl_basic_map_get_ctx(bmap);
list = isl_alloc_array(ctx, int, bmap->n_ineq);
var = isl_vec_alloc(ctx, n_out);
if ((bmap->n_ineq && !list) || (n_out && !var))
goto error;
list[0] = first;
list[1] = second;
isl_seq_cpy(var->el, bmap->ineq[first] + 1 + n_in, n_out);
for (i = second + 1, n = 2; i < bmap->n_ineq; ++i) {
if (isl_seq_eq(var->el, bmap->ineq[i] + 1 + n_in, n_out) &&
all_single_occurrence(bmap, i, n_in))
list[n++] = i;
}
cst = isl_mat_alloc(ctx, n, 1 + n_in);
if (!cst)
goto error;
for (i = 0; i < n; ++i)
isl_seq_cpy(cst->row[i], bmap->ineq[list[i]], 1 + n_in);
bmap = isl_basic_map_cow(bmap);
if (!bmap)
goto error;
for (i = n - 1; i >= 0; --i)
if (isl_basic_map_drop_inequality(bmap, list[i]) < 0)
goto error;
bmap = isl_basic_map_add_dims(bmap, isl_dim_in, 1);
bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
k = isl_basic_map_alloc_inequality(bmap);
if (k < 0)
goto error;
isl_seq_clr(bmap->ineq[k], 1 + n_in);
isl_int_set_si(bmap->ineq[k][1 + n_in], 1);
isl_seq_cpy(bmap->ineq[k] + 1 + n_in + 1, var->el, n_out);
bmap = isl_basic_map_finalize(bmap);
n_div = isl_basic_set_dim(dom, isl_dim_div);
dom = isl_basic_set_add_dims(dom, isl_dim_set, 1);
dom = isl_basic_set_extend_constraints(dom, 0, n);
for (i = 0; i < n; ++i) {
k = isl_basic_set_alloc_inequality(dom);
if (k < 0)
goto error;
isl_seq_cpy(dom->ineq[k], cst->row[i], 1 + n_in);
isl_int_set_si(dom->ineq[k][1 + n_in], -1);
isl_seq_clr(dom->ineq[k] + 1 + n_in + 1, n_div);
}
isl_vec_free(var);
free(list);
return SF(basic_map_partial_lexopt_symm_core,SUFFIX)(bmap, dom, empty,
max, cst, map_space, set_space);
error:
isl_space_free(map_space);
isl_space_free(set_space);
isl_mat_free(cst);
isl_vec_free(var);
free(list);
isl_basic_set_free(dom);
isl_basic_map_free(bmap);
return NULL;
}
/* Recursive part of isl_tab_basic_map_partial_lexopt*, after detecting
* equalities and removing redundant constraints.
*
* We first check if there are any parallel constraints (left).
* If not, we are in the base case.
* If there are parallel constraints, we replace them by a single
* constraint in basic_map_partial_lexopt_symm_pma and then call
* this function recursively to look for more parallel constraints.
*/
static __isl_give TYPE *SF(basic_map_partial_lexopt,SUFFIX)(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, int max)
{
isl_bool par = isl_bool_false;
int first, second;
if (!bmap)
goto error;
if (bmap->ctx->opt->pip_symmetry)
par = parallel_constraints(bmap, &first, &second);
if (par < 0)
goto error;
if (!par)
return SF(basic_map_partial_lexopt_base,SUFFIX)(bmap, dom,
empty, max);
return SF(basic_map_partial_lexopt_symm,SUFFIX)(bmap, dom, empty, max,
first, second);
error:
isl_basic_set_free(dom);
isl_basic_map_free(bmap);
return NULL;
}
/* Compute the lexicographic minimum (or maximum if "flags" includes
* ISL_OPT_MAX) of "bmap" over the domain "dom" and return the result as
* either a map or a piecewise multi-affine expression depending on TYPE.
* If "empty" is not NULL, then *empty is assigned a set that
* contains those parts of the domain where there is no solution.
* If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
* should be computed over the domain of "bmap". "empty" is also NULL
* in this case.
* If "bmap" is marked as rational (ISL_BASIC_MAP_RATIONAL),
* then we compute the rational optimum. Otherwise, we compute
* the integral optimum.
*
* We perform some preprocessing. As the PILP solver does not
* handle implicit equalities very well, we first make sure all
* the equalities are explicitly available.
*
* We also add context constraints to the basic map and remove
* redundant constraints. This is only needed because of the
* way we handle simple symmetries. In particular, we currently look
* for symmetries on the constraints, before we set up the main tableau.
* It is then no good to look for symmetries on possibly redundant constraints.
* If the domain was extracted from the basic map, then there is
* no need to add back those constraints again.
*/
__isl_give TYPE *SF(isl_tab_basic_map_partial_lexopt,SUFFIX)(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, unsigned flags)
{
int max, full;
isl_bool compatible;
if (empty)
*empty = NULL;
full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
if (full)
dom = extract_domain(bmap, flags);
compatible = isl_basic_map_compatible_domain(bmap, dom);
if (compatible < 0)
goto error;
if (!compatible)
isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
"domain does not match input", goto error);
max = ISL_FL_ISSET(flags, ISL_OPT_MAX);
if (isl_basic_set_dim(dom, isl_dim_all) == 0)
return SF(basic_map_partial_lexopt,SUFFIX)(bmap, dom, empty,
max);
if (!full)
bmap = isl_basic_map_intersect_domain(bmap,
isl_basic_set_copy(dom));
bmap = isl_basic_map_detect_equalities(bmap);
bmap = isl_basic_map_remove_redundancies(bmap);
return SF(basic_map_partial_lexopt,SUFFIX)(bmap, dom, empty, max);
error:
isl_basic_set_free(dom);
isl_basic_map_free(bmap);
return NULL;
}